xref: /aosp_15_r20/external/bc/src/bc_parse.c (revision 5a6e848804d15c18a0125914844ee4eb0bda4fcf)
1*5a6e8488SAndroid Build Coastguard Worker /*
2*5a6e8488SAndroid Build Coastguard Worker  * *****************************************************************************
3*5a6e8488SAndroid Build Coastguard Worker  *
4*5a6e8488SAndroid Build Coastguard Worker  * SPDX-License-Identifier: BSD-2-Clause
5*5a6e8488SAndroid Build Coastguard Worker  *
6*5a6e8488SAndroid Build Coastguard Worker  * Copyright (c) 2018-2024 Gavin D. Howard and contributors.
7*5a6e8488SAndroid Build Coastguard Worker  *
8*5a6e8488SAndroid Build Coastguard Worker  * Redistribution and use in source and binary forms, with or without
9*5a6e8488SAndroid Build Coastguard Worker  * modification, are permitted provided that the following conditions are met:
10*5a6e8488SAndroid Build Coastguard Worker  *
11*5a6e8488SAndroid Build Coastguard Worker  * * Redistributions of source code must retain the above copyright notice, this
12*5a6e8488SAndroid Build Coastguard Worker  *   list of conditions and the following disclaimer.
13*5a6e8488SAndroid Build Coastguard Worker  *
14*5a6e8488SAndroid Build Coastguard Worker  * * Redistributions in binary form must reproduce the above copyright notice,
15*5a6e8488SAndroid Build Coastguard Worker  *   this list of conditions and the following disclaimer in the documentation
16*5a6e8488SAndroid Build Coastguard Worker  *   and/or other materials provided with the distribution.
17*5a6e8488SAndroid Build Coastguard Worker  *
18*5a6e8488SAndroid Build Coastguard Worker  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19*5a6e8488SAndroid Build Coastguard Worker  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20*5a6e8488SAndroid Build Coastguard Worker  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21*5a6e8488SAndroid Build Coastguard Worker  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22*5a6e8488SAndroid Build Coastguard Worker  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23*5a6e8488SAndroid Build Coastguard Worker  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24*5a6e8488SAndroid Build Coastguard Worker  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25*5a6e8488SAndroid Build Coastguard Worker  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26*5a6e8488SAndroid Build Coastguard Worker  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27*5a6e8488SAndroid Build Coastguard Worker  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28*5a6e8488SAndroid Build Coastguard Worker  * POSSIBILITY OF SUCH DAMAGE.
29*5a6e8488SAndroid Build Coastguard Worker  *
30*5a6e8488SAndroid Build Coastguard Worker  * *****************************************************************************
31*5a6e8488SAndroid Build Coastguard Worker  *
32*5a6e8488SAndroid Build Coastguard Worker  * The parser for bc.
33*5a6e8488SAndroid Build Coastguard Worker  *
34*5a6e8488SAndroid Build Coastguard Worker  */
35*5a6e8488SAndroid Build Coastguard Worker 
36*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLED
37*5a6e8488SAndroid Build Coastguard Worker 
38*5a6e8488SAndroid Build Coastguard Worker #include <assert.h>
39*5a6e8488SAndroid Build Coastguard Worker #include <stdbool.h>
40*5a6e8488SAndroid Build Coastguard Worker #include <stdlib.h>
41*5a6e8488SAndroid Build Coastguard Worker #include <string.h>
42*5a6e8488SAndroid Build Coastguard Worker 
43*5a6e8488SAndroid Build Coastguard Worker #include <setjmp.h>
44*5a6e8488SAndroid Build Coastguard Worker 
45*5a6e8488SAndroid Build Coastguard Worker #include <bc.h>
46*5a6e8488SAndroid Build Coastguard Worker #include <num.h>
47*5a6e8488SAndroid Build Coastguard Worker #include <vm.h>
48*5a6e8488SAndroid Build Coastguard Worker 
49*5a6e8488SAndroid Build Coastguard Worker // Before you embark on trying to understand this code, have you read the
50*5a6e8488SAndroid Build Coastguard Worker // Development manual (manuals/development.md) and the comment in include/bc.h
51*5a6e8488SAndroid Build Coastguard Worker // yet? No? Do that first. I'm serious.
52*5a6e8488SAndroid Build Coastguard Worker //
53*5a6e8488SAndroid Build Coastguard Worker // The reason is because this file holds the most sensitive and finicky code in
54*5a6e8488SAndroid Build Coastguard Worker // the entire codebase. Even getting history to work on Windows was nothing
55*5a6e8488SAndroid Build Coastguard Worker // compared to this. This is where dreams go to die, where dragons live, and
56*5a6e8488SAndroid Build Coastguard Worker // from which Ken Thompson himself would flee.
57*5a6e8488SAndroid Build Coastguard Worker 
58*5a6e8488SAndroid Build Coastguard Worker static void
59*5a6e8488SAndroid Build Coastguard Worker bc_parse_else(BcParse* p);
60*5a6e8488SAndroid Build Coastguard Worker 
61*5a6e8488SAndroid Build Coastguard Worker static void
62*5a6e8488SAndroid Build Coastguard Worker bc_parse_stmt(BcParse* p);
63*5a6e8488SAndroid Build Coastguard Worker 
64*5a6e8488SAndroid Build Coastguard Worker static BcParseStatus
65*5a6e8488SAndroid Build Coastguard Worker bc_parse_expr_err(BcParse* p, uint8_t flags, BcParseNext next);
66*5a6e8488SAndroid Build Coastguard Worker 
67*5a6e8488SAndroid Build Coastguard Worker static void
68*5a6e8488SAndroid Build Coastguard Worker bc_parse_expr_status(BcParse* p, uint8_t flags, BcParseNext next);
69*5a6e8488SAndroid Build Coastguard Worker 
70*5a6e8488SAndroid Build Coastguard Worker /**
71*5a6e8488SAndroid Build Coastguard Worker  * Returns true if an instruction could only have come from a "leaf" expression.
72*5a6e8488SAndroid Build Coastguard Worker  * For more on what leaf expressions are, read the comment for BC_PARSE_LEAF().
73*5a6e8488SAndroid Build Coastguard Worker  * @param t  The instruction to test.
74*5a6e8488SAndroid Build Coastguard Worker  * @return   True if the instruction is a from a leaf expression.
75*5a6e8488SAndroid Build Coastguard Worker  */
76*5a6e8488SAndroid Build Coastguard Worker static bool
bc_parse_inst_isLeaf(BcInst t)77*5a6e8488SAndroid Build Coastguard Worker bc_parse_inst_isLeaf(BcInst t)
78*5a6e8488SAndroid Build Coastguard Worker {
79*5a6e8488SAndroid Build Coastguard Worker 	return (t >= BC_INST_NUM && t <= BC_INST_LEADING_ZERO) ||
80*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_EXTRA_MATH
81*5a6e8488SAndroid Build Coastguard Worker 	       t == BC_INST_TRUNC ||
82*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_EXTRA_MATH
83*5a6e8488SAndroid Build Coastguard Worker 	       t <= BC_INST_DEC;
84*5a6e8488SAndroid Build Coastguard Worker }
85*5a6e8488SAndroid Build Coastguard Worker 
86*5a6e8488SAndroid Build Coastguard Worker /**
87*5a6e8488SAndroid Build Coastguard Worker  * Returns true if the *previous* token was a delimiter. A delimiter is anything
88*5a6e8488SAndroid Build Coastguard Worker  * that can legally end a statement. In bc's case, it could be a newline, a
89*5a6e8488SAndroid Build Coastguard Worker  * semicolon, and a brace in certain cases.
90*5a6e8488SAndroid Build Coastguard Worker  * @param p  The parser.
91*5a6e8488SAndroid Build Coastguard Worker  * @return   True if the token is a legal delimiter.
92*5a6e8488SAndroid Build Coastguard Worker  */
93*5a6e8488SAndroid Build Coastguard Worker static bool
bc_parse_isDelimiter(const BcParse * p)94*5a6e8488SAndroid Build Coastguard Worker bc_parse_isDelimiter(const BcParse* p)
95*5a6e8488SAndroid Build Coastguard Worker {
96*5a6e8488SAndroid Build Coastguard Worker 	BcLexType t = p->l.t;
97*5a6e8488SAndroid Build Coastguard Worker 	bool good;
98*5a6e8488SAndroid Build Coastguard Worker 
99*5a6e8488SAndroid Build Coastguard Worker 	// If it's an obvious delimiter, say so.
100*5a6e8488SAndroid Build Coastguard Worker 	if (BC_PARSE_DELIMITER(t)) return true;
101*5a6e8488SAndroid Build Coastguard Worker 
102*5a6e8488SAndroid Build Coastguard Worker 	good = false;
103*5a6e8488SAndroid Build Coastguard Worker 
104*5a6e8488SAndroid Build Coastguard Worker 	// If the current token is a keyword, then...beware. That means that we need
105*5a6e8488SAndroid Build Coastguard Worker 	// to check for a "dangling" else, where there was no brace-delimited block
106*5a6e8488SAndroid Build Coastguard Worker 	// on the previous if.
107*5a6e8488SAndroid Build Coastguard Worker 	if (t == BC_LEX_KW_ELSE)
108*5a6e8488SAndroid Build Coastguard Worker 	{
109*5a6e8488SAndroid Build Coastguard Worker 		size_t i;
110*5a6e8488SAndroid Build Coastguard Worker 		uint16_t *fptr = NULL, flags = BC_PARSE_FLAG_ELSE;
111*5a6e8488SAndroid Build Coastguard Worker 
112*5a6e8488SAndroid Build Coastguard Worker 		// As long as going up the stack is valid for a dangling else, keep on.
113*5a6e8488SAndroid Build Coastguard Worker 		for (i = 0; i < p->flags.len && BC_PARSE_BLOCK_STMT(flags); ++i)
114*5a6e8488SAndroid Build Coastguard Worker 		{
115*5a6e8488SAndroid Build Coastguard Worker 			fptr = bc_vec_item_rev(&p->flags, i);
116*5a6e8488SAndroid Build Coastguard Worker 			flags = *fptr;
117*5a6e8488SAndroid Build Coastguard Worker 
118*5a6e8488SAndroid Build Coastguard Worker 			// If we need a brace and don't have one, then we don't have a
119*5a6e8488SAndroid Build Coastguard Worker 			// delimiter.
120*5a6e8488SAndroid Build Coastguard Worker 			if ((flags & BC_PARSE_FLAG_BRACE) && p->l.last != BC_LEX_RBRACE)
121*5a6e8488SAndroid Build Coastguard Worker 			{
122*5a6e8488SAndroid Build Coastguard Worker 				return false;
123*5a6e8488SAndroid Build Coastguard Worker 			}
124*5a6e8488SAndroid Build Coastguard Worker 		}
125*5a6e8488SAndroid Build Coastguard Worker 
126*5a6e8488SAndroid Build Coastguard Worker 		// Oh, and we had also better have an if statement somewhere.
127*5a6e8488SAndroid Build Coastguard Worker 		good = ((flags & BC_PARSE_FLAG_IF) != 0);
128*5a6e8488SAndroid Build Coastguard Worker 	}
129*5a6e8488SAndroid Build Coastguard Worker 	else if (t == BC_LEX_RBRACE)
130*5a6e8488SAndroid Build Coastguard Worker 	{
131*5a6e8488SAndroid Build Coastguard Worker 		size_t i;
132*5a6e8488SAndroid Build Coastguard Worker 
133*5a6e8488SAndroid Build Coastguard Worker 		// Since we have a brace, we need to just check if a brace was needed.
134*5a6e8488SAndroid Build Coastguard Worker 		for (i = 0; !good && i < p->flags.len; ++i)
135*5a6e8488SAndroid Build Coastguard Worker 		{
136*5a6e8488SAndroid Build Coastguard Worker 			uint16_t* fptr = bc_vec_item_rev(&p->flags, i);
137*5a6e8488SAndroid Build Coastguard Worker 			good = (((*fptr) & BC_PARSE_FLAG_BRACE) != 0);
138*5a6e8488SAndroid Build Coastguard Worker 		}
139*5a6e8488SAndroid Build Coastguard Worker 	}
140*5a6e8488SAndroid Build Coastguard Worker 
141*5a6e8488SAndroid Build Coastguard Worker 	return good;
142*5a6e8488SAndroid Build Coastguard Worker }
143*5a6e8488SAndroid Build Coastguard Worker 
144*5a6e8488SAndroid Build Coastguard Worker /**
145*5a6e8488SAndroid Build Coastguard Worker  * Returns true if we are in top level of a function body. The POSIX grammar
146*5a6e8488SAndroid Build Coastguard Worker  * is defined such that anything is allowed after a function body, so we must
147*5a6e8488SAndroid Build Coastguard Worker  * use this function to detect that case when ending a function body.
148*5a6e8488SAndroid Build Coastguard Worker  * @param p  The parser.
149*5a6e8488SAndroid Build Coastguard Worker  * @return   True if we are in the top level of parsing a function body.
150*5a6e8488SAndroid Build Coastguard Worker  */
151*5a6e8488SAndroid Build Coastguard Worker static bool
bc_parse_TopFunc(const BcParse * p)152*5a6e8488SAndroid Build Coastguard Worker bc_parse_TopFunc(const BcParse* p)
153*5a6e8488SAndroid Build Coastguard Worker {
154*5a6e8488SAndroid Build Coastguard Worker 	bool good = p->flags.len == 2;
155*5a6e8488SAndroid Build Coastguard Worker 
156*5a6e8488SAndroid Build Coastguard Worker 	uint16_t val = BC_PARSE_FLAG_BRACE | BC_PARSE_FLAG_FUNC_INNER;
157*5a6e8488SAndroid Build Coastguard Worker 	val |= BC_PARSE_FLAG_FUNC;
158*5a6e8488SAndroid Build Coastguard Worker 
159*5a6e8488SAndroid Build Coastguard Worker 	return good && BC_PARSE_TOP_FLAG(p) == val;
160*5a6e8488SAndroid Build Coastguard Worker }
161*5a6e8488SAndroid Build Coastguard Worker 
162*5a6e8488SAndroid Build Coastguard Worker /**
163*5a6e8488SAndroid Build Coastguard Worker  * Sets a previously defined exit label. What are labels? See the bc Parsing
164*5a6e8488SAndroid Build Coastguard Worker  * section of the Development manual (manuals/development.md).
165*5a6e8488SAndroid Build Coastguard Worker  * @param p  The parser.
166*5a6e8488SAndroid Build Coastguard Worker  */
167*5a6e8488SAndroid Build Coastguard Worker static void
bc_parse_setLabel(BcParse * p)168*5a6e8488SAndroid Build Coastguard Worker bc_parse_setLabel(BcParse* p)
169*5a6e8488SAndroid Build Coastguard Worker {
170*5a6e8488SAndroid Build Coastguard Worker 	BcFunc* func = p->func;
171*5a6e8488SAndroid Build Coastguard Worker 	BcInstPtr* ip = bc_vec_top(&p->exits);
172*5a6e8488SAndroid Build Coastguard Worker 	size_t* label;
173*5a6e8488SAndroid Build Coastguard Worker 
174*5a6e8488SAndroid Build Coastguard Worker 	assert(func == bc_vec_item(&p->prog->fns, p->fidx));
175*5a6e8488SAndroid Build Coastguard Worker 
176*5a6e8488SAndroid Build Coastguard Worker 	// Set the preallocated label to the correct index.
177*5a6e8488SAndroid Build Coastguard Worker 	label = bc_vec_item(&func->labels, ip->idx);
178*5a6e8488SAndroid Build Coastguard Worker 	*label = func->code.len;
179*5a6e8488SAndroid Build Coastguard Worker 
180*5a6e8488SAndroid Build Coastguard Worker 	// Now, we don't need the exit label; it is done.
181*5a6e8488SAndroid Build Coastguard Worker 	bc_vec_pop(&p->exits);
182*5a6e8488SAndroid Build Coastguard Worker }
183*5a6e8488SAndroid Build Coastguard Worker 
184*5a6e8488SAndroid Build Coastguard Worker /**
185*5a6e8488SAndroid Build Coastguard Worker  * Creates a label and sets it to idx. If this is an exit label, then idx is
186*5a6e8488SAndroid Build Coastguard Worker  * actually invalid, but it doesn't matter because it will be fixed by
187*5a6e8488SAndroid Build Coastguard Worker  * bc_parse_setLabel() later.
188*5a6e8488SAndroid Build Coastguard Worker  * @param p    The parser.
189*5a6e8488SAndroid Build Coastguard Worker  * @param idx  The index of the label.
190*5a6e8488SAndroid Build Coastguard Worker  */
191*5a6e8488SAndroid Build Coastguard Worker static void
bc_parse_createLabel(BcParse * p,size_t idx)192*5a6e8488SAndroid Build Coastguard Worker bc_parse_createLabel(BcParse* p, size_t idx)
193*5a6e8488SAndroid Build Coastguard Worker {
194*5a6e8488SAndroid Build Coastguard Worker 	bc_vec_push(&p->func->labels, &idx);
195*5a6e8488SAndroid Build Coastguard Worker }
196*5a6e8488SAndroid Build Coastguard Worker 
197*5a6e8488SAndroid Build Coastguard Worker /**
198*5a6e8488SAndroid Build Coastguard Worker  * Creates a conditional label. Unlike an exit label, this label is set at
199*5a6e8488SAndroid Build Coastguard Worker  * creation time because it comes *before* the code that will target it.
200*5a6e8488SAndroid Build Coastguard Worker  * @param p    The parser.
201*5a6e8488SAndroid Build Coastguard Worker  * @param idx  The index of the label.
202*5a6e8488SAndroid Build Coastguard Worker  */
203*5a6e8488SAndroid Build Coastguard Worker static void
bc_parse_createCondLabel(BcParse * p,size_t idx)204*5a6e8488SAndroid Build Coastguard Worker bc_parse_createCondLabel(BcParse* p, size_t idx)
205*5a6e8488SAndroid Build Coastguard Worker {
206*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_createLabel(p, p->func->code.len);
207*5a6e8488SAndroid Build Coastguard Worker 	bc_vec_push(&p->conds, &idx);
208*5a6e8488SAndroid Build Coastguard Worker }
209*5a6e8488SAndroid Build Coastguard Worker 
210*5a6e8488SAndroid Build Coastguard Worker /**
211*5a6e8488SAndroid Build Coastguard Worker  * Creates an exit label to be filled in later by bc_parse_setLabel(). Also, why
212*5a6e8488SAndroid Build Coastguard Worker  * create a label to be filled in later? Because exit labels are meant to be
213*5a6e8488SAndroid Build Coastguard Worker  * targeted by code that comes *before* the label. Since we have to parse that
214*5a6e8488SAndroid Build Coastguard Worker  * code first, and don't know how long it will be, we need to just make sure to
215*5a6e8488SAndroid Build Coastguard Worker  * reserve a slot to be filled in later when we know.
216*5a6e8488SAndroid Build Coastguard Worker  *
217*5a6e8488SAndroid Build Coastguard Worker  * By the way, this uses BcInstPtr because it was convenient. The field idx
218*5a6e8488SAndroid Build Coastguard Worker  * holds the index, and the field func holds the loop boolean.
219*5a6e8488SAndroid Build Coastguard Worker  *
220*5a6e8488SAndroid Build Coastguard Worker  * @param p     The parser.
221*5a6e8488SAndroid Build Coastguard Worker  * @param idx   The index of the label's position.
222*5a6e8488SAndroid Build Coastguard Worker  * @param loop  True if the exit label is for a loop or not.
223*5a6e8488SAndroid Build Coastguard Worker  */
224*5a6e8488SAndroid Build Coastguard Worker static void
bc_parse_createExitLabel(BcParse * p,size_t idx,bool loop)225*5a6e8488SAndroid Build Coastguard Worker bc_parse_createExitLabel(BcParse* p, size_t idx, bool loop)
226*5a6e8488SAndroid Build Coastguard Worker {
227*5a6e8488SAndroid Build Coastguard Worker 	BcInstPtr ip;
228*5a6e8488SAndroid Build Coastguard Worker 
229*5a6e8488SAndroid Build Coastguard Worker 	assert(p->func == bc_vec_item(&p->prog->fns, p->fidx));
230*5a6e8488SAndroid Build Coastguard Worker 
231*5a6e8488SAndroid Build Coastguard Worker 	ip.func = loop;
232*5a6e8488SAndroid Build Coastguard Worker 	ip.idx = idx;
233*5a6e8488SAndroid Build Coastguard Worker 	ip.len = 0;
234*5a6e8488SAndroid Build Coastguard Worker 
235*5a6e8488SAndroid Build Coastguard Worker 	bc_vec_push(&p->exits, &ip);
236*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_createLabel(p, SIZE_MAX);
237*5a6e8488SAndroid Build Coastguard Worker }
238*5a6e8488SAndroid Build Coastguard Worker 
239*5a6e8488SAndroid Build Coastguard Worker /**
240*5a6e8488SAndroid Build Coastguard Worker  * Pops the correct operators off of the operator stack based on the current
241*5a6e8488SAndroid Build Coastguard Worker  * operator. This is because of the Shunting-Yard algorithm. Lower prec means
242*5a6e8488SAndroid Build Coastguard Worker  * higher precedence.
243*5a6e8488SAndroid Build Coastguard Worker  * @param p       The parser.
244*5a6e8488SAndroid Build Coastguard Worker  * @param type    The operator.
245*5a6e8488SAndroid Build Coastguard Worker  * @param start   The previous start of the operator stack. For more
246*5a6e8488SAndroid Build Coastguard Worker  *                information, see the bc Parsing section of the Development
247*5a6e8488SAndroid Build Coastguard Worker  *                manual (manuals/development.md).
248*5a6e8488SAndroid Build Coastguard Worker  * @param nexprs  A pointer to the current number of expressions that have not
249*5a6e8488SAndroid Build Coastguard Worker  *                been consumed yet. This is an IN and OUT parameter.
250*5a6e8488SAndroid Build Coastguard Worker  */
251*5a6e8488SAndroid Build Coastguard Worker static void
bc_parse_operator(BcParse * p,BcLexType type,size_t start,size_t * nexprs)252*5a6e8488SAndroid Build Coastguard Worker bc_parse_operator(BcParse* p, BcLexType type, size_t start, size_t* nexprs)
253*5a6e8488SAndroid Build Coastguard Worker {
254*5a6e8488SAndroid Build Coastguard Worker 	BcLexType t;
255*5a6e8488SAndroid Build Coastguard Worker 	uchar l, r = BC_PARSE_OP_PREC(type);
256*5a6e8488SAndroid Build Coastguard Worker 	uchar left = BC_PARSE_OP_LEFT(type);
257*5a6e8488SAndroid Build Coastguard Worker 
258*5a6e8488SAndroid Build Coastguard Worker 	// While we haven't hit the stop point yet...
259*5a6e8488SAndroid Build Coastguard Worker 	while (p->ops.len > start)
260*5a6e8488SAndroid Build Coastguard Worker 	{
261*5a6e8488SAndroid Build Coastguard Worker 		// Get the top operator.
262*5a6e8488SAndroid Build Coastguard Worker 		t = BC_PARSE_TOP_OP(p);
263*5a6e8488SAndroid Build Coastguard Worker 
264*5a6e8488SAndroid Build Coastguard Worker 		// If it's a left paren, we have reached the end of whatever expression
265*5a6e8488SAndroid Build Coastguard Worker 		// this is no matter what. We also don't pop the left paren because it
266*5a6e8488SAndroid Build Coastguard Worker 		// will need to stay for the rest of the subexpression.
267*5a6e8488SAndroid Build Coastguard Worker 		if (t == BC_LEX_LPAREN) break;
268*5a6e8488SAndroid Build Coastguard Worker 
269*5a6e8488SAndroid Build Coastguard Worker 		// Break for precedence. Precedence operates differently on left and
270*5a6e8488SAndroid Build Coastguard Worker 		// right associativity, by the way. A left associative operator that
271*5a6e8488SAndroid Build Coastguard Worker 		// matches the current precedence should take priority, but a right
272*5a6e8488SAndroid Build Coastguard Worker 		// associative operator should not.
273*5a6e8488SAndroid Build Coastguard Worker 		//
274*5a6e8488SAndroid Build Coastguard Worker 		// Also, a lower precedence value means a higher precedence.
275*5a6e8488SAndroid Build Coastguard Worker 		l = BC_PARSE_OP_PREC(t);
276*5a6e8488SAndroid Build Coastguard Worker 		if (l >= r && (l != r || !left)) break;
277*5a6e8488SAndroid Build Coastguard Worker 
278*5a6e8488SAndroid Build Coastguard Worker 		// Do the housekeeping. In particular, make sure to note that one
279*5a6e8488SAndroid Build Coastguard Worker 		// expression was consumed (well, two were, but another was added) if
280*5a6e8488SAndroid Build Coastguard Worker 		// the operator was not a prefix operator. (Postfix operators are not
281*5a6e8488SAndroid Build Coastguard Worker 		// handled by this function at all.)
282*5a6e8488SAndroid Build Coastguard Worker 		bc_parse_push(p, BC_PARSE_TOKEN_INST(t));
283*5a6e8488SAndroid Build Coastguard Worker 		bc_vec_pop(&p->ops);
284*5a6e8488SAndroid Build Coastguard Worker 		*nexprs -= !BC_PARSE_OP_PREFIX(t);
285*5a6e8488SAndroid Build Coastguard Worker 	}
286*5a6e8488SAndroid Build Coastguard Worker 
287*5a6e8488SAndroid Build Coastguard Worker 	bc_vec_push(&p->ops, &type);
288*5a6e8488SAndroid Build Coastguard Worker }
289*5a6e8488SAndroid Build Coastguard Worker 
290*5a6e8488SAndroid Build Coastguard Worker /**
291*5a6e8488SAndroid Build Coastguard Worker  * Parses a right paren. In the Shunting-Yard algorithm, it needs to be put on
292*5a6e8488SAndroid Build Coastguard Worker  * the operator stack. But before that, it needs to consume whatever operators
293*5a6e8488SAndroid Build Coastguard Worker  * there are until it hits a left paren.
294*5a6e8488SAndroid Build Coastguard Worker  * @param p       The parser.
295*5a6e8488SAndroid Build Coastguard Worker  * @param nexprs  A pointer to the current number of expressions that have not
296*5a6e8488SAndroid Build Coastguard Worker  *                been consumed yet. This is an IN and OUT parameter.
297*5a6e8488SAndroid Build Coastguard Worker  */
298*5a6e8488SAndroid Build Coastguard Worker static void
bc_parse_rightParen(BcParse * p,size_t * nexprs)299*5a6e8488SAndroid Build Coastguard Worker bc_parse_rightParen(BcParse* p, size_t* nexprs)
300*5a6e8488SAndroid Build Coastguard Worker {
301*5a6e8488SAndroid Build Coastguard Worker 	BcLexType top;
302*5a6e8488SAndroid Build Coastguard Worker 
303*5a6e8488SAndroid Build Coastguard Worker 	// Consume operators until a left paren.
304*5a6e8488SAndroid Build Coastguard Worker 	while ((top = BC_PARSE_TOP_OP(p)) != BC_LEX_LPAREN)
305*5a6e8488SAndroid Build Coastguard Worker 	{
306*5a6e8488SAndroid Build Coastguard Worker 		bc_parse_push(p, BC_PARSE_TOKEN_INST(top));
307*5a6e8488SAndroid Build Coastguard Worker 		bc_vec_pop(&p->ops);
308*5a6e8488SAndroid Build Coastguard Worker 		*nexprs -= !BC_PARSE_OP_PREFIX(top);
309*5a6e8488SAndroid Build Coastguard Worker 	}
310*5a6e8488SAndroid Build Coastguard Worker 
311*5a6e8488SAndroid Build Coastguard Worker 	// We need to pop the left paren as well.
312*5a6e8488SAndroid Build Coastguard Worker 	bc_vec_pop(&p->ops);
313*5a6e8488SAndroid Build Coastguard Worker 
314*5a6e8488SAndroid Build Coastguard Worker 	// Oh, and we also want the next token.
315*5a6e8488SAndroid Build Coastguard Worker 	bc_lex_next(&p->l);
316*5a6e8488SAndroid Build Coastguard Worker }
317*5a6e8488SAndroid Build Coastguard Worker 
318*5a6e8488SAndroid Build Coastguard Worker /**
319*5a6e8488SAndroid Build Coastguard Worker  * Parses function arguments.
320*5a6e8488SAndroid Build Coastguard Worker  * @param p      The parser.
321*5a6e8488SAndroid Build Coastguard Worker  * @param flags  Flags restricting what kind of expressions the arguments can
322*5a6e8488SAndroid Build Coastguard Worker  *               be.
323*5a6e8488SAndroid Build Coastguard Worker  */
324*5a6e8488SAndroid Build Coastguard Worker static void
bc_parse_args(BcParse * p,uint8_t flags)325*5a6e8488SAndroid Build Coastguard Worker bc_parse_args(BcParse* p, uint8_t flags)
326*5a6e8488SAndroid Build Coastguard Worker {
327*5a6e8488SAndroid Build Coastguard Worker 	bool comma = false;
328*5a6e8488SAndroid Build Coastguard Worker 	size_t nargs;
329*5a6e8488SAndroid Build Coastguard Worker 
330*5a6e8488SAndroid Build Coastguard Worker 	bc_lex_next(&p->l);
331*5a6e8488SAndroid Build Coastguard Worker 
332*5a6e8488SAndroid Build Coastguard Worker 	// Print and comparison operators not allowed. Well, comparison operators
333*5a6e8488SAndroid Build Coastguard Worker 	// only for POSIX. But we do allow arrays, and we *must* get a value.
334*5a6e8488SAndroid Build Coastguard Worker 	flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL);
335*5a6e8488SAndroid Build Coastguard Worker 	flags |= (BC_PARSE_ARRAY | BC_PARSE_NEEDVAL);
336*5a6e8488SAndroid Build Coastguard Worker 
337*5a6e8488SAndroid Build Coastguard Worker 	// Count the arguments and parse them.
338*5a6e8488SAndroid Build Coastguard Worker 	for (nargs = 0; p->l.t != BC_LEX_RPAREN; ++nargs)
339*5a6e8488SAndroid Build Coastguard Worker 	{
340*5a6e8488SAndroid Build Coastguard Worker 		bc_parse_expr_status(p, flags, bc_parse_next_arg);
341*5a6e8488SAndroid Build Coastguard Worker 
342*5a6e8488SAndroid Build Coastguard Worker 		comma = (p->l.t == BC_LEX_COMMA);
343*5a6e8488SAndroid Build Coastguard Worker 		if (comma) bc_lex_next(&p->l);
344*5a6e8488SAndroid Build Coastguard Worker 	}
345*5a6e8488SAndroid Build Coastguard Worker 
346*5a6e8488SAndroid Build Coastguard Worker 	// An ending comma is FAIL.
347*5a6e8488SAndroid Build Coastguard Worker 	if (BC_ERR(comma)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
348*5a6e8488SAndroid Build Coastguard Worker 
349*5a6e8488SAndroid Build Coastguard Worker 	// Now do the call with the number of arguments.
350*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_push(p, BC_INST_CALL);
351*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_pushIndex(p, nargs);
352*5a6e8488SAndroid Build Coastguard Worker }
353*5a6e8488SAndroid Build Coastguard Worker 
354*5a6e8488SAndroid Build Coastguard Worker /**
355*5a6e8488SAndroid Build Coastguard Worker  * Parses a function call.
356*5a6e8488SAndroid Build Coastguard Worker  * @param p      The parser.
357*5a6e8488SAndroid Build Coastguard Worker  * @param flags  Flags restricting what kind of expressions the arguments can
358*5a6e8488SAndroid Build Coastguard Worker  *               be.
359*5a6e8488SAndroid Build Coastguard Worker  */
360*5a6e8488SAndroid Build Coastguard Worker static void
bc_parse_call(BcParse * p,const char * name,uint8_t flags)361*5a6e8488SAndroid Build Coastguard Worker bc_parse_call(BcParse* p, const char* name, uint8_t flags)
362*5a6e8488SAndroid Build Coastguard Worker {
363*5a6e8488SAndroid Build Coastguard Worker 	size_t idx;
364*5a6e8488SAndroid Build Coastguard Worker 
365*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_args(p, flags);
366*5a6e8488SAndroid Build Coastguard Worker 
367*5a6e8488SAndroid Build Coastguard Worker 	// We just assert this because bc_parse_args() should
368*5a6e8488SAndroid Build Coastguard Worker 	// ensure that the next token is what it should be.
369*5a6e8488SAndroid Build Coastguard Worker 	assert(p->l.t == BC_LEX_RPAREN);
370*5a6e8488SAndroid Build Coastguard Worker 
371*5a6e8488SAndroid Build Coastguard Worker 	// We cannot use bc_program_insertFunc() here
372*5a6e8488SAndroid Build Coastguard Worker 	// because it will overwrite an existing function.
373*5a6e8488SAndroid Build Coastguard Worker 	idx = bc_map_index(&p->prog->fn_map, name);
374*5a6e8488SAndroid Build Coastguard Worker 
375*5a6e8488SAndroid Build Coastguard Worker 	// The function does not exist yet. Create a space for it. If the user does
376*5a6e8488SAndroid Build Coastguard Worker 	// not define it, it's a *runtime* error, not a parse error.
377*5a6e8488SAndroid Build Coastguard Worker 	if (idx == BC_VEC_INVALID_IDX)
378*5a6e8488SAndroid Build Coastguard Worker 	{
379*5a6e8488SAndroid Build Coastguard Worker 		idx = bc_program_insertFunc(p->prog, name);
380*5a6e8488SAndroid Build Coastguard Worker 
381*5a6e8488SAndroid Build Coastguard Worker 		assert(idx != BC_VEC_INVALID_IDX);
382*5a6e8488SAndroid Build Coastguard Worker 
383*5a6e8488SAndroid Build Coastguard Worker 		// Make sure that this pointer was not invalidated.
384*5a6e8488SAndroid Build Coastguard Worker 		p->func = bc_vec_item(&p->prog->fns, p->fidx);
385*5a6e8488SAndroid Build Coastguard Worker 	}
386*5a6e8488SAndroid Build Coastguard Worker 	// The function exists, so set the right function index.
387*5a6e8488SAndroid Build Coastguard Worker 	else idx = ((BcId*) bc_vec_item(&p->prog->fn_map, idx))->idx;
388*5a6e8488SAndroid Build Coastguard Worker 
389*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_pushIndex(p, idx);
390*5a6e8488SAndroid Build Coastguard Worker 
391*5a6e8488SAndroid Build Coastguard Worker 	// Make sure to get the next token.
392*5a6e8488SAndroid Build Coastguard Worker 	bc_lex_next(&p->l);
393*5a6e8488SAndroid Build Coastguard Worker }
394*5a6e8488SAndroid Build Coastguard Worker 
395*5a6e8488SAndroid Build Coastguard Worker /**
396*5a6e8488SAndroid Build Coastguard Worker  * Parses a name/identifier-based expression. It could be a variable, an array
397*5a6e8488SAndroid Build Coastguard Worker  * element, an array itself (for function arguments), a function call, etc.
398*5a6e8488SAndroid Build Coastguard Worker  * @param p           The parser.
399*5a6e8488SAndroid Build Coastguard Worker  * @param type        A pointer to return the resulting instruction.
400*5a6e8488SAndroid Build Coastguard Worker  * @param can_assign  A pointer to return true if the name can be assigned to,
401*5a6e8488SAndroid Build Coastguard Worker  *                    false otherwise.
402*5a6e8488SAndroid Build Coastguard Worker  * @param flags       Flags restricting what kind of expression the name can be.
403*5a6e8488SAndroid Build Coastguard Worker  */
404*5a6e8488SAndroid Build Coastguard Worker static void
bc_parse_name(BcParse * p,BcInst * type,bool * can_assign,uint8_t flags)405*5a6e8488SAndroid Build Coastguard Worker bc_parse_name(BcParse* p, BcInst* type, bool* can_assign, uint8_t flags)
406*5a6e8488SAndroid Build Coastguard Worker {
407*5a6e8488SAndroid Build Coastguard Worker 	char* name;
408*5a6e8488SAndroid Build Coastguard Worker 
409*5a6e8488SAndroid Build Coastguard Worker 	BC_SIG_ASSERT_LOCKED;
410*5a6e8488SAndroid Build Coastguard Worker 
411*5a6e8488SAndroid Build Coastguard Worker 	// We want a copy of the name since the lexer might overwrite its copy.
412*5a6e8488SAndroid Build Coastguard Worker 	name = bc_vm_strdup(p->l.str.v);
413*5a6e8488SAndroid Build Coastguard Worker 
414*5a6e8488SAndroid Build Coastguard Worker 	BC_SETJMP_LOCKED(vm, err);
415*5a6e8488SAndroid Build Coastguard Worker 
416*5a6e8488SAndroid Build Coastguard Worker 	// We need the next token to see if it's just a variable or something more.
417*5a6e8488SAndroid Build Coastguard Worker 	bc_lex_next(&p->l);
418*5a6e8488SAndroid Build Coastguard Worker 
419*5a6e8488SAndroid Build Coastguard Worker 	// Array element or array.
420*5a6e8488SAndroid Build Coastguard Worker 	if (p->l.t == BC_LEX_LBRACKET)
421*5a6e8488SAndroid Build Coastguard Worker 	{
422*5a6e8488SAndroid Build Coastguard Worker 		bc_lex_next(&p->l);
423*5a6e8488SAndroid Build Coastguard Worker 
424*5a6e8488SAndroid Build Coastguard Worker 		// Array only. This has to be a function parameter.
425*5a6e8488SAndroid Build Coastguard Worker 		if (p->l.t == BC_LEX_RBRACKET)
426*5a6e8488SAndroid Build Coastguard Worker 		{
427*5a6e8488SAndroid Build Coastguard Worker 			// Error if arrays are not allowed.
428*5a6e8488SAndroid Build Coastguard Worker 			if (BC_ERR(!(flags & BC_PARSE_ARRAY)))
429*5a6e8488SAndroid Build Coastguard Worker 			{
430*5a6e8488SAndroid Build Coastguard Worker 				bc_parse_err(p, BC_ERR_PARSE_EXPR);
431*5a6e8488SAndroid Build Coastguard Worker 			}
432*5a6e8488SAndroid Build Coastguard Worker 
433*5a6e8488SAndroid Build Coastguard Worker 			*type = BC_INST_ARRAY;
434*5a6e8488SAndroid Build Coastguard Worker 			*can_assign = false;
435*5a6e8488SAndroid Build Coastguard Worker 		}
436*5a6e8488SAndroid Build Coastguard Worker 		else
437*5a6e8488SAndroid Build Coastguard Worker 		{
438*5a6e8488SAndroid Build Coastguard Worker 			// If we are here, we have an array element. We need to set the
439*5a6e8488SAndroid Build Coastguard Worker 			// expression parsing flags.
440*5a6e8488SAndroid Build Coastguard Worker 			uint8_t flags2 = (flags & ~(BC_PARSE_PRINT | BC_PARSE_REL)) |
441*5a6e8488SAndroid Build Coastguard Worker 			                 BC_PARSE_NEEDVAL;
442*5a6e8488SAndroid Build Coastguard Worker 
443*5a6e8488SAndroid Build Coastguard Worker 			bc_parse_expr_status(p, flags2, bc_parse_next_elem);
444*5a6e8488SAndroid Build Coastguard Worker 
445*5a6e8488SAndroid Build Coastguard Worker 			// The next token *must* be a right bracket.
446*5a6e8488SAndroid Build Coastguard Worker 			if (BC_ERR(p->l.t != BC_LEX_RBRACKET))
447*5a6e8488SAndroid Build Coastguard Worker 			{
448*5a6e8488SAndroid Build Coastguard Worker 				bc_parse_err(p, BC_ERR_PARSE_TOKEN);
449*5a6e8488SAndroid Build Coastguard Worker 			}
450*5a6e8488SAndroid Build Coastguard Worker 
451*5a6e8488SAndroid Build Coastguard Worker 			*type = BC_INST_ARRAY_ELEM;
452*5a6e8488SAndroid Build Coastguard Worker 			*can_assign = true;
453*5a6e8488SAndroid Build Coastguard Worker 		}
454*5a6e8488SAndroid Build Coastguard Worker 
455*5a6e8488SAndroid Build Coastguard Worker 		// Make sure to get the next token.
456*5a6e8488SAndroid Build Coastguard Worker 		bc_lex_next(&p->l);
457*5a6e8488SAndroid Build Coastguard Worker 
458*5a6e8488SAndroid Build Coastguard Worker 		// Push the instruction and the name of the identifier.
459*5a6e8488SAndroid Build Coastguard Worker 		bc_parse_push(p, *type);
460*5a6e8488SAndroid Build Coastguard Worker 		bc_parse_pushName(p, name, false);
461*5a6e8488SAndroid Build Coastguard Worker 	}
462*5a6e8488SAndroid Build Coastguard Worker 	else if (p->l.t == BC_LEX_LPAREN)
463*5a6e8488SAndroid Build Coastguard Worker 	{
464*5a6e8488SAndroid Build Coastguard Worker 		// We are parsing a function call; error if not allowed.
465*5a6e8488SAndroid Build Coastguard Worker 		if (BC_ERR(flags & BC_PARSE_NOCALL))
466*5a6e8488SAndroid Build Coastguard Worker 		{
467*5a6e8488SAndroid Build Coastguard Worker 			bc_parse_err(p, BC_ERR_PARSE_TOKEN);
468*5a6e8488SAndroid Build Coastguard Worker 		}
469*5a6e8488SAndroid Build Coastguard Worker 
470*5a6e8488SAndroid Build Coastguard Worker 		*type = BC_INST_CALL;
471*5a6e8488SAndroid Build Coastguard Worker 		*can_assign = false;
472*5a6e8488SAndroid Build Coastguard Worker 
473*5a6e8488SAndroid Build Coastguard Worker 		bc_parse_call(p, name, flags);
474*5a6e8488SAndroid Build Coastguard Worker 	}
475*5a6e8488SAndroid Build Coastguard Worker 	else
476*5a6e8488SAndroid Build Coastguard Worker 	{
477*5a6e8488SAndroid Build Coastguard Worker 		// Just a variable.
478*5a6e8488SAndroid Build Coastguard Worker 		*type = BC_INST_VAR;
479*5a6e8488SAndroid Build Coastguard Worker 		*can_assign = true;
480*5a6e8488SAndroid Build Coastguard Worker 		bc_parse_push(p, BC_INST_VAR);
481*5a6e8488SAndroid Build Coastguard Worker 		bc_parse_pushName(p, name, true);
482*5a6e8488SAndroid Build Coastguard Worker 	}
483*5a6e8488SAndroid Build Coastguard Worker 
484*5a6e8488SAndroid Build Coastguard Worker err:
485*5a6e8488SAndroid Build Coastguard Worker 	// Need to make sure to unallocate the name.
486*5a6e8488SAndroid Build Coastguard Worker 	free(name);
487*5a6e8488SAndroid Build Coastguard Worker 	BC_LONGJMP_CONT(vm);
488*5a6e8488SAndroid Build Coastguard Worker 	BC_SIG_MAYLOCK;
489*5a6e8488SAndroid Build Coastguard Worker }
490*5a6e8488SAndroid Build Coastguard Worker 
491*5a6e8488SAndroid Build Coastguard Worker /**
492*5a6e8488SAndroid Build Coastguard Worker  * Parses a builtin function that takes no arguments. This includes read(),
493*5a6e8488SAndroid Build Coastguard Worker  * rand(), maxibase(), maxobase(), maxscale(), and maxrand().
494*5a6e8488SAndroid Build Coastguard Worker  * @param p     The parser.
495*5a6e8488SAndroid Build Coastguard Worker  * @param inst  The instruction corresponding to the builtin.
496*5a6e8488SAndroid Build Coastguard Worker  */
497*5a6e8488SAndroid Build Coastguard Worker static void
bc_parse_noArgBuiltin(BcParse * p,BcInst inst)498*5a6e8488SAndroid Build Coastguard Worker bc_parse_noArgBuiltin(BcParse* p, BcInst inst)
499*5a6e8488SAndroid Build Coastguard Worker {
500*5a6e8488SAndroid Build Coastguard Worker 	// Must have a left paren.
501*5a6e8488SAndroid Build Coastguard Worker 	bc_lex_next(&p->l);
502*5a6e8488SAndroid Build Coastguard Worker 	if (BC_ERR(p->l.t != BC_LEX_LPAREN)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
503*5a6e8488SAndroid Build Coastguard Worker 
504*5a6e8488SAndroid Build Coastguard Worker 	// Must have a right paren.
505*5a6e8488SAndroid Build Coastguard Worker 	bc_lex_next(&p->l);
506*5a6e8488SAndroid Build Coastguard Worker 	if ((p->l.t != BC_LEX_RPAREN)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
507*5a6e8488SAndroid Build Coastguard Worker 
508*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_push(p, inst);
509*5a6e8488SAndroid Build Coastguard Worker 
510*5a6e8488SAndroid Build Coastguard Worker 	bc_lex_next(&p->l);
511*5a6e8488SAndroid Build Coastguard Worker }
512*5a6e8488SAndroid Build Coastguard Worker 
513*5a6e8488SAndroid Build Coastguard Worker /**
514*5a6e8488SAndroid Build Coastguard Worker  * Parses a builtin function that takes 1 argument. This includes length(),
515*5a6e8488SAndroid Build Coastguard Worker  * sqrt(), abs(), scale(), and irand().
516*5a6e8488SAndroid Build Coastguard Worker  * @param p      The parser.
517*5a6e8488SAndroid Build Coastguard Worker  * @param type   The lex token.
518*5a6e8488SAndroid Build Coastguard Worker  * @param flags  The expression parsing flags for parsing the argument.
519*5a6e8488SAndroid Build Coastguard Worker  * @param prev   An out parameter; the previous instruction pointer.
520*5a6e8488SAndroid Build Coastguard Worker  */
521*5a6e8488SAndroid Build Coastguard Worker static void
bc_parse_builtin(BcParse * p,BcLexType type,uint8_t flags,BcInst * prev)522*5a6e8488SAndroid Build Coastguard Worker bc_parse_builtin(BcParse* p, BcLexType type, uint8_t flags, BcInst* prev)
523*5a6e8488SAndroid Build Coastguard Worker {
524*5a6e8488SAndroid Build Coastguard Worker 	// Must have a left paren.
525*5a6e8488SAndroid Build Coastguard Worker 	bc_lex_next(&p->l);
526*5a6e8488SAndroid Build Coastguard Worker 	if (BC_ERR(p->l.t != BC_LEX_LPAREN)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
527*5a6e8488SAndroid Build Coastguard Worker 
528*5a6e8488SAndroid Build Coastguard Worker 	bc_lex_next(&p->l);
529*5a6e8488SAndroid Build Coastguard Worker 
530*5a6e8488SAndroid Build Coastguard Worker 	// Change the flags as needed for parsing the argument.
531*5a6e8488SAndroid Build Coastguard Worker 	flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL);
532*5a6e8488SAndroid Build Coastguard Worker 	flags |= BC_PARSE_NEEDVAL;
533*5a6e8488SAndroid Build Coastguard Worker 
534*5a6e8488SAndroid Build Coastguard Worker 	// Since length can take arrays, we need to specially add that flag.
535*5a6e8488SAndroid Build Coastguard Worker 	if (type == BC_LEX_KW_LENGTH || type == BC_LEX_KW_ASCIIFY)
536*5a6e8488SAndroid Build Coastguard Worker 	{
537*5a6e8488SAndroid Build Coastguard Worker 		flags |= BC_PARSE_ARRAY;
538*5a6e8488SAndroid Build Coastguard Worker 	}
539*5a6e8488SAndroid Build Coastguard Worker 
540*5a6e8488SAndroid Build Coastguard Worker 	// Otherwise, we need to clear it because it could be set.
541*5a6e8488SAndroid Build Coastguard Worker 	else flags &= ~(BC_PARSE_ARRAY);
542*5a6e8488SAndroid Build Coastguard Worker 
543*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_expr_status(p, flags, bc_parse_next_rel);
544*5a6e8488SAndroid Build Coastguard Worker 
545*5a6e8488SAndroid Build Coastguard Worker 	// Must have a right paren.
546*5a6e8488SAndroid Build Coastguard Worker 	if (BC_ERR(p->l.t != BC_LEX_RPAREN)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
547*5a6e8488SAndroid Build Coastguard Worker 
548*5a6e8488SAndroid Build Coastguard Worker 	// Adjust previous based on the token and push it.
549*5a6e8488SAndroid Build Coastguard Worker 	*prev = type - BC_LEX_KW_LENGTH + BC_INST_LENGTH;
550*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_push(p, *prev);
551*5a6e8488SAndroid Build Coastguard Worker 
552*5a6e8488SAndroid Build Coastguard Worker 	bc_lex_next(&p->l);
553*5a6e8488SAndroid Build Coastguard Worker }
554*5a6e8488SAndroid Build Coastguard Worker 
555*5a6e8488SAndroid Build Coastguard Worker /**
556*5a6e8488SAndroid Build Coastguard Worker  * Parses a builtin function that takes 3 arguments. This includes modexp() and
557*5a6e8488SAndroid Build Coastguard Worker  * divmod().
558*5a6e8488SAndroid Build Coastguard Worker  * @param p      The parser.
559*5a6e8488SAndroid Build Coastguard Worker  * @param type   The lex token.
560*5a6e8488SAndroid Build Coastguard Worker  * @param flags  The expression parsing flags for parsing the argument.
561*5a6e8488SAndroid Build Coastguard Worker  * @param prev   An out parameter; the previous instruction pointer.
562*5a6e8488SAndroid Build Coastguard Worker  */
563*5a6e8488SAndroid Build Coastguard Worker static void
bc_parse_builtin3(BcParse * p,BcLexType type,uint8_t flags,BcInst * prev)564*5a6e8488SAndroid Build Coastguard Worker bc_parse_builtin3(BcParse* p, BcLexType type, uint8_t flags, BcInst* prev)
565*5a6e8488SAndroid Build Coastguard Worker {
566*5a6e8488SAndroid Build Coastguard Worker 	assert(type == BC_LEX_KW_MODEXP || type == BC_LEX_KW_DIVMOD);
567*5a6e8488SAndroid Build Coastguard Worker 
568*5a6e8488SAndroid Build Coastguard Worker 	// Must have a left paren.
569*5a6e8488SAndroid Build Coastguard Worker 	bc_lex_next(&p->l);
570*5a6e8488SAndroid Build Coastguard Worker 	if (BC_ERR(p->l.t != BC_LEX_LPAREN)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
571*5a6e8488SAndroid Build Coastguard Worker 
572*5a6e8488SAndroid Build Coastguard Worker 	bc_lex_next(&p->l);
573*5a6e8488SAndroid Build Coastguard Worker 
574*5a6e8488SAndroid Build Coastguard Worker 	// Change the flags as needed for parsing the argument.
575*5a6e8488SAndroid Build Coastguard Worker 	flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL);
576*5a6e8488SAndroid Build Coastguard Worker 	flags |= BC_PARSE_NEEDVAL;
577*5a6e8488SAndroid Build Coastguard Worker 
578*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_expr_status(p, flags, bc_parse_next_builtin);
579*5a6e8488SAndroid Build Coastguard Worker 
580*5a6e8488SAndroid Build Coastguard Worker 	// Must have a comma.
581*5a6e8488SAndroid Build Coastguard Worker 	if (BC_ERR(p->l.t != BC_LEX_COMMA)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
582*5a6e8488SAndroid Build Coastguard Worker 
583*5a6e8488SAndroid Build Coastguard Worker 	bc_lex_next(&p->l);
584*5a6e8488SAndroid Build Coastguard Worker 
585*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_expr_status(p, flags, bc_parse_next_builtin);
586*5a6e8488SAndroid Build Coastguard Worker 
587*5a6e8488SAndroid Build Coastguard Worker 	// Must have a comma.
588*5a6e8488SAndroid Build Coastguard Worker 	if (BC_ERR(p->l.t != BC_LEX_COMMA)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
589*5a6e8488SAndroid Build Coastguard Worker 
590*5a6e8488SAndroid Build Coastguard Worker 	bc_lex_next(&p->l);
591*5a6e8488SAndroid Build Coastguard Worker 
592*5a6e8488SAndroid Build Coastguard Worker 	// If it is a divmod, parse an array name. Otherwise, just parse another
593*5a6e8488SAndroid Build Coastguard Worker 	// expression.
594*5a6e8488SAndroid Build Coastguard Worker 	if (type == BC_LEX_KW_DIVMOD)
595*5a6e8488SAndroid Build Coastguard Worker 	{
596*5a6e8488SAndroid Build Coastguard Worker 		// Must have a name.
597*5a6e8488SAndroid Build Coastguard Worker 		if (BC_ERR(p->l.t != BC_LEX_NAME)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
598*5a6e8488SAndroid Build Coastguard Worker 
599*5a6e8488SAndroid Build Coastguard Worker 		// This is safe because the next token should not overwrite the name.
600*5a6e8488SAndroid Build Coastguard Worker 		bc_lex_next(&p->l);
601*5a6e8488SAndroid Build Coastguard Worker 
602*5a6e8488SAndroid Build Coastguard Worker 		// Must have a left bracket.
603*5a6e8488SAndroid Build Coastguard Worker 		if (BC_ERR(p->l.t != BC_LEX_LBRACKET))
604*5a6e8488SAndroid Build Coastguard Worker 		{
605*5a6e8488SAndroid Build Coastguard Worker 			bc_parse_err(p, BC_ERR_PARSE_TOKEN);
606*5a6e8488SAndroid Build Coastguard Worker 		}
607*5a6e8488SAndroid Build Coastguard Worker 
608*5a6e8488SAndroid Build Coastguard Worker 		// This is safe because the next token should not overwrite the name.
609*5a6e8488SAndroid Build Coastguard Worker 		bc_lex_next(&p->l);
610*5a6e8488SAndroid Build Coastguard Worker 
611*5a6e8488SAndroid Build Coastguard Worker 		// Must have a right bracket.
612*5a6e8488SAndroid Build Coastguard Worker 		if (BC_ERR(p->l.t != BC_LEX_RBRACKET))
613*5a6e8488SAndroid Build Coastguard Worker 		{
614*5a6e8488SAndroid Build Coastguard Worker 			bc_parse_err(p, BC_ERR_PARSE_TOKEN);
615*5a6e8488SAndroid Build Coastguard Worker 		}
616*5a6e8488SAndroid Build Coastguard Worker 
617*5a6e8488SAndroid Build Coastguard Worker 		// This is safe because the next token should not overwrite the name.
618*5a6e8488SAndroid Build Coastguard Worker 		bc_lex_next(&p->l);
619*5a6e8488SAndroid Build Coastguard Worker 	}
620*5a6e8488SAndroid Build Coastguard Worker 	else bc_parse_expr_status(p, flags, bc_parse_next_rel);
621*5a6e8488SAndroid Build Coastguard Worker 
622*5a6e8488SAndroid Build Coastguard Worker 	// Must have a right paren.
623*5a6e8488SAndroid Build Coastguard Worker 	if (BC_ERR(p->l.t != BC_LEX_RPAREN)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
624*5a6e8488SAndroid Build Coastguard Worker 
625*5a6e8488SAndroid Build Coastguard Worker 	// Adjust previous based on the token and push it.
626*5a6e8488SAndroid Build Coastguard Worker 	*prev = type - BC_LEX_KW_MODEXP + BC_INST_MODEXP;
627*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_push(p, *prev);
628*5a6e8488SAndroid Build Coastguard Worker 
629*5a6e8488SAndroid Build Coastguard Worker 	// If we have divmod, we need to assign the modulus to the array element, so
630*5a6e8488SAndroid Build Coastguard Worker 	// we need to push the instructions for doing so.
631*5a6e8488SAndroid Build Coastguard Worker 	if (type == BC_LEX_KW_DIVMOD)
632*5a6e8488SAndroid Build Coastguard Worker 	{
633*5a6e8488SAndroid Build Coastguard Worker 		// The zeroth element.
634*5a6e8488SAndroid Build Coastguard Worker 		bc_parse_push(p, BC_INST_ZERO);
635*5a6e8488SAndroid Build Coastguard Worker 		bc_parse_push(p, BC_INST_ARRAY_ELEM);
636*5a6e8488SAndroid Build Coastguard Worker 
637*5a6e8488SAndroid Build Coastguard Worker 		// Push the array.
638*5a6e8488SAndroid Build Coastguard Worker 		bc_parse_pushName(p, p->l.str.v, false);
639*5a6e8488SAndroid Build Coastguard Worker 
640*5a6e8488SAndroid Build Coastguard Worker 		// Swap them and assign. After this, the top item on the stack should
641*5a6e8488SAndroid Build Coastguard Worker 		// be the quotient.
642*5a6e8488SAndroid Build Coastguard Worker 		bc_parse_push(p, BC_INST_SWAP);
643*5a6e8488SAndroid Build Coastguard Worker 		bc_parse_push(p, BC_INST_ASSIGN_NO_VAL);
644*5a6e8488SAndroid Build Coastguard Worker 	}
645*5a6e8488SAndroid Build Coastguard Worker 
646*5a6e8488SAndroid Build Coastguard Worker 	bc_lex_next(&p->l);
647*5a6e8488SAndroid Build Coastguard Worker }
648*5a6e8488SAndroid Build Coastguard Worker 
649*5a6e8488SAndroid Build Coastguard Worker /**
650*5a6e8488SAndroid Build Coastguard Worker  * Parses the scale keyword. This is special because scale can be a value or a
651*5a6e8488SAndroid Build Coastguard Worker  * builtin function.
652*5a6e8488SAndroid Build Coastguard Worker  * @param p           The parser.
653*5a6e8488SAndroid Build Coastguard Worker  * @param type        An out parameter; the instruction for the parse.
654*5a6e8488SAndroid Build Coastguard Worker  * @param can_assign  An out parameter; whether the expression can be assigned
655*5a6e8488SAndroid Build Coastguard Worker  *                    to.
656*5a6e8488SAndroid Build Coastguard Worker  * @param flags       The expression parsing flags for parsing a scale() arg.
657*5a6e8488SAndroid Build Coastguard Worker  */
658*5a6e8488SAndroid Build Coastguard Worker static void
bc_parse_scale(BcParse * p,BcInst * type,bool * can_assign,uint8_t flags)659*5a6e8488SAndroid Build Coastguard Worker bc_parse_scale(BcParse* p, BcInst* type, bool* can_assign, uint8_t flags)
660*5a6e8488SAndroid Build Coastguard Worker {
661*5a6e8488SAndroid Build Coastguard Worker 	bc_lex_next(&p->l);
662*5a6e8488SAndroid Build Coastguard Worker 
663*5a6e8488SAndroid Build Coastguard Worker 	// Without the left paren, it's just the keyword.
664*5a6e8488SAndroid Build Coastguard Worker 	if (p->l.t != BC_LEX_LPAREN)
665*5a6e8488SAndroid Build Coastguard Worker 	{
666*5a6e8488SAndroid Build Coastguard Worker 		// Set, push, and return.
667*5a6e8488SAndroid Build Coastguard Worker 		*type = BC_INST_SCALE;
668*5a6e8488SAndroid Build Coastguard Worker 		*can_assign = true;
669*5a6e8488SAndroid Build Coastguard Worker 		bc_parse_push(p, BC_INST_SCALE);
670*5a6e8488SAndroid Build Coastguard Worker 		return;
671*5a6e8488SAndroid Build Coastguard Worker 	}
672*5a6e8488SAndroid Build Coastguard Worker 
673*5a6e8488SAndroid Build Coastguard Worker 	// Handle the scale function.
674*5a6e8488SAndroid Build Coastguard Worker 	*type = BC_INST_SCALE_FUNC;
675*5a6e8488SAndroid Build Coastguard Worker 	*can_assign = false;
676*5a6e8488SAndroid Build Coastguard Worker 
677*5a6e8488SAndroid Build Coastguard Worker 	// Once again, adjust the flags.
678*5a6e8488SAndroid Build Coastguard Worker 	flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL);
679*5a6e8488SAndroid Build Coastguard Worker 	flags |= BC_PARSE_NEEDVAL;
680*5a6e8488SAndroid Build Coastguard Worker 
681*5a6e8488SAndroid Build Coastguard Worker 	bc_lex_next(&p->l);
682*5a6e8488SAndroid Build Coastguard Worker 
683*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_expr_status(p, flags, bc_parse_next_rel);
684*5a6e8488SAndroid Build Coastguard Worker 
685*5a6e8488SAndroid Build Coastguard Worker 	// Must have a right paren.
686*5a6e8488SAndroid Build Coastguard Worker 	if (BC_ERR(p->l.t != BC_LEX_RPAREN)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
687*5a6e8488SAndroid Build Coastguard Worker 
688*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_push(p, BC_INST_SCALE_FUNC);
689*5a6e8488SAndroid Build Coastguard Worker 
690*5a6e8488SAndroid Build Coastguard Worker 	bc_lex_next(&p->l);
691*5a6e8488SAndroid Build Coastguard Worker }
692*5a6e8488SAndroid Build Coastguard Worker 
693*5a6e8488SAndroid Build Coastguard Worker /**
694*5a6e8488SAndroid Build Coastguard Worker  * Parses and increment or decrement operator. This is a bit complex.
695*5a6e8488SAndroid Build Coastguard Worker  * @param p           The parser.
696*5a6e8488SAndroid Build Coastguard Worker  * @param prev        An out parameter; the previous instruction pointer.
697*5a6e8488SAndroid Build Coastguard Worker  * @param can_assign  An out parameter; whether the expression can be assigned
698*5a6e8488SAndroid Build Coastguard Worker  *                    to.
699*5a6e8488SAndroid Build Coastguard Worker  * @param nexs        An in/out parameter; the number of expressions in the
700*5a6e8488SAndroid Build Coastguard Worker  *                    parse tree that are not used.
701*5a6e8488SAndroid Build Coastguard Worker  * @param flags       The expression parsing flags for parsing a scale() arg.
702*5a6e8488SAndroid Build Coastguard Worker  */
703*5a6e8488SAndroid Build Coastguard Worker static void
bc_parse_incdec(BcParse * p,BcInst * prev,bool * can_assign,size_t * nexs,uint8_t flags)704*5a6e8488SAndroid Build Coastguard Worker bc_parse_incdec(BcParse* p, BcInst* prev, bool* can_assign, size_t* nexs,
705*5a6e8488SAndroid Build Coastguard Worker                 uint8_t flags)
706*5a6e8488SAndroid Build Coastguard Worker {
707*5a6e8488SAndroid Build Coastguard Worker 	BcLexType type;
708*5a6e8488SAndroid Build Coastguard Worker 	uchar inst;
709*5a6e8488SAndroid Build Coastguard Worker 	BcInst etype = *prev;
710*5a6e8488SAndroid Build Coastguard Worker 	BcLexType last = p->l.last;
711*5a6e8488SAndroid Build Coastguard Worker 
712*5a6e8488SAndroid Build Coastguard Worker 	assert(prev != NULL && can_assign != NULL);
713*5a6e8488SAndroid Build Coastguard Worker 
714*5a6e8488SAndroid Build Coastguard Worker 	// If we can't assign to the previous token, then we have an error.
715*5a6e8488SAndroid Build Coastguard Worker 	if (BC_ERR(last == BC_LEX_OP_INC || last == BC_LEX_OP_DEC ||
716*5a6e8488SAndroid Build Coastguard Worker 	           last == BC_LEX_RPAREN))
717*5a6e8488SAndroid Build Coastguard Worker 	{
718*5a6e8488SAndroid Build Coastguard Worker 		bc_parse_err(p, BC_ERR_PARSE_ASSIGN);
719*5a6e8488SAndroid Build Coastguard Worker 	}
720*5a6e8488SAndroid Build Coastguard Worker 
721*5a6e8488SAndroid Build Coastguard Worker 	// Is the previous instruction for a variable?
722*5a6e8488SAndroid Build Coastguard Worker 	if (BC_PARSE_INST_VAR(etype))
723*5a6e8488SAndroid Build Coastguard Worker 	{
724*5a6e8488SAndroid Build Coastguard Worker 		// If so, this is a postfix operator.
725*5a6e8488SAndroid Build Coastguard Worker 		if (!*can_assign) bc_parse_err(p, BC_ERR_PARSE_ASSIGN);
726*5a6e8488SAndroid Build Coastguard Worker 
727*5a6e8488SAndroid Build Coastguard Worker 		// Only postfix uses BC_INST_INC and BC_INST_DEC.
728*5a6e8488SAndroid Build Coastguard Worker 		*prev = inst = BC_INST_INC + (p->l.t != BC_LEX_OP_INC);
729*5a6e8488SAndroid Build Coastguard Worker 		bc_parse_push(p, inst);
730*5a6e8488SAndroid Build Coastguard Worker 		bc_lex_next(&p->l);
731*5a6e8488SAndroid Build Coastguard Worker 		*can_assign = false;
732*5a6e8488SAndroid Build Coastguard Worker 	}
733*5a6e8488SAndroid Build Coastguard Worker 	else
734*5a6e8488SAndroid Build Coastguard Worker 	{
735*5a6e8488SAndroid Build Coastguard Worker 		// This is a prefix operator. In that case, we just convert it to
736*5a6e8488SAndroid Build Coastguard Worker 		// an assignment instruction.
737*5a6e8488SAndroid Build Coastguard Worker 		*prev = inst = BC_INST_ASSIGN_PLUS + (p->l.t != BC_LEX_OP_INC);
738*5a6e8488SAndroid Build Coastguard Worker 
739*5a6e8488SAndroid Build Coastguard Worker 		bc_lex_next(&p->l);
740*5a6e8488SAndroid Build Coastguard Worker 		type = p->l.t;
741*5a6e8488SAndroid Build Coastguard Worker 
742*5a6e8488SAndroid Build Coastguard Worker 		// Because we parse the next part of the expression
743*5a6e8488SAndroid Build Coastguard Worker 		// right here, we need to increment this.
744*5a6e8488SAndroid Build Coastguard Worker 		*nexs = *nexs + 1;
745*5a6e8488SAndroid Build Coastguard Worker 
746*5a6e8488SAndroid Build Coastguard Worker 		// Is the next token a normal identifier?
747*5a6e8488SAndroid Build Coastguard Worker 		if (type == BC_LEX_NAME)
748*5a6e8488SAndroid Build Coastguard Worker 		{
749*5a6e8488SAndroid Build Coastguard Worker 			// Parse the name.
750*5a6e8488SAndroid Build Coastguard Worker 			uint8_t flags2 = flags & ~(BC_PARSE_ARRAY);
751*5a6e8488SAndroid Build Coastguard Worker 			bc_parse_name(p, prev, can_assign, flags2 | BC_PARSE_NOCALL);
752*5a6e8488SAndroid Build Coastguard Worker 		}
753*5a6e8488SAndroid Build Coastguard Worker 		// Is the next token a global?
754*5a6e8488SAndroid Build Coastguard Worker 		else if (type >= BC_LEX_KW_LAST && type <= BC_LEX_KW_OBASE)
755*5a6e8488SAndroid Build Coastguard Worker 		{
756*5a6e8488SAndroid Build Coastguard Worker 			bc_parse_push(p, type - BC_LEX_KW_LAST + BC_INST_LAST);
757*5a6e8488SAndroid Build Coastguard Worker 			bc_lex_next(&p->l);
758*5a6e8488SAndroid Build Coastguard Worker 		}
759*5a6e8488SAndroid Build Coastguard Worker 		// Is the next token specifically scale, which needs special treatment?
760*5a6e8488SAndroid Build Coastguard Worker 		else if (BC_NO_ERR(type == BC_LEX_KW_SCALE))
761*5a6e8488SAndroid Build Coastguard Worker 		{
762*5a6e8488SAndroid Build Coastguard Worker 			bc_lex_next(&p->l);
763*5a6e8488SAndroid Build Coastguard Worker 
764*5a6e8488SAndroid Build Coastguard Worker 			// Check that scale() was not used.
765*5a6e8488SAndroid Build Coastguard Worker 			if (BC_ERR(p->l.t == BC_LEX_LPAREN))
766*5a6e8488SAndroid Build Coastguard Worker 			{
767*5a6e8488SAndroid Build Coastguard Worker 				bc_parse_err(p, BC_ERR_PARSE_TOKEN);
768*5a6e8488SAndroid Build Coastguard Worker 			}
769*5a6e8488SAndroid Build Coastguard Worker 			else bc_parse_push(p, BC_INST_SCALE);
770*5a6e8488SAndroid Build Coastguard Worker 		}
771*5a6e8488SAndroid Build Coastguard Worker 		// Now we know we have an error.
772*5a6e8488SAndroid Build Coastguard Worker 		else bc_parse_err(p, BC_ERR_PARSE_TOKEN);
773*5a6e8488SAndroid Build Coastguard Worker 
774*5a6e8488SAndroid Build Coastguard Worker 		*can_assign = false;
775*5a6e8488SAndroid Build Coastguard Worker 
776*5a6e8488SAndroid Build Coastguard Worker 		bc_parse_push(p, BC_INST_ONE);
777*5a6e8488SAndroid Build Coastguard Worker 		bc_parse_push(p, inst);
778*5a6e8488SAndroid Build Coastguard Worker 	}
779*5a6e8488SAndroid Build Coastguard Worker }
780*5a6e8488SAndroid Build Coastguard Worker 
781*5a6e8488SAndroid Build Coastguard Worker /**
782*5a6e8488SAndroid Build Coastguard Worker  * Parses the minus operator. This needs special treatment because it is either
783*5a6e8488SAndroid Build Coastguard Worker  * subtract or negation.
784*5a6e8488SAndroid Build Coastguard Worker  * @param p        The parser.
785*5a6e8488SAndroid Build Coastguard Worker  * @param prev     An in/out parameter; the previous instruction.
786*5a6e8488SAndroid Build Coastguard Worker  * @param ops_bgn  The size of the operator stack.
787*5a6e8488SAndroid Build Coastguard Worker  * @param rparen   True if the last token was a right paren.
788*5a6e8488SAndroid Build Coastguard Worker  * @param binlast  True if the last token was a binary operator.
789*5a6e8488SAndroid Build Coastguard Worker  * @param nexprs   An in/out parameter; the number of unused expressions.
790*5a6e8488SAndroid Build Coastguard Worker  */
791*5a6e8488SAndroid Build Coastguard Worker static void
bc_parse_minus(BcParse * p,BcInst * prev,size_t ops_bgn,bool rparen,bool binlast,size_t * nexprs)792*5a6e8488SAndroid Build Coastguard Worker bc_parse_minus(BcParse* p, BcInst* prev, size_t ops_bgn, bool rparen,
793*5a6e8488SAndroid Build Coastguard Worker                bool binlast, size_t* nexprs)
794*5a6e8488SAndroid Build Coastguard Worker {
795*5a6e8488SAndroid Build Coastguard Worker 	BcLexType type;
796*5a6e8488SAndroid Build Coastguard Worker 
797*5a6e8488SAndroid Build Coastguard Worker 	bc_lex_next(&p->l);
798*5a6e8488SAndroid Build Coastguard Worker 
799*5a6e8488SAndroid Build Coastguard Worker 	// Figure out if it's a minus or a negation.
800*5a6e8488SAndroid Build Coastguard Worker 	type = BC_PARSE_LEAF(*prev, binlast, rparen) ? BC_LEX_OP_MINUS : BC_LEX_NEG;
801*5a6e8488SAndroid Build Coastguard Worker 	*prev = BC_PARSE_TOKEN_INST(type);
802*5a6e8488SAndroid Build Coastguard Worker 
803*5a6e8488SAndroid Build Coastguard Worker 	// We can just push onto the op stack because this is the largest
804*5a6e8488SAndroid Build Coastguard Worker 	// precedence operator that gets pushed. Inc/dec does not.
805*5a6e8488SAndroid Build Coastguard Worker 	if (type != BC_LEX_OP_MINUS) bc_vec_push(&p->ops, &type);
806*5a6e8488SAndroid Build Coastguard Worker 	else bc_parse_operator(p, type, ops_bgn, nexprs);
807*5a6e8488SAndroid Build Coastguard Worker }
808*5a6e8488SAndroid Build Coastguard Worker 
809*5a6e8488SAndroid Build Coastguard Worker /**
810*5a6e8488SAndroid Build Coastguard Worker  * Parses a string.
811*5a6e8488SAndroid Build Coastguard Worker  * @param p     The parser.
812*5a6e8488SAndroid Build Coastguard Worker  * @param inst  The instruction corresponding to how the string was found and
813*5a6e8488SAndroid Build Coastguard Worker  *              how it should be printed.
814*5a6e8488SAndroid Build Coastguard Worker  */
815*5a6e8488SAndroid Build Coastguard Worker static void
bc_parse_str(BcParse * p,BcInst inst)816*5a6e8488SAndroid Build Coastguard Worker bc_parse_str(BcParse* p, BcInst inst)
817*5a6e8488SAndroid Build Coastguard Worker {
818*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_addString(p);
819*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_push(p, inst);
820*5a6e8488SAndroid Build Coastguard Worker 	bc_lex_next(&p->l);
821*5a6e8488SAndroid Build Coastguard Worker }
822*5a6e8488SAndroid Build Coastguard Worker 
823*5a6e8488SAndroid Build Coastguard Worker /**
824*5a6e8488SAndroid Build Coastguard Worker  * Parses a print statement.
825*5a6e8488SAndroid Build Coastguard Worker  * @param p  The parser.
826*5a6e8488SAndroid Build Coastguard Worker  */
827*5a6e8488SAndroid Build Coastguard Worker static void
bc_parse_print(BcParse * p,BcLexType type)828*5a6e8488SAndroid Build Coastguard Worker bc_parse_print(BcParse* p, BcLexType type)
829*5a6e8488SAndroid Build Coastguard Worker {
830*5a6e8488SAndroid Build Coastguard Worker 	BcLexType t;
831*5a6e8488SAndroid Build Coastguard Worker 	bool comma = false;
832*5a6e8488SAndroid Build Coastguard Worker 	BcInst inst = type == BC_LEX_KW_STREAM ? BC_INST_PRINT_STREAM :
833*5a6e8488SAndroid Build Coastguard Worker 	                                         BC_INST_PRINT_POP;
834*5a6e8488SAndroid Build Coastguard Worker 
835*5a6e8488SAndroid Build Coastguard Worker 	bc_lex_next(&p->l);
836*5a6e8488SAndroid Build Coastguard Worker 
837*5a6e8488SAndroid Build Coastguard Worker 	t = p->l.t;
838*5a6e8488SAndroid Build Coastguard Worker 
839*5a6e8488SAndroid Build Coastguard Worker 	// A print or stream statement has to have *something*.
840*5a6e8488SAndroid Build Coastguard Worker 	if (bc_parse_isDelimiter(p)) bc_parse_err(p, BC_ERR_PARSE_PRINT);
841*5a6e8488SAndroid Build Coastguard Worker 
842*5a6e8488SAndroid Build Coastguard Worker 	do
843*5a6e8488SAndroid Build Coastguard Worker 	{
844*5a6e8488SAndroid Build Coastguard Worker 		// If the token is a string, then print it with escapes.
845*5a6e8488SAndroid Build Coastguard Worker 		// BC_INST_PRINT_POP plays that role for bc.
846*5a6e8488SAndroid Build Coastguard Worker 		if (t == BC_LEX_STR) bc_parse_str(p, inst);
847*5a6e8488SAndroid Build Coastguard Worker 		else
848*5a6e8488SAndroid Build Coastguard Worker 		{
849*5a6e8488SAndroid Build Coastguard Worker 			// We have an actual number; parse and add a print instruction.
850*5a6e8488SAndroid Build Coastguard Worker 			bc_parse_expr_status(p, BC_PARSE_NEEDVAL, bc_parse_next_print);
851*5a6e8488SAndroid Build Coastguard Worker 			bc_parse_push(p, inst);
852*5a6e8488SAndroid Build Coastguard Worker 		}
853*5a6e8488SAndroid Build Coastguard Worker 
854*5a6e8488SAndroid Build Coastguard Worker 		// Is the next token a comma?
855*5a6e8488SAndroid Build Coastguard Worker 		comma = (p->l.t == BC_LEX_COMMA);
856*5a6e8488SAndroid Build Coastguard Worker 
857*5a6e8488SAndroid Build Coastguard Worker 		// Get the next token if we have a comma.
858*5a6e8488SAndroid Build Coastguard Worker 		if (comma) bc_lex_next(&p->l);
859*5a6e8488SAndroid Build Coastguard Worker 		else
860*5a6e8488SAndroid Build Coastguard Worker 		{
861*5a6e8488SAndroid Build Coastguard Worker 			// If we don't have a comma, the statement needs to end.
862*5a6e8488SAndroid Build Coastguard Worker 			if (!bc_parse_isDelimiter(p)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
863*5a6e8488SAndroid Build Coastguard Worker 			else break;
864*5a6e8488SAndroid Build Coastguard Worker 		}
865*5a6e8488SAndroid Build Coastguard Worker 
866*5a6e8488SAndroid Build Coastguard Worker 		t = p->l.t;
867*5a6e8488SAndroid Build Coastguard Worker 	}
868*5a6e8488SAndroid Build Coastguard Worker 	while (true);
869*5a6e8488SAndroid Build Coastguard Worker 
870*5a6e8488SAndroid Build Coastguard Worker 	// If we have a comma but no token, that's bad.
871*5a6e8488SAndroid Build Coastguard Worker 	if (BC_ERR(comma)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
872*5a6e8488SAndroid Build Coastguard Worker }
873*5a6e8488SAndroid Build Coastguard Worker 
874*5a6e8488SAndroid Build Coastguard Worker /**
875*5a6e8488SAndroid Build Coastguard Worker  * Parses a return statement.
876*5a6e8488SAndroid Build Coastguard Worker  * @param p  The parser.
877*5a6e8488SAndroid Build Coastguard Worker  */
878*5a6e8488SAndroid Build Coastguard Worker static void
bc_parse_return(BcParse * p)879*5a6e8488SAndroid Build Coastguard Worker bc_parse_return(BcParse* p)
880*5a6e8488SAndroid Build Coastguard Worker {
881*5a6e8488SAndroid Build Coastguard Worker 	BcLexType t;
882*5a6e8488SAndroid Build Coastguard Worker 	bool paren;
883*5a6e8488SAndroid Build Coastguard Worker 	uchar inst = BC_INST_RET0;
884*5a6e8488SAndroid Build Coastguard Worker 
885*5a6e8488SAndroid Build Coastguard Worker 	// If we are not in a function, that's an error.
886*5a6e8488SAndroid Build Coastguard Worker 	if (BC_ERR(!BC_PARSE_FUNC(p))) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
887*5a6e8488SAndroid Build Coastguard Worker 
888*5a6e8488SAndroid Build Coastguard Worker 	// If we are in a void function, make sure to return void.
889*5a6e8488SAndroid Build Coastguard Worker 	if (p->func->voidfn) inst = BC_INST_RET_VOID;
890*5a6e8488SAndroid Build Coastguard Worker 
891*5a6e8488SAndroid Build Coastguard Worker 	bc_lex_next(&p->l);
892*5a6e8488SAndroid Build Coastguard Worker 
893*5a6e8488SAndroid Build Coastguard Worker 	t = p->l.t;
894*5a6e8488SAndroid Build Coastguard Worker 	paren = (t == BC_LEX_LPAREN);
895*5a6e8488SAndroid Build Coastguard Worker 
896*5a6e8488SAndroid Build Coastguard Worker 	// An empty return statement just needs to push the selected instruction.
897*5a6e8488SAndroid Build Coastguard Worker 	if (bc_parse_isDelimiter(p)) bc_parse_push(p, inst);
898*5a6e8488SAndroid Build Coastguard Worker 	else
899*5a6e8488SAndroid Build Coastguard Worker 	{
900*5a6e8488SAndroid Build Coastguard Worker 		BcParseStatus s;
901*5a6e8488SAndroid Build Coastguard Worker 
902*5a6e8488SAndroid Build Coastguard Worker 		// Need to parse the expression whose value will be returned.
903*5a6e8488SAndroid Build Coastguard Worker 		s = bc_parse_expr_err(p, BC_PARSE_NEEDVAL, bc_parse_next_expr);
904*5a6e8488SAndroid Build Coastguard Worker 
905*5a6e8488SAndroid Build Coastguard Worker 		// If the expression was empty, just push the selected instruction.
906*5a6e8488SAndroid Build Coastguard Worker 		if (s == BC_PARSE_STATUS_EMPTY_EXPR)
907*5a6e8488SAndroid Build Coastguard Worker 		{
908*5a6e8488SAndroid Build Coastguard Worker 			bc_parse_push(p, inst);
909*5a6e8488SAndroid Build Coastguard Worker 			bc_lex_next(&p->l);
910*5a6e8488SAndroid Build Coastguard Worker 		}
911*5a6e8488SAndroid Build Coastguard Worker 
912*5a6e8488SAndroid Build Coastguard Worker 		// POSIX requires parentheses.
913*5a6e8488SAndroid Build Coastguard Worker 		if (!paren || p->l.last != BC_LEX_RPAREN)
914*5a6e8488SAndroid Build Coastguard Worker 		{
915*5a6e8488SAndroid Build Coastguard Worker 			bc_parse_err(p, BC_ERR_POSIX_RET);
916*5a6e8488SAndroid Build Coastguard Worker 		}
917*5a6e8488SAndroid Build Coastguard Worker 
918*5a6e8488SAndroid Build Coastguard Worker 		// Void functions require an empty expression.
919*5a6e8488SAndroid Build Coastguard Worker 		if (BC_ERR(p->func->voidfn))
920*5a6e8488SAndroid Build Coastguard Worker 		{
921*5a6e8488SAndroid Build Coastguard Worker 			if (s != BC_PARSE_STATUS_EMPTY_EXPR)
922*5a6e8488SAndroid Build Coastguard Worker 			{
923*5a6e8488SAndroid Build Coastguard Worker 				bc_parse_verr(p, BC_ERR_PARSE_RET_VOID, p->func->name);
924*5a6e8488SAndroid Build Coastguard Worker 			}
925*5a6e8488SAndroid Build Coastguard Worker 		}
926*5a6e8488SAndroid Build Coastguard Worker 		// If we got here, we want to be sure to end the function with a real
927*5a6e8488SAndroid Build Coastguard Worker 		// return instruction, just in case.
928*5a6e8488SAndroid Build Coastguard Worker 		else bc_parse_push(p, BC_INST_RET);
929*5a6e8488SAndroid Build Coastguard Worker 	}
930*5a6e8488SAndroid Build Coastguard Worker }
931*5a6e8488SAndroid Build Coastguard Worker 
932*5a6e8488SAndroid Build Coastguard Worker /**
933*5a6e8488SAndroid Build Coastguard Worker  * Clears flags that indicate the end of an if statement and its block and sets
934*5a6e8488SAndroid Build Coastguard Worker  * the jump location.
935*5a6e8488SAndroid Build Coastguard Worker  * @param p  The parser.
936*5a6e8488SAndroid Build Coastguard Worker  */
937*5a6e8488SAndroid Build Coastguard Worker static void
bc_parse_noElse(BcParse * p)938*5a6e8488SAndroid Build Coastguard Worker bc_parse_noElse(BcParse* p)
939*5a6e8488SAndroid Build Coastguard Worker {
940*5a6e8488SAndroid Build Coastguard Worker 	uint16_t* flag_ptr = BC_PARSE_TOP_FLAG_PTR(p);
941*5a6e8488SAndroid Build Coastguard Worker 	*flag_ptr = (*flag_ptr & ~(BC_PARSE_FLAG_IF_END));
942*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_setLabel(p);
943*5a6e8488SAndroid Build Coastguard Worker }
944*5a6e8488SAndroid Build Coastguard Worker 
945*5a6e8488SAndroid Build Coastguard Worker /**
946*5a6e8488SAndroid Build Coastguard Worker  * Ends (finishes parsing) the body of a control statement or a function.
947*5a6e8488SAndroid Build Coastguard Worker  * @param p      The parser.
948*5a6e8488SAndroid Build Coastguard Worker  * @param brace  True if the body was ended by a brace, false otherwise.
949*5a6e8488SAndroid Build Coastguard Worker  */
950*5a6e8488SAndroid Build Coastguard Worker static void
bc_parse_endBody(BcParse * p,bool brace)951*5a6e8488SAndroid Build Coastguard Worker bc_parse_endBody(BcParse* p, bool brace)
952*5a6e8488SAndroid Build Coastguard Worker {
953*5a6e8488SAndroid Build Coastguard Worker 	bool has_brace, new_else = false;
954*5a6e8488SAndroid Build Coastguard Worker 
955*5a6e8488SAndroid Build Coastguard Worker 	// We cannot be ending a body if there are no bodies to end.
956*5a6e8488SAndroid Build Coastguard Worker 	if (BC_ERR(p->flags.len <= 1)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
957*5a6e8488SAndroid Build Coastguard Worker 
958*5a6e8488SAndroid Build Coastguard Worker 	if (brace)
959*5a6e8488SAndroid Build Coastguard Worker 	{
960*5a6e8488SAndroid Build Coastguard Worker 		// The brace was already gotten; make sure that the caller did not lie.
961*5a6e8488SAndroid Build Coastguard Worker 		// We check for the requirement of braces later.
962*5a6e8488SAndroid Build Coastguard Worker 		assert(p->l.t == BC_LEX_RBRACE);
963*5a6e8488SAndroid Build Coastguard Worker 
964*5a6e8488SAndroid Build Coastguard Worker 		bc_lex_next(&p->l);
965*5a6e8488SAndroid Build Coastguard Worker 
966*5a6e8488SAndroid Build Coastguard Worker 		// If the next token is not a delimiter, that is a problem.
967*5a6e8488SAndroid Build Coastguard Worker 		if (BC_ERR(!bc_parse_isDelimiter(p) && !bc_parse_TopFunc(p)))
968*5a6e8488SAndroid Build Coastguard Worker 		{
969*5a6e8488SAndroid Build Coastguard Worker 			bc_parse_err(p, BC_ERR_PARSE_TOKEN);
970*5a6e8488SAndroid Build Coastguard Worker 		}
971*5a6e8488SAndroid Build Coastguard Worker 	}
972*5a6e8488SAndroid Build Coastguard Worker 
973*5a6e8488SAndroid Build Coastguard Worker 	// Do we have a brace flag?
974*5a6e8488SAndroid Build Coastguard Worker 	has_brace = (BC_PARSE_BRACE(p) != 0);
975*5a6e8488SAndroid Build Coastguard Worker 
976*5a6e8488SAndroid Build Coastguard Worker 	do
977*5a6e8488SAndroid Build Coastguard Worker 	{
978*5a6e8488SAndroid Build Coastguard Worker 		size_t len = p->flags.len;
979*5a6e8488SAndroid Build Coastguard Worker 		bool loop;
980*5a6e8488SAndroid Build Coastguard Worker 
981*5a6e8488SAndroid Build Coastguard Worker 		// If we have a brace flag but not a brace, that's a problem.
982*5a6e8488SAndroid Build Coastguard Worker 		if (has_brace && !brace) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
983*5a6e8488SAndroid Build Coastguard Worker 
984*5a6e8488SAndroid Build Coastguard Worker 		// Are we inside a loop?
985*5a6e8488SAndroid Build Coastguard Worker 		loop = (BC_PARSE_LOOP_INNER(p) != 0);
986*5a6e8488SAndroid Build Coastguard Worker 
987*5a6e8488SAndroid Build Coastguard Worker 		// If we are ending a loop or an else...
988*5a6e8488SAndroid Build Coastguard Worker 		if (loop || BC_PARSE_ELSE(p))
989*5a6e8488SAndroid Build Coastguard Worker 		{
990*5a6e8488SAndroid Build Coastguard Worker 			// Loops have condition labels that we have to take care of as well.
991*5a6e8488SAndroid Build Coastguard Worker 			if (loop)
992*5a6e8488SAndroid Build Coastguard Worker 			{
993*5a6e8488SAndroid Build Coastguard Worker 				size_t* label = bc_vec_top(&p->conds);
994*5a6e8488SAndroid Build Coastguard Worker 
995*5a6e8488SAndroid Build Coastguard Worker 				bc_parse_push(p, BC_INST_JUMP);
996*5a6e8488SAndroid Build Coastguard Worker 				bc_parse_pushIndex(p, *label);
997*5a6e8488SAndroid Build Coastguard Worker 
998*5a6e8488SAndroid Build Coastguard Worker 				bc_vec_pop(&p->conds);
999*5a6e8488SAndroid Build Coastguard Worker 			}
1000*5a6e8488SAndroid Build Coastguard Worker 
1001*5a6e8488SAndroid Build Coastguard Worker 			bc_parse_setLabel(p);
1002*5a6e8488SAndroid Build Coastguard Worker 			bc_vec_pop(&p->flags);
1003*5a6e8488SAndroid Build Coastguard Worker 		}
1004*5a6e8488SAndroid Build Coastguard Worker 		// If we are ending a function...
1005*5a6e8488SAndroid Build Coastguard Worker 		else if (BC_PARSE_FUNC_INNER(p))
1006*5a6e8488SAndroid Build Coastguard Worker 		{
1007*5a6e8488SAndroid Build Coastguard Worker 			BcInst inst = (p->func->voidfn ? BC_INST_RET_VOID : BC_INST_RET0);
1008*5a6e8488SAndroid Build Coastguard Worker 			bc_parse_push(p, inst);
1009*5a6e8488SAndroid Build Coastguard Worker 			bc_parse_updateFunc(p, BC_PROG_MAIN);
1010*5a6e8488SAndroid Build Coastguard Worker 			bc_vec_pop(&p->flags);
1011*5a6e8488SAndroid Build Coastguard Worker 		}
1012*5a6e8488SAndroid Build Coastguard Worker 		// If we have a brace flag and not an if statement, we can pop the top
1013*5a6e8488SAndroid Build Coastguard Worker 		// of the flags stack because they have been taken care of above.
1014*5a6e8488SAndroid Build Coastguard Worker 		else if (has_brace && !BC_PARSE_IF(p)) bc_vec_pop(&p->flags);
1015*5a6e8488SAndroid Build Coastguard Worker 
1016*5a6e8488SAndroid Build Coastguard Worker 		// This needs to be last to parse nested if's properly.
1017*5a6e8488SAndroid Build Coastguard Worker 		if (BC_PARSE_IF(p) && (len == p->flags.len || !BC_PARSE_BRACE(p)))
1018*5a6e8488SAndroid Build Coastguard Worker 		{
1019*5a6e8488SAndroid Build Coastguard Worker 			// Eat newlines.
1020*5a6e8488SAndroid Build Coastguard Worker 			while (p->l.t == BC_LEX_NLINE)
1021*5a6e8488SAndroid Build Coastguard Worker 			{
1022*5a6e8488SAndroid Build Coastguard Worker 				bc_lex_next(&p->l);
1023*5a6e8488SAndroid Build Coastguard Worker 			}
1024*5a6e8488SAndroid Build Coastguard Worker 
1025*5a6e8488SAndroid Build Coastguard Worker 			// *Now* we can pop the flags.
1026*5a6e8488SAndroid Build Coastguard Worker 			bc_vec_pop(&p->flags);
1027*5a6e8488SAndroid Build Coastguard Worker 
1028*5a6e8488SAndroid Build Coastguard Worker 			// If we are allowed non-POSIX stuff...
1029*5a6e8488SAndroid Build Coastguard Worker 			if (!BC_S)
1030*5a6e8488SAndroid Build Coastguard Worker 			{
1031*5a6e8488SAndroid Build Coastguard Worker 				// Have we found yet another dangling else?
1032*5a6e8488SAndroid Build Coastguard Worker 				*(BC_PARSE_TOP_FLAG_PTR(p)) |= BC_PARSE_FLAG_IF_END;
1033*5a6e8488SAndroid Build Coastguard Worker 				new_else = (p->l.t == BC_LEX_KW_ELSE);
1034*5a6e8488SAndroid Build Coastguard Worker 
1035*5a6e8488SAndroid Build Coastguard Worker 				// Parse the else or end the if statement body.
1036*5a6e8488SAndroid Build Coastguard Worker 				if (new_else) bc_parse_else(p);
1037*5a6e8488SAndroid Build Coastguard Worker 				else if (!has_brace && (!BC_PARSE_IF_END(p) || brace))
1038*5a6e8488SAndroid Build Coastguard Worker 				{
1039*5a6e8488SAndroid Build Coastguard Worker 					bc_parse_noElse(p);
1040*5a6e8488SAndroid Build Coastguard Worker 				}
1041*5a6e8488SAndroid Build Coastguard Worker 			}
1042*5a6e8488SAndroid Build Coastguard Worker 			// POSIX requires us to do the bare minimum only.
1043*5a6e8488SAndroid Build Coastguard Worker 			else bc_parse_noElse(p);
1044*5a6e8488SAndroid Build Coastguard Worker 		}
1045*5a6e8488SAndroid Build Coastguard Worker 
1046*5a6e8488SAndroid Build Coastguard Worker 		// If these are both true, we have "used" the braces that we found.
1047*5a6e8488SAndroid Build Coastguard Worker 		if (brace && has_brace) brace = false;
1048*5a6e8488SAndroid Build Coastguard Worker 	}
1049*5a6e8488SAndroid Build Coastguard Worker 	// This condition was perhaps the hardest single part of the parser. If
1050*5a6e8488SAndroid Build Coastguard Worker 	// the flags stack does not have enough, we should stop. If we have a
1051*5a6e8488SAndroid Build Coastguard Worker 	// new else statement, we should stop. If we do have the end of an if
1052*5a6e8488SAndroid Build Coastguard Worker 	// statement and we have eaten the brace, we should stop. If we do have
1053*5a6e8488SAndroid Build Coastguard Worker 	// a brace flag, we should stop.
1054*5a6e8488SAndroid Build Coastguard Worker 	while (p->flags.len > 1 && !new_else && (!BC_PARSE_IF_END(p) || brace) &&
1055*5a6e8488SAndroid Build Coastguard Worker 	       !(has_brace = (BC_PARSE_BRACE(p) != 0)));
1056*5a6e8488SAndroid Build Coastguard Worker 
1057*5a6e8488SAndroid Build Coastguard Worker 	// If we have a brace, yet no body for it, that's a problem.
1058*5a6e8488SAndroid Build Coastguard Worker 	if (BC_ERR(p->flags.len == 1 && brace)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
1059*5a6e8488SAndroid Build Coastguard Worker 	else if (brace && BC_PARSE_BRACE(p))
1060*5a6e8488SAndroid Build Coastguard Worker 	{
1061*5a6e8488SAndroid Build Coastguard Worker 		// If we make it here, we have a brace and a flag for it.
1062*5a6e8488SAndroid Build Coastguard Worker 		uint16_t flags = BC_PARSE_TOP_FLAG(p);
1063*5a6e8488SAndroid Build Coastguard Worker 
1064*5a6e8488SAndroid Build Coastguard Worker 		// This condition ensure that the *last* body is correctly finished by
1065*5a6e8488SAndroid Build Coastguard Worker 		// popping its flags.
1066*5a6e8488SAndroid Build Coastguard Worker 		if (!(flags & (BC_PARSE_FLAG_FUNC_INNER | BC_PARSE_FLAG_LOOP_INNER)) &&
1067*5a6e8488SAndroid Build Coastguard Worker 		    !(flags & (BC_PARSE_FLAG_IF | BC_PARSE_FLAG_ELSE)) &&
1068*5a6e8488SAndroid Build Coastguard Worker 		    !(flags & (BC_PARSE_FLAG_IF_END)))
1069*5a6e8488SAndroid Build Coastguard Worker 		{
1070*5a6e8488SAndroid Build Coastguard Worker 			bc_vec_pop(&p->flags);
1071*5a6e8488SAndroid Build Coastguard Worker 		}
1072*5a6e8488SAndroid Build Coastguard Worker 	}
1073*5a6e8488SAndroid Build Coastguard Worker }
1074*5a6e8488SAndroid Build Coastguard Worker 
1075*5a6e8488SAndroid Build Coastguard Worker /**
1076*5a6e8488SAndroid Build Coastguard Worker  * Starts the body of a control statement or function.
1077*5a6e8488SAndroid Build Coastguard Worker  * @param p      The parser.
1078*5a6e8488SAndroid Build Coastguard Worker  * @param flags  The current flags (will be edited).
1079*5a6e8488SAndroid Build Coastguard Worker  */
1080*5a6e8488SAndroid Build Coastguard Worker static void
bc_parse_startBody(BcParse * p,uint16_t flags)1081*5a6e8488SAndroid Build Coastguard Worker bc_parse_startBody(BcParse* p, uint16_t flags)
1082*5a6e8488SAndroid Build Coastguard Worker {
1083*5a6e8488SAndroid Build Coastguard Worker 	assert(flags);
1084*5a6e8488SAndroid Build Coastguard Worker 	flags |= (BC_PARSE_TOP_FLAG(p) & (BC_PARSE_FLAG_FUNC | BC_PARSE_FLAG_LOOP));
1085*5a6e8488SAndroid Build Coastguard Worker 	flags |= BC_PARSE_FLAG_BODY;
1086*5a6e8488SAndroid Build Coastguard Worker 	bc_vec_push(&p->flags, &flags);
1087*5a6e8488SAndroid Build Coastguard Worker }
1088*5a6e8488SAndroid Build Coastguard Worker 
1089*5a6e8488SAndroid Build Coastguard Worker void
bc_parse_endif(BcParse * p)1090*5a6e8488SAndroid Build Coastguard Worker bc_parse_endif(BcParse* p)
1091*5a6e8488SAndroid Build Coastguard Worker {
1092*5a6e8488SAndroid Build Coastguard Worker 	size_t i;
1093*5a6e8488SAndroid Build Coastguard Worker 	bool good;
1094*5a6e8488SAndroid Build Coastguard Worker 
1095*5a6e8488SAndroid Build Coastguard Worker 	// Not a problem if this is true.
1096*5a6e8488SAndroid Build Coastguard Worker 	if (BC_NO_ERR(!BC_PARSE_NO_EXEC(p))) return;
1097*5a6e8488SAndroid Build Coastguard Worker 
1098*5a6e8488SAndroid Build Coastguard Worker 	good = true;
1099*5a6e8488SAndroid Build Coastguard Worker 
1100*5a6e8488SAndroid Build Coastguard Worker 	// Find an instance of a body that needs closing, i.e., a statement that did
1101*5a6e8488SAndroid Build Coastguard Worker 	// not have a right brace when it should have.
1102*5a6e8488SAndroid Build Coastguard Worker 	for (i = 0; good && i < p->flags.len; ++i)
1103*5a6e8488SAndroid Build Coastguard Worker 	{
1104*5a6e8488SAndroid Build Coastguard Worker 		uint16_t flag = *((uint16_t*) bc_vec_item(&p->flags, i));
1105*5a6e8488SAndroid Build Coastguard Worker 		good = ((flag & BC_PARSE_FLAG_BRACE) != BC_PARSE_FLAG_BRACE);
1106*5a6e8488SAndroid Build Coastguard Worker 	}
1107*5a6e8488SAndroid Build Coastguard Worker 
1108*5a6e8488SAndroid Build Coastguard Worker 	// If we did not find such an instance...
1109*5a6e8488SAndroid Build Coastguard Worker 	if (good)
1110*5a6e8488SAndroid Build Coastguard Worker 	{
1111*5a6e8488SAndroid Build Coastguard Worker 		// We set this to restore it later. We don't want the parser thinking
1112*5a6e8488SAndroid Build Coastguard Worker 		// that we are on stdin for this one because it will want more.
1113*5a6e8488SAndroid Build Coastguard Worker 		BcMode mode = vm->mode;
1114*5a6e8488SAndroid Build Coastguard Worker 
1115*5a6e8488SAndroid Build Coastguard Worker 		vm->mode = BC_MODE_FILE;
1116*5a6e8488SAndroid Build Coastguard Worker 
1117*5a6e8488SAndroid Build Coastguard Worker 		// End all of the if statements and loops.
1118*5a6e8488SAndroid Build Coastguard Worker 		while (p->flags.len > 1 || BC_PARSE_IF_END(p))
1119*5a6e8488SAndroid Build Coastguard Worker 		{
1120*5a6e8488SAndroid Build Coastguard Worker 			if (BC_PARSE_IF_END(p)) bc_parse_noElse(p);
1121*5a6e8488SAndroid Build Coastguard Worker 			if (p->flags.len > 1) bc_parse_endBody(p, false);
1122*5a6e8488SAndroid Build Coastguard Worker 		}
1123*5a6e8488SAndroid Build Coastguard Worker 
1124*5a6e8488SAndroid Build Coastguard Worker 		vm->mode = (uchar) mode;
1125*5a6e8488SAndroid Build Coastguard Worker 	}
1126*5a6e8488SAndroid Build Coastguard Worker 	// If we reach here, a block was not properly closed, and we should error.
1127*5a6e8488SAndroid Build Coastguard Worker 	else bc_parse_err(&vm->prs, BC_ERR_PARSE_BLOCK);
1128*5a6e8488SAndroid Build Coastguard Worker }
1129*5a6e8488SAndroid Build Coastguard Worker 
1130*5a6e8488SAndroid Build Coastguard Worker /**
1131*5a6e8488SAndroid Build Coastguard Worker  * Parses an if statement.
1132*5a6e8488SAndroid Build Coastguard Worker  * @param p  The parser.
1133*5a6e8488SAndroid Build Coastguard Worker  */
1134*5a6e8488SAndroid Build Coastguard Worker static void
bc_parse_if(BcParse * p)1135*5a6e8488SAndroid Build Coastguard Worker bc_parse_if(BcParse* p)
1136*5a6e8488SAndroid Build Coastguard Worker {
1137*5a6e8488SAndroid Build Coastguard Worker 	// We are allowed relational operators, and we must have a value.
1138*5a6e8488SAndroid Build Coastguard Worker 	size_t idx;
1139*5a6e8488SAndroid Build Coastguard Worker 	uint8_t flags = (BC_PARSE_REL | BC_PARSE_NEEDVAL);
1140*5a6e8488SAndroid Build Coastguard Worker 
1141*5a6e8488SAndroid Build Coastguard Worker 	// Get the left paren and barf if necessary.
1142*5a6e8488SAndroid Build Coastguard Worker 	bc_lex_next(&p->l);
1143*5a6e8488SAndroid Build Coastguard Worker 	if (BC_ERR(p->l.t != BC_LEX_LPAREN)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
1144*5a6e8488SAndroid Build Coastguard Worker 
1145*5a6e8488SAndroid Build Coastguard Worker 	// Parse the condition.
1146*5a6e8488SAndroid Build Coastguard Worker 	bc_lex_next(&p->l);
1147*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_expr_status(p, flags, bc_parse_next_rel);
1148*5a6e8488SAndroid Build Coastguard Worker 
1149*5a6e8488SAndroid Build Coastguard Worker 	// Must have a right paren.
1150*5a6e8488SAndroid Build Coastguard Worker 	if (BC_ERR(p->l.t != BC_LEX_RPAREN)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
1151*5a6e8488SAndroid Build Coastguard Worker 
1152*5a6e8488SAndroid Build Coastguard Worker 	bc_lex_next(&p->l);
1153*5a6e8488SAndroid Build Coastguard Worker 
1154*5a6e8488SAndroid Build Coastguard Worker 	// Insert the conditional jump instruction.
1155*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_push(p, BC_INST_JUMP_ZERO);
1156*5a6e8488SAndroid Build Coastguard Worker 
1157*5a6e8488SAndroid Build Coastguard Worker 	idx = p->func->labels.len;
1158*5a6e8488SAndroid Build Coastguard Worker 
1159*5a6e8488SAndroid Build Coastguard Worker 	// Push the index for the instruction and create an exit label for an else
1160*5a6e8488SAndroid Build Coastguard Worker 	// statement.
1161*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_pushIndex(p, idx);
1162*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_createExitLabel(p, idx, false);
1163*5a6e8488SAndroid Build Coastguard Worker 
1164*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_startBody(p, BC_PARSE_FLAG_IF);
1165*5a6e8488SAndroid Build Coastguard Worker }
1166*5a6e8488SAndroid Build Coastguard Worker 
1167*5a6e8488SAndroid Build Coastguard Worker /**
1168*5a6e8488SAndroid Build Coastguard Worker  * Parses an else statement.
1169*5a6e8488SAndroid Build Coastguard Worker  * @param p  The parser.
1170*5a6e8488SAndroid Build Coastguard Worker  */
1171*5a6e8488SAndroid Build Coastguard Worker static void
bc_parse_else(BcParse * p)1172*5a6e8488SAndroid Build Coastguard Worker bc_parse_else(BcParse* p)
1173*5a6e8488SAndroid Build Coastguard Worker {
1174*5a6e8488SAndroid Build Coastguard Worker 	size_t idx = p->func->labels.len;
1175*5a6e8488SAndroid Build Coastguard Worker 
1176*5a6e8488SAndroid Build Coastguard Worker 	// We must be at the end of an if statement.
1177*5a6e8488SAndroid Build Coastguard Worker 	if (BC_ERR(!BC_PARSE_IF_END(p))) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
1178*5a6e8488SAndroid Build Coastguard Worker 
1179*5a6e8488SAndroid Build Coastguard Worker 	// Push an unconditional jump to make bc jump over the else statement if it
1180*5a6e8488SAndroid Build Coastguard Worker 	// executed the original if statement.
1181*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_push(p, BC_INST_JUMP);
1182*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_pushIndex(p, idx);
1183*5a6e8488SAndroid Build Coastguard Worker 
1184*5a6e8488SAndroid Build Coastguard Worker 	// Clear the else stuff. Yes, that function is misnamed for its use here,
1185*5a6e8488SAndroid Build Coastguard Worker 	// but deal with it.
1186*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_noElse(p);
1187*5a6e8488SAndroid Build Coastguard Worker 
1188*5a6e8488SAndroid Build Coastguard Worker 	// Create the exit label and parse the body.
1189*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_createExitLabel(p, idx, false);
1190*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_startBody(p, BC_PARSE_FLAG_ELSE);
1191*5a6e8488SAndroid Build Coastguard Worker 
1192*5a6e8488SAndroid Build Coastguard Worker 	bc_lex_next(&p->l);
1193*5a6e8488SAndroid Build Coastguard Worker }
1194*5a6e8488SAndroid Build Coastguard Worker 
1195*5a6e8488SAndroid Build Coastguard Worker /**
1196*5a6e8488SAndroid Build Coastguard Worker  * Parse a while loop.
1197*5a6e8488SAndroid Build Coastguard Worker  * @param p  The parser.
1198*5a6e8488SAndroid Build Coastguard Worker  */
1199*5a6e8488SAndroid Build Coastguard Worker static void
bc_parse_while(BcParse * p)1200*5a6e8488SAndroid Build Coastguard Worker bc_parse_while(BcParse* p)
1201*5a6e8488SAndroid Build Coastguard Worker {
1202*5a6e8488SAndroid Build Coastguard Worker 	// We are allowed relational operators, and we must have a value.
1203*5a6e8488SAndroid Build Coastguard Worker 	size_t idx;
1204*5a6e8488SAndroid Build Coastguard Worker 	uint8_t flags = (BC_PARSE_REL | BC_PARSE_NEEDVAL);
1205*5a6e8488SAndroid Build Coastguard Worker 
1206*5a6e8488SAndroid Build Coastguard Worker 	// Get the left paren and barf if necessary.
1207*5a6e8488SAndroid Build Coastguard Worker 	bc_lex_next(&p->l);
1208*5a6e8488SAndroid Build Coastguard Worker 	if (BC_ERR(p->l.t != BC_LEX_LPAREN)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
1209*5a6e8488SAndroid Build Coastguard Worker 	bc_lex_next(&p->l);
1210*5a6e8488SAndroid Build Coastguard Worker 
1211*5a6e8488SAndroid Build Coastguard Worker 	// Create the labels. Loops need both.
1212*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_createCondLabel(p, p->func->labels.len);
1213*5a6e8488SAndroid Build Coastguard Worker 	idx = p->func->labels.len;
1214*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_createExitLabel(p, idx, true);
1215*5a6e8488SAndroid Build Coastguard Worker 
1216*5a6e8488SAndroid Build Coastguard Worker 	// Parse the actual condition and barf on non-right paren.
1217*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_expr_status(p, flags, bc_parse_next_rel);
1218*5a6e8488SAndroid Build Coastguard Worker 	if (BC_ERR(p->l.t != BC_LEX_RPAREN)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
1219*5a6e8488SAndroid Build Coastguard Worker 	bc_lex_next(&p->l);
1220*5a6e8488SAndroid Build Coastguard Worker 
1221*5a6e8488SAndroid Build Coastguard Worker 	// Now we can push the conditional jump and start the body.
1222*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_push(p, BC_INST_JUMP_ZERO);
1223*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_pushIndex(p, idx);
1224*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_startBody(p, BC_PARSE_FLAG_LOOP | BC_PARSE_FLAG_LOOP_INNER);
1225*5a6e8488SAndroid Build Coastguard Worker }
1226*5a6e8488SAndroid Build Coastguard Worker 
1227*5a6e8488SAndroid Build Coastguard Worker /**
1228*5a6e8488SAndroid Build Coastguard Worker  * Parse a for loop.
1229*5a6e8488SAndroid Build Coastguard Worker  * @param p  The parser.
1230*5a6e8488SAndroid Build Coastguard Worker  */
1231*5a6e8488SAndroid Build Coastguard Worker static void
bc_parse_for(BcParse * p)1232*5a6e8488SAndroid Build Coastguard Worker bc_parse_for(BcParse* p)
1233*5a6e8488SAndroid Build Coastguard Worker {
1234*5a6e8488SAndroid Build Coastguard Worker 	size_t cond_idx, exit_idx, body_idx, update_idx;
1235*5a6e8488SAndroid Build Coastguard Worker 
1236*5a6e8488SAndroid Build Coastguard Worker 	// Barf on the missing left paren.
1237*5a6e8488SAndroid Build Coastguard Worker 	bc_lex_next(&p->l);
1238*5a6e8488SAndroid Build Coastguard Worker 	if (BC_ERR(p->l.t != BC_LEX_LPAREN)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
1239*5a6e8488SAndroid Build Coastguard Worker 	bc_lex_next(&p->l);
1240*5a6e8488SAndroid Build Coastguard Worker 
1241*5a6e8488SAndroid Build Coastguard Worker 	// The first statement can be empty, but if it is, check for error in POSIX
1242*5a6e8488SAndroid Build Coastguard Worker 	// mode. Otherwise, parse it.
1243*5a6e8488SAndroid Build Coastguard Worker 	if (p->l.t != BC_LEX_SCOLON) bc_parse_expr_status(p, 0, bc_parse_next_for);
1244*5a6e8488SAndroid Build Coastguard Worker 	else bc_parse_err(p, BC_ERR_POSIX_FOR);
1245*5a6e8488SAndroid Build Coastguard Worker 
1246*5a6e8488SAndroid Build Coastguard Worker 	// Must have a semicolon.
1247*5a6e8488SAndroid Build Coastguard Worker 	if (BC_ERR(p->l.t != BC_LEX_SCOLON)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
1248*5a6e8488SAndroid Build Coastguard Worker 	bc_lex_next(&p->l);
1249*5a6e8488SAndroid Build Coastguard Worker 
1250*5a6e8488SAndroid Build Coastguard Worker 	// These are indices for labels. There are so many of them because the end
1251*5a6e8488SAndroid Build Coastguard Worker 	// of the loop must unconditionally jump to the update code. Then the update
1252*5a6e8488SAndroid Build Coastguard Worker 	// code must unconditionally jump to the condition code. Then the condition
1253*5a6e8488SAndroid Build Coastguard Worker 	// code must *conditionally* jump to the exit.
1254*5a6e8488SAndroid Build Coastguard Worker 	cond_idx = p->func->labels.len;
1255*5a6e8488SAndroid Build Coastguard Worker 	update_idx = cond_idx + 1;
1256*5a6e8488SAndroid Build Coastguard Worker 	body_idx = update_idx + 1;
1257*5a6e8488SAndroid Build Coastguard Worker 	exit_idx = body_idx + 1;
1258*5a6e8488SAndroid Build Coastguard Worker 
1259*5a6e8488SAndroid Build Coastguard Worker 	// This creates the condition label.
1260*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_createLabel(p, p->func->code.len);
1261*5a6e8488SAndroid Build Coastguard Worker 
1262*5a6e8488SAndroid Build Coastguard Worker 	// Parse an expression if it exists.
1263*5a6e8488SAndroid Build Coastguard Worker 	if (p->l.t != BC_LEX_SCOLON)
1264*5a6e8488SAndroid Build Coastguard Worker 	{
1265*5a6e8488SAndroid Build Coastguard Worker 		uint8_t flags = (BC_PARSE_REL | BC_PARSE_NEEDVAL);
1266*5a6e8488SAndroid Build Coastguard Worker 		bc_parse_expr_status(p, flags, bc_parse_next_for);
1267*5a6e8488SAndroid Build Coastguard Worker 	}
1268*5a6e8488SAndroid Build Coastguard Worker 	else
1269*5a6e8488SAndroid Build Coastguard Worker 	{
1270*5a6e8488SAndroid Build Coastguard Worker 		// Set this for the next call to bc_parse_number because an empty
1271*5a6e8488SAndroid Build Coastguard Worker 		// condition means that it is an infinite loop, so the condition must be
1272*5a6e8488SAndroid Build Coastguard Worker 		// non-zero. This is safe to set because the current token is a
1273*5a6e8488SAndroid Build Coastguard Worker 		// semicolon, which has no string requirement.
1274*5a6e8488SAndroid Build Coastguard Worker 		bc_vec_string(&p->l.str, sizeof(bc_parse_one) - 1, bc_parse_one);
1275*5a6e8488SAndroid Build Coastguard Worker 		bc_parse_number(p);
1276*5a6e8488SAndroid Build Coastguard Worker 
1277*5a6e8488SAndroid Build Coastguard Worker 		// An empty condition makes POSIX mad.
1278*5a6e8488SAndroid Build Coastguard Worker 		bc_parse_err(p, BC_ERR_POSIX_FOR);
1279*5a6e8488SAndroid Build Coastguard Worker 	}
1280*5a6e8488SAndroid Build Coastguard Worker 
1281*5a6e8488SAndroid Build Coastguard Worker 	// Must have a semicolon.
1282*5a6e8488SAndroid Build Coastguard Worker 	if (BC_ERR(p->l.t != BC_LEX_SCOLON)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
1283*5a6e8488SAndroid Build Coastguard Worker 	bc_lex_next(&p->l);
1284*5a6e8488SAndroid Build Coastguard Worker 
1285*5a6e8488SAndroid Build Coastguard Worker 	// Now we can set up the conditional jump to the exit and an unconditional
1286*5a6e8488SAndroid Build Coastguard Worker 	// jump to the body right after. The unconditional jump to the body is
1287*5a6e8488SAndroid Build Coastguard Worker 	// because there is update code coming right after the condition, so we need
1288*5a6e8488SAndroid Build Coastguard Worker 	// to skip it to get to the body.
1289*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_push(p, BC_INST_JUMP_ZERO);
1290*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_pushIndex(p, exit_idx);
1291*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_push(p, BC_INST_JUMP);
1292*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_pushIndex(p, body_idx);
1293*5a6e8488SAndroid Build Coastguard Worker 
1294*5a6e8488SAndroid Build Coastguard Worker 	// Now create the label for the update code.
1295*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_createCondLabel(p, update_idx);
1296*5a6e8488SAndroid Build Coastguard Worker 
1297*5a6e8488SAndroid Build Coastguard Worker 	// Parse if not empty, and if it is, let POSIX yell if necessary.
1298*5a6e8488SAndroid Build Coastguard Worker 	if (p->l.t != BC_LEX_RPAREN) bc_parse_expr_status(p, 0, bc_parse_next_rel);
1299*5a6e8488SAndroid Build Coastguard Worker 	else bc_parse_err(p, BC_ERR_POSIX_FOR);
1300*5a6e8488SAndroid Build Coastguard Worker 
1301*5a6e8488SAndroid Build Coastguard Worker 	// Must have a right paren.
1302*5a6e8488SAndroid Build Coastguard Worker 	if (BC_ERR(p->l.t != BC_LEX_RPAREN)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
1303*5a6e8488SAndroid Build Coastguard Worker 
1304*5a6e8488SAndroid Build Coastguard Worker 	// Set up a jump to the condition right after the update code.
1305*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_push(p, BC_INST_JUMP);
1306*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_pushIndex(p, cond_idx);
1307*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_createLabel(p, p->func->code.len);
1308*5a6e8488SAndroid Build Coastguard Worker 
1309*5a6e8488SAndroid Build Coastguard Worker 	// Create an exit label for the body and start the body.
1310*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_createExitLabel(p, exit_idx, true);
1311*5a6e8488SAndroid Build Coastguard Worker 	bc_lex_next(&p->l);
1312*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_startBody(p, BC_PARSE_FLAG_LOOP | BC_PARSE_FLAG_LOOP_INNER);
1313*5a6e8488SAndroid Build Coastguard Worker }
1314*5a6e8488SAndroid Build Coastguard Worker 
1315*5a6e8488SAndroid Build Coastguard Worker /**
1316*5a6e8488SAndroid Build Coastguard Worker  * Parse a statement or token that indicates a loop exit. This includes an
1317*5a6e8488SAndroid Build Coastguard Worker  * actual loop exit, the break keyword, or the continue keyword.
1318*5a6e8488SAndroid Build Coastguard Worker  * @param p     The parser.
1319*5a6e8488SAndroid Build Coastguard Worker  * @param type  The type of exit.
1320*5a6e8488SAndroid Build Coastguard Worker  */
1321*5a6e8488SAndroid Build Coastguard Worker static void
bc_parse_loopExit(BcParse * p,BcLexType type)1322*5a6e8488SAndroid Build Coastguard Worker bc_parse_loopExit(BcParse* p, BcLexType type)
1323*5a6e8488SAndroid Build Coastguard Worker {
1324*5a6e8488SAndroid Build Coastguard Worker 	size_t i;
1325*5a6e8488SAndroid Build Coastguard Worker 	BcInstPtr* ip;
1326*5a6e8488SAndroid Build Coastguard Worker 
1327*5a6e8488SAndroid Build Coastguard Worker 	// Must have a loop. If we don't, that's an error.
1328*5a6e8488SAndroid Build Coastguard Worker 	if (BC_ERR(!BC_PARSE_LOOP(p))) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
1329*5a6e8488SAndroid Build Coastguard Worker 
1330*5a6e8488SAndroid Build Coastguard Worker 	// If we have a break statement...
1331*5a6e8488SAndroid Build Coastguard Worker 	if (type == BC_LEX_KW_BREAK)
1332*5a6e8488SAndroid Build Coastguard Worker 	{
1333*5a6e8488SAndroid Build Coastguard Worker 		// If there are no exits, something went wrong somewhere.
1334*5a6e8488SAndroid Build Coastguard Worker 		if (BC_ERR(!p->exits.len)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
1335*5a6e8488SAndroid Build Coastguard Worker 
1336*5a6e8488SAndroid Build Coastguard Worker 		// Get the exit.
1337*5a6e8488SAndroid Build Coastguard Worker 		i = p->exits.len - 1;
1338*5a6e8488SAndroid Build Coastguard Worker 		ip = bc_vec_item(&p->exits, i);
1339*5a6e8488SAndroid Build Coastguard Worker 
1340*5a6e8488SAndroid Build Coastguard Worker 		// The condition !ip->func is true if the exit is not for a loop, so we
1341*5a6e8488SAndroid Build Coastguard Worker 		// need to find the first actual loop exit.
1342*5a6e8488SAndroid Build Coastguard Worker 		while (!ip->func && i < p->exits.len)
1343*5a6e8488SAndroid Build Coastguard Worker 		{
1344*5a6e8488SAndroid Build Coastguard Worker 			ip = bc_vec_item(&p->exits, i);
1345*5a6e8488SAndroid Build Coastguard Worker 			i -= 1;
1346*5a6e8488SAndroid Build Coastguard Worker 		}
1347*5a6e8488SAndroid Build Coastguard Worker 
1348*5a6e8488SAndroid Build Coastguard Worker 		// Make sure everything is hunky dory.
1349*5a6e8488SAndroid Build Coastguard Worker 		assert(ip != NULL && (i < p->exits.len || ip->func));
1350*5a6e8488SAndroid Build Coastguard Worker 
1351*5a6e8488SAndroid Build Coastguard Worker 		// Set the index for the exit.
1352*5a6e8488SAndroid Build Coastguard Worker 		i = ip->idx;
1353*5a6e8488SAndroid Build Coastguard Worker 	}
1354*5a6e8488SAndroid Build Coastguard Worker 	// If we have a continue statement or just the loop end, jump to the
1355*5a6e8488SAndroid Build Coastguard Worker 	// condition (or update for a foor loop).
1356*5a6e8488SAndroid Build Coastguard Worker 	else i = *((size_t*) bc_vec_top(&p->conds));
1357*5a6e8488SAndroid Build Coastguard Worker 
1358*5a6e8488SAndroid Build Coastguard Worker 	// Add the unconditional jump.
1359*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_push(p, BC_INST_JUMP);
1360*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_pushIndex(p, i);
1361*5a6e8488SAndroid Build Coastguard Worker 
1362*5a6e8488SAndroid Build Coastguard Worker 	bc_lex_next(&p->l);
1363*5a6e8488SAndroid Build Coastguard Worker }
1364*5a6e8488SAndroid Build Coastguard Worker 
1365*5a6e8488SAndroid Build Coastguard Worker /**
1366*5a6e8488SAndroid Build Coastguard Worker  * Parse a function (header).
1367*5a6e8488SAndroid Build Coastguard Worker  * @param p  The parser.
1368*5a6e8488SAndroid Build Coastguard Worker  */
1369*5a6e8488SAndroid Build Coastguard Worker static void
bc_parse_func(BcParse * p)1370*5a6e8488SAndroid Build Coastguard Worker bc_parse_func(BcParse* p)
1371*5a6e8488SAndroid Build Coastguard Worker {
1372*5a6e8488SAndroid Build Coastguard Worker 	bool comma = false, voidfn;
1373*5a6e8488SAndroid Build Coastguard Worker 	uint16_t flags;
1374*5a6e8488SAndroid Build Coastguard Worker 	size_t idx;
1375*5a6e8488SAndroid Build Coastguard Worker 
1376*5a6e8488SAndroid Build Coastguard Worker 	bc_lex_next(&p->l);
1377*5a6e8488SAndroid Build Coastguard Worker 
1378*5a6e8488SAndroid Build Coastguard Worker 	// Must have a name.
1379*5a6e8488SAndroid Build Coastguard Worker 	if (BC_ERR(p->l.t != BC_LEX_NAME)) bc_parse_err(p, BC_ERR_PARSE_FUNC);
1380*5a6e8488SAndroid Build Coastguard Worker 
1381*5a6e8488SAndroid Build Coastguard Worker 	// If the name is "void", and POSIX is not on, mark as void.
1382*5a6e8488SAndroid Build Coastguard Worker 	voidfn = (!BC_IS_POSIX && p->l.t == BC_LEX_NAME &&
1383*5a6e8488SAndroid Build Coastguard Worker 	          !strcmp(p->l.str.v, "void"));
1384*5a6e8488SAndroid Build Coastguard Worker 
1385*5a6e8488SAndroid Build Coastguard Worker 	// We can safely do this because the expected token should not overwrite the
1386*5a6e8488SAndroid Build Coastguard Worker 	// function name.
1387*5a6e8488SAndroid Build Coastguard Worker 	bc_lex_next(&p->l);
1388*5a6e8488SAndroid Build Coastguard Worker 
1389*5a6e8488SAndroid Build Coastguard Worker 	// If we *don't* have another name, then void is the name of the function.
1390*5a6e8488SAndroid Build Coastguard Worker 	voidfn = (voidfn && p->l.t == BC_LEX_NAME);
1391*5a6e8488SAndroid Build Coastguard Worker 
1392*5a6e8488SAndroid Build Coastguard Worker 	// With a void function, allow POSIX to complain and get a new token.
1393*5a6e8488SAndroid Build Coastguard Worker 	if (voidfn)
1394*5a6e8488SAndroid Build Coastguard Worker 	{
1395*5a6e8488SAndroid Build Coastguard Worker 		bc_parse_err(p, BC_ERR_POSIX_VOID);
1396*5a6e8488SAndroid Build Coastguard Worker 
1397*5a6e8488SAndroid Build Coastguard Worker 		// We can safely do this because the expected token should not overwrite
1398*5a6e8488SAndroid Build Coastguard Worker 		// the function name.
1399*5a6e8488SAndroid Build Coastguard Worker 		bc_lex_next(&p->l);
1400*5a6e8488SAndroid Build Coastguard Worker 	}
1401*5a6e8488SAndroid Build Coastguard Worker 
1402*5a6e8488SAndroid Build Coastguard Worker 	// Must have a left paren.
1403*5a6e8488SAndroid Build Coastguard Worker 	if (BC_ERR(p->l.t != BC_LEX_LPAREN)) bc_parse_err(p, BC_ERR_PARSE_FUNC);
1404*5a6e8488SAndroid Build Coastguard Worker 
1405*5a6e8488SAndroid Build Coastguard Worker 	// Make sure the functions map and vector are synchronized.
1406*5a6e8488SAndroid Build Coastguard Worker 	assert(p->prog->fns.len == p->prog->fn_map.len);
1407*5a6e8488SAndroid Build Coastguard Worker 
1408*5a6e8488SAndroid Build Coastguard Worker 	// Insert the function by name into the map and vector.
1409*5a6e8488SAndroid Build Coastguard Worker 	idx = bc_program_insertFunc(p->prog, p->l.str.v);
1410*5a6e8488SAndroid Build Coastguard Worker 
1411*5a6e8488SAndroid Build Coastguard Worker 	// Make sure the insert worked.
1412*5a6e8488SAndroid Build Coastguard Worker 	assert(idx);
1413*5a6e8488SAndroid Build Coastguard Worker 
1414*5a6e8488SAndroid Build Coastguard Worker 	// Update the function pointer and stuff in the parser and set its void.
1415*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_updateFunc(p, idx);
1416*5a6e8488SAndroid Build Coastguard Worker 	p->func->voidfn = voidfn;
1417*5a6e8488SAndroid Build Coastguard Worker 
1418*5a6e8488SAndroid Build Coastguard Worker 	bc_lex_next(&p->l);
1419*5a6e8488SAndroid Build Coastguard Worker 
1420*5a6e8488SAndroid Build Coastguard Worker 	// While we do not have a right paren, we are still parsing arguments.
1421*5a6e8488SAndroid Build Coastguard Worker 	while (p->l.t != BC_LEX_RPAREN)
1422*5a6e8488SAndroid Build Coastguard Worker 	{
1423*5a6e8488SAndroid Build Coastguard Worker 		BcType t = BC_TYPE_VAR;
1424*5a6e8488SAndroid Build Coastguard Worker 
1425*5a6e8488SAndroid Build Coastguard Worker 		// If we have an asterisk, we are parsing a reference argument.
1426*5a6e8488SAndroid Build Coastguard Worker 		if (p->l.t == BC_LEX_OP_MULTIPLY)
1427*5a6e8488SAndroid Build Coastguard Worker 		{
1428*5a6e8488SAndroid Build Coastguard Worker 			t = BC_TYPE_REF;
1429*5a6e8488SAndroid Build Coastguard Worker 			bc_lex_next(&p->l);
1430*5a6e8488SAndroid Build Coastguard Worker 
1431*5a6e8488SAndroid Build Coastguard Worker 			// Let POSIX complain if necessary.
1432*5a6e8488SAndroid Build Coastguard Worker 			bc_parse_err(p, BC_ERR_POSIX_REF);
1433*5a6e8488SAndroid Build Coastguard Worker 		}
1434*5a6e8488SAndroid Build Coastguard Worker 
1435*5a6e8488SAndroid Build Coastguard Worker 		// If we don't have a name, the argument will not have a name. Barf.
1436*5a6e8488SAndroid Build Coastguard Worker 		if (BC_ERR(p->l.t != BC_LEX_NAME)) bc_parse_err(p, BC_ERR_PARSE_FUNC);
1437*5a6e8488SAndroid Build Coastguard Worker 
1438*5a6e8488SAndroid Build Coastguard Worker 		// Increment the number of parameters.
1439*5a6e8488SAndroid Build Coastguard Worker 		p->func->nparams += 1;
1440*5a6e8488SAndroid Build Coastguard Worker 
1441*5a6e8488SAndroid Build Coastguard Worker 		// Copy the string in the lexer so that we can use the lexer again.
1442*5a6e8488SAndroid Build Coastguard Worker 		bc_vec_string(&p->buf, p->l.str.len, p->l.str.v);
1443*5a6e8488SAndroid Build Coastguard Worker 
1444*5a6e8488SAndroid Build Coastguard Worker 		bc_lex_next(&p->l);
1445*5a6e8488SAndroid Build Coastguard Worker 
1446*5a6e8488SAndroid Build Coastguard Worker 		// We are parsing an array parameter if this is true.
1447*5a6e8488SAndroid Build Coastguard Worker 		if (p->l.t == BC_LEX_LBRACKET)
1448*5a6e8488SAndroid Build Coastguard Worker 		{
1449*5a6e8488SAndroid Build Coastguard Worker 			// Set the array type, unless we are already parsing a reference.
1450*5a6e8488SAndroid Build Coastguard Worker 			if (t == BC_TYPE_VAR) t = BC_TYPE_ARRAY;
1451*5a6e8488SAndroid Build Coastguard Worker 
1452*5a6e8488SAndroid Build Coastguard Worker 			bc_lex_next(&p->l);
1453*5a6e8488SAndroid Build Coastguard Worker 
1454*5a6e8488SAndroid Build Coastguard Worker 			// The brackets *must* be empty.
1455*5a6e8488SAndroid Build Coastguard Worker 			if (BC_ERR(p->l.t != BC_LEX_RBRACKET))
1456*5a6e8488SAndroid Build Coastguard Worker 			{
1457*5a6e8488SAndroid Build Coastguard Worker 				bc_parse_err(p, BC_ERR_PARSE_FUNC);
1458*5a6e8488SAndroid Build Coastguard Worker 			}
1459*5a6e8488SAndroid Build Coastguard Worker 
1460*5a6e8488SAndroid Build Coastguard Worker 			bc_lex_next(&p->l);
1461*5a6e8488SAndroid Build Coastguard Worker 		}
1462*5a6e8488SAndroid Build Coastguard Worker 		// If we did *not* get a bracket, but we are expecting a reference, we
1463*5a6e8488SAndroid Build Coastguard Worker 		// have a problem.
1464*5a6e8488SAndroid Build Coastguard Worker 		else if (BC_ERR(t == BC_TYPE_REF))
1465*5a6e8488SAndroid Build Coastguard Worker 		{
1466*5a6e8488SAndroid Build Coastguard Worker 			bc_parse_verr(p, BC_ERR_PARSE_REF_VAR, p->buf.v);
1467*5a6e8488SAndroid Build Coastguard Worker 		}
1468*5a6e8488SAndroid Build Coastguard Worker 
1469*5a6e8488SAndroid Build Coastguard Worker 		// Test for comma and get the next token if it exists.
1470*5a6e8488SAndroid Build Coastguard Worker 		comma = (p->l.t == BC_LEX_COMMA);
1471*5a6e8488SAndroid Build Coastguard Worker 		if (comma) bc_lex_next(&p->l);
1472*5a6e8488SAndroid Build Coastguard Worker 
1473*5a6e8488SAndroid Build Coastguard Worker 		// Insert the parameter into the function.
1474*5a6e8488SAndroid Build Coastguard Worker 		bc_func_insert(p->func, p->prog, p->buf.v, t, p->l.line);
1475*5a6e8488SAndroid Build Coastguard Worker 	}
1476*5a6e8488SAndroid Build Coastguard Worker 
1477*5a6e8488SAndroid Build Coastguard Worker 	// If we have a comma, but no parameter, barf.
1478*5a6e8488SAndroid Build Coastguard Worker 	if (BC_ERR(comma)) bc_parse_err(p, BC_ERR_PARSE_FUNC);
1479*5a6e8488SAndroid Build Coastguard Worker 
1480*5a6e8488SAndroid Build Coastguard Worker 	// Start the body.
1481*5a6e8488SAndroid Build Coastguard Worker 	flags = BC_PARSE_FLAG_FUNC | BC_PARSE_FLAG_FUNC_INNER;
1482*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_startBody(p, flags);
1483*5a6e8488SAndroid Build Coastguard Worker 
1484*5a6e8488SAndroid Build Coastguard Worker 	bc_lex_next(&p->l);
1485*5a6e8488SAndroid Build Coastguard Worker 
1486*5a6e8488SAndroid Build Coastguard Worker 	// POSIX requires that a brace be on the same line as the function header.
1487*5a6e8488SAndroid Build Coastguard Worker 	// If we don't have a brace, let POSIX throw an error.
1488*5a6e8488SAndroid Build Coastguard Worker 	if (p->l.t != BC_LEX_LBRACE) bc_parse_err(p, BC_ERR_POSIX_BRACE);
1489*5a6e8488SAndroid Build Coastguard Worker }
1490*5a6e8488SAndroid Build Coastguard Worker 
1491*5a6e8488SAndroid Build Coastguard Worker /**
1492*5a6e8488SAndroid Build Coastguard Worker  * Parse an auto list.
1493*5a6e8488SAndroid Build Coastguard Worker  * @param p  The parser.
1494*5a6e8488SAndroid Build Coastguard Worker  */
1495*5a6e8488SAndroid Build Coastguard Worker static void
bc_parse_auto(BcParse * p)1496*5a6e8488SAndroid Build Coastguard Worker bc_parse_auto(BcParse* p)
1497*5a6e8488SAndroid Build Coastguard Worker {
1498*5a6e8488SAndroid Build Coastguard Worker 	bool comma, one;
1499*5a6e8488SAndroid Build Coastguard Worker 
1500*5a6e8488SAndroid Build Coastguard Worker 	// Error if the auto keyword appeared in the wrong place.
1501*5a6e8488SAndroid Build Coastguard Worker 	if (BC_ERR(!p->auto_part)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
1502*5a6e8488SAndroid Build Coastguard Worker 	bc_lex_next(&p->l);
1503*5a6e8488SAndroid Build Coastguard Worker 
1504*5a6e8488SAndroid Build Coastguard Worker 	p->auto_part = comma = false;
1505*5a6e8488SAndroid Build Coastguard Worker 
1506*5a6e8488SAndroid Build Coastguard Worker 	// We need at least one variable or array.
1507*5a6e8488SAndroid Build Coastguard Worker 	one = (p->l.t == BC_LEX_NAME);
1508*5a6e8488SAndroid Build Coastguard Worker 
1509*5a6e8488SAndroid Build Coastguard Worker 	// While we have a variable or array.
1510*5a6e8488SAndroid Build Coastguard Worker 	while (p->l.t == BC_LEX_NAME)
1511*5a6e8488SAndroid Build Coastguard Worker 	{
1512*5a6e8488SAndroid Build Coastguard Worker 		BcType t;
1513*5a6e8488SAndroid Build Coastguard Worker 
1514*5a6e8488SAndroid Build Coastguard Worker 		// Copy the name from the lexer, so we can use it again.
1515*5a6e8488SAndroid Build Coastguard Worker 		bc_vec_string(&p->buf, p->l.str.len - 1, p->l.str.v);
1516*5a6e8488SAndroid Build Coastguard Worker 
1517*5a6e8488SAndroid Build Coastguard Worker 		bc_lex_next(&p->l);
1518*5a6e8488SAndroid Build Coastguard Worker 
1519*5a6e8488SAndroid Build Coastguard Worker 		// If we are parsing an array...
1520*5a6e8488SAndroid Build Coastguard Worker 		if (p->l.t == BC_LEX_LBRACKET)
1521*5a6e8488SAndroid Build Coastguard Worker 		{
1522*5a6e8488SAndroid Build Coastguard Worker 			t = BC_TYPE_ARRAY;
1523*5a6e8488SAndroid Build Coastguard Worker 
1524*5a6e8488SAndroid Build Coastguard Worker 			bc_lex_next(&p->l);
1525*5a6e8488SAndroid Build Coastguard Worker 
1526*5a6e8488SAndroid Build Coastguard Worker 			// The brackets *must* be empty.
1527*5a6e8488SAndroid Build Coastguard Worker 			if (BC_ERR(p->l.t != BC_LEX_RBRACKET))
1528*5a6e8488SAndroid Build Coastguard Worker 			{
1529*5a6e8488SAndroid Build Coastguard Worker 				bc_parse_err(p, BC_ERR_PARSE_FUNC);
1530*5a6e8488SAndroid Build Coastguard Worker 			}
1531*5a6e8488SAndroid Build Coastguard Worker 
1532*5a6e8488SAndroid Build Coastguard Worker 			bc_lex_next(&p->l);
1533*5a6e8488SAndroid Build Coastguard Worker 		}
1534*5a6e8488SAndroid Build Coastguard Worker 		else t = BC_TYPE_VAR;
1535*5a6e8488SAndroid Build Coastguard Worker 
1536*5a6e8488SAndroid Build Coastguard Worker 		// Test for comma and get the next token if it exists.
1537*5a6e8488SAndroid Build Coastguard Worker 		comma = (p->l.t == BC_LEX_COMMA);
1538*5a6e8488SAndroid Build Coastguard Worker 		if (comma) bc_lex_next(&p->l);
1539*5a6e8488SAndroid Build Coastguard Worker 
1540*5a6e8488SAndroid Build Coastguard Worker 		// Insert the auto into the function.
1541*5a6e8488SAndroid Build Coastguard Worker 		bc_func_insert(p->func, p->prog, p->buf.v, t, p->l.line);
1542*5a6e8488SAndroid Build Coastguard Worker 	}
1543*5a6e8488SAndroid Build Coastguard Worker 
1544*5a6e8488SAndroid Build Coastguard Worker 	// If we have a comma, but no auto, barf.
1545*5a6e8488SAndroid Build Coastguard Worker 	if (BC_ERR(comma)) bc_parse_err(p, BC_ERR_PARSE_FUNC);
1546*5a6e8488SAndroid Build Coastguard Worker 
1547*5a6e8488SAndroid Build Coastguard Worker 	// If we don't have any variables or arrays, barf.
1548*5a6e8488SAndroid Build Coastguard Worker 	if (BC_ERR(!one)) bc_parse_err(p, BC_ERR_PARSE_NO_AUTO);
1549*5a6e8488SAndroid Build Coastguard Worker 
1550*5a6e8488SAndroid Build Coastguard Worker 	// The auto statement should be all that's in the statement.
1551*5a6e8488SAndroid Build Coastguard Worker 	if (BC_ERR(!bc_parse_isDelimiter(p))) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
1552*5a6e8488SAndroid Build Coastguard Worker }
1553*5a6e8488SAndroid Build Coastguard Worker 
1554*5a6e8488SAndroid Build Coastguard Worker /**
1555*5a6e8488SAndroid Build Coastguard Worker  * Parses a body.
1556*5a6e8488SAndroid Build Coastguard Worker  * @param p      The parser.
1557*5a6e8488SAndroid Build Coastguard Worker  * @param brace  True if a brace was encountered, false otherwise.
1558*5a6e8488SAndroid Build Coastguard Worker  */
1559*5a6e8488SAndroid Build Coastguard Worker static void
bc_parse_body(BcParse * p,bool brace)1560*5a6e8488SAndroid Build Coastguard Worker bc_parse_body(BcParse* p, bool brace)
1561*5a6e8488SAndroid Build Coastguard Worker {
1562*5a6e8488SAndroid Build Coastguard Worker 	uint16_t* flag_ptr = BC_PARSE_TOP_FLAG_PTR(p);
1563*5a6e8488SAndroid Build Coastguard Worker 
1564*5a6e8488SAndroid Build Coastguard Worker 	assert(flag_ptr != NULL);
1565*5a6e8488SAndroid Build Coastguard Worker 	assert(p->flags.len >= 2);
1566*5a6e8488SAndroid Build Coastguard Worker 
1567*5a6e8488SAndroid Build Coastguard Worker 	// The body flag is for when we expect a body. We got a body, so clear the
1568*5a6e8488SAndroid Build Coastguard Worker 	// flag.
1569*5a6e8488SAndroid Build Coastguard Worker 	*flag_ptr &= ~(BC_PARSE_FLAG_BODY);
1570*5a6e8488SAndroid Build Coastguard Worker 
1571*5a6e8488SAndroid Build Coastguard Worker 	// If we are inside a function, that means we just barely entered it, and
1572*5a6e8488SAndroid Build Coastguard Worker 	// we can expect an auto list.
1573*5a6e8488SAndroid Build Coastguard Worker 	if (*flag_ptr & BC_PARSE_FLAG_FUNC_INNER)
1574*5a6e8488SAndroid Build Coastguard Worker 	{
1575*5a6e8488SAndroid Build Coastguard Worker 		// We *must* have a brace in this case.
1576*5a6e8488SAndroid Build Coastguard Worker 		if (BC_ERR(!brace)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
1577*5a6e8488SAndroid Build Coastguard Worker 
1578*5a6e8488SAndroid Build Coastguard Worker 		p->auto_part = (p->l.t != BC_LEX_KW_AUTO);
1579*5a6e8488SAndroid Build Coastguard Worker 
1580*5a6e8488SAndroid Build Coastguard Worker 		if (!p->auto_part)
1581*5a6e8488SAndroid Build Coastguard Worker 		{
1582*5a6e8488SAndroid Build Coastguard Worker 			// Make sure this is true to not get a parse error.
1583*5a6e8488SAndroid Build Coastguard Worker 			p->auto_part = true;
1584*5a6e8488SAndroid Build Coastguard Worker 
1585*5a6e8488SAndroid Build Coastguard Worker 			// Since we already have the auto keyword, parse.
1586*5a6e8488SAndroid Build Coastguard Worker 			bc_parse_auto(p);
1587*5a6e8488SAndroid Build Coastguard Worker 		}
1588*5a6e8488SAndroid Build Coastguard Worker 
1589*5a6e8488SAndroid Build Coastguard Worker 		// Eat a newline.
1590*5a6e8488SAndroid Build Coastguard Worker 		if (p->l.t == BC_LEX_NLINE) bc_lex_next(&p->l);
1591*5a6e8488SAndroid Build Coastguard Worker 	}
1592*5a6e8488SAndroid Build Coastguard Worker 	else
1593*5a6e8488SAndroid Build Coastguard Worker 	{
1594*5a6e8488SAndroid Build Coastguard Worker 		// This is the easy part.
1595*5a6e8488SAndroid Build Coastguard Worker 		size_t len = p->flags.len;
1596*5a6e8488SAndroid Build Coastguard Worker 
1597*5a6e8488SAndroid Build Coastguard Worker 		assert(*flag_ptr);
1598*5a6e8488SAndroid Build Coastguard Worker 
1599*5a6e8488SAndroid Build Coastguard Worker 		// Parse a statement.
1600*5a6e8488SAndroid Build Coastguard Worker 		bc_parse_stmt(p);
1601*5a6e8488SAndroid Build Coastguard Worker 
1602*5a6e8488SAndroid Build Coastguard Worker 		// This is a very important condition to get right. If there is no
1603*5a6e8488SAndroid Build Coastguard Worker 		// brace, and no body flag, and the flags len hasn't shrunk, then we
1604*5a6e8488SAndroid Build Coastguard Worker 		// have a body that was not delimited by braces, so we need to end it
1605*5a6e8488SAndroid Build Coastguard Worker 		// now, after just one statement.
1606*5a6e8488SAndroid Build Coastguard Worker 		if (!brace && !BC_PARSE_BODY(p) && len <= p->flags.len)
1607*5a6e8488SAndroid Build Coastguard Worker 		{
1608*5a6e8488SAndroid Build Coastguard Worker 			bc_parse_endBody(p, false);
1609*5a6e8488SAndroid Build Coastguard Worker 		}
1610*5a6e8488SAndroid Build Coastguard Worker 	}
1611*5a6e8488SAndroid Build Coastguard Worker }
1612*5a6e8488SAndroid Build Coastguard Worker 
1613*5a6e8488SAndroid Build Coastguard Worker /**
1614*5a6e8488SAndroid Build Coastguard Worker  * Parses a statement. This is the entry point for just about everything, except
1615*5a6e8488SAndroid Build Coastguard Worker  * function definitions.
1616*5a6e8488SAndroid Build Coastguard Worker  * @param p  The parser.
1617*5a6e8488SAndroid Build Coastguard Worker  */
1618*5a6e8488SAndroid Build Coastguard Worker static void
bc_parse_stmt(BcParse * p)1619*5a6e8488SAndroid Build Coastguard Worker bc_parse_stmt(BcParse* p)
1620*5a6e8488SAndroid Build Coastguard Worker {
1621*5a6e8488SAndroid Build Coastguard Worker 	size_t len;
1622*5a6e8488SAndroid Build Coastguard Worker 	uint16_t flags;
1623*5a6e8488SAndroid Build Coastguard Worker 	BcLexType type = p->l.t;
1624*5a6e8488SAndroid Build Coastguard Worker 
1625*5a6e8488SAndroid Build Coastguard Worker 	// Eat newline.
1626*5a6e8488SAndroid Build Coastguard Worker 	if (type == BC_LEX_NLINE)
1627*5a6e8488SAndroid Build Coastguard Worker 	{
1628*5a6e8488SAndroid Build Coastguard Worker 		bc_lex_next(&p->l);
1629*5a6e8488SAndroid Build Coastguard Worker 		return;
1630*5a6e8488SAndroid Build Coastguard Worker 	}
1631*5a6e8488SAndroid Build Coastguard Worker 
1632*5a6e8488SAndroid Build Coastguard Worker 	// Eat auto list.
1633*5a6e8488SAndroid Build Coastguard Worker 	if (type == BC_LEX_KW_AUTO)
1634*5a6e8488SAndroid Build Coastguard Worker 	{
1635*5a6e8488SAndroid Build Coastguard Worker 		bc_parse_auto(p);
1636*5a6e8488SAndroid Build Coastguard Worker 		return;
1637*5a6e8488SAndroid Build Coastguard Worker 	}
1638*5a6e8488SAndroid Build Coastguard Worker 
1639*5a6e8488SAndroid Build Coastguard Worker 	// If we reach this point, no auto list is allowed.
1640*5a6e8488SAndroid Build Coastguard Worker 	p->auto_part = false;
1641*5a6e8488SAndroid Build Coastguard Worker 
1642*5a6e8488SAndroid Build Coastguard Worker 	// Everything but an else needs to be taken care of here, but else is
1643*5a6e8488SAndroid Build Coastguard Worker 	// special.
1644*5a6e8488SAndroid Build Coastguard Worker 	if (type != BC_LEX_KW_ELSE)
1645*5a6e8488SAndroid Build Coastguard Worker 	{
1646*5a6e8488SAndroid Build Coastguard Worker 		// After an if, no else found.
1647*5a6e8488SAndroid Build Coastguard Worker 		if (BC_PARSE_IF_END(p))
1648*5a6e8488SAndroid Build Coastguard Worker 		{
1649*5a6e8488SAndroid Build Coastguard Worker 			// Clear the expectation for else, end body, and return. Returning
1650*5a6e8488SAndroid Build Coastguard Worker 			// gives us a clean slate for parsing again.
1651*5a6e8488SAndroid Build Coastguard Worker 			bc_parse_noElse(p);
1652*5a6e8488SAndroid Build Coastguard Worker 			if (p->flags.len > 1 && !BC_PARSE_BRACE(p))
1653*5a6e8488SAndroid Build Coastguard Worker 			{
1654*5a6e8488SAndroid Build Coastguard Worker 				bc_parse_endBody(p, false);
1655*5a6e8488SAndroid Build Coastguard Worker 			}
1656*5a6e8488SAndroid Build Coastguard Worker 
1657*5a6e8488SAndroid Build Coastguard Worker 			return;
1658*5a6e8488SAndroid Build Coastguard Worker 		}
1659*5a6e8488SAndroid Build Coastguard Worker 		// With a left brace, we are parsing a body.
1660*5a6e8488SAndroid Build Coastguard Worker 		else if (type == BC_LEX_LBRACE)
1661*5a6e8488SAndroid Build Coastguard Worker 		{
1662*5a6e8488SAndroid Build Coastguard Worker 			// We need to start a body if we are not expecting one yet.
1663*5a6e8488SAndroid Build Coastguard Worker 			if (!BC_PARSE_BODY(p))
1664*5a6e8488SAndroid Build Coastguard Worker 			{
1665*5a6e8488SAndroid Build Coastguard Worker 				bc_parse_startBody(p, BC_PARSE_FLAG_BRACE);
1666*5a6e8488SAndroid Build Coastguard Worker 				bc_lex_next(&p->l);
1667*5a6e8488SAndroid Build Coastguard Worker 			}
1668*5a6e8488SAndroid Build Coastguard Worker 			// If we *are* expecting a body, that body should get a brace. This
1669*5a6e8488SAndroid Build Coastguard Worker 			// takes care of braces being on a different line than if and loop
1670*5a6e8488SAndroid Build Coastguard Worker 			// headers.
1671*5a6e8488SAndroid Build Coastguard Worker 			else
1672*5a6e8488SAndroid Build Coastguard Worker 			{
1673*5a6e8488SAndroid Build Coastguard Worker 				*(BC_PARSE_TOP_FLAG_PTR(p)) |= BC_PARSE_FLAG_BRACE;
1674*5a6e8488SAndroid Build Coastguard Worker 				bc_lex_next(&p->l);
1675*5a6e8488SAndroid Build Coastguard Worker 				bc_parse_body(p, true);
1676*5a6e8488SAndroid Build Coastguard Worker 			}
1677*5a6e8488SAndroid Build Coastguard Worker 
1678*5a6e8488SAndroid Build Coastguard Worker 			// If we have reached this point, we need to return for a clean
1679*5a6e8488SAndroid Build Coastguard Worker 			// slate.
1680*5a6e8488SAndroid Build Coastguard Worker 			return;
1681*5a6e8488SAndroid Build Coastguard Worker 		}
1682*5a6e8488SAndroid Build Coastguard Worker 		// This happens when we are expecting a body and get a single statement,
1683*5a6e8488SAndroid Build Coastguard Worker 		// i.e., a body with no braces surrounding it. Returns after for a clean
1684*5a6e8488SAndroid Build Coastguard Worker 		// slate.
1685*5a6e8488SAndroid Build Coastguard Worker 		else if (BC_PARSE_BODY(p) && !BC_PARSE_BRACE(p))
1686*5a6e8488SAndroid Build Coastguard Worker 		{
1687*5a6e8488SAndroid Build Coastguard Worker 			bc_parse_body(p, false);
1688*5a6e8488SAndroid Build Coastguard Worker 			return;
1689*5a6e8488SAndroid Build Coastguard Worker 		}
1690*5a6e8488SAndroid Build Coastguard Worker 	}
1691*5a6e8488SAndroid Build Coastguard Worker 
1692*5a6e8488SAndroid Build Coastguard Worker 	len = p->flags.len;
1693*5a6e8488SAndroid Build Coastguard Worker 	flags = BC_PARSE_TOP_FLAG(p);
1694*5a6e8488SAndroid Build Coastguard Worker 
1695*5a6e8488SAndroid Build Coastguard Worker 	switch (type)
1696*5a6e8488SAndroid Build Coastguard Worker 	{
1697*5a6e8488SAndroid Build Coastguard Worker 		// All of these are valid for expressions.
1698*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_OP_INC:
1699*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_OP_DEC:
1700*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_OP_MINUS:
1701*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_OP_BOOL_NOT:
1702*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_LPAREN:
1703*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_NAME:
1704*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_NUMBER:
1705*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_KW_IBASE:
1706*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_KW_LAST:
1707*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_KW_LENGTH:
1708*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_KW_OBASE:
1709*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_KW_SCALE:
1710*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_EXTRA_MATH
1711*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_KW_SEED:
1712*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_EXTRA_MATH
1713*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_KW_SQRT:
1714*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_KW_ABS:
1715*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_KW_IS_NUMBER:
1716*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_KW_IS_STRING:
1717*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_EXTRA_MATH
1718*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_KW_IRAND:
1719*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_EXTRA_MATH
1720*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_KW_ASCIIFY:
1721*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_KW_MODEXP:
1722*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_KW_DIVMOD:
1723*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_KW_READ:
1724*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_EXTRA_MATH
1725*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_KW_RAND:
1726*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_EXTRA_MATH
1727*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_KW_MAXIBASE:
1728*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_KW_MAXOBASE:
1729*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_KW_MAXSCALE:
1730*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_EXTRA_MATH
1731*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_KW_MAXRAND:
1732*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_EXTRA_MATH
1733*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_KW_LINE_LENGTH:
1734*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_KW_GLOBAL_STACKS:
1735*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_KW_LEADING_ZERO:
1736*5a6e8488SAndroid Build Coastguard Worker 		{
1737*5a6e8488SAndroid Build Coastguard Worker 			bc_parse_expr_status(p, BC_PARSE_PRINT, bc_parse_next_expr);
1738*5a6e8488SAndroid Build Coastguard Worker 			break;
1739*5a6e8488SAndroid Build Coastguard Worker 		}
1740*5a6e8488SAndroid Build Coastguard Worker 
1741*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_KW_ELSE:
1742*5a6e8488SAndroid Build Coastguard Worker 		{
1743*5a6e8488SAndroid Build Coastguard Worker 			bc_parse_else(p);
1744*5a6e8488SAndroid Build Coastguard Worker 			break;
1745*5a6e8488SAndroid Build Coastguard Worker 		}
1746*5a6e8488SAndroid Build Coastguard Worker 
1747*5a6e8488SAndroid Build Coastguard Worker 		// Just eat.
1748*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_SCOLON:
1749*5a6e8488SAndroid Build Coastguard Worker 		{
1750*5a6e8488SAndroid Build Coastguard Worker 			// Do nothing.
1751*5a6e8488SAndroid Build Coastguard Worker 			break;
1752*5a6e8488SAndroid Build Coastguard Worker 		}
1753*5a6e8488SAndroid Build Coastguard Worker 
1754*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_RBRACE:
1755*5a6e8488SAndroid Build Coastguard Worker 		{
1756*5a6e8488SAndroid Build Coastguard Worker 			bc_parse_endBody(p, true);
1757*5a6e8488SAndroid Build Coastguard Worker 			break;
1758*5a6e8488SAndroid Build Coastguard Worker 		}
1759*5a6e8488SAndroid Build Coastguard Worker 
1760*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_STR:
1761*5a6e8488SAndroid Build Coastguard Worker 		{
1762*5a6e8488SAndroid Build Coastguard Worker 			bc_parse_str(p, BC_INST_PRINT_STR);
1763*5a6e8488SAndroid Build Coastguard Worker 			break;
1764*5a6e8488SAndroid Build Coastguard Worker 		}
1765*5a6e8488SAndroid Build Coastguard Worker 
1766*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_KW_BREAK:
1767*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_KW_CONTINUE:
1768*5a6e8488SAndroid Build Coastguard Worker 		{
1769*5a6e8488SAndroid Build Coastguard Worker 			bc_parse_loopExit(p, p->l.t);
1770*5a6e8488SAndroid Build Coastguard Worker 			break;
1771*5a6e8488SAndroid Build Coastguard Worker 		}
1772*5a6e8488SAndroid Build Coastguard Worker 
1773*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_KW_FOR:
1774*5a6e8488SAndroid Build Coastguard Worker 		{
1775*5a6e8488SAndroid Build Coastguard Worker 			bc_parse_for(p);
1776*5a6e8488SAndroid Build Coastguard Worker 			break;
1777*5a6e8488SAndroid Build Coastguard Worker 		}
1778*5a6e8488SAndroid Build Coastguard Worker 
1779*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_KW_HALT:
1780*5a6e8488SAndroid Build Coastguard Worker 		{
1781*5a6e8488SAndroid Build Coastguard Worker 			bc_parse_push(p, BC_INST_HALT);
1782*5a6e8488SAndroid Build Coastguard Worker 			bc_lex_next(&p->l);
1783*5a6e8488SAndroid Build Coastguard Worker 			break;
1784*5a6e8488SAndroid Build Coastguard Worker 		}
1785*5a6e8488SAndroid Build Coastguard Worker 
1786*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_KW_IF:
1787*5a6e8488SAndroid Build Coastguard Worker 		{
1788*5a6e8488SAndroid Build Coastguard Worker 			bc_parse_if(p);
1789*5a6e8488SAndroid Build Coastguard Worker 			break;
1790*5a6e8488SAndroid Build Coastguard Worker 		}
1791*5a6e8488SAndroid Build Coastguard Worker 
1792*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_KW_LIMITS:
1793*5a6e8488SAndroid Build Coastguard Worker 		{
1794*5a6e8488SAndroid Build Coastguard Worker 			// `limits` is a compile-time command, so execute it right away.
1795*5a6e8488SAndroid Build Coastguard Worker 			bc_vm_printf("BC_LONG_BIT      = %lu\n", (ulong) BC_LONG_BIT);
1796*5a6e8488SAndroid Build Coastguard Worker 			bc_vm_printf("BC_BASE_DIGS     = %lu\n", (ulong) BC_BASE_DIGS);
1797*5a6e8488SAndroid Build Coastguard Worker 			bc_vm_printf("BC_BASE_POW      = %lu\n", (ulong) BC_BASE_POW);
1798*5a6e8488SAndroid Build Coastguard Worker 			bc_vm_printf("BC_OVERFLOW_MAX  = %lu\n", (ulong) BC_NUM_BIGDIG_MAX);
1799*5a6e8488SAndroid Build Coastguard Worker 			bc_vm_printf("\n");
1800*5a6e8488SAndroid Build Coastguard Worker 			bc_vm_printf("BC_BASE_MAX      = %lu\n", BC_MAX_OBASE);
1801*5a6e8488SAndroid Build Coastguard Worker 			bc_vm_printf("BC_DIM_MAX       = %lu\n", BC_MAX_DIM);
1802*5a6e8488SAndroid Build Coastguard Worker 			bc_vm_printf("BC_SCALE_MAX     = %lu\n", BC_MAX_SCALE);
1803*5a6e8488SAndroid Build Coastguard Worker 			bc_vm_printf("BC_STRING_MAX    = %lu\n", BC_MAX_STRING);
1804*5a6e8488SAndroid Build Coastguard Worker 			bc_vm_printf("BC_NAME_MAX      = %lu\n", BC_MAX_NAME);
1805*5a6e8488SAndroid Build Coastguard Worker 			bc_vm_printf("BC_NUM_MAX       = %lu\n", BC_MAX_NUM);
1806*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_EXTRA_MATH
1807*5a6e8488SAndroid Build Coastguard Worker 			bc_vm_printf("BC_RAND_MAX      = %lu\n", BC_MAX_RAND);
1808*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_EXTRA_MATH
1809*5a6e8488SAndroid Build Coastguard Worker 			bc_vm_printf("MAX Exponent     = %lu\n", BC_MAX_EXP);
1810*5a6e8488SAndroid Build Coastguard Worker 			bc_vm_printf("Number of vars   = %lu\n", BC_MAX_VARS);
1811*5a6e8488SAndroid Build Coastguard Worker 
1812*5a6e8488SAndroid Build Coastguard Worker 			bc_lex_next(&p->l);
1813*5a6e8488SAndroid Build Coastguard Worker 
1814*5a6e8488SAndroid Build Coastguard Worker 			break;
1815*5a6e8488SAndroid Build Coastguard Worker 		}
1816*5a6e8488SAndroid Build Coastguard Worker 
1817*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_KW_STREAM:
1818*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_KW_PRINT:
1819*5a6e8488SAndroid Build Coastguard Worker 		{
1820*5a6e8488SAndroid Build Coastguard Worker 			bc_parse_print(p, type);
1821*5a6e8488SAndroid Build Coastguard Worker 			break;
1822*5a6e8488SAndroid Build Coastguard Worker 		}
1823*5a6e8488SAndroid Build Coastguard Worker 
1824*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_KW_QUIT:
1825*5a6e8488SAndroid Build Coastguard Worker 		{
1826*5a6e8488SAndroid Build Coastguard Worker 			// Quit is a compile-time command. We don't exit directly, so the vm
1827*5a6e8488SAndroid Build Coastguard Worker 			// can clean up.
1828*5a6e8488SAndroid Build Coastguard Worker 			vm->status = BC_STATUS_QUIT;
1829*5a6e8488SAndroid Build Coastguard Worker 			BC_JMP;
1830*5a6e8488SAndroid Build Coastguard Worker 			break;
1831*5a6e8488SAndroid Build Coastguard Worker 		}
1832*5a6e8488SAndroid Build Coastguard Worker 
1833*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_KW_RETURN:
1834*5a6e8488SAndroid Build Coastguard Worker 		{
1835*5a6e8488SAndroid Build Coastguard Worker 			bc_parse_return(p);
1836*5a6e8488SAndroid Build Coastguard Worker 			break;
1837*5a6e8488SAndroid Build Coastguard Worker 		}
1838*5a6e8488SAndroid Build Coastguard Worker 
1839*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_KW_WHILE:
1840*5a6e8488SAndroid Build Coastguard Worker 		{
1841*5a6e8488SAndroid Build Coastguard Worker 			bc_parse_while(p);
1842*5a6e8488SAndroid Build Coastguard Worker 			break;
1843*5a6e8488SAndroid Build Coastguard Worker 		}
1844*5a6e8488SAndroid Build Coastguard Worker 
1845*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_EOF:
1846*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_INVALID:
1847*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_NEG:
1848*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_EXTRA_MATH
1849*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_OP_TRUNC:
1850*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_EXTRA_MATH
1851*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_OP_POWER:
1852*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_OP_MULTIPLY:
1853*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_OP_DIVIDE:
1854*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_OP_MODULUS:
1855*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_OP_PLUS:
1856*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_EXTRA_MATH
1857*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_OP_PLACES:
1858*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_OP_LSHIFT:
1859*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_OP_RSHIFT:
1860*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_EXTRA_MATH
1861*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_OP_REL_EQ:
1862*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_OP_REL_LE:
1863*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_OP_REL_GE:
1864*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_OP_REL_NE:
1865*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_OP_REL_LT:
1866*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_OP_REL_GT:
1867*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_OP_BOOL_OR:
1868*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_OP_BOOL_AND:
1869*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_OP_ASSIGN_POWER:
1870*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_OP_ASSIGN_MULTIPLY:
1871*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_OP_ASSIGN_DIVIDE:
1872*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_OP_ASSIGN_MODULUS:
1873*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_OP_ASSIGN_PLUS:
1874*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_OP_ASSIGN_MINUS:
1875*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_EXTRA_MATH
1876*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_OP_ASSIGN_PLACES:
1877*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_OP_ASSIGN_LSHIFT:
1878*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_OP_ASSIGN_RSHIFT:
1879*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_EXTRA_MATH
1880*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_OP_ASSIGN:
1881*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_NLINE:
1882*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_WHITESPACE:
1883*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_RPAREN:
1884*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_LBRACKET:
1885*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_COMMA:
1886*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_RBRACKET:
1887*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_LBRACE:
1888*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_KW_AUTO:
1889*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_KW_DEFINE:
1890*5a6e8488SAndroid Build Coastguard Worker #if DC_ENABLED
1891*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_EXTENDED_REGISTERS:
1892*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_EQ_NO_REG:
1893*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_COLON:
1894*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_EXECUTE:
1895*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_PRINT_STACK:
1896*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_CLEAR_STACK:
1897*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_REG_STACK_LEVEL:
1898*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_STACK_LEVEL:
1899*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_DUPLICATE:
1900*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_SWAP:
1901*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_POP:
1902*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_STORE_IBASE:
1903*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_STORE_OBASE:
1904*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_STORE_SCALE:
1905*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_EXTRA_MATH
1906*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_STORE_SEED:
1907*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_EXTRA_MATH
1908*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_LOAD:
1909*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_LOAD_POP:
1910*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_STORE_PUSH:
1911*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_PRINT_POP:
1912*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_NQUIT:
1913*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_EXEC_STACK_LENGTH:
1914*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_SCALE_FACTOR:
1915*5a6e8488SAndroid Build Coastguard Worker 		case BC_LEX_ARRAY_LENGTH:
1916*5a6e8488SAndroid Build Coastguard Worker #endif // DC_ENABLED
1917*5a6e8488SAndroid Build Coastguard Worker 		{
1918*5a6e8488SAndroid Build Coastguard Worker 			bc_parse_err(p, BC_ERR_PARSE_TOKEN);
1919*5a6e8488SAndroid Build Coastguard Worker 		}
1920*5a6e8488SAndroid Build Coastguard Worker 	}
1921*5a6e8488SAndroid Build Coastguard Worker 
1922*5a6e8488SAndroid Build Coastguard Worker 	// If the flags did not change, we expect a delimiter.
1923*5a6e8488SAndroid Build Coastguard Worker 	if (len == p->flags.len && flags == BC_PARSE_TOP_FLAG(p))
1924*5a6e8488SAndroid Build Coastguard Worker 	{
1925*5a6e8488SAndroid Build Coastguard Worker 		if (BC_ERR(!bc_parse_isDelimiter(p)))
1926*5a6e8488SAndroid Build Coastguard Worker 		{
1927*5a6e8488SAndroid Build Coastguard Worker 			bc_parse_err(p, BC_ERR_PARSE_TOKEN);
1928*5a6e8488SAndroid Build Coastguard Worker 		}
1929*5a6e8488SAndroid Build Coastguard Worker 	}
1930*5a6e8488SAndroid Build Coastguard Worker 
1931*5a6e8488SAndroid Build Coastguard Worker 	// Make sure semicolons are eaten.
1932*5a6e8488SAndroid Build Coastguard Worker 	while (p->l.t == BC_LEX_SCOLON || p->l.t == BC_LEX_NLINE)
1933*5a6e8488SAndroid Build Coastguard Worker 	{
1934*5a6e8488SAndroid Build Coastguard Worker 		bc_lex_next(&p->l);
1935*5a6e8488SAndroid Build Coastguard Worker 	}
1936*5a6e8488SAndroid Build Coastguard Worker 
1937*5a6e8488SAndroid Build Coastguard Worker 	// POSIX's grammar does not allow a function definition after a semicolon
1938*5a6e8488SAndroid Build Coastguard Worker 	// without a newline, so check specifically for that case and error if
1939*5a6e8488SAndroid Build Coastguard Worker 	// the POSIX standard flag is set.
1940*5a6e8488SAndroid Build Coastguard Worker 	if (p->l.last == BC_LEX_SCOLON && p->l.t == BC_LEX_KW_DEFINE && BC_IS_POSIX)
1941*5a6e8488SAndroid Build Coastguard Worker 	{
1942*5a6e8488SAndroid Build Coastguard Worker 		bc_parse_err(p, BC_ERR_POSIX_FUNC_AFTER_SEMICOLON);
1943*5a6e8488SAndroid Build Coastguard Worker 	}
1944*5a6e8488SAndroid Build Coastguard Worker }
1945*5a6e8488SAndroid Build Coastguard Worker 
1946*5a6e8488SAndroid Build Coastguard Worker void
bc_parse_parse(BcParse * p)1947*5a6e8488SAndroid Build Coastguard Worker bc_parse_parse(BcParse* p)
1948*5a6e8488SAndroid Build Coastguard Worker {
1949*5a6e8488SAndroid Build Coastguard Worker 	assert(p);
1950*5a6e8488SAndroid Build Coastguard Worker 
1951*5a6e8488SAndroid Build Coastguard Worker 	BC_SETJMP_LOCKED(vm, exit);
1952*5a6e8488SAndroid Build Coastguard Worker 
1953*5a6e8488SAndroid Build Coastguard Worker 	// We should not let an EOF get here unless some partial parse was not
1954*5a6e8488SAndroid Build Coastguard Worker 	// completed, in which case, it's the user's fault.
1955*5a6e8488SAndroid Build Coastguard Worker 	if (BC_ERR(p->l.t == BC_LEX_EOF)) bc_parse_err(p, BC_ERR_PARSE_EOF);
1956*5a6e8488SAndroid Build Coastguard Worker 
1957*5a6e8488SAndroid Build Coastguard Worker 	// Functions need special parsing.
1958*5a6e8488SAndroid Build Coastguard Worker 	else if (p->l.t == BC_LEX_KW_DEFINE)
1959*5a6e8488SAndroid Build Coastguard Worker 	{
1960*5a6e8488SAndroid Build Coastguard Worker 		if (BC_ERR(BC_PARSE_NO_EXEC(p)))
1961*5a6e8488SAndroid Build Coastguard Worker 		{
1962*5a6e8488SAndroid Build Coastguard Worker 			bc_parse_endif(p);
1963*5a6e8488SAndroid Build Coastguard Worker 			if (BC_ERR(BC_PARSE_NO_EXEC(p)))
1964*5a6e8488SAndroid Build Coastguard Worker 			{
1965*5a6e8488SAndroid Build Coastguard Worker 				bc_parse_err(p, BC_ERR_PARSE_TOKEN);
1966*5a6e8488SAndroid Build Coastguard Worker 			}
1967*5a6e8488SAndroid Build Coastguard Worker 		}
1968*5a6e8488SAndroid Build Coastguard Worker 		bc_parse_func(p);
1969*5a6e8488SAndroid Build Coastguard Worker 	}
1970*5a6e8488SAndroid Build Coastguard Worker 
1971*5a6e8488SAndroid Build Coastguard Worker 	// Otherwise, parse a normal statement.
1972*5a6e8488SAndroid Build Coastguard Worker 	else bc_parse_stmt(p);
1973*5a6e8488SAndroid Build Coastguard Worker 
1974*5a6e8488SAndroid Build Coastguard Worker exit:
1975*5a6e8488SAndroid Build Coastguard Worker 
1976*5a6e8488SAndroid Build Coastguard Worker 	// We need to reset on error.
1977*5a6e8488SAndroid Build Coastguard Worker 	if (BC_ERR(((vm->status && vm->status != BC_STATUS_QUIT) || vm->sig != 0)))
1978*5a6e8488SAndroid Build Coastguard Worker 	{
1979*5a6e8488SAndroid Build Coastguard Worker 		bc_parse_reset(p);
1980*5a6e8488SAndroid Build Coastguard Worker 	}
1981*5a6e8488SAndroid Build Coastguard Worker 
1982*5a6e8488SAndroid Build Coastguard Worker 	BC_LONGJMP_CONT(vm);
1983*5a6e8488SAndroid Build Coastguard Worker 	BC_SIG_MAYLOCK;
1984*5a6e8488SAndroid Build Coastguard Worker }
1985*5a6e8488SAndroid Build Coastguard Worker 
1986*5a6e8488SAndroid Build Coastguard Worker /**
1987*5a6e8488SAndroid Build Coastguard Worker  * Parse an expression. This is the actual implementation of the Shunting-Yard
1988*5a6e8488SAndroid Build Coastguard Worker  * Algorithm.
1989*5a6e8488SAndroid Build Coastguard Worker  * @param p      The parser.
1990*5a6e8488SAndroid Build Coastguard Worker  * @param flags  The flags for what is valid in the expression.
1991*5a6e8488SAndroid Build Coastguard Worker  * @param next   A set of tokens for what is valid *after* the expression.
1992*5a6e8488SAndroid Build Coastguard Worker  * @return       A parse status. In some places, an empty expression is an
1993*5a6e8488SAndroid Build Coastguard Worker  *               error, and sometimes, it is required. This allows this function
1994*5a6e8488SAndroid Build Coastguard Worker  *               to tell the caller if the expression was empty and let the
1995*5a6e8488SAndroid Build Coastguard Worker  *               caller handle it.
1996*5a6e8488SAndroid Build Coastguard Worker  */
1997*5a6e8488SAndroid Build Coastguard Worker static BcParseStatus
bc_parse_expr_err(BcParse * p,uint8_t flags,BcParseNext next)1998*5a6e8488SAndroid Build Coastguard Worker bc_parse_expr_err(BcParse* p, uint8_t flags, BcParseNext next)
1999*5a6e8488SAndroid Build Coastguard Worker {
2000*5a6e8488SAndroid Build Coastguard Worker 	BcInst prev = BC_INST_PRINT;
2001*5a6e8488SAndroid Build Coastguard Worker 	uchar inst = BC_INST_INVALID;
2002*5a6e8488SAndroid Build Coastguard Worker 	BcLexType top, t;
2003*5a6e8488SAndroid Build Coastguard Worker 	size_t nexprs, ops_bgn;
2004*5a6e8488SAndroid Build Coastguard Worker 	uint32_t i, nparens, nrelops;
2005*5a6e8488SAndroid Build Coastguard Worker 	bool pfirst, rprn, array_last, done, get_token, assign;
2006*5a6e8488SAndroid Build Coastguard Worker 	bool bin_last, incdec, can_assign;
2007*5a6e8488SAndroid Build Coastguard Worker 
2008*5a6e8488SAndroid Build Coastguard Worker 	// One of these *must* be true.
2009*5a6e8488SAndroid Build Coastguard Worker 	assert(!(flags & BC_PARSE_PRINT) || !(flags & BC_PARSE_NEEDVAL));
2010*5a6e8488SAndroid Build Coastguard Worker 
2011*5a6e8488SAndroid Build Coastguard Worker 	// These are set very carefully. In fact, controlling the values of these
2012*5a6e8488SAndroid Build Coastguard Worker 	// locals is the biggest part of making this work. ops_bgn especially is
2013*5a6e8488SAndroid Build Coastguard Worker 	// important because it marks where the operator stack begins for *this*
2014*5a6e8488SAndroid Build Coastguard Worker 	// invocation of this function. That's because bc_parse_expr_err() is
2015*5a6e8488SAndroid Build Coastguard Worker 	// recursive (the Shunting-Yard Algorithm is most easily expressed
2016*5a6e8488SAndroid Build Coastguard Worker 	// recursively when parsing subexpressions), and each invocation needs to
2017*5a6e8488SAndroid Build Coastguard Worker 	// know where to stop.
2018*5a6e8488SAndroid Build Coastguard Worker 	//
2019*5a6e8488SAndroid Build Coastguard Worker 	// - nparens is the number of left parens without matches.
2020*5a6e8488SAndroid Build Coastguard Worker 	// - nrelops is the number of relational operators that appear in the expr.
2021*5a6e8488SAndroid Build Coastguard Worker 	// - nexprs is the number of unused expressions.
2022*5a6e8488SAndroid Build Coastguard Worker 	// - rprn is a right paren encountered last.
2023*5a6e8488SAndroid Build Coastguard Worker 	// - array_last is an array item encountered last.
2024*5a6e8488SAndroid Build Coastguard Worker 	// - done means the expression has been fully parsed.
2025*5a6e8488SAndroid Build Coastguard Worker 	// - get_token is true when a token is needed at the end of an iteration.
2026*5a6e8488SAndroid Build Coastguard Worker 	// - assign is true when an assignment statement was parsed last.
2027*5a6e8488SAndroid Build Coastguard Worker 	// - incdec is true when the previous operator was an inc or dec operator.
2028*5a6e8488SAndroid Build Coastguard Worker 	// - can_assign is true when an assignemnt is valid.
2029*5a6e8488SAndroid Build Coastguard Worker 	// - bin_last is true when the previous instruction was a binary operator.
2030*5a6e8488SAndroid Build Coastguard Worker 	t = p->l.t;
2031*5a6e8488SAndroid Build Coastguard Worker 	pfirst = (p->l.t == BC_LEX_LPAREN);
2032*5a6e8488SAndroid Build Coastguard Worker 	nparens = nrelops = 0;
2033*5a6e8488SAndroid Build Coastguard Worker 	nexprs = 0;
2034*5a6e8488SAndroid Build Coastguard Worker 	ops_bgn = p->ops.len;
2035*5a6e8488SAndroid Build Coastguard Worker 	rprn = array_last = done = get_token = assign = incdec = can_assign = false;
2036*5a6e8488SAndroid Build Coastguard Worker 	bin_last = true;
2037*5a6e8488SAndroid Build Coastguard Worker 
2038*5a6e8488SAndroid Build Coastguard Worker 	// We want to eat newlines if newlines are not a valid ending token.
2039*5a6e8488SAndroid Build Coastguard Worker 	// This is for spacing in things like for loop headers.
2040*5a6e8488SAndroid Build Coastguard Worker 	if (!(flags & BC_PARSE_NOREAD))
2041*5a6e8488SAndroid Build Coastguard Worker 	{
2042*5a6e8488SAndroid Build Coastguard Worker 		while ((t = p->l.t) == BC_LEX_NLINE)
2043*5a6e8488SAndroid Build Coastguard Worker 		{
2044*5a6e8488SAndroid Build Coastguard Worker 			bc_lex_next(&p->l);
2045*5a6e8488SAndroid Build Coastguard Worker 		}
2046*5a6e8488SAndroid Build Coastguard Worker 	}
2047*5a6e8488SAndroid Build Coastguard Worker 
2048*5a6e8488SAndroid Build Coastguard Worker 	// This is the Shunting-Yard algorithm loop.
2049*5a6e8488SAndroid Build Coastguard Worker 	for (; !done && BC_PARSE_EXPR(t); t = p->l.t)
2050*5a6e8488SAndroid Build Coastguard Worker 	{
2051*5a6e8488SAndroid Build Coastguard Worker 		// Make sure an array expression is not mixed with any others. However,
2052*5a6e8488SAndroid Build Coastguard Worker 		// a right parenthesis may end the expression, so we will need to take
2053*5a6e8488SAndroid Build Coastguard Worker 		// care of that right there.
2054*5a6e8488SAndroid Build Coastguard Worker 		if (BC_ERR(array_last && t != BC_LEX_RPAREN))
2055*5a6e8488SAndroid Build Coastguard Worker 		{
2056*5a6e8488SAndroid Build Coastguard Worker 			bc_parse_err(p, BC_ERR_PARSE_EXPR);
2057*5a6e8488SAndroid Build Coastguard Worker 		}
2058*5a6e8488SAndroid Build Coastguard Worker 
2059*5a6e8488SAndroid Build Coastguard Worker 		switch (t)
2060*5a6e8488SAndroid Build Coastguard Worker 		{
2061*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_OP_INC:
2062*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_OP_DEC:
2063*5a6e8488SAndroid Build Coastguard Worker 			{
2064*5a6e8488SAndroid Build Coastguard Worker 				// These operators can only be used with items that can be
2065*5a6e8488SAndroid Build Coastguard Worker 				// assigned to.
2066*5a6e8488SAndroid Build Coastguard Worker 				if (BC_ERR(incdec)) bc_parse_err(p, BC_ERR_PARSE_ASSIGN);
2067*5a6e8488SAndroid Build Coastguard Worker 
2068*5a6e8488SAndroid Build Coastguard Worker 				bc_parse_incdec(p, &prev, &can_assign, &nexprs, flags);
2069*5a6e8488SAndroid Build Coastguard Worker 
2070*5a6e8488SAndroid Build Coastguard Worker 				rprn = get_token = bin_last = false;
2071*5a6e8488SAndroid Build Coastguard Worker 				incdec = true;
2072*5a6e8488SAndroid Build Coastguard Worker 				flags &= ~(BC_PARSE_ARRAY);
2073*5a6e8488SAndroid Build Coastguard Worker 
2074*5a6e8488SAndroid Build Coastguard Worker 				break;
2075*5a6e8488SAndroid Build Coastguard Worker 			}
2076*5a6e8488SAndroid Build Coastguard Worker 
2077*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_EXTRA_MATH
2078*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_OP_TRUNC:
2079*5a6e8488SAndroid Build Coastguard Worker 			{
2080*5a6e8488SAndroid Build Coastguard Worker 				// The previous token must have been a leaf expression, or the
2081*5a6e8488SAndroid Build Coastguard Worker 				// operator is in the wrong place.
2082*5a6e8488SAndroid Build Coastguard Worker 				if (BC_ERR(!BC_PARSE_LEAF(prev, bin_last, rprn)))
2083*5a6e8488SAndroid Build Coastguard Worker 				{
2084*5a6e8488SAndroid Build Coastguard Worker 					bc_parse_err(p, BC_ERR_PARSE_TOKEN);
2085*5a6e8488SAndroid Build Coastguard Worker 				}
2086*5a6e8488SAndroid Build Coastguard Worker 
2087*5a6e8488SAndroid Build Coastguard Worker 				// I can just add the instruction because
2088*5a6e8488SAndroid Build Coastguard Worker 				// negative will already be taken care of.
2089*5a6e8488SAndroid Build Coastguard Worker 				bc_parse_push(p, BC_INST_TRUNC);
2090*5a6e8488SAndroid Build Coastguard Worker 
2091*5a6e8488SAndroid Build Coastguard Worker 				rprn = can_assign = incdec = false;
2092*5a6e8488SAndroid Build Coastguard Worker 				get_token = true;
2093*5a6e8488SAndroid Build Coastguard Worker 				flags &= ~(BC_PARSE_ARRAY);
2094*5a6e8488SAndroid Build Coastguard Worker 
2095*5a6e8488SAndroid Build Coastguard Worker 				break;
2096*5a6e8488SAndroid Build Coastguard Worker 			}
2097*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_EXTRA_MATH
2098*5a6e8488SAndroid Build Coastguard Worker 
2099*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_OP_MINUS:
2100*5a6e8488SAndroid Build Coastguard Worker 			{
2101*5a6e8488SAndroid Build Coastguard Worker 				bc_parse_minus(p, &prev, ops_bgn, rprn, bin_last, &nexprs);
2102*5a6e8488SAndroid Build Coastguard Worker 
2103*5a6e8488SAndroid Build Coastguard Worker 				rprn = get_token = can_assign = false;
2104*5a6e8488SAndroid Build Coastguard Worker 
2105*5a6e8488SAndroid Build Coastguard Worker 				// This is true if it was a binary operator last.
2106*5a6e8488SAndroid Build Coastguard Worker 				bin_last = (prev == BC_INST_MINUS);
2107*5a6e8488SAndroid Build Coastguard Worker 				if (bin_last) incdec = false;
2108*5a6e8488SAndroid Build Coastguard Worker 
2109*5a6e8488SAndroid Build Coastguard Worker 				flags &= ~(BC_PARSE_ARRAY);
2110*5a6e8488SAndroid Build Coastguard Worker 
2111*5a6e8488SAndroid Build Coastguard Worker 				break;
2112*5a6e8488SAndroid Build Coastguard Worker 			}
2113*5a6e8488SAndroid Build Coastguard Worker 
2114*5a6e8488SAndroid Build Coastguard Worker 			// All of this group, including the fallthrough, is to parse binary
2115*5a6e8488SAndroid Build Coastguard Worker 			// operators.
2116*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_OP_ASSIGN_POWER:
2117*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_OP_ASSIGN_MULTIPLY:
2118*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_OP_ASSIGN_DIVIDE:
2119*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_OP_ASSIGN_MODULUS:
2120*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_OP_ASSIGN_PLUS:
2121*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_OP_ASSIGN_MINUS:
2122*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_EXTRA_MATH
2123*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_OP_ASSIGN_PLACES:
2124*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_OP_ASSIGN_LSHIFT:
2125*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_OP_ASSIGN_RSHIFT:
2126*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_EXTRA_MATH
2127*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_OP_ASSIGN:
2128*5a6e8488SAndroid Build Coastguard Worker 			{
2129*5a6e8488SAndroid Build Coastguard Worker 				// We need to make sure the assignment is valid.
2130*5a6e8488SAndroid Build Coastguard Worker 				if (!BC_PARSE_INST_VAR(prev))
2131*5a6e8488SAndroid Build Coastguard Worker 				{
2132*5a6e8488SAndroid Build Coastguard Worker 					bc_parse_err(p, BC_ERR_PARSE_ASSIGN);
2133*5a6e8488SAndroid Build Coastguard Worker 				}
2134*5a6e8488SAndroid Build Coastguard Worker 
2135*5a6e8488SAndroid Build Coastguard Worker 				// Fallthrough.
2136*5a6e8488SAndroid Build Coastguard Worker 				BC_FALLTHROUGH
2137*5a6e8488SAndroid Build Coastguard Worker 			}
2138*5a6e8488SAndroid Build Coastguard Worker 
2139*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_OP_POWER:
2140*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_OP_MULTIPLY:
2141*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_OP_DIVIDE:
2142*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_OP_MODULUS:
2143*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_OP_PLUS:
2144*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_EXTRA_MATH
2145*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_OP_PLACES:
2146*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_OP_LSHIFT:
2147*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_OP_RSHIFT:
2148*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_EXTRA_MATH
2149*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_OP_REL_EQ:
2150*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_OP_REL_LE:
2151*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_OP_REL_GE:
2152*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_OP_REL_NE:
2153*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_OP_REL_LT:
2154*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_OP_REL_GT:
2155*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_OP_BOOL_NOT:
2156*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_OP_BOOL_OR:
2157*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_OP_BOOL_AND:
2158*5a6e8488SAndroid Build Coastguard Worker 			{
2159*5a6e8488SAndroid Build Coastguard Worker 				// This is true if the operator if the token is a prefix
2160*5a6e8488SAndroid Build Coastguard Worker 				// operator. This is only for boolean not.
2161*5a6e8488SAndroid Build Coastguard Worker 				if (BC_PARSE_OP_PREFIX(t))
2162*5a6e8488SAndroid Build Coastguard Worker 				{
2163*5a6e8488SAndroid Build Coastguard Worker 					// Prefix operators are only allowed after binary operators
2164*5a6e8488SAndroid Build Coastguard Worker 					// or prefix operators.
2165*5a6e8488SAndroid Build Coastguard Worker 					if (BC_ERR(!bin_last && !BC_PARSE_OP_PREFIX(p->l.last)))
2166*5a6e8488SAndroid Build Coastguard Worker 					{
2167*5a6e8488SAndroid Build Coastguard Worker 						bc_parse_err(p, BC_ERR_PARSE_EXPR);
2168*5a6e8488SAndroid Build Coastguard Worker 					}
2169*5a6e8488SAndroid Build Coastguard Worker 				}
2170*5a6e8488SAndroid Build Coastguard Worker 				// If we execute the else, that means we have a binary operator.
2171*5a6e8488SAndroid Build Coastguard Worker 				// If the previous operator was a prefix or a binary operator,
2172*5a6e8488SAndroid Build Coastguard Worker 				// then a binary operator is not allowed.
2173*5a6e8488SAndroid Build Coastguard Worker 				else if (BC_ERR(BC_PARSE_PREV_PREFIX(prev) || bin_last))
2174*5a6e8488SAndroid Build Coastguard Worker 				{
2175*5a6e8488SAndroid Build Coastguard Worker 					bc_parse_err(p, BC_ERR_PARSE_EXPR);
2176*5a6e8488SAndroid Build Coastguard Worker 				}
2177*5a6e8488SAndroid Build Coastguard Worker 
2178*5a6e8488SAndroid Build Coastguard Worker 				nrelops += (t >= BC_LEX_OP_REL_EQ && t <= BC_LEX_OP_REL_GT);
2179*5a6e8488SAndroid Build Coastguard Worker 				prev = BC_PARSE_TOKEN_INST(t);
2180*5a6e8488SAndroid Build Coastguard Worker 
2181*5a6e8488SAndroid Build Coastguard Worker 				bc_parse_operator(p, t, ops_bgn, &nexprs);
2182*5a6e8488SAndroid Build Coastguard Worker 
2183*5a6e8488SAndroid Build Coastguard Worker 				rprn = incdec = can_assign = false;
2184*5a6e8488SAndroid Build Coastguard Worker 				get_token = true;
2185*5a6e8488SAndroid Build Coastguard Worker 				bin_last = !BC_PARSE_OP_PREFIX(t);
2186*5a6e8488SAndroid Build Coastguard Worker 				flags &= ~(BC_PARSE_ARRAY);
2187*5a6e8488SAndroid Build Coastguard Worker 
2188*5a6e8488SAndroid Build Coastguard Worker 				break;
2189*5a6e8488SAndroid Build Coastguard Worker 			}
2190*5a6e8488SAndroid Build Coastguard Worker 
2191*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_LPAREN:
2192*5a6e8488SAndroid Build Coastguard Worker 			{
2193*5a6e8488SAndroid Build Coastguard Worker 				// A left paren is *not* allowed right after a leaf expr.
2194*5a6e8488SAndroid Build Coastguard Worker 				if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn)))
2195*5a6e8488SAndroid Build Coastguard Worker 				{
2196*5a6e8488SAndroid Build Coastguard Worker 					bc_parse_err(p, BC_ERR_PARSE_EXPR);
2197*5a6e8488SAndroid Build Coastguard Worker 				}
2198*5a6e8488SAndroid Build Coastguard Worker 
2199*5a6e8488SAndroid Build Coastguard Worker 				nparens += 1;
2200*5a6e8488SAndroid Build Coastguard Worker 				rprn = incdec = can_assign = false;
2201*5a6e8488SAndroid Build Coastguard Worker 				get_token = true;
2202*5a6e8488SAndroid Build Coastguard Worker 
2203*5a6e8488SAndroid Build Coastguard Worker 				// Push the paren onto the operator stack.
2204*5a6e8488SAndroid Build Coastguard Worker 				bc_vec_push(&p->ops, &t);
2205*5a6e8488SAndroid Build Coastguard Worker 
2206*5a6e8488SAndroid Build Coastguard Worker 				break;
2207*5a6e8488SAndroid Build Coastguard Worker 			}
2208*5a6e8488SAndroid Build Coastguard Worker 
2209*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_RPAREN:
2210*5a6e8488SAndroid Build Coastguard Worker 			{
2211*5a6e8488SAndroid Build Coastguard Worker 				// This needs to be a status. The error is handled in
2212*5a6e8488SAndroid Build Coastguard Worker 				// bc_parse_expr_status().
2213*5a6e8488SAndroid Build Coastguard Worker 				if (BC_ERR(p->l.last == BC_LEX_LPAREN))
2214*5a6e8488SAndroid Build Coastguard Worker 				{
2215*5a6e8488SAndroid Build Coastguard Worker 					return BC_PARSE_STATUS_EMPTY_EXPR;
2216*5a6e8488SAndroid Build Coastguard Worker 				}
2217*5a6e8488SAndroid Build Coastguard Worker 
2218*5a6e8488SAndroid Build Coastguard Worker 				// The right paren must not come after a prefix or binary
2219*5a6e8488SAndroid Build Coastguard Worker 				// operator.
2220*5a6e8488SAndroid Build Coastguard Worker 				if (BC_ERR(bin_last || BC_PARSE_PREV_PREFIX(prev)))
2221*5a6e8488SAndroid Build Coastguard Worker 				{
2222*5a6e8488SAndroid Build Coastguard Worker 					bc_parse_err(p, BC_ERR_PARSE_EXPR);
2223*5a6e8488SAndroid Build Coastguard Worker 				}
2224*5a6e8488SAndroid Build Coastguard Worker 
2225*5a6e8488SAndroid Build Coastguard Worker 				// If there are no parens left, we are done, but we need another
2226*5a6e8488SAndroid Build Coastguard Worker 				// token.
2227*5a6e8488SAndroid Build Coastguard Worker 				if (!nparens)
2228*5a6e8488SAndroid Build Coastguard Worker 				{
2229*5a6e8488SAndroid Build Coastguard Worker 					done = true;
2230*5a6e8488SAndroid Build Coastguard Worker 					get_token = false;
2231*5a6e8488SAndroid Build Coastguard Worker 					break;
2232*5a6e8488SAndroid Build Coastguard Worker 				}
2233*5a6e8488SAndroid Build Coastguard Worker 
2234*5a6e8488SAndroid Build Coastguard Worker 				// Now that we know the right paren has not ended the
2235*5a6e8488SAndroid Build Coastguard Worker 				// expression, make sure an array expression is not mixed with
2236*5a6e8488SAndroid Build Coastguard Worker 				// any others.
2237*5a6e8488SAndroid Build Coastguard Worker 				if (BC_ERR(array_last))
2238*5a6e8488SAndroid Build Coastguard Worker 				{
2239*5a6e8488SAndroid Build Coastguard Worker 					bc_parse_err(p, BC_ERR_PARSE_EXPR);
2240*5a6e8488SAndroid Build Coastguard Worker 				}
2241*5a6e8488SAndroid Build Coastguard Worker 
2242*5a6e8488SAndroid Build Coastguard Worker 				nparens -= 1;
2243*5a6e8488SAndroid Build Coastguard Worker 				rprn = true;
2244*5a6e8488SAndroid Build Coastguard Worker 				get_token = bin_last = incdec = false;
2245*5a6e8488SAndroid Build Coastguard Worker 
2246*5a6e8488SAndroid Build Coastguard Worker 				bc_parse_rightParen(p, &nexprs);
2247*5a6e8488SAndroid Build Coastguard Worker 
2248*5a6e8488SAndroid Build Coastguard Worker 				break;
2249*5a6e8488SAndroid Build Coastguard Worker 			}
2250*5a6e8488SAndroid Build Coastguard Worker 
2251*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_STR:
2252*5a6e8488SAndroid Build Coastguard Worker 			{
2253*5a6e8488SAndroid Build Coastguard Worker 				// POSIX only allows strings alone.
2254*5a6e8488SAndroid Build Coastguard Worker 				if (BC_IS_POSIX) bc_parse_err(p, BC_ERR_POSIX_EXPR_STRING);
2255*5a6e8488SAndroid Build Coastguard Worker 
2256*5a6e8488SAndroid Build Coastguard Worker 				// A string is a leaf and cannot come right after a leaf.
2257*5a6e8488SAndroid Build Coastguard Worker 				if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn)))
2258*5a6e8488SAndroid Build Coastguard Worker 				{
2259*5a6e8488SAndroid Build Coastguard Worker 					bc_parse_err(p, BC_ERR_PARSE_EXPR);
2260*5a6e8488SAndroid Build Coastguard Worker 				}
2261*5a6e8488SAndroid Build Coastguard Worker 
2262*5a6e8488SAndroid Build Coastguard Worker 				bc_parse_addString(p);
2263*5a6e8488SAndroid Build Coastguard Worker 
2264*5a6e8488SAndroid Build Coastguard Worker 				get_token = true;
2265*5a6e8488SAndroid Build Coastguard Worker 				bin_last = rprn = false;
2266*5a6e8488SAndroid Build Coastguard Worker 				nexprs += 1;
2267*5a6e8488SAndroid Build Coastguard Worker 
2268*5a6e8488SAndroid Build Coastguard Worker 				break;
2269*5a6e8488SAndroid Build Coastguard Worker 			}
2270*5a6e8488SAndroid Build Coastguard Worker 
2271*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_NAME:
2272*5a6e8488SAndroid Build Coastguard Worker 			{
2273*5a6e8488SAndroid Build Coastguard Worker 				// A name is a leaf and cannot come right after a leaf.
2274*5a6e8488SAndroid Build Coastguard Worker 				if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn)))
2275*5a6e8488SAndroid Build Coastguard Worker 				{
2276*5a6e8488SAndroid Build Coastguard Worker 					bc_parse_err(p, BC_ERR_PARSE_EXPR);
2277*5a6e8488SAndroid Build Coastguard Worker 				}
2278*5a6e8488SAndroid Build Coastguard Worker 
2279*5a6e8488SAndroid Build Coastguard Worker 				get_token = bin_last = false;
2280*5a6e8488SAndroid Build Coastguard Worker 
2281*5a6e8488SAndroid Build Coastguard Worker 				bc_parse_name(p, &prev, &can_assign, flags & ~BC_PARSE_NOCALL);
2282*5a6e8488SAndroid Build Coastguard Worker 
2283*5a6e8488SAndroid Build Coastguard Worker 				rprn = (prev == BC_INST_CALL);
2284*5a6e8488SAndroid Build Coastguard Worker 				array_last = (prev == BC_INST_ARRAY);
2285*5a6e8488SAndroid Build Coastguard Worker 				nexprs += 1;
2286*5a6e8488SAndroid Build Coastguard Worker 				flags &= ~(BC_PARSE_ARRAY);
2287*5a6e8488SAndroid Build Coastguard Worker 
2288*5a6e8488SAndroid Build Coastguard Worker 				break;
2289*5a6e8488SAndroid Build Coastguard Worker 			}
2290*5a6e8488SAndroid Build Coastguard Worker 
2291*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_NUMBER:
2292*5a6e8488SAndroid Build Coastguard Worker 			{
2293*5a6e8488SAndroid Build Coastguard Worker 				// A number is a leaf and cannot come right after a leaf.
2294*5a6e8488SAndroid Build Coastguard Worker 				if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn)))
2295*5a6e8488SAndroid Build Coastguard Worker 				{
2296*5a6e8488SAndroid Build Coastguard Worker 					bc_parse_err(p, BC_ERR_PARSE_EXPR);
2297*5a6e8488SAndroid Build Coastguard Worker 				}
2298*5a6e8488SAndroid Build Coastguard Worker 
2299*5a6e8488SAndroid Build Coastguard Worker 				// The number instruction is pushed in here.
2300*5a6e8488SAndroid Build Coastguard Worker 				bc_parse_number(p);
2301*5a6e8488SAndroid Build Coastguard Worker 
2302*5a6e8488SAndroid Build Coastguard Worker 				nexprs += 1;
2303*5a6e8488SAndroid Build Coastguard Worker 				prev = BC_INST_NUM;
2304*5a6e8488SAndroid Build Coastguard Worker 				get_token = true;
2305*5a6e8488SAndroid Build Coastguard Worker 				rprn = bin_last = can_assign = false;
2306*5a6e8488SAndroid Build Coastguard Worker 				flags &= ~(BC_PARSE_ARRAY);
2307*5a6e8488SAndroid Build Coastguard Worker 
2308*5a6e8488SAndroid Build Coastguard Worker 				break;
2309*5a6e8488SAndroid Build Coastguard Worker 			}
2310*5a6e8488SAndroid Build Coastguard Worker 
2311*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_KW_IBASE:
2312*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_KW_LAST:
2313*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_KW_OBASE:
2314*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_EXTRA_MATH
2315*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_KW_SEED:
2316*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_EXTRA_MATH
2317*5a6e8488SAndroid Build Coastguard Worker 			{
2318*5a6e8488SAndroid Build Coastguard Worker 				// All of these are leaves and cannot come right after a leaf.
2319*5a6e8488SAndroid Build Coastguard Worker 				if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn)))
2320*5a6e8488SAndroid Build Coastguard Worker 				{
2321*5a6e8488SAndroid Build Coastguard Worker 					bc_parse_err(p, BC_ERR_PARSE_EXPR);
2322*5a6e8488SAndroid Build Coastguard Worker 				}
2323*5a6e8488SAndroid Build Coastguard Worker 
2324*5a6e8488SAndroid Build Coastguard Worker 				prev = t - BC_LEX_KW_LAST + BC_INST_LAST;
2325*5a6e8488SAndroid Build Coastguard Worker 				bc_parse_push(p, prev);
2326*5a6e8488SAndroid Build Coastguard Worker 
2327*5a6e8488SAndroid Build Coastguard Worker 				get_token = can_assign = true;
2328*5a6e8488SAndroid Build Coastguard Worker 				rprn = bin_last = false;
2329*5a6e8488SAndroid Build Coastguard Worker 				nexprs += 1;
2330*5a6e8488SAndroid Build Coastguard Worker 				flags &= ~(BC_PARSE_ARRAY);
2331*5a6e8488SAndroid Build Coastguard Worker 
2332*5a6e8488SAndroid Build Coastguard Worker 				break;
2333*5a6e8488SAndroid Build Coastguard Worker 			}
2334*5a6e8488SAndroid Build Coastguard Worker 
2335*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_KW_LENGTH:
2336*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_KW_SQRT:
2337*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_KW_ABS:
2338*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_KW_IS_NUMBER:
2339*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_KW_IS_STRING:
2340*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_EXTRA_MATH
2341*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_KW_IRAND:
2342*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_EXTRA_MATH
2343*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_KW_ASCIIFY:
2344*5a6e8488SAndroid Build Coastguard Worker 			{
2345*5a6e8488SAndroid Build Coastguard Worker 				// All of these are leaves and cannot come right after a leaf.
2346*5a6e8488SAndroid Build Coastguard Worker 				if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn)))
2347*5a6e8488SAndroid Build Coastguard Worker 				{
2348*5a6e8488SAndroid Build Coastguard Worker 					bc_parse_err(p, BC_ERR_PARSE_EXPR);
2349*5a6e8488SAndroid Build Coastguard Worker 				}
2350*5a6e8488SAndroid Build Coastguard Worker 
2351*5a6e8488SAndroid Build Coastguard Worker 				bc_parse_builtin(p, t, flags, &prev);
2352*5a6e8488SAndroid Build Coastguard Worker 
2353*5a6e8488SAndroid Build Coastguard Worker 				rprn = get_token = bin_last = incdec = can_assign = false;
2354*5a6e8488SAndroid Build Coastguard Worker 				nexprs += 1;
2355*5a6e8488SAndroid Build Coastguard Worker 				flags &= ~(BC_PARSE_ARRAY);
2356*5a6e8488SAndroid Build Coastguard Worker 
2357*5a6e8488SAndroid Build Coastguard Worker 				break;
2358*5a6e8488SAndroid Build Coastguard Worker 			}
2359*5a6e8488SAndroid Build Coastguard Worker 
2360*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_KW_READ:
2361*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_EXTRA_MATH
2362*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_KW_RAND:
2363*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_EXTRA_MATH
2364*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_KW_MAXIBASE:
2365*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_KW_MAXOBASE:
2366*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_KW_MAXSCALE:
2367*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_EXTRA_MATH
2368*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_KW_MAXRAND:
2369*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_EXTRA_MATH
2370*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_KW_LINE_LENGTH:
2371*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_KW_GLOBAL_STACKS:
2372*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_KW_LEADING_ZERO:
2373*5a6e8488SAndroid Build Coastguard Worker 			{
2374*5a6e8488SAndroid Build Coastguard Worker 				// All of these are leaves and cannot come right after a leaf.
2375*5a6e8488SAndroid Build Coastguard Worker 				if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn)))
2376*5a6e8488SAndroid Build Coastguard Worker 				{
2377*5a6e8488SAndroid Build Coastguard Worker 					bc_parse_err(p, BC_ERR_PARSE_EXPR);
2378*5a6e8488SAndroid Build Coastguard Worker 				}
2379*5a6e8488SAndroid Build Coastguard Worker 
2380*5a6e8488SAndroid Build Coastguard Worker 				// Error if we have read and it's not allowed.
2381*5a6e8488SAndroid Build Coastguard Worker 				else if (t == BC_LEX_KW_READ && BC_ERR(flags & BC_PARSE_NOREAD))
2382*5a6e8488SAndroid Build Coastguard Worker 				{
2383*5a6e8488SAndroid Build Coastguard Worker 					bc_parse_err(p, BC_ERR_EXEC_REC_READ);
2384*5a6e8488SAndroid Build Coastguard Worker 				}
2385*5a6e8488SAndroid Build Coastguard Worker 
2386*5a6e8488SAndroid Build Coastguard Worker 				prev = t - BC_LEX_KW_READ + BC_INST_READ;
2387*5a6e8488SAndroid Build Coastguard Worker 				bc_parse_noArgBuiltin(p, prev);
2388*5a6e8488SAndroid Build Coastguard Worker 
2389*5a6e8488SAndroid Build Coastguard Worker 				rprn = get_token = bin_last = incdec = can_assign = false;
2390*5a6e8488SAndroid Build Coastguard Worker 				nexprs += 1;
2391*5a6e8488SAndroid Build Coastguard Worker 				flags &= ~(BC_PARSE_ARRAY);
2392*5a6e8488SAndroid Build Coastguard Worker 
2393*5a6e8488SAndroid Build Coastguard Worker 				break;
2394*5a6e8488SAndroid Build Coastguard Worker 			}
2395*5a6e8488SAndroid Build Coastguard Worker 
2396*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_KW_SCALE:
2397*5a6e8488SAndroid Build Coastguard Worker 			{
2398*5a6e8488SAndroid Build Coastguard Worker 				// This is a leaf and cannot come right after a leaf.
2399*5a6e8488SAndroid Build Coastguard Worker 				if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn)))
2400*5a6e8488SAndroid Build Coastguard Worker 				{
2401*5a6e8488SAndroid Build Coastguard Worker 					bc_parse_err(p, BC_ERR_PARSE_EXPR);
2402*5a6e8488SAndroid Build Coastguard Worker 				}
2403*5a6e8488SAndroid Build Coastguard Worker 
2404*5a6e8488SAndroid Build Coastguard Worker 				// Scale needs special work because it can be a variable *or* a
2405*5a6e8488SAndroid Build Coastguard Worker 				// function.
2406*5a6e8488SAndroid Build Coastguard Worker 				bc_parse_scale(p, &prev, &can_assign, flags);
2407*5a6e8488SAndroid Build Coastguard Worker 
2408*5a6e8488SAndroid Build Coastguard Worker 				rprn = get_token = bin_last = false;
2409*5a6e8488SAndroid Build Coastguard Worker 				nexprs += 1;
2410*5a6e8488SAndroid Build Coastguard Worker 				flags &= ~(BC_PARSE_ARRAY);
2411*5a6e8488SAndroid Build Coastguard Worker 
2412*5a6e8488SAndroid Build Coastguard Worker 				break;
2413*5a6e8488SAndroid Build Coastguard Worker 			}
2414*5a6e8488SAndroid Build Coastguard Worker 
2415*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_KW_MODEXP:
2416*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_KW_DIVMOD:
2417*5a6e8488SAndroid Build Coastguard Worker 			{
2418*5a6e8488SAndroid Build Coastguard Worker 				// This is a leaf and cannot come right after a leaf.
2419*5a6e8488SAndroid Build Coastguard Worker 				if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn)))
2420*5a6e8488SAndroid Build Coastguard Worker 				{
2421*5a6e8488SAndroid Build Coastguard Worker 					bc_parse_err(p, BC_ERR_PARSE_EXPR);
2422*5a6e8488SAndroid Build Coastguard Worker 				}
2423*5a6e8488SAndroid Build Coastguard Worker 
2424*5a6e8488SAndroid Build Coastguard Worker 				bc_parse_builtin3(p, t, flags, &prev);
2425*5a6e8488SAndroid Build Coastguard Worker 
2426*5a6e8488SAndroid Build Coastguard Worker 				rprn = get_token = bin_last = incdec = can_assign = false;
2427*5a6e8488SAndroid Build Coastguard Worker 				nexprs += 1;
2428*5a6e8488SAndroid Build Coastguard Worker 				flags &= ~(BC_PARSE_ARRAY);
2429*5a6e8488SAndroid Build Coastguard Worker 
2430*5a6e8488SAndroid Build Coastguard Worker 				break;
2431*5a6e8488SAndroid Build Coastguard Worker 			}
2432*5a6e8488SAndroid Build Coastguard Worker 
2433*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_EOF:
2434*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_INVALID:
2435*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_NEG:
2436*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_NLINE:
2437*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_WHITESPACE:
2438*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_LBRACKET:
2439*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_COMMA:
2440*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_RBRACKET:
2441*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_LBRACE:
2442*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_SCOLON:
2443*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_RBRACE:
2444*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_KW_AUTO:
2445*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_KW_BREAK:
2446*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_KW_CONTINUE:
2447*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_KW_DEFINE:
2448*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_KW_FOR:
2449*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_KW_IF:
2450*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_KW_LIMITS:
2451*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_KW_RETURN:
2452*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_KW_WHILE:
2453*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_KW_HALT:
2454*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_KW_PRINT:
2455*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_KW_QUIT:
2456*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_KW_STREAM:
2457*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_KW_ELSE:
2458*5a6e8488SAndroid Build Coastguard Worker #if DC_ENABLED
2459*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_EXTENDED_REGISTERS:
2460*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_EQ_NO_REG:
2461*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_COLON:
2462*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_EXECUTE:
2463*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_PRINT_STACK:
2464*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_CLEAR_STACK:
2465*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_REG_STACK_LEVEL:
2466*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_STACK_LEVEL:
2467*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_DUPLICATE:
2468*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_SWAP:
2469*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_POP:
2470*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_STORE_IBASE:
2471*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_STORE_OBASE:
2472*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_STORE_SCALE:
2473*5a6e8488SAndroid Build Coastguard Worker #if BC_ENABLE_EXTRA_MATH
2474*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_STORE_SEED:
2475*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLE_EXTRA_MATH
2476*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_LOAD:
2477*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_LOAD_POP:
2478*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_STORE_PUSH:
2479*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_PRINT_POP:
2480*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_NQUIT:
2481*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_EXEC_STACK_LENGTH:
2482*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_SCALE_FACTOR:
2483*5a6e8488SAndroid Build Coastguard Worker 			case BC_LEX_ARRAY_LENGTH:
2484*5a6e8488SAndroid Build Coastguard Worker #endif // DC_ENABLED
2485*5a6e8488SAndroid Build Coastguard Worker 			{
2486*5a6e8488SAndroid Build Coastguard Worker #if BC_DEBUG
2487*5a6e8488SAndroid Build Coastguard Worker 				// We should never get here, even in debug builds.
2488*5a6e8488SAndroid Build Coastguard Worker 				bc_parse_err(p, BC_ERR_PARSE_TOKEN);
2489*5a6e8488SAndroid Build Coastguard Worker 				break;
2490*5a6e8488SAndroid Build Coastguard Worker #endif // BC_DEBUG
2491*5a6e8488SAndroid Build Coastguard Worker 			}
2492*5a6e8488SAndroid Build Coastguard Worker 		}
2493*5a6e8488SAndroid Build Coastguard Worker 
2494*5a6e8488SAndroid Build Coastguard Worker 		if (get_token) bc_lex_next(&p->l);
2495*5a6e8488SAndroid Build Coastguard Worker 	}
2496*5a6e8488SAndroid Build Coastguard Worker 
2497*5a6e8488SAndroid Build Coastguard Worker 	// Now that we have parsed the expression, we need to empty the operator
2498*5a6e8488SAndroid Build Coastguard Worker 	// stack.
2499*5a6e8488SAndroid Build Coastguard Worker 	while (p->ops.len > ops_bgn)
2500*5a6e8488SAndroid Build Coastguard Worker 	{
2501*5a6e8488SAndroid Build Coastguard Worker 		top = BC_PARSE_TOP_OP(p);
2502*5a6e8488SAndroid Build Coastguard Worker 		assign = top >= BC_LEX_OP_ASSIGN_POWER && top <= BC_LEX_OP_ASSIGN;
2503*5a6e8488SAndroid Build Coastguard Worker 
2504*5a6e8488SAndroid Build Coastguard Worker 		// There should not be *any* parens on the stack anymore.
2505*5a6e8488SAndroid Build Coastguard Worker 		if (BC_ERR(top == BC_LEX_LPAREN || top == BC_LEX_RPAREN))
2506*5a6e8488SAndroid Build Coastguard Worker 		{
2507*5a6e8488SAndroid Build Coastguard Worker 			bc_parse_err(p, BC_ERR_PARSE_EXPR);
2508*5a6e8488SAndroid Build Coastguard Worker 		}
2509*5a6e8488SAndroid Build Coastguard Worker 
2510*5a6e8488SAndroid Build Coastguard Worker 		bc_parse_push(p, BC_PARSE_TOKEN_INST(top));
2511*5a6e8488SAndroid Build Coastguard Worker 
2512*5a6e8488SAndroid Build Coastguard Worker 		// Adjust the number of unused expressions.
2513*5a6e8488SAndroid Build Coastguard Worker 		nexprs -= !BC_PARSE_OP_PREFIX(top);
2514*5a6e8488SAndroid Build Coastguard Worker 		bc_vec_pop(&p->ops);
2515*5a6e8488SAndroid Build Coastguard Worker 
2516*5a6e8488SAndroid Build Coastguard Worker 		incdec = false;
2517*5a6e8488SAndroid Build Coastguard Worker 	}
2518*5a6e8488SAndroid Build Coastguard Worker 
2519*5a6e8488SAndroid Build Coastguard Worker 	// There must be only one expression at the top.
2520*5a6e8488SAndroid Build Coastguard Worker 	if (BC_ERR(nexprs != 1)) bc_parse_err(p, BC_ERR_PARSE_EXPR);
2521*5a6e8488SAndroid Build Coastguard Worker 
2522*5a6e8488SAndroid Build Coastguard Worker 	// Check that the next token is correct.
2523*5a6e8488SAndroid Build Coastguard Worker 	for (i = 0; i < next.len && t != next.tokens[i]; ++i)
2524*5a6e8488SAndroid Build Coastguard Worker 	{
2525*5a6e8488SAndroid Build Coastguard Worker 		continue;
2526*5a6e8488SAndroid Build Coastguard Worker 	}
2527*5a6e8488SAndroid Build Coastguard Worker 	if (BC_ERR(i == next.len && !bc_parse_isDelimiter(p)))
2528*5a6e8488SAndroid Build Coastguard Worker 	{
2529*5a6e8488SAndroid Build Coastguard Worker 		bc_parse_err(p, BC_ERR_PARSE_EXPR);
2530*5a6e8488SAndroid Build Coastguard Worker 	}
2531*5a6e8488SAndroid Build Coastguard Worker 
2532*5a6e8488SAndroid Build Coastguard Worker 	// Check that POSIX would be happy with the number of relational operators.
2533*5a6e8488SAndroid Build Coastguard Worker 	if (!(flags & BC_PARSE_REL) && nrelops)
2534*5a6e8488SAndroid Build Coastguard Worker 	{
2535*5a6e8488SAndroid Build Coastguard Worker 		bc_parse_err(p, BC_ERR_POSIX_REL_POS);
2536*5a6e8488SAndroid Build Coastguard Worker 	}
2537*5a6e8488SAndroid Build Coastguard Worker 	else if ((flags & BC_PARSE_REL) && nrelops > 1)
2538*5a6e8488SAndroid Build Coastguard Worker 	{
2539*5a6e8488SAndroid Build Coastguard Worker 		bc_parse_err(p, BC_ERR_POSIX_MULTIREL);
2540*5a6e8488SAndroid Build Coastguard Worker 	}
2541*5a6e8488SAndroid Build Coastguard Worker 
2542*5a6e8488SAndroid Build Coastguard Worker 	// If this is true, then we might be in a situation where we don't print.
2543*5a6e8488SAndroid Build Coastguard Worker 	// We would want to have the increment/decrement operator not make an extra
2544*5a6e8488SAndroid Build Coastguard Worker 	// copy if it's not necessary.
2545*5a6e8488SAndroid Build Coastguard Worker 	if (!(flags & BC_PARSE_NEEDVAL) && !pfirst)
2546*5a6e8488SAndroid Build Coastguard Worker 	{
2547*5a6e8488SAndroid Build Coastguard Worker 		// We have the easy case if the last operator was an assignment
2548*5a6e8488SAndroid Build Coastguard Worker 		// operator.
2549*5a6e8488SAndroid Build Coastguard Worker 		if (assign)
2550*5a6e8488SAndroid Build Coastguard Worker 		{
2551*5a6e8488SAndroid Build Coastguard Worker 			inst = *((uchar*) bc_vec_top(&p->func->code));
2552*5a6e8488SAndroid Build Coastguard Worker 			inst += (BC_INST_ASSIGN_POWER_NO_VAL - BC_INST_ASSIGN_POWER);
2553*5a6e8488SAndroid Build Coastguard Worker 			incdec = false;
2554*5a6e8488SAndroid Build Coastguard Worker 		}
2555*5a6e8488SAndroid Build Coastguard Worker 		// If we have an inc/dec operator and we are *not* printing, implement
2556*5a6e8488SAndroid Build Coastguard Worker 		// the optimization to get rid of the extra copy.
2557*5a6e8488SAndroid Build Coastguard Worker 		else if (incdec && !(flags & BC_PARSE_PRINT))
2558*5a6e8488SAndroid Build Coastguard Worker 		{
2559*5a6e8488SAndroid Build Coastguard Worker 			inst = *((uchar*) bc_vec_top(&p->func->code));
2560*5a6e8488SAndroid Build Coastguard Worker 			incdec = (inst <= BC_INST_DEC);
2561*5a6e8488SAndroid Build Coastguard Worker 			inst = BC_INST_ASSIGN_PLUS_NO_VAL +
2562*5a6e8488SAndroid Build Coastguard Worker 			       (inst != BC_INST_INC && inst != BC_INST_ASSIGN_PLUS);
2563*5a6e8488SAndroid Build Coastguard Worker 		}
2564*5a6e8488SAndroid Build Coastguard Worker 
2565*5a6e8488SAndroid Build Coastguard Worker 		// This condition allows us to change the previous assignment
2566*5a6e8488SAndroid Build Coastguard Worker 		// instruction (which does a copy) for a NO_VAL version, which does not.
2567*5a6e8488SAndroid Build Coastguard Worker 		// This condition is set if either of the above if statements ends up
2568*5a6e8488SAndroid Build Coastguard Worker 		// being true.
2569*5a6e8488SAndroid Build Coastguard Worker 		if (inst >= BC_INST_ASSIGN_POWER_NO_VAL &&
2570*5a6e8488SAndroid Build Coastguard Worker 		    inst <= BC_INST_ASSIGN_NO_VAL)
2571*5a6e8488SAndroid Build Coastguard Worker 		{
2572*5a6e8488SAndroid Build Coastguard Worker 			// Pop the previous assignment instruction and push a new one.
2573*5a6e8488SAndroid Build Coastguard Worker 			// Inc/dec needs the extra instruction because it is now a binary
2574*5a6e8488SAndroid Build Coastguard Worker 			// operator and needs a second operand.
2575*5a6e8488SAndroid Build Coastguard Worker 			bc_vec_pop(&p->func->code);
2576*5a6e8488SAndroid Build Coastguard Worker 			if (incdec) bc_parse_push(p, BC_INST_ONE);
2577*5a6e8488SAndroid Build Coastguard Worker 			bc_parse_push(p, inst);
2578*5a6e8488SAndroid Build Coastguard Worker 		}
2579*5a6e8488SAndroid Build Coastguard Worker 	}
2580*5a6e8488SAndroid Build Coastguard Worker 
2581*5a6e8488SAndroid Build Coastguard Worker 	// If we might have to print...
2582*5a6e8488SAndroid Build Coastguard Worker 	if ((flags & BC_PARSE_PRINT))
2583*5a6e8488SAndroid Build Coastguard Worker 	{
2584*5a6e8488SAndroid Build Coastguard Worker 		// With a paren first or the last operator not being an assignment, we
2585*5a6e8488SAndroid Build Coastguard Worker 		// *do* want to print.
2586*5a6e8488SAndroid Build Coastguard Worker 		if (pfirst || !assign) bc_parse_push(p, BC_INST_PRINT);
2587*5a6e8488SAndroid Build Coastguard Worker 	}
2588*5a6e8488SAndroid Build Coastguard Worker 	// We need to make sure to push a pop instruction for assignment statements
2589*5a6e8488SAndroid Build Coastguard Worker 	// that will not print. The print will pop, but without it, we need to pop.
2590*5a6e8488SAndroid Build Coastguard Worker 	else if (!(flags & BC_PARSE_NEEDVAL) &&
2591*5a6e8488SAndroid Build Coastguard Worker 	         (inst < BC_INST_ASSIGN_POWER_NO_VAL ||
2592*5a6e8488SAndroid Build Coastguard Worker 	          inst > BC_INST_ASSIGN_NO_VAL))
2593*5a6e8488SAndroid Build Coastguard Worker 	{
2594*5a6e8488SAndroid Build Coastguard Worker 		bc_parse_push(p, BC_INST_POP);
2595*5a6e8488SAndroid Build Coastguard Worker 	}
2596*5a6e8488SAndroid Build Coastguard Worker 
2597*5a6e8488SAndroid Build Coastguard Worker 	// We want to eat newlines if newlines are not a valid ending token.
2598*5a6e8488SAndroid Build Coastguard Worker 	// This is for spacing in things like for loop headers.
2599*5a6e8488SAndroid Build Coastguard Worker 	//
2600*5a6e8488SAndroid Build Coastguard Worker 	// Yes, this is one case where I reuse a variable for a different purpose;
2601*5a6e8488SAndroid Build Coastguard Worker 	// in this case, incdec being true now means that newlines are not valid.
2602*5a6e8488SAndroid Build Coastguard Worker 	for (incdec = true, i = 0; i < next.len && incdec; ++i)
2603*5a6e8488SAndroid Build Coastguard Worker 	{
2604*5a6e8488SAndroid Build Coastguard Worker 		incdec = (next.tokens[i] != BC_LEX_NLINE);
2605*5a6e8488SAndroid Build Coastguard Worker 	}
2606*5a6e8488SAndroid Build Coastguard Worker 	if (incdec)
2607*5a6e8488SAndroid Build Coastguard Worker 	{
2608*5a6e8488SAndroid Build Coastguard Worker 		while (p->l.t == BC_LEX_NLINE)
2609*5a6e8488SAndroid Build Coastguard Worker 		{
2610*5a6e8488SAndroid Build Coastguard Worker 			bc_lex_next(&p->l);
2611*5a6e8488SAndroid Build Coastguard Worker 		}
2612*5a6e8488SAndroid Build Coastguard Worker 	}
2613*5a6e8488SAndroid Build Coastguard Worker 
2614*5a6e8488SAndroid Build Coastguard Worker 	return BC_PARSE_STATUS_SUCCESS;
2615*5a6e8488SAndroid Build Coastguard Worker }
2616*5a6e8488SAndroid Build Coastguard Worker 
2617*5a6e8488SAndroid Build Coastguard Worker /**
2618*5a6e8488SAndroid Build Coastguard Worker  * Parses an expression with bc_parse_expr_err(), but throws an error if it gets
2619*5a6e8488SAndroid Build Coastguard Worker  * an empty expression.
2620*5a6e8488SAndroid Build Coastguard Worker  * @param p      The parser.
2621*5a6e8488SAndroid Build Coastguard Worker  * @param flags  The flags for what is valid in the expression.
2622*5a6e8488SAndroid Build Coastguard Worker  * @param next   A set of tokens for what is valid *after* the expression.
2623*5a6e8488SAndroid Build Coastguard Worker  */
2624*5a6e8488SAndroid Build Coastguard Worker static void
bc_parse_expr_status(BcParse * p,uint8_t flags,BcParseNext next)2625*5a6e8488SAndroid Build Coastguard Worker bc_parse_expr_status(BcParse* p, uint8_t flags, BcParseNext next)
2626*5a6e8488SAndroid Build Coastguard Worker {
2627*5a6e8488SAndroid Build Coastguard Worker 	BcParseStatus s = bc_parse_expr_err(p, flags, next);
2628*5a6e8488SAndroid Build Coastguard Worker 
2629*5a6e8488SAndroid Build Coastguard Worker 	if (BC_ERR(s == BC_PARSE_STATUS_EMPTY_EXPR))
2630*5a6e8488SAndroid Build Coastguard Worker 	{
2631*5a6e8488SAndroid Build Coastguard Worker 		bc_parse_err(p, BC_ERR_PARSE_EMPTY_EXPR);
2632*5a6e8488SAndroid Build Coastguard Worker 	}
2633*5a6e8488SAndroid Build Coastguard Worker }
2634*5a6e8488SAndroid Build Coastguard Worker 
2635*5a6e8488SAndroid Build Coastguard Worker void
bc_parse_expr(BcParse * p,uint8_t flags)2636*5a6e8488SAndroid Build Coastguard Worker bc_parse_expr(BcParse* p, uint8_t flags)
2637*5a6e8488SAndroid Build Coastguard Worker {
2638*5a6e8488SAndroid Build Coastguard Worker 	assert(p);
2639*5a6e8488SAndroid Build Coastguard Worker 	bc_parse_expr_status(p, flags, bc_parse_next_read);
2640*5a6e8488SAndroid Build Coastguard Worker }
2641*5a6e8488SAndroid Build Coastguard Worker #endif // BC_ENABLED
2642