1*cf5a6c84SAndroid Build Coastguard Worker /* bc.c - An implementation of POSIX bc.
2*cf5a6c84SAndroid Build Coastguard Worker *
3*cf5a6c84SAndroid Build Coastguard Worker * Copyright 2018 Gavin D. Howard <[email protected]>
4*cf5a6c84SAndroid Build Coastguard Worker *
5*cf5a6c84SAndroid Build Coastguard Worker * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html
6*cf5a6c84SAndroid Build Coastguard Worker
7*cf5a6c84SAndroid Build Coastguard Worker USE_BC(NEWTOY(bc, "i(interactive)l(mathlib)q(quiet)s(standard)w(warn)", TOYFLAG_USR|TOYFLAG_BIN))
8*cf5a6c84SAndroid Build Coastguard Worker
9*cf5a6c84SAndroid Build Coastguard Worker config BC
10*cf5a6c84SAndroid Build Coastguard Worker bool "bc"
11*cf5a6c84SAndroid Build Coastguard Worker default n
12*cf5a6c84SAndroid Build Coastguard Worker help
13*cf5a6c84SAndroid Build Coastguard Worker usage: bc [-ilqsw] [file ...]
14*cf5a6c84SAndroid Build Coastguard Worker
15*cf5a6c84SAndroid Build Coastguard Worker bc is a command-line calculator with a Turing-complete language.
16*cf5a6c84SAndroid Build Coastguard Worker
17*cf5a6c84SAndroid Build Coastguard Worker options:
18*cf5a6c84SAndroid Build Coastguard Worker
19*cf5a6c84SAndroid Build Coastguard Worker -i --interactive force interactive mode
20*cf5a6c84SAndroid Build Coastguard Worker -l --mathlib use predefined math routines:
21*cf5a6c84SAndroid Build Coastguard Worker
22*cf5a6c84SAndroid Build Coastguard Worker s(expr) = sine of expr in radians
23*cf5a6c84SAndroid Build Coastguard Worker c(expr) = cosine of expr in radians
24*cf5a6c84SAndroid Build Coastguard Worker a(expr) = arctangent of expr, returning radians
25*cf5a6c84SAndroid Build Coastguard Worker l(expr) = natural log of expr
26*cf5a6c84SAndroid Build Coastguard Worker e(expr) = raises e to the power of expr
27*cf5a6c84SAndroid Build Coastguard Worker j(n, x) = Bessel function of integer order n of x
28*cf5a6c84SAndroid Build Coastguard Worker
29*cf5a6c84SAndroid Build Coastguard Worker -q --quiet don't print version and copyright
30*cf5a6c84SAndroid Build Coastguard Worker -s --standard error if any non-POSIX extensions are used
31*cf5a6c84SAndroid Build Coastguard Worker -w --warn warn if any non-POSIX extensions are used
32*cf5a6c84SAndroid Build Coastguard Worker
33*cf5a6c84SAndroid Build Coastguard Worker */
34*cf5a6c84SAndroid Build Coastguard Worker
35*cf5a6c84SAndroid Build Coastguard Worker #define FOR_bc
36*cf5a6c84SAndroid Build Coastguard Worker #include "toys.h"
37*cf5a6c84SAndroid Build Coastguard Worker
38*cf5a6c84SAndroid Build Coastguard Worker GLOBALS(
39*cf5a6c84SAndroid Build Coastguard Worker // This actually needs to be a BcVm*, but the toybox build
40*cf5a6c84SAndroid Build Coastguard Worker // system complains if I make it so. Instead, we'll just cast.
41*cf5a6c84SAndroid Build Coastguard Worker char *vm;
42*cf5a6c84SAndroid Build Coastguard Worker
43*cf5a6c84SAndroid Build Coastguard Worker size_t nchars;
44*cf5a6c84SAndroid Build Coastguard Worker char *file, sig, max_ibase;
45*cf5a6c84SAndroid Build Coastguard Worker uint16_t line_len;
46*cf5a6c84SAndroid Build Coastguard Worker )
47*cf5a6c84SAndroid Build Coastguard Worker
48*cf5a6c84SAndroid Build Coastguard Worker struct str_len {
49*cf5a6c84SAndroid Build Coastguard Worker char *str;
50*cf5a6c84SAndroid Build Coastguard Worker long len;
51*cf5a6c84SAndroid Build Coastguard Worker };
52*cf5a6c84SAndroid Build Coastguard Worker
53*cf5a6c84SAndroid Build Coastguard Worker #define BC_VM ((BcVm*) TT.vm)
54*cf5a6c84SAndroid Build Coastguard Worker
55*cf5a6c84SAndroid Build Coastguard Worker typedef enum BcStatus {
56*cf5a6c84SAndroid Build Coastguard Worker
57*cf5a6c84SAndroid Build Coastguard Worker BC_STATUS_SUCCESS = 0,
58*cf5a6c84SAndroid Build Coastguard Worker BC_STATUS_ERROR,
59*cf5a6c84SAndroid Build Coastguard Worker BC_STATUS_EOF,
60*cf5a6c84SAndroid Build Coastguard Worker BC_STATUS_EMPTY_EXPR,
61*cf5a6c84SAndroid Build Coastguard Worker BC_STATUS_SIGNAL,
62*cf5a6c84SAndroid Build Coastguard Worker BC_STATUS_QUIT,
63*cf5a6c84SAndroid Build Coastguard Worker
64*cf5a6c84SAndroid Build Coastguard Worker } BcStatus;
65*cf5a6c84SAndroid Build Coastguard Worker
66*cf5a6c84SAndroid Build Coastguard Worker typedef enum BcError {
67*cf5a6c84SAndroid Build Coastguard Worker
68*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_VM_ALLOC_ERR,
69*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_VM_IO_ERR,
70*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_VM_BIN_FILE,
71*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_VM_PATH_DIR,
72*cf5a6c84SAndroid Build Coastguard Worker
73*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_PARSE_EOF,
74*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_PARSE_CHAR,
75*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_PARSE_STRING,
76*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_PARSE_COMMENT,
77*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_PARSE_TOKEN,
78*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_EXEC_NUM_LEN,
79*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_EXEC_NAME_LEN,
80*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_EXEC_STRING_LEN,
81*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_PARSE_EXPR,
82*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_PARSE_EMPTY_EXPR,
83*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_PARSE_PRINT,
84*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_PARSE_FUNC,
85*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_PARSE_ASSIGN,
86*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_PARSE_NO_AUTO,
87*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_PARSE_DUP_LOCAL,
88*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_PARSE_BLOCK,
89*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_PARSE_RET_VOID,
90*cf5a6c84SAndroid Build Coastguard Worker
91*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_MATH_NEGATIVE,
92*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_MATH_NON_INTEGER,
93*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_MATH_OVERFLOW,
94*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_MATH_DIVIDE_BY_ZERO,
95*cf5a6c84SAndroid Build Coastguard Worker
96*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_EXEC_FILE_ERR,
97*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_EXEC_ARRAY_LEN,
98*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_EXEC_IBASE,
99*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_EXEC_OBASE,
100*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_EXEC_SCALE,
101*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_EXEC_READ_EXPR,
102*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_EXEC_REC_READ,
103*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_EXEC_TYPE,
104*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_EXEC_PARAMS,
105*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_EXEC_UNDEF_FUNC,
106*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_EXEC_VOID_VAL,
107*cf5a6c84SAndroid Build Coastguard Worker
108*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_POSIX_START,
109*cf5a6c84SAndroid Build Coastguard Worker
110*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_POSIX_NAME_LEN = BC_ERROR_POSIX_START,
111*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_POSIX_COMMENT,
112*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_POSIX_KW,
113*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_POSIX_DOT,
114*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_POSIX_RET,
115*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_POSIX_BOOL,
116*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_POSIX_REL_POS,
117*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_POSIX_MULTIREL,
118*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_POSIX_FOR1,
119*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_POSIX_FOR2,
120*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_POSIX_FOR3,
121*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_POSIX_BRACE,
122*cf5a6c84SAndroid Build Coastguard Worker BC_ERROR_POSIX_REF,
123*cf5a6c84SAndroid Build Coastguard Worker
124*cf5a6c84SAndroid Build Coastguard Worker } BcError;
125*cf5a6c84SAndroid Build Coastguard Worker
126*cf5a6c84SAndroid Build Coastguard Worker #define BC_ERR_IDX_VM (0)
127*cf5a6c84SAndroid Build Coastguard Worker #define BC_ERR_IDX_PARSE (1)
128*cf5a6c84SAndroid Build Coastguard Worker #define BC_ERR_IDX_MATH (2)
129*cf5a6c84SAndroid Build Coastguard Worker #define BC_ERR_IDX_EXEC (3)
130*cf5a6c84SAndroid Build Coastguard Worker #define BC_ERR_IDX_POSIX (4)
131*cf5a6c84SAndroid Build Coastguard Worker
132*cf5a6c84SAndroid Build Coastguard Worker #define BC_VEC_START_CAP (1<<5)
133*cf5a6c84SAndroid Build Coastguard Worker
134*cf5a6c84SAndroid Build Coastguard Worker typedef void (*BcVecFree)(void*);
135*cf5a6c84SAndroid Build Coastguard Worker
136*cf5a6c84SAndroid Build Coastguard Worker typedef struct BcVec {
137*cf5a6c84SAndroid Build Coastguard Worker char *v;
138*cf5a6c84SAndroid Build Coastguard Worker size_t len, cap, size;
139*cf5a6c84SAndroid Build Coastguard Worker BcVecFree dtor;
140*cf5a6c84SAndroid Build Coastguard Worker } BcVec;
141*cf5a6c84SAndroid Build Coastguard Worker
142*cf5a6c84SAndroid Build Coastguard Worker #define bc_vec_pop(v) (bc_vec_npop((v), 1))
143*cf5a6c84SAndroid Build Coastguard Worker #define bc_vec_top(v) (bc_vec_item_rev((v), 0))
144*cf5a6c84SAndroid Build Coastguard Worker
145*cf5a6c84SAndroid Build Coastguard Worker typedef signed char BcDig;
146*cf5a6c84SAndroid Build Coastguard Worker
147*cf5a6c84SAndroid Build Coastguard Worker typedef struct BcNum {
148*cf5a6c84SAndroid Build Coastguard Worker signed char *num;
149*cf5a6c84SAndroid Build Coastguard Worker unsigned long rdx, len, cap;
150*cf5a6c84SAndroid Build Coastguard Worker int neg;
151*cf5a6c84SAndroid Build Coastguard Worker } BcNum;
152*cf5a6c84SAndroid Build Coastguard Worker
153*cf5a6c84SAndroid Build Coastguard Worker #define BC_NUM_DEF_SIZE (16)
154*cf5a6c84SAndroid Build Coastguard Worker
155*cf5a6c84SAndroid Build Coastguard Worker // A crude, but always big enough, calculation of
156*cf5a6c84SAndroid Build Coastguard Worker // the size required for ibase and obase BcNum's.
157*cf5a6c84SAndroid Build Coastguard Worker #define BC_NUM_LONG_LOG10 ((CHAR_BIT * sizeof(unsigned long) + 1) / 2 + 1)
158*cf5a6c84SAndroid Build Coastguard Worker
159*cf5a6c84SAndroid Build Coastguard Worker #define BC_NUM_NEG(n, neg) ((((ssize_t) (n)) ^ -((ssize_t) (neg))) + (neg))
160*cf5a6c84SAndroid Build Coastguard Worker
161*cf5a6c84SAndroid Build Coastguard Worker #define BC_NUM_ONE(n) ((n)->len == 1 && (n)->rdx == 0 && (n)->num[0] == 1)
162*cf5a6c84SAndroid Build Coastguard Worker #define BC_NUM_INT(n) ((n)->len - (n)->rdx)
163*cf5a6c84SAndroid Build Coastguard Worker #define BC_NUM_CMP_ZERO(a) (BC_NUM_NEG((a)->len != 0, (a)->neg))
164*cf5a6c84SAndroid Build Coastguard Worker
165*cf5a6c84SAndroid Build Coastguard Worker typedef BcStatus (*BcNumBinaryOp)(BcNum*, BcNum*, BcNum*, size_t);
166*cf5a6c84SAndroid Build Coastguard Worker typedef size_t (*BcNumBinaryOpReq)(BcNum*, BcNum*, size_t);
167*cf5a6c84SAndroid Build Coastguard Worker typedef void (*BcNumDigitOp)(size_t, size_t, int);
168*cf5a6c84SAndroid Build Coastguard Worker
169*cf5a6c84SAndroid Build Coastguard Worker void bc_num_init(BcNum *n, size_t req);
170*cf5a6c84SAndroid Build Coastguard Worker void bc_num_expand(BcNum *n, size_t req);
171*cf5a6c84SAndroid Build Coastguard Worker void bc_num_copy(BcNum *d, BcNum *s);
172*cf5a6c84SAndroid Build Coastguard Worker void bc_num_createCopy(BcNum *d, BcNum *s);
173*cf5a6c84SAndroid Build Coastguard Worker void bc_num_createFromUlong(BcNum *n, unsigned long val);
174*cf5a6c84SAndroid Build Coastguard Worker void bc_num_free(void *num);
175*cf5a6c84SAndroid Build Coastguard Worker
176*cf5a6c84SAndroid Build Coastguard Worker BcStatus bc_num_ulong(BcNum *n, unsigned long *result);
177*cf5a6c84SAndroid Build Coastguard Worker void bc_num_ulong2num(BcNum *n, unsigned long val);
178*cf5a6c84SAndroid Build Coastguard Worker
179*cf5a6c84SAndroid Build Coastguard Worker BcStatus bc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale);
180*cf5a6c84SAndroid Build Coastguard Worker BcStatus bc_num_sub(BcNum *a, BcNum *b, BcNum *c, size_t scale);
181*cf5a6c84SAndroid Build Coastguard Worker BcStatus bc_num_mul(BcNum *a, BcNum *b, BcNum *c, size_t scale);
182*cf5a6c84SAndroid Build Coastguard Worker BcStatus bc_num_div(BcNum *a, BcNum *b, BcNum *c, size_t scale);
183*cf5a6c84SAndroid Build Coastguard Worker BcStatus bc_num_mod(BcNum *a, BcNum *b, BcNum *c, size_t scale);
184*cf5a6c84SAndroid Build Coastguard Worker BcStatus bc_num_pow(BcNum *a, BcNum *b, BcNum *c, size_t scale);
185*cf5a6c84SAndroid Build Coastguard Worker BcStatus bc_num_sqrt(BcNum *a, BcNum *b, size_t scale);
186*cf5a6c84SAndroid Build Coastguard Worker BcStatus bc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d, size_t scale);
187*cf5a6c84SAndroid Build Coastguard Worker
188*cf5a6c84SAndroid Build Coastguard Worker size_t bc_num_addReq(BcNum *a, BcNum *b, size_t scale);
189*cf5a6c84SAndroid Build Coastguard Worker
190*cf5a6c84SAndroid Build Coastguard Worker size_t bc_num_mulReq(BcNum *a, BcNum *b, size_t scale);
191*cf5a6c84SAndroid Build Coastguard Worker size_t bc_num_powReq(BcNum *a, BcNum *b, size_t scale);
192*cf5a6c84SAndroid Build Coastguard Worker
193*cf5a6c84SAndroid Build Coastguard Worker typedef enum BcInst {
194*cf5a6c84SAndroid Build Coastguard Worker
195*cf5a6c84SAndroid Build Coastguard Worker BC_INST_INC_POST = 0,
196*cf5a6c84SAndroid Build Coastguard Worker BC_INST_DEC_POST,
197*cf5a6c84SAndroid Build Coastguard Worker BC_INST_INC_PRE,
198*cf5a6c84SAndroid Build Coastguard Worker BC_INST_DEC_PRE,
199*cf5a6c84SAndroid Build Coastguard Worker
200*cf5a6c84SAndroid Build Coastguard Worker BC_INST_NEG,
201*cf5a6c84SAndroid Build Coastguard Worker BC_INST_BOOL_NOT,
202*cf5a6c84SAndroid Build Coastguard Worker
203*cf5a6c84SAndroid Build Coastguard Worker BC_INST_POWER,
204*cf5a6c84SAndroid Build Coastguard Worker BC_INST_MULTIPLY,
205*cf5a6c84SAndroid Build Coastguard Worker BC_INST_DIVIDE,
206*cf5a6c84SAndroid Build Coastguard Worker BC_INST_MODULUS,
207*cf5a6c84SAndroid Build Coastguard Worker BC_INST_PLUS,
208*cf5a6c84SAndroid Build Coastguard Worker BC_INST_MINUS,
209*cf5a6c84SAndroid Build Coastguard Worker
210*cf5a6c84SAndroid Build Coastguard Worker BC_INST_REL_EQ,
211*cf5a6c84SAndroid Build Coastguard Worker BC_INST_REL_LE,
212*cf5a6c84SAndroid Build Coastguard Worker BC_INST_REL_GE,
213*cf5a6c84SAndroid Build Coastguard Worker BC_INST_REL_NE,
214*cf5a6c84SAndroid Build Coastguard Worker BC_INST_REL_LT,
215*cf5a6c84SAndroid Build Coastguard Worker BC_INST_REL_GT,
216*cf5a6c84SAndroid Build Coastguard Worker
217*cf5a6c84SAndroid Build Coastguard Worker BC_INST_BOOL_OR,
218*cf5a6c84SAndroid Build Coastguard Worker BC_INST_BOOL_AND,
219*cf5a6c84SAndroid Build Coastguard Worker
220*cf5a6c84SAndroid Build Coastguard Worker BC_INST_ASSIGN_POWER,
221*cf5a6c84SAndroid Build Coastguard Worker BC_INST_ASSIGN_MULTIPLY,
222*cf5a6c84SAndroid Build Coastguard Worker BC_INST_ASSIGN_DIVIDE,
223*cf5a6c84SAndroid Build Coastguard Worker BC_INST_ASSIGN_MODULUS,
224*cf5a6c84SAndroid Build Coastguard Worker BC_INST_ASSIGN_PLUS,
225*cf5a6c84SAndroid Build Coastguard Worker BC_INST_ASSIGN_MINUS,
226*cf5a6c84SAndroid Build Coastguard Worker BC_INST_ASSIGN,
227*cf5a6c84SAndroid Build Coastguard Worker
228*cf5a6c84SAndroid Build Coastguard Worker BC_INST_NUM,
229*cf5a6c84SAndroid Build Coastguard Worker BC_INST_VAR,
230*cf5a6c84SAndroid Build Coastguard Worker BC_INST_ARRAY_ELEM,
231*cf5a6c84SAndroid Build Coastguard Worker BC_INST_ARRAY,
232*cf5a6c84SAndroid Build Coastguard Worker
233*cf5a6c84SAndroid Build Coastguard Worker BC_INST_LAST,
234*cf5a6c84SAndroid Build Coastguard Worker BC_INST_IBASE,
235*cf5a6c84SAndroid Build Coastguard Worker BC_INST_OBASE,
236*cf5a6c84SAndroid Build Coastguard Worker BC_INST_SCALE,
237*cf5a6c84SAndroid Build Coastguard Worker BC_INST_LENGTH,
238*cf5a6c84SAndroid Build Coastguard Worker BC_INST_SCALE_FUNC,
239*cf5a6c84SAndroid Build Coastguard Worker BC_INST_SQRT,
240*cf5a6c84SAndroid Build Coastguard Worker BC_INST_ABS,
241*cf5a6c84SAndroid Build Coastguard Worker BC_INST_READ,
242*cf5a6c84SAndroid Build Coastguard Worker
243*cf5a6c84SAndroid Build Coastguard Worker BC_INST_PRINT,
244*cf5a6c84SAndroid Build Coastguard Worker BC_INST_PRINT_POP,
245*cf5a6c84SAndroid Build Coastguard Worker BC_INST_STR,
246*cf5a6c84SAndroid Build Coastguard Worker BC_INST_PRINT_STR,
247*cf5a6c84SAndroid Build Coastguard Worker
248*cf5a6c84SAndroid Build Coastguard Worker BC_INST_JUMP,
249*cf5a6c84SAndroid Build Coastguard Worker BC_INST_JUMP_ZERO,
250*cf5a6c84SAndroid Build Coastguard Worker
251*cf5a6c84SAndroid Build Coastguard Worker BC_INST_CALL,
252*cf5a6c84SAndroid Build Coastguard Worker
253*cf5a6c84SAndroid Build Coastguard Worker BC_INST_RET,
254*cf5a6c84SAndroid Build Coastguard Worker BC_INST_RET0,
255*cf5a6c84SAndroid Build Coastguard Worker BC_INST_RET_VOID,
256*cf5a6c84SAndroid Build Coastguard Worker
257*cf5a6c84SAndroid Build Coastguard Worker BC_INST_HALT,
258*cf5a6c84SAndroid Build Coastguard Worker
259*cf5a6c84SAndroid Build Coastguard Worker BC_INST_POP,
260*cf5a6c84SAndroid Build Coastguard Worker BC_INST_POP_EXEC,
261*cf5a6c84SAndroid Build Coastguard Worker
262*cf5a6c84SAndroid Build Coastguard Worker } BcInst;
263*cf5a6c84SAndroid Build Coastguard Worker
264*cf5a6c84SAndroid Build Coastguard Worker typedef struct BcFunc {
265*cf5a6c84SAndroid Build Coastguard Worker
266*cf5a6c84SAndroid Build Coastguard Worker BcVec code;
267*cf5a6c84SAndroid Build Coastguard Worker BcVec labels;
268*cf5a6c84SAndroid Build Coastguard Worker BcVec autos;
269*cf5a6c84SAndroid Build Coastguard Worker size_t nparams;
270*cf5a6c84SAndroid Build Coastguard Worker
271*cf5a6c84SAndroid Build Coastguard Worker BcVec strs;
272*cf5a6c84SAndroid Build Coastguard Worker BcVec consts;
273*cf5a6c84SAndroid Build Coastguard Worker
274*cf5a6c84SAndroid Build Coastguard Worker char *name;
275*cf5a6c84SAndroid Build Coastguard Worker int voidfn;
276*cf5a6c84SAndroid Build Coastguard Worker
277*cf5a6c84SAndroid Build Coastguard Worker } BcFunc;
278*cf5a6c84SAndroid Build Coastguard Worker
279*cf5a6c84SAndroid Build Coastguard Worker typedef enum BcResultType {
280*cf5a6c84SAndroid Build Coastguard Worker
281*cf5a6c84SAndroid Build Coastguard Worker BC_RESULT_VAR,
282*cf5a6c84SAndroid Build Coastguard Worker BC_RESULT_ARRAY_ELEM,
283*cf5a6c84SAndroid Build Coastguard Worker BC_RESULT_ARRAY,
284*cf5a6c84SAndroid Build Coastguard Worker
285*cf5a6c84SAndroid Build Coastguard Worker BC_RESULT_STR,
286*cf5a6c84SAndroid Build Coastguard Worker
287*cf5a6c84SAndroid Build Coastguard Worker BC_RESULT_CONSTANT,
288*cf5a6c84SAndroid Build Coastguard Worker BC_RESULT_TEMP,
289*cf5a6c84SAndroid Build Coastguard Worker
290*cf5a6c84SAndroid Build Coastguard Worker BC_RESULT_VOID,
291*cf5a6c84SAndroid Build Coastguard Worker BC_RESULT_ONE,
292*cf5a6c84SAndroid Build Coastguard Worker BC_RESULT_LAST,
293*cf5a6c84SAndroid Build Coastguard Worker BC_RESULT_IBASE,
294*cf5a6c84SAndroid Build Coastguard Worker BC_RESULT_OBASE,
295*cf5a6c84SAndroid Build Coastguard Worker BC_RESULT_SCALE,
296*cf5a6c84SAndroid Build Coastguard Worker
297*cf5a6c84SAndroid Build Coastguard Worker } BcResultType;
298*cf5a6c84SAndroid Build Coastguard Worker
299*cf5a6c84SAndroid Build Coastguard Worker typedef union BcResultData {
300*cf5a6c84SAndroid Build Coastguard Worker BcNum n;
301*cf5a6c84SAndroid Build Coastguard Worker BcVec v;
302*cf5a6c84SAndroid Build Coastguard Worker struct str_len id;
303*cf5a6c84SAndroid Build Coastguard Worker } BcResultData;
304*cf5a6c84SAndroid Build Coastguard Worker
305*cf5a6c84SAndroid Build Coastguard Worker typedef struct BcResult {
306*cf5a6c84SAndroid Build Coastguard Worker BcResultType t;
307*cf5a6c84SAndroid Build Coastguard Worker BcResultData d;
308*cf5a6c84SAndroid Build Coastguard Worker } BcResult;
309*cf5a6c84SAndroid Build Coastguard Worker
310*cf5a6c84SAndroid Build Coastguard Worker typedef struct BcInstPtr {
311*cf5a6c84SAndroid Build Coastguard Worker size_t func;
312*cf5a6c84SAndroid Build Coastguard Worker size_t idx;
313*cf5a6c84SAndroid Build Coastguard Worker size_t len;
314*cf5a6c84SAndroid Build Coastguard Worker } BcInstPtr;
315*cf5a6c84SAndroid Build Coastguard Worker
316*cf5a6c84SAndroid Build Coastguard Worker typedef enum BcType {
317*cf5a6c84SAndroid Build Coastguard Worker BC_TYPE_VAR,
318*cf5a6c84SAndroid Build Coastguard Worker BC_TYPE_ARRAY,
319*cf5a6c84SAndroid Build Coastguard Worker } BcType;
320*cf5a6c84SAndroid Build Coastguard Worker
321*cf5a6c84SAndroid Build Coastguard Worker void bc_array_expand(BcVec *a, size_t len);
322*cf5a6c84SAndroid Build Coastguard Worker int bc_id_cmp(struct str_len *e1, struct str_len *e2);
323*cf5a6c84SAndroid Build Coastguard Worker
324*cf5a6c84SAndroid Build Coastguard Worker #define bc_lex_err(l, e) (bc_vm_error((e), (l)->line))
325*cf5a6c84SAndroid Build Coastguard Worker #define bc_lex_verr(l, e, ...) (bc_vm_error((e), (l)->line, __VA_ARGS__))
326*cf5a6c84SAndroid Build Coastguard Worker
327*cf5a6c84SAndroid Build Coastguard Worker #define BC_LEX_NUM_CHAR(c, l, pt) \
328*cf5a6c84SAndroid Build Coastguard Worker (isdigit(c) || ((c) >= 'A' && (c) <= (l)) || ((c) == '.' && !(pt)))
329*cf5a6c84SAndroid Build Coastguard Worker
330*cf5a6c84SAndroid Build Coastguard Worker // BC_LEX_NEG is not used in lexing; it is only for parsing.
331*cf5a6c84SAndroid Build Coastguard Worker typedef enum BcLexType {
332*cf5a6c84SAndroid Build Coastguard Worker
333*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_EOF,
334*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_INVALID,
335*cf5a6c84SAndroid Build Coastguard Worker
336*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_OP_INC,
337*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_OP_DEC,
338*cf5a6c84SAndroid Build Coastguard Worker
339*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_NEG,
340*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_OP_BOOL_NOT,
341*cf5a6c84SAndroid Build Coastguard Worker
342*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_OP_POWER,
343*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_OP_MULTIPLY,
344*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_OP_DIVIDE,
345*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_OP_MODULUS,
346*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_OP_PLUS,
347*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_OP_MINUS,
348*cf5a6c84SAndroid Build Coastguard Worker
349*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_OP_REL_EQ,
350*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_OP_REL_LE,
351*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_OP_REL_GE,
352*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_OP_REL_NE,
353*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_OP_REL_LT,
354*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_OP_REL_GT,
355*cf5a6c84SAndroid Build Coastguard Worker
356*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_OP_BOOL_OR,
357*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_OP_BOOL_AND,
358*cf5a6c84SAndroid Build Coastguard Worker
359*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_OP_ASSIGN_POWER,
360*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_OP_ASSIGN_MULTIPLY,
361*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_OP_ASSIGN_DIVIDE,
362*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_OP_ASSIGN_MODULUS,
363*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_OP_ASSIGN_PLUS,
364*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_OP_ASSIGN_MINUS,
365*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_OP_ASSIGN,
366*cf5a6c84SAndroid Build Coastguard Worker
367*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_NLINE,
368*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_WHITESPACE,
369*cf5a6c84SAndroid Build Coastguard Worker
370*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_LPAREN,
371*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_RPAREN,
372*cf5a6c84SAndroid Build Coastguard Worker
373*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_LBRACKET,
374*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_COMMA,
375*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_RBRACKET,
376*cf5a6c84SAndroid Build Coastguard Worker
377*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_LBRACE,
378*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_SCOLON,
379*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_RBRACE,
380*cf5a6c84SAndroid Build Coastguard Worker
381*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_STR,
382*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_NAME,
383*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_NUMBER,
384*cf5a6c84SAndroid Build Coastguard Worker
385*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_KEY_AUTO,
386*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_KEY_BREAK,
387*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_KEY_CONTINUE,
388*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_KEY_DEFINE,
389*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_KEY_FOR,
390*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_KEY_IF,
391*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_KEY_LIMITS,
392*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_KEY_RETURN,
393*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_KEY_WHILE,
394*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_KEY_HALT,
395*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_KEY_LAST,
396*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_KEY_IBASE,
397*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_KEY_OBASE,
398*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_KEY_SCALE,
399*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_KEY_LENGTH,
400*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_KEY_PRINT,
401*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_KEY_SQRT,
402*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_KEY_ABS,
403*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_KEY_QUIT,
404*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_KEY_READ,
405*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_KEY_ELSE,
406*cf5a6c84SAndroid Build Coastguard Worker
407*cf5a6c84SAndroid Build Coastguard Worker } BcLexType;
408*cf5a6c84SAndroid Build Coastguard Worker
409*cf5a6c84SAndroid Build Coastguard Worker typedef struct BcLex {
410*cf5a6c84SAndroid Build Coastguard Worker
411*cf5a6c84SAndroid Build Coastguard Worker char *buf;
412*cf5a6c84SAndroid Build Coastguard Worker size_t i;
413*cf5a6c84SAndroid Build Coastguard Worker size_t line;
414*cf5a6c84SAndroid Build Coastguard Worker size_t len;
415*cf5a6c84SAndroid Build Coastguard Worker
416*cf5a6c84SAndroid Build Coastguard Worker BcLexType t;
417*cf5a6c84SAndroid Build Coastguard Worker BcLexType last;
418*cf5a6c84SAndroid Build Coastguard Worker BcVec str;
419*cf5a6c84SAndroid Build Coastguard Worker
420*cf5a6c84SAndroid Build Coastguard Worker } BcLex;
421*cf5a6c84SAndroid Build Coastguard Worker
422*cf5a6c84SAndroid Build Coastguard Worker #define BC_PARSE_REL (1<<0)
423*cf5a6c84SAndroid Build Coastguard Worker #define BC_PARSE_PRINT (1<<1)
424*cf5a6c84SAndroid Build Coastguard Worker #define BC_PARSE_NOCALL (1<<2)
425*cf5a6c84SAndroid Build Coastguard Worker #define BC_PARSE_NOREAD (1<<3)
426*cf5a6c84SAndroid Build Coastguard Worker #define BC_PARSE_ARRAY (1<<4)
427*cf5a6c84SAndroid Build Coastguard Worker
428*cf5a6c84SAndroid Build Coastguard Worker #define bc_parse_push(p, i) (bc_vec_pushByte(&(p)->func->code, i))
429*cf5a6c84SAndroid Build Coastguard Worker #define bc_parse_number(p)(bc_parse_addId((p), BC_INST_NUM))
430*cf5a6c84SAndroid Build Coastguard Worker #define bc_parse_string(p)(bc_parse_addId((p), BC_INST_STR))
431*cf5a6c84SAndroid Build Coastguard Worker
432*cf5a6c84SAndroid Build Coastguard Worker #define bc_parse_err(p, e) (bc_vm_error((e), (p)->l.line))
433*cf5a6c84SAndroid Build Coastguard Worker #define bc_parse_verr(p, e, ...) (bc_vm_error((e), (p)->l.line, __VA_ARGS__))
434*cf5a6c84SAndroid Build Coastguard Worker
435*cf5a6c84SAndroid Build Coastguard Worker typedef struct BcParseNext {
436*cf5a6c84SAndroid Build Coastguard Worker char len, tokens[4];
437*cf5a6c84SAndroid Build Coastguard Worker } BcParseNext;
438*cf5a6c84SAndroid Build Coastguard Worker
439*cf5a6c84SAndroid Build Coastguard Worker #define BC_PARSE_NEXT_TOKENS(...) .tokens = { __VA_ARGS__ }
440*cf5a6c84SAndroid Build Coastguard Worker #define BC_PARSE_NEXT(a, ...) { .len = a, BC_PARSE_NEXT_TOKENS(__VA_ARGS__) }
441*cf5a6c84SAndroid Build Coastguard Worker
442*cf5a6c84SAndroid Build Coastguard Worker struct BcProgram;
443*cf5a6c84SAndroid Build Coastguard Worker
444*cf5a6c84SAndroid Build Coastguard Worker typedef struct BcParse {
445*cf5a6c84SAndroid Build Coastguard Worker
446*cf5a6c84SAndroid Build Coastguard Worker BcLex l;
447*cf5a6c84SAndroid Build Coastguard Worker
448*cf5a6c84SAndroid Build Coastguard Worker BcVec flags;
449*cf5a6c84SAndroid Build Coastguard Worker BcVec exits;
450*cf5a6c84SAndroid Build Coastguard Worker BcVec conds;
451*cf5a6c84SAndroid Build Coastguard Worker BcVec ops;
452*cf5a6c84SAndroid Build Coastguard Worker
453*cf5a6c84SAndroid Build Coastguard Worker struct BcProgram *prog;
454*cf5a6c84SAndroid Build Coastguard Worker BcFunc *func;
455*cf5a6c84SAndroid Build Coastguard Worker size_t fidx;
456*cf5a6c84SAndroid Build Coastguard Worker
457*cf5a6c84SAndroid Build Coastguard Worker int auto_part;
458*cf5a6c84SAndroid Build Coastguard Worker
459*cf5a6c84SAndroid Build Coastguard Worker } BcParse;
460*cf5a6c84SAndroid Build Coastguard Worker
461*cf5a6c84SAndroid Build Coastguard Worker typedef struct BcLexKeyword {
462*cf5a6c84SAndroid Build Coastguard Worker char data, name[9];
463*cf5a6c84SAndroid Build Coastguard Worker } BcLexKeyword;
464*cf5a6c84SAndroid Build Coastguard Worker
465*cf5a6c84SAndroid Build Coastguard Worker #define BC_LEX_CHAR_MSB(bit) ((bit) << (CHAR_BIT - 1))
466*cf5a6c84SAndroid Build Coastguard Worker
467*cf5a6c84SAndroid Build Coastguard Worker #define BC_LEX_KW_POSIX(kw) ((kw)->data & (BC_LEX_CHAR_MSB(1)))
468*cf5a6c84SAndroid Build Coastguard Worker #define BC_LEX_KW_LEN(kw) ((size_t) ((kw)->data & ~(BC_LEX_CHAR_MSB(1))))
469*cf5a6c84SAndroid Build Coastguard Worker
470*cf5a6c84SAndroid Build Coastguard Worker #define BC_LEX_KW_ENTRY(a, b, c) \
471*cf5a6c84SAndroid Build Coastguard Worker { .data = ((b) & ~(BC_LEX_CHAR_MSB(1))) | BC_LEX_CHAR_MSB(c),.name = a }
472*cf5a6c84SAndroid Build Coastguard Worker
473*cf5a6c84SAndroid Build Coastguard Worker #define bc_lex_posixErr(l, e) (bc_vm_posixError((e), (l)->line))
474*cf5a6c84SAndroid Build Coastguard Worker #define bc_lex_vposixErr(l, e, ...) \
475*cf5a6c84SAndroid Build Coastguard Worker (bc_vm_posixError((e), (l)->line, __VA_ARGS__))
476*cf5a6c84SAndroid Build Coastguard Worker
477*cf5a6c84SAndroid Build Coastguard Worker BcStatus bc_lex_token(BcLex *l);
478*cf5a6c84SAndroid Build Coastguard Worker
479*cf5a6c84SAndroid Build Coastguard Worker #define BC_PARSE_TOP_FLAG_PTR(p) ((uint16_t*) bc_vec_top(&(p)->flags))
480*cf5a6c84SAndroid Build Coastguard Worker #define BC_PARSE_TOP_FLAG(p) (*(BC_PARSE_TOP_FLAG_PTR(p)))
481*cf5a6c84SAndroid Build Coastguard Worker
482*cf5a6c84SAndroid Build Coastguard Worker #define BC_PARSE_FLAG_BRACE (1<<0)
483*cf5a6c84SAndroid Build Coastguard Worker #define BC_PARSE_BRACE(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_BRACE)
484*cf5a6c84SAndroid Build Coastguard Worker
485*cf5a6c84SAndroid Build Coastguard Worker #define BC_PARSE_FLAG_FUNC_INNER (1<<1)
486*cf5a6c84SAndroid Build Coastguard Worker #define BC_PARSE_FUNC_INNER(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_FUNC_INNER)
487*cf5a6c84SAndroid Build Coastguard Worker
488*cf5a6c84SAndroid Build Coastguard Worker #define BC_PARSE_FLAG_FUNC (1<<2)
489*cf5a6c84SAndroid Build Coastguard Worker #define BC_PARSE_FUNC(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_FUNC)
490*cf5a6c84SAndroid Build Coastguard Worker
491*cf5a6c84SAndroid Build Coastguard Worker #define BC_PARSE_FLAG_BODY (1<<3)
492*cf5a6c84SAndroid Build Coastguard Worker #define BC_PARSE_BODY(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_BODY)
493*cf5a6c84SAndroid Build Coastguard Worker
494*cf5a6c84SAndroid Build Coastguard Worker #define BC_PARSE_FLAG_LOOP (1<<4)
495*cf5a6c84SAndroid Build Coastguard Worker #define BC_PARSE_LOOP(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_LOOP)
496*cf5a6c84SAndroid Build Coastguard Worker
497*cf5a6c84SAndroid Build Coastguard Worker #define BC_PARSE_FLAG_LOOP_INNER (1<<5)
498*cf5a6c84SAndroid Build Coastguard Worker #define BC_PARSE_LOOP_INNER(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_LOOP_INNER)
499*cf5a6c84SAndroid Build Coastguard Worker
500*cf5a6c84SAndroid Build Coastguard Worker #define BC_PARSE_FLAG_IF (1<<6)
501*cf5a6c84SAndroid Build Coastguard Worker #define BC_PARSE_IF(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_IF)
502*cf5a6c84SAndroid Build Coastguard Worker
503*cf5a6c84SAndroid Build Coastguard Worker #define BC_PARSE_FLAG_ELSE (1<<7)
504*cf5a6c84SAndroid Build Coastguard Worker #define BC_PARSE_ELSE(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_ELSE)
505*cf5a6c84SAndroid Build Coastguard Worker
506*cf5a6c84SAndroid Build Coastguard Worker #define BC_PARSE_FLAG_IF_END (1<<8)
507*cf5a6c84SAndroid Build Coastguard Worker #define BC_PARSE_IF_END(p) (BC_PARSE_TOP_FLAG(p) & BC_PARSE_FLAG_IF_END)
508*cf5a6c84SAndroid Build Coastguard Worker
509*cf5a6c84SAndroid Build Coastguard Worker #define BC_PARSE_NO_EXEC(p) ((p)->flags.len != 1 || BC_PARSE_TOP_FLAG(p) != 0)
510*cf5a6c84SAndroid Build Coastguard Worker
511*cf5a6c84SAndroid Build Coastguard Worker #define BC_PARSE_DELIMITER(t) \
512*cf5a6c84SAndroid Build Coastguard Worker ((t) == BC_LEX_SCOLON || (t) == BC_LEX_NLINE || (t) == BC_LEX_EOF)
513*cf5a6c84SAndroid Build Coastguard Worker
514*cf5a6c84SAndroid Build Coastguard Worker #define BC_PARSE_BLOCK_STMT(f) \
515*cf5a6c84SAndroid Build Coastguard Worker ((f) & (BC_PARSE_FLAG_ELSE | BC_PARSE_FLAG_LOOP_INNER))
516*cf5a6c84SAndroid Build Coastguard Worker
517*cf5a6c84SAndroid Build Coastguard Worker #define BC_PARSE_OP(p, l) (((p) & ~(BC_LEX_CHAR_MSB(1))) | (BC_LEX_CHAR_MSB(l)))
518*cf5a6c84SAndroid Build Coastguard Worker
519*cf5a6c84SAndroid Build Coastguard Worker #define BC_PARSE_OP_DATA(t) bc_parse_ops[((t) - BC_LEX_OP_INC)]
520*cf5a6c84SAndroid Build Coastguard Worker #define BC_PARSE_OP_LEFT(op) (BC_PARSE_OP_DATA(op) & BC_LEX_CHAR_MSB(1))
521*cf5a6c84SAndroid Build Coastguard Worker #define BC_PARSE_OP_PREC(op) (BC_PARSE_OP_DATA(op) & ~(BC_LEX_CHAR_MSB(1)))
522*cf5a6c84SAndroid Build Coastguard Worker
523*cf5a6c84SAndroid Build Coastguard Worker #define BC_PARSE_TOP_OP(p) (*((BcLexType*) bc_vec_top(&(p)->ops)))
524*cf5a6c84SAndroid Build Coastguard Worker #define BC_PARSE_LEAF(prev, bin_last, rparen) \
525*cf5a6c84SAndroid Build Coastguard Worker (!(bin_last) && ((rparen) || bc_parse_inst_isLeaf(prev)))
526*cf5a6c84SAndroid Build Coastguard Worker #define BC_PARSE_INST_VAR(t) \
527*cf5a6c84SAndroid Build Coastguard Worker ((t) >= BC_INST_VAR && (t) <= BC_INST_SCALE && (t) != BC_INST_ARRAY)
528*cf5a6c84SAndroid Build Coastguard Worker
529*cf5a6c84SAndroid Build Coastguard Worker #define BC_PARSE_PREV_PREFIX(p) \
530*cf5a6c84SAndroid Build Coastguard Worker ((p) >= BC_INST_INC_PRE && (p) <= BC_INST_BOOL_NOT)
531*cf5a6c84SAndroid Build Coastguard Worker #define BC_PARSE_OP_PREFIX(t) ((t) == BC_LEX_OP_BOOL_NOT || (t) == BC_LEX_NEG)
532*cf5a6c84SAndroid Build Coastguard Worker
533*cf5a6c84SAndroid Build Coastguard Worker // We can calculate the conversion between tokens and exprs by subtracting the
534*cf5a6c84SAndroid Build Coastguard Worker // position of the first operator in the lex enum and adding the position of
535*cf5a6c84SAndroid Build Coastguard Worker // the first in the expr enum. Note: This only works for binary operators.
536*cf5a6c84SAndroid Build Coastguard Worker #define BC_PARSE_TOKEN_INST(t) ((char) ((t) - BC_LEX_NEG + BC_INST_NEG))
537*cf5a6c84SAndroid Build Coastguard Worker
538*cf5a6c84SAndroid Build Coastguard Worker #define bc_parse_posixErr(p, e) (bc_vm_posixError((e), (p)->l.line))
539*cf5a6c84SAndroid Build Coastguard Worker
540*cf5a6c84SAndroid Build Coastguard Worker BcStatus bc_parse_parse(BcParse *p);
541*cf5a6c84SAndroid Build Coastguard Worker BcStatus bc_parse_expr_status(BcParse *p, uint8_t flags, BcParseNext next);
542*cf5a6c84SAndroid Build Coastguard Worker void bc_parse_noElse(BcParse *p);
543*cf5a6c84SAndroid Build Coastguard Worker
544*cf5a6c84SAndroid Build Coastguard Worker #define BC_PROG_ONE_CAP (1)
545*cf5a6c84SAndroid Build Coastguard Worker
546*cf5a6c84SAndroid Build Coastguard Worker typedef struct BcProgram {
547*cf5a6c84SAndroid Build Coastguard Worker
548*cf5a6c84SAndroid Build Coastguard Worker size_t scale;
549*cf5a6c84SAndroid Build Coastguard Worker
550*cf5a6c84SAndroid Build Coastguard Worker BcNum ib;
551*cf5a6c84SAndroid Build Coastguard Worker size_t ib_t;
552*cf5a6c84SAndroid Build Coastguard Worker BcNum ob;
553*cf5a6c84SAndroid Build Coastguard Worker size_t ob_t;
554*cf5a6c84SAndroid Build Coastguard Worker
555*cf5a6c84SAndroid Build Coastguard Worker BcVec results;
556*cf5a6c84SAndroid Build Coastguard Worker BcVec stack;
557*cf5a6c84SAndroid Build Coastguard Worker
558*cf5a6c84SAndroid Build Coastguard Worker BcVec fns;
559*cf5a6c84SAndroid Build Coastguard Worker BcVec fn_map;
560*cf5a6c84SAndroid Build Coastguard Worker
561*cf5a6c84SAndroid Build Coastguard Worker BcVec vars;
562*cf5a6c84SAndroid Build Coastguard Worker BcVec var_map;
563*cf5a6c84SAndroid Build Coastguard Worker
564*cf5a6c84SAndroid Build Coastguard Worker BcVec arrs;
565*cf5a6c84SAndroid Build Coastguard Worker BcVec arr_map;
566*cf5a6c84SAndroid Build Coastguard Worker
567*cf5a6c84SAndroid Build Coastguard Worker BcNum one;
568*cf5a6c84SAndroid Build Coastguard Worker BcNum last;
569*cf5a6c84SAndroid Build Coastguard Worker
570*cf5a6c84SAndroid Build Coastguard Worker signed char ib_num[BC_NUM_LONG_LOG10], ob_num[BC_NUM_LONG_LOG10],
571*cf5a6c84SAndroid Build Coastguard Worker one_num[BC_PROG_ONE_CAP];
572*cf5a6c84SAndroid Build Coastguard Worker } BcProgram;
573*cf5a6c84SAndroid Build Coastguard Worker
574*cf5a6c84SAndroid Build Coastguard Worker #define BC_PROG_STACK(s, n) ((s)->len >= ((size_t) (n)))
575*cf5a6c84SAndroid Build Coastguard Worker
576*cf5a6c84SAndroid Build Coastguard Worker #define BC_PROG_MAIN (0)
577*cf5a6c84SAndroid Build Coastguard Worker #define BC_PROG_READ (1)
578*cf5a6c84SAndroid Build Coastguard Worker
579*cf5a6c84SAndroid Build Coastguard Worker #define BC_PROG_STR(n) (!(n)->num && !(n)->cap)
580*cf5a6c84SAndroid Build Coastguard Worker #define BC_PROG_NUM(r, n) \
581*cf5a6c84SAndroid Build Coastguard Worker ((r)->t != BC_RESULT_ARRAY && (r)->t != BC_RESULT_STR && !BC_PROG_STR(n))
582*cf5a6c84SAndroid Build Coastguard Worker
583*cf5a6c84SAndroid Build Coastguard Worker typedef void (*BcProgramUnary)(BcResult*, BcNum*);
584*cf5a6c84SAndroid Build Coastguard Worker
585*cf5a6c84SAndroid Build Coastguard Worker void bc_program_addFunc(BcProgram *p, BcFunc *f, char *name);
586*cf5a6c84SAndroid Build Coastguard Worker size_t bc_program_insertFunc(BcProgram *p, char *name);
587*cf5a6c84SAndroid Build Coastguard Worker BcStatus bc_program_reset(BcProgram *p, BcStatus s);
588*cf5a6c84SAndroid Build Coastguard Worker BcStatus bc_program_exec(BcProgram *p);
589*cf5a6c84SAndroid Build Coastguard Worker
590*cf5a6c84SAndroid Build Coastguard Worker unsigned long bc_program_scale(BcNum *n);
591*cf5a6c84SAndroid Build Coastguard Worker unsigned long bc_program_len(BcNum *n);
592*cf5a6c84SAndroid Build Coastguard Worker
593*cf5a6c84SAndroid Build Coastguard Worker void bc_program_negate(BcResult *r, BcNum *n);
594*cf5a6c84SAndroid Build Coastguard Worker void bc_program_not(BcResult *r, BcNum *n);
595*cf5a6c84SAndroid Build Coastguard Worker
596*cf5a6c84SAndroid Build Coastguard Worker #define BC_FLAG_TTYIN (1<<7)
597*cf5a6c84SAndroid Build Coastguard Worker #define BC_TTYIN (toys.optflags & BC_FLAG_TTYIN)
598*cf5a6c84SAndroid Build Coastguard Worker
599*cf5a6c84SAndroid Build Coastguard Worker #define BC_MAX_OBASE ((unsigned long) INT_MAX)
600*cf5a6c84SAndroid Build Coastguard Worker #define BC_MAX_DIM ((unsigned long) INT_MAX)
601*cf5a6c84SAndroid Build Coastguard Worker #define BC_MAX_SCALE ((unsigned long) UINT_MAX)
602*cf5a6c84SAndroid Build Coastguard Worker #define BC_MAX_STRING ((unsigned long) UINT_MAX - 1)
603*cf5a6c84SAndroid Build Coastguard Worker #define BC_MAX_NAME BC_MAX_STRING
604*cf5a6c84SAndroid Build Coastguard Worker #define BC_MAX_NUM BC_MAX_STRING
605*cf5a6c84SAndroid Build Coastguard Worker #define BC_MAX_EXP ((unsigned long) ULONG_MAX)
606*cf5a6c84SAndroid Build Coastguard Worker #define BC_MAX_VARS ((unsigned long) SIZE_MAX - 1)
607*cf5a6c84SAndroid Build Coastguard Worker
608*cf5a6c84SAndroid Build Coastguard Worker #define bc_vm_err(e) (bc_vm_error((e), 0))
609*cf5a6c84SAndroid Build Coastguard Worker #define bc_vm_verr(e, ...) (bc_vm_error((e), 0, __VA_ARGS__))
610*cf5a6c84SAndroid Build Coastguard Worker
611*cf5a6c84SAndroid Build Coastguard Worker typedef struct BcVm {
612*cf5a6c84SAndroid Build Coastguard Worker BcParse prs;
613*cf5a6c84SAndroid Build Coastguard Worker BcProgram prog;
614*cf5a6c84SAndroid Build Coastguard Worker } BcVm;
615*cf5a6c84SAndroid Build Coastguard Worker
616*cf5a6c84SAndroid Build Coastguard Worker BcStatus bc_vm_posixError(BcError e, size_t line, ...);
617*cf5a6c84SAndroid Build Coastguard Worker
618*cf5a6c84SAndroid Build Coastguard Worker BcStatus bc_vm_error(BcError e, size_t line, ...);
619*cf5a6c84SAndroid Build Coastguard Worker
620*cf5a6c84SAndroid Build Coastguard Worker char bc_sig_msg[] = "\ninterrupt (type \"quit\" to exit)\n";
621*cf5a6c84SAndroid Build Coastguard Worker
622*cf5a6c84SAndroid Build Coastguard Worker char bc_copyright[] =
623*cf5a6c84SAndroid Build Coastguard Worker "Copyright (c) 2018 Gavin D. Howard and contributors\n"
624*cf5a6c84SAndroid Build Coastguard Worker "Report bugs at: https://github.com/gavinhoward/bc\n\n"
625*cf5a6c84SAndroid Build Coastguard Worker "This is free software with ABSOLUTELY NO WARRANTY.\n";
626*cf5a6c84SAndroid Build Coastguard Worker
627*cf5a6c84SAndroid Build Coastguard Worker char *bc_err_fmt = "\n%s error: ";
628*cf5a6c84SAndroid Build Coastguard Worker char *bc_warn_fmt = "\n%s warning: ";
629*cf5a6c84SAndroid Build Coastguard Worker char *bc_err_line = ":%zu";
630*cf5a6c84SAndroid Build Coastguard Worker
631*cf5a6c84SAndroid Build Coastguard Worker char *bc_errs[] = {
632*cf5a6c84SAndroid Build Coastguard Worker "VM",
633*cf5a6c84SAndroid Build Coastguard Worker "Parse",
634*cf5a6c84SAndroid Build Coastguard Worker "Math",
635*cf5a6c84SAndroid Build Coastguard Worker "Runtime",
636*cf5a6c84SAndroid Build Coastguard Worker "POSIX",
637*cf5a6c84SAndroid Build Coastguard Worker };
638*cf5a6c84SAndroid Build Coastguard Worker
639*cf5a6c84SAndroid Build Coastguard Worker char bc_err_ids[] = {
640*cf5a6c84SAndroid Build Coastguard Worker BC_ERR_IDX_VM, BC_ERR_IDX_VM, BC_ERR_IDX_VM, BC_ERR_IDX_VM,
641*cf5a6c84SAndroid Build Coastguard Worker BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE,
642*cf5a6c84SAndroid Build Coastguard Worker BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE,
643*cf5a6c84SAndroid Build Coastguard Worker BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE,
644*cf5a6c84SAndroid Build Coastguard Worker BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE,
645*cf5a6c84SAndroid Build Coastguard Worker BC_ERR_IDX_PARSE,
646*cf5a6c84SAndroid Build Coastguard Worker BC_ERR_IDX_MATH, BC_ERR_IDX_MATH, BC_ERR_IDX_MATH, BC_ERR_IDX_MATH,
647*cf5a6c84SAndroid Build Coastguard Worker BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC,
648*cf5a6c84SAndroid Build Coastguard Worker BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC,
649*cf5a6c84SAndroid Build Coastguard Worker BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC,
650*cf5a6c84SAndroid Build Coastguard Worker BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX,
651*cf5a6c84SAndroid Build Coastguard Worker BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX,
652*cf5a6c84SAndroid Build Coastguard Worker BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX,
653*cf5a6c84SAndroid Build Coastguard Worker BC_ERR_IDX_POSIX,
654*cf5a6c84SAndroid Build Coastguard Worker };
655*cf5a6c84SAndroid Build Coastguard Worker
656*cf5a6c84SAndroid Build Coastguard Worker char *bc_err_msgs[] = {
657*cf5a6c84SAndroid Build Coastguard Worker
658*cf5a6c84SAndroid Build Coastguard Worker "memory allocation error",
659*cf5a6c84SAndroid Build Coastguard Worker "I/O error",
660*cf5a6c84SAndroid Build Coastguard Worker "file is not ASCII: %s",
661*cf5a6c84SAndroid Build Coastguard Worker "path is a directory: %s",
662*cf5a6c84SAndroid Build Coastguard Worker
663*cf5a6c84SAndroid Build Coastguard Worker "end of file",
664*cf5a6c84SAndroid Build Coastguard Worker "bad character (%c)",
665*cf5a6c84SAndroid Build Coastguard Worker "string end could not be found",
666*cf5a6c84SAndroid Build Coastguard Worker "comment end could not be found",
667*cf5a6c84SAndroid Build Coastguard Worker "bad token",
668*cf5a6c84SAndroid Build Coastguard Worker "name too long: must be [1, %lu]",
669*cf5a6c84SAndroid Build Coastguard Worker "string too long: must be [1, %lu]",
670*cf5a6c84SAndroid Build Coastguard Worker "array too long; must be [1, %lu]",
671*cf5a6c84SAndroid Build Coastguard Worker "bad expression",
672*cf5a6c84SAndroid Build Coastguard Worker "empty expression",
673*cf5a6c84SAndroid Build Coastguard Worker "bad print statement",
674*cf5a6c84SAndroid Build Coastguard Worker "bad function definition",
675*cf5a6c84SAndroid Build Coastguard Worker "bad assignment: left side must be scale, ibase, "
676*cf5a6c84SAndroid Build Coastguard Worker "obase, last, var, or array element",
677*cf5a6c84SAndroid Build Coastguard Worker "no auto variable found",
678*cf5a6c84SAndroid Build Coastguard Worker "function parameter or auto \"%s\" already exists",
679*cf5a6c84SAndroid Build Coastguard Worker "block end could not be found",
680*cf5a6c84SAndroid Build Coastguard Worker "cannot return a value from void function: %s()",
681*cf5a6c84SAndroid Build Coastguard Worker
682*cf5a6c84SAndroid Build Coastguard Worker "negative number",
683*cf5a6c84SAndroid Build Coastguard Worker "non integer number",
684*cf5a6c84SAndroid Build Coastguard Worker "overflow",
685*cf5a6c84SAndroid Build Coastguard Worker "divide by zero",
686*cf5a6c84SAndroid Build Coastguard Worker
687*cf5a6c84SAndroid Build Coastguard Worker "could not open file: %s",
688*cf5a6c84SAndroid Build Coastguard Worker "number too long: must be [1, %lu]",
689*cf5a6c84SAndroid Build Coastguard Worker "bad ibase; must be [%lu, %lu]",
690*cf5a6c84SAndroid Build Coastguard Worker "bad obase; must be [%lu, %lu]",
691*cf5a6c84SAndroid Build Coastguard Worker "bad scale; must be [%lu, %lu]",
692*cf5a6c84SAndroid Build Coastguard Worker "bad read() expression",
693*cf5a6c84SAndroid Build Coastguard Worker "read() call inside of a read() call",
694*cf5a6c84SAndroid Build Coastguard Worker "variable is wrong type",
695*cf5a6c84SAndroid Build Coastguard Worker "mismatched parameters; need %zu, have %zu",
696*cf5a6c84SAndroid Build Coastguard Worker "undefined function: %s()",
697*cf5a6c84SAndroid Build Coastguard Worker "cannot use a void value in an expression",
698*cf5a6c84SAndroid Build Coastguard Worker
699*cf5a6c84SAndroid Build Coastguard Worker "POSIX does not allow names longer than 1 character, like \"%s\"",
700*cf5a6c84SAndroid Build Coastguard Worker "POSIX does not allow '#' script comments",
701*cf5a6c84SAndroid Build Coastguard Worker "POSIX does not allow \"%s\" as a keyword",
702*cf5a6c84SAndroid Build Coastguard Worker "POSIX does not allow a period ('.') as a shortcut for the last result",
703*cf5a6c84SAndroid Build Coastguard Worker "POSIX requires parentheses around return expressions",
704*cf5a6c84SAndroid Build Coastguard Worker "POSIX does not allow the \"%s\" operators",
705*cf5a6c84SAndroid Build Coastguard Worker "POSIX does not allow comparison operators outside if or loops",
706*cf5a6c84SAndroid Build Coastguard Worker "POSIX requires zero or one comparison operator per condition",
707*cf5a6c84SAndroid Build Coastguard Worker "POSIX does not allow an empty init expression in a for loop",
708*cf5a6c84SAndroid Build Coastguard Worker "POSIX does not allow an empty condition expression in a for loop",
709*cf5a6c84SAndroid Build Coastguard Worker "POSIX does not allow an empty update expression in a for loop",
710*cf5a6c84SAndroid Build Coastguard Worker "POSIX requires the left brace be on the same line as the function header",
711*cf5a6c84SAndroid Build Coastguard Worker "POSIX does not allow array references as function parameters",
712*cf5a6c84SAndroid Build Coastguard Worker
713*cf5a6c84SAndroid Build Coastguard Worker };
714*cf5a6c84SAndroid Build Coastguard Worker
715*cf5a6c84SAndroid Build Coastguard Worker char bc_func_main[] = "(main)";
716*cf5a6c84SAndroid Build Coastguard Worker char bc_func_read[] = "(read)";
717*cf5a6c84SAndroid Build Coastguard Worker
718*cf5a6c84SAndroid Build Coastguard Worker BcLexKeyword bc_lex_kws[] = {
719*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_KW_ENTRY("auto", 4, 1),
720*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_KW_ENTRY("break", 5, 1),
721*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_KW_ENTRY("continue", 8, 0),
722*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_KW_ENTRY("define", 6, 1),
723*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_KW_ENTRY("for", 3, 1),
724*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_KW_ENTRY("if", 2, 1),
725*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_KW_ENTRY("limits", 6, 0),
726*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_KW_ENTRY("return", 6, 1),
727*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_KW_ENTRY("while", 5, 1),
728*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_KW_ENTRY("halt", 4, 0),
729*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_KW_ENTRY("last", 4, 0),
730*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_KW_ENTRY("ibase", 5, 1),
731*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_KW_ENTRY("obase", 5, 1),
732*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_KW_ENTRY("scale", 5, 1),
733*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_KW_ENTRY("length", 6, 1),
734*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_KW_ENTRY("print", 5, 0),
735*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_KW_ENTRY("sqrt", 4, 1),
736*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_KW_ENTRY("abs", 3, 0),
737*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_KW_ENTRY("quit", 4, 1),
738*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_KW_ENTRY("read", 4, 0),
739*cf5a6c84SAndroid Build Coastguard Worker BC_LEX_KW_ENTRY("else", 4, 0),
740*cf5a6c84SAndroid Build Coastguard Worker };
741*cf5a6c84SAndroid Build Coastguard Worker
742*cf5a6c84SAndroid Build Coastguard Worker size_t bc_lex_kws_len = sizeof(bc_lex_kws) / sizeof(BcLexKeyword);
743*cf5a6c84SAndroid Build Coastguard Worker
744*cf5a6c84SAndroid Build Coastguard Worker char *bc_parse_const1 = "1";
745*cf5a6c84SAndroid Build Coastguard Worker
746*cf5a6c84SAndroid Build Coastguard Worker // This is an array of data for operators that correspond to token types.
747*cf5a6c84SAndroid Build Coastguard Worker char bc_parse_ops[] = {
748*cf5a6c84SAndroid Build Coastguard Worker BC_PARSE_OP(0, 0), BC_PARSE_OP(0, 0),
749*cf5a6c84SAndroid Build Coastguard Worker BC_PARSE_OP(1, 0), BC_PARSE_OP(1, 0),
750*cf5a6c84SAndroid Build Coastguard Worker BC_PARSE_OP(4, 0),
751*cf5a6c84SAndroid Build Coastguard Worker BC_PARSE_OP(5, 1), BC_PARSE_OP(5, 1), BC_PARSE_OP(5, 1),
752*cf5a6c84SAndroid Build Coastguard Worker BC_PARSE_OP(6, 1), BC_PARSE_OP(6, 1),
753*cf5a6c84SAndroid Build Coastguard Worker BC_PARSE_OP(9, 1), BC_PARSE_OP(9, 1), BC_PARSE_OP(9, 1),
754*cf5a6c84SAndroid Build Coastguard Worker BC_PARSE_OP(9, 1), BC_PARSE_OP(9, 1), BC_PARSE_OP(9, 1),
755*cf5a6c84SAndroid Build Coastguard Worker BC_PARSE_OP(11, 1), BC_PARSE_OP(10, 1),
756*cf5a6c84SAndroid Build Coastguard Worker BC_PARSE_OP(8, 0), BC_PARSE_OP(8, 0), BC_PARSE_OP(8, 0),
757*cf5a6c84SAndroid Build Coastguard Worker BC_PARSE_OP(8, 0), BC_PARSE_OP(8, 0), BC_PARSE_OP(8, 0),
758*cf5a6c84SAndroid Build Coastguard Worker BC_PARSE_OP(8, 0),
759*cf5a6c84SAndroid Build Coastguard Worker };
760*cf5a6c84SAndroid Build Coastguard Worker
761*cf5a6c84SAndroid Build Coastguard Worker // These identify what tokens can come after expressions in certain cases.
762*cf5a6c84SAndroid Build Coastguard Worker BcParseNext bc_parse_next_expr =
763*cf5a6c84SAndroid Build Coastguard Worker BC_PARSE_NEXT(4, BC_LEX_NLINE, BC_LEX_SCOLON, BC_LEX_RBRACE, BC_LEX_EOF);
764*cf5a6c84SAndroid Build Coastguard Worker BcParseNext bc_parse_next_param =
765*cf5a6c84SAndroid Build Coastguard Worker BC_PARSE_NEXT(2, BC_LEX_RPAREN, BC_LEX_COMMA);
766*cf5a6c84SAndroid Build Coastguard Worker BcParseNext bc_parse_next_print =
767*cf5a6c84SAndroid Build Coastguard Worker BC_PARSE_NEXT(4, BC_LEX_COMMA, BC_LEX_NLINE, BC_LEX_SCOLON, BC_LEX_EOF);
768*cf5a6c84SAndroid Build Coastguard Worker BcParseNext bc_parse_next_rel = BC_PARSE_NEXT(1, BC_LEX_RPAREN);
769*cf5a6c84SAndroid Build Coastguard Worker BcParseNext bc_parse_next_elem = BC_PARSE_NEXT(1, BC_LEX_RBRACKET);
770*cf5a6c84SAndroid Build Coastguard Worker BcParseNext bc_parse_next_for = BC_PARSE_NEXT(1, BC_LEX_SCOLON);
771*cf5a6c84SAndroid Build Coastguard Worker BcParseNext bc_parse_next_read =
772*cf5a6c84SAndroid Build Coastguard Worker BC_PARSE_NEXT(2, BC_LEX_NLINE, BC_LEX_EOF);
773*cf5a6c84SAndroid Build Coastguard Worker
774*cf5a6c84SAndroid Build Coastguard Worker char bc_num_hex_digits[] = "0123456789ABCDEF";
775*cf5a6c84SAndroid Build Coastguard Worker
776*cf5a6c84SAndroid Build Coastguard Worker BcNumBinaryOp bc_program_ops[] = {
777*cf5a6c84SAndroid Build Coastguard Worker bc_num_pow, bc_num_mul, bc_num_div, bc_num_mod, bc_num_add, bc_num_sub,
778*cf5a6c84SAndroid Build Coastguard Worker };
779*cf5a6c84SAndroid Build Coastguard Worker
780*cf5a6c84SAndroid Build Coastguard Worker BcNumBinaryOpReq bc_program_opReqs[] = {
781*cf5a6c84SAndroid Build Coastguard Worker bc_num_powReq, bc_num_mulReq, bc_num_mulReq, bc_num_mulReq,
782*cf5a6c84SAndroid Build Coastguard Worker bc_num_addReq, bc_num_addReq,
783*cf5a6c84SAndroid Build Coastguard Worker };
784*cf5a6c84SAndroid Build Coastguard Worker
785*cf5a6c84SAndroid Build Coastguard Worker BcProgramUnary bc_program_unarys[] = {
786*cf5a6c84SAndroid Build Coastguard Worker bc_program_negate, bc_program_not,
787*cf5a6c84SAndroid Build Coastguard Worker };
788*cf5a6c84SAndroid Build Coastguard Worker
789*cf5a6c84SAndroid Build Coastguard Worker char bc_program_ready_msg[] = "ready for more input\n";
790*cf5a6c84SAndroid Build Coastguard Worker
791*cf5a6c84SAndroid Build Coastguard Worker char *bc_lib_name = "gen/lib.bc";
792*cf5a6c84SAndroid Build Coastguard Worker
793*cf5a6c84SAndroid Build Coastguard Worker char *bc_lib =
794*cf5a6c84SAndroid Build Coastguard Worker "scale=20;\n"
795*cf5a6c84SAndroid Build Coastguard Worker
796*cf5a6c84SAndroid Build Coastguard Worker "define e(x){\n"
797*cf5a6c84SAndroid Build Coastguard Worker " auto b,s,n,r,d,i,p,f,v;\n"
798*cf5a6c84SAndroid Build Coastguard Worker " b=ibase;\n"
799*cf5a6c84SAndroid Build Coastguard Worker " ibase=A;\n"
800*cf5a6c84SAndroid Build Coastguard Worker " if(x<0){\n"
801*cf5a6c84SAndroid Build Coastguard Worker " n=1; x=-x;\n"
802*cf5a6c84SAndroid Build Coastguard Worker " }\n"
803*cf5a6c84SAndroid Build Coastguard Worker " s=scale;\n"
804*cf5a6c84SAndroid Build Coastguard Worker " r=6+s+.44*x;\n"
805*cf5a6c84SAndroid Build Coastguard Worker " scale=scale(x)+1;\n"
806*cf5a6c84SAndroid Build Coastguard Worker " while(x>1){\n"
807*cf5a6c84SAndroid Build Coastguard Worker " d+=1; x/=2;\n"
808*cf5a6c84SAndroid Build Coastguard Worker " scale+=1;\n"
809*cf5a6c84SAndroid Build Coastguard Worker " }\n"
810*cf5a6c84SAndroid Build Coastguard Worker " scale=r;\n"
811*cf5a6c84SAndroid Build Coastguard Worker " r=x+1; p=x; f=v=1;\n"
812*cf5a6c84SAndroid Build Coastguard Worker " for(i=2;v;++i){;\n"
813*cf5a6c84SAndroid Build Coastguard Worker " p*=x; f*=i; v=p/f; r+=v;\n"
814*cf5a6c84SAndroid Build Coastguard Worker " }\n"
815*cf5a6c84SAndroid Build Coastguard Worker " while(d--)r*=r;\n"
816*cf5a6c84SAndroid Build Coastguard Worker " scale=s;\n"
817*cf5a6c84SAndroid Build Coastguard Worker " ibase=b;\n"
818*cf5a6c84SAndroid Build Coastguard Worker " if(n)return(1/r)\n"
819*cf5a6c84SAndroid Build Coastguard Worker " return(r/1)\n"
820*cf5a6c84SAndroid Build Coastguard Worker "}\n"
821*cf5a6c84SAndroid Build Coastguard Worker
822*cf5a6c84SAndroid Build Coastguard Worker "define l(x){\n"
823*cf5a6c84SAndroid Build Coastguard Worker " auto b,s,r,p,a,q,i,v;\n"
824*cf5a6c84SAndroid Build Coastguard Worker " b=ibase;\n"
825*cf5a6c84SAndroid Build Coastguard Worker " ibase=A;\n"
826*cf5a6c84SAndroid Build Coastguard Worker " if(x<=0){;\n"
827*cf5a6c84SAndroid Build Coastguard Worker " r=(1-10^scale)/1;\n"
828*cf5a6c84SAndroid Build Coastguard Worker " ibase=b;\n"
829*cf5a6c84SAndroid Build Coastguard Worker " return(r)\n"
830*cf5a6c84SAndroid Build Coastguard Worker " }\n"
831*cf5a6c84SAndroid Build Coastguard Worker " s=scale;\n"
832*cf5a6c84SAndroid Build Coastguard Worker " scale+=6;\n"
833*cf5a6c84SAndroid Build Coastguard Worker " p=2;\n"
834*cf5a6c84SAndroid Build Coastguard Worker " while(x>=2){;\n"
835*cf5a6c84SAndroid Build Coastguard Worker " p*=2;\n"
836*cf5a6c84SAndroid Build Coastguard Worker " x=sqrt(x);\n"
837*cf5a6c84SAndroid Build Coastguard Worker " }\n"
838*cf5a6c84SAndroid Build Coastguard Worker " while(x<=.5){;\n"
839*cf5a6c84SAndroid Build Coastguard Worker " p*=2;\n"
840*cf5a6c84SAndroid Build Coastguard Worker " x=sqrt(x);\n"
841*cf5a6c84SAndroid Build Coastguard Worker " }\n"
842*cf5a6c84SAndroid Build Coastguard Worker " r=a=(x-1)/(x+1);\n"
843*cf5a6c84SAndroid Build Coastguard Worker " q=a*a;\n"
844*cf5a6c84SAndroid Build Coastguard Worker " v=1;\n"
845*cf5a6c84SAndroid Build Coastguard Worker " for(i=3;v;i+=2){;\n"
846*cf5a6c84SAndroid Build Coastguard Worker " a*=q; v=a/i; r+=v;\n"
847*cf5a6c84SAndroid Build Coastguard Worker " }\n"
848*cf5a6c84SAndroid Build Coastguard Worker " r*=p;\n"
849*cf5a6c84SAndroid Build Coastguard Worker " scale=s;\n"
850*cf5a6c84SAndroid Build Coastguard Worker " ibase=b;\n"
851*cf5a6c84SAndroid Build Coastguard Worker " return(r/1)\n"
852*cf5a6c84SAndroid Build Coastguard Worker "}\n"
853*cf5a6c84SAndroid Build Coastguard Worker
854*cf5a6c84SAndroid Build Coastguard Worker "define s(x){\n"
855*cf5a6c84SAndroid Build Coastguard Worker " auto b,s,r,a,q,i;\n"
856*cf5a6c84SAndroid Build Coastguard Worker " if(x<0)return(-s(-x))\n"
857*cf5a6c84SAndroid Build Coastguard Worker " b=ibase;\n"
858*cf5a6c84SAndroid Build Coastguard Worker " ibase=A;\n"
859*cf5a6c84SAndroid Build Coastguard Worker " s=scale;\n"
860*cf5a6c84SAndroid Build Coastguard Worker " scale=1.1*s+2;\n"
861*cf5a6c84SAndroid Build Coastguard Worker " a=a(1);\n"
862*cf5a6c84SAndroid Build Coastguard Worker " scale=0;\n"
863*cf5a6c84SAndroid Build Coastguard Worker " q=(x/a+2)/4;\n"
864*cf5a6c84SAndroid Build Coastguard Worker " x-=4*q*a;\n"
865*cf5a6c84SAndroid Build Coastguard Worker " if(q%2) x=-x;\n"
866*cf5a6c84SAndroid Build Coastguard Worker " scale=s+2;\n"
867*cf5a6c84SAndroid Build Coastguard Worker " r=a=x;\n"
868*cf5a6c84SAndroid Build Coastguard Worker " q=-x*x;\n"
869*cf5a6c84SAndroid Build Coastguard Worker " for(i=3;a;i+=2){;\n"
870*cf5a6c84SAndroid Build Coastguard Worker " a*=q/(i*(i-1)); r+=a;\n"
871*cf5a6c84SAndroid Build Coastguard Worker " }\n"
872*cf5a6c84SAndroid Build Coastguard Worker " scale=s;\n"
873*cf5a6c84SAndroid Build Coastguard Worker " ibase=b;\n"
874*cf5a6c84SAndroid Build Coastguard Worker " return(r/1)\n"
875*cf5a6c84SAndroid Build Coastguard Worker "}\n"
876*cf5a6c84SAndroid Build Coastguard Worker
877*cf5a6c84SAndroid Build Coastguard Worker "define c(x){\n"
878*cf5a6c84SAndroid Build Coastguard Worker " auto b,s;\n"
879*cf5a6c84SAndroid Build Coastguard Worker " b=ibase;\n"
880*cf5a6c84SAndroid Build Coastguard Worker " ibase=A;\n"
881*cf5a6c84SAndroid Build Coastguard Worker " s=scale;\n"
882*cf5a6c84SAndroid Build Coastguard Worker " scale*=1.2;\n"
883*cf5a6c84SAndroid Build Coastguard Worker " x=s(2*a(1)+x);\n"
884*cf5a6c84SAndroid Build Coastguard Worker " scale=s;\n"
885*cf5a6c84SAndroid Build Coastguard Worker " ibase=b;\n"
886*cf5a6c84SAndroid Build Coastguard Worker " return(x/1)\n"
887*cf5a6c84SAndroid Build Coastguard Worker "}\n"
888*cf5a6c84SAndroid Build Coastguard Worker
889*cf5a6c84SAndroid Build Coastguard Worker "define a(x){\n"
890*cf5a6c84SAndroid Build Coastguard Worker " auto b,s,r,n,a,m,t,f,i,u;\n"
891*cf5a6c84SAndroid Build Coastguard Worker " b=ibase;\n"
892*cf5a6c84SAndroid Build Coastguard Worker " ibase=A;\n"
893*cf5a6c84SAndroid Build Coastguard Worker " n=1;\n"
894*cf5a6c84SAndroid Build Coastguard Worker " if(x<0){\n"
895*cf5a6c84SAndroid Build Coastguard Worker " n=-1;\n"
896*cf5a6c84SAndroid Build Coastguard Worker " x=-x;\n"
897*cf5a6c84SAndroid Build Coastguard Worker " }\n"
898*cf5a6c84SAndroid Build Coastguard Worker " if(scale<65){\n"
899*cf5a6c84SAndroid Build Coastguard Worker " if(x==1){;\n"
900*cf5a6c84SAndroid Build Coastguard Worker " r=.7853981633974483096156608458198757210492923498437764552437361480/n;\n"
901*cf5a6c84SAndroid Build Coastguard Worker " ibase=b;\n"
902*cf5a6c84SAndroid Build Coastguard Worker " return(r)\n"
903*cf5a6c84SAndroid Build Coastguard Worker " }\n"
904*cf5a6c84SAndroid Build Coastguard Worker " if(x==.2){;\n"
905*cf5a6c84SAndroid Build Coastguard Worker " r=.1973955598498807583700497651947902934475851037878521015176889402/n;\n"
906*cf5a6c84SAndroid Build Coastguard Worker " ibase=b;\n"
907*cf5a6c84SAndroid Build Coastguard Worker " return(r)\n"
908*cf5a6c84SAndroid Build Coastguard Worker " }\n"
909*cf5a6c84SAndroid Build Coastguard Worker " }\n"
910*cf5a6c84SAndroid Build Coastguard Worker " s=scale;\n"
911*cf5a6c84SAndroid Build Coastguard Worker " if(x>.2){\n"
912*cf5a6c84SAndroid Build Coastguard Worker " scale+=5; a=a(.2);\n"
913*cf5a6c84SAndroid Build Coastguard Worker " }\n"
914*cf5a6c84SAndroid Build Coastguard Worker " scale=s+3;\n"
915*cf5a6c84SAndroid Build Coastguard Worker " while(x>.2){\n"
916*cf5a6c84SAndroid Build Coastguard Worker " m+=1; x=(x-.2)/(1+.2*x);\n"
917*cf5a6c84SAndroid Build Coastguard Worker " }\n"
918*cf5a6c84SAndroid Build Coastguard Worker " r=u=x; f=-x*x; t=1;\n"
919*cf5a6c84SAndroid Build Coastguard Worker " for(i=3;t;i+=2){;\n"
920*cf5a6c84SAndroid Build Coastguard Worker " u*=f; t=u/i; r+=t;\n"
921*cf5a6c84SAndroid Build Coastguard Worker " }\n"
922*cf5a6c84SAndroid Build Coastguard Worker " scale=s;\n"
923*cf5a6c84SAndroid Build Coastguard Worker " ibase=b;\n"
924*cf5a6c84SAndroid Build Coastguard Worker " return((m*a+r)/n)\n"
925*cf5a6c84SAndroid Build Coastguard Worker "}\n"
926*cf5a6c84SAndroid Build Coastguard Worker
927*cf5a6c84SAndroid Build Coastguard Worker "define j(n,x){\n"
928*cf5a6c84SAndroid Build Coastguard Worker " auto b,s,o,a,i,v,f;\n"
929*cf5a6c84SAndroid Build Coastguard Worker " b=ibase;\n"
930*cf5a6c84SAndroid Build Coastguard Worker " ibase=A;\n"
931*cf5a6c84SAndroid Build Coastguard Worker " s=scale;\n"
932*cf5a6c84SAndroid Build Coastguard Worker " scale=0;\n"
933*cf5a6c84SAndroid Build Coastguard Worker " n/=1;\n"
934*cf5a6c84SAndroid Build Coastguard Worker " if(n<0){\n"
935*cf5a6c84SAndroid Build Coastguard Worker " n=-n; o=n%2;\n"
936*cf5a6c84SAndroid Build Coastguard Worker " }\n"
937*cf5a6c84SAndroid Build Coastguard Worker " a=1;\n"
938*cf5a6c84SAndroid Build Coastguard Worker " for(i=2;i<=n;++i)a*=i;\n"
939*cf5a6c84SAndroid Build Coastguard Worker " scale=1.5*s;\n"
940*cf5a6c84SAndroid Build Coastguard Worker " a=(x^n)/2^n/a;\n"
941*cf5a6c84SAndroid Build Coastguard Worker " r=v=1;\n"
942*cf5a6c84SAndroid Build Coastguard Worker " f=-x*x/4;\n"
943*cf5a6c84SAndroid Build Coastguard Worker " scale+=length(a)-scale(a);\n"
944*cf5a6c84SAndroid Build Coastguard Worker " for(i=1;v;++i){;\n"
945*cf5a6c84SAndroid Build Coastguard Worker " v=v*f/i/(n+i); r+=v;\n"
946*cf5a6c84SAndroid Build Coastguard Worker " }\n"
947*cf5a6c84SAndroid Build Coastguard Worker " scale=s;\n"
948*cf5a6c84SAndroid Build Coastguard Worker " ibase=b;\n"
949*cf5a6c84SAndroid Build Coastguard Worker " if(o)a=-a;\n"
950*cf5a6c84SAndroid Build Coastguard Worker " return(a*r/1)\n"
951*cf5a6c84SAndroid Build Coastguard Worker "}\n";
952*cf5a6c84SAndroid Build Coastguard Worker
bc_vec_grow(BcVec * v,unsigned long n)953*cf5a6c84SAndroid Build Coastguard Worker static void bc_vec_grow(BcVec *v, unsigned long n) {
954*cf5a6c84SAndroid Build Coastguard Worker unsigned long old = v->cap;
955*cf5a6c84SAndroid Build Coastguard Worker
956*cf5a6c84SAndroid Build Coastguard Worker while (v->cap < v->len + n) v->cap *= 2;
957*cf5a6c84SAndroid Build Coastguard Worker if (old != v->cap) v->v = xrealloc(v->v, v->size * v->cap);
958*cf5a6c84SAndroid Build Coastguard Worker }
959*cf5a6c84SAndroid Build Coastguard Worker
bc_vec_init(BcVec * v,size_t esize,BcVecFree dtor)960*cf5a6c84SAndroid Build Coastguard Worker void bc_vec_init(BcVec *v, size_t esize, BcVecFree dtor) {
961*cf5a6c84SAndroid Build Coastguard Worker v->size = esize;
962*cf5a6c84SAndroid Build Coastguard Worker v->cap = BC_VEC_START_CAP;
963*cf5a6c84SAndroid Build Coastguard Worker v->len = 0;
964*cf5a6c84SAndroid Build Coastguard Worker v->dtor = dtor;
965*cf5a6c84SAndroid Build Coastguard Worker v->v = xmalloc(esize * BC_VEC_START_CAP);
966*cf5a6c84SAndroid Build Coastguard Worker }
967*cf5a6c84SAndroid Build Coastguard Worker
bc_vec_expand(BcVec * v,size_t req)968*cf5a6c84SAndroid Build Coastguard Worker void bc_vec_expand(BcVec *v, size_t req) {
969*cf5a6c84SAndroid Build Coastguard Worker if (v->cap < req) {
970*cf5a6c84SAndroid Build Coastguard Worker v->v = xrealloc(v->v, v->size * req);
971*cf5a6c84SAndroid Build Coastguard Worker v->cap = req;
972*cf5a6c84SAndroid Build Coastguard Worker }
973*cf5a6c84SAndroid Build Coastguard Worker }
974*cf5a6c84SAndroid Build Coastguard Worker
bc_vec_npop(BcVec * v,size_t n)975*cf5a6c84SAndroid Build Coastguard Worker void bc_vec_npop(BcVec *v, size_t n) {
976*cf5a6c84SAndroid Build Coastguard Worker if (!v->dtor) v->len -= n;
977*cf5a6c84SAndroid Build Coastguard Worker else {
978*cf5a6c84SAndroid Build Coastguard Worker size_t len = v->len - n;
979*cf5a6c84SAndroid Build Coastguard Worker while (v->len > len) v->dtor(v->v + (v->size * --v->len));
980*cf5a6c84SAndroid Build Coastguard Worker }
981*cf5a6c84SAndroid Build Coastguard Worker }
982*cf5a6c84SAndroid Build Coastguard Worker
bc_vec_npush(BcVec * v,size_t n,void * data)983*cf5a6c84SAndroid Build Coastguard Worker void bc_vec_npush(BcVec *v, size_t n, void *data) {
984*cf5a6c84SAndroid Build Coastguard Worker bc_vec_grow(v, n);
985*cf5a6c84SAndroid Build Coastguard Worker memcpy(v->v + (v->size * v->len), data, v->size * n);
986*cf5a6c84SAndroid Build Coastguard Worker v->len += n;
987*cf5a6c84SAndroid Build Coastguard Worker }
988*cf5a6c84SAndroid Build Coastguard Worker
bc_vec_push(BcVec * v,void * data)989*cf5a6c84SAndroid Build Coastguard Worker void bc_vec_push(BcVec *v, void *data) {
990*cf5a6c84SAndroid Build Coastguard Worker bc_vec_npush(v, 1, data);
991*cf5a6c84SAndroid Build Coastguard Worker }
992*cf5a6c84SAndroid Build Coastguard Worker
bc_vec_pushByte(BcVec * v,char data)993*cf5a6c84SAndroid Build Coastguard Worker void bc_vec_pushByte(BcVec *v, char data) {
994*cf5a6c84SAndroid Build Coastguard Worker bc_vec_push(v, &data);
995*cf5a6c84SAndroid Build Coastguard Worker }
996*cf5a6c84SAndroid Build Coastguard Worker
bc_vec_pushIndex(BcVec * v,size_t idx)997*cf5a6c84SAndroid Build Coastguard Worker void bc_vec_pushIndex(BcVec *v, size_t idx) {
998*cf5a6c84SAndroid Build Coastguard Worker
999*cf5a6c84SAndroid Build Coastguard Worker char amt, nums[sizeof(size_t)];
1000*cf5a6c84SAndroid Build Coastguard Worker
1001*cf5a6c84SAndroid Build Coastguard Worker for (amt = 0; idx; ++amt) {
1002*cf5a6c84SAndroid Build Coastguard Worker nums[amt] = (char) idx;
1003*cf5a6c84SAndroid Build Coastguard Worker idx &= ((size_t) ~(UCHAR_MAX));
1004*cf5a6c84SAndroid Build Coastguard Worker idx >>= sizeof(char) * CHAR_BIT;
1005*cf5a6c84SAndroid Build Coastguard Worker }
1006*cf5a6c84SAndroid Build Coastguard Worker
1007*cf5a6c84SAndroid Build Coastguard Worker bc_vec_push(v, &amt);
1008*cf5a6c84SAndroid Build Coastguard Worker bc_vec_npush(v, amt, nums);
1009*cf5a6c84SAndroid Build Coastguard Worker }
1010*cf5a6c84SAndroid Build Coastguard Worker
bc_vec_pushAt(BcVec * v,void * data,size_t idx)1011*cf5a6c84SAndroid Build Coastguard Worker static void bc_vec_pushAt(BcVec *v, void *data, size_t idx) {
1012*cf5a6c84SAndroid Build Coastguard Worker
1013*cf5a6c84SAndroid Build Coastguard Worker if (idx == v->len) bc_vec_push(v, data);
1014*cf5a6c84SAndroid Build Coastguard Worker else {
1015*cf5a6c84SAndroid Build Coastguard Worker
1016*cf5a6c84SAndroid Build Coastguard Worker char *ptr;
1017*cf5a6c84SAndroid Build Coastguard Worker
1018*cf5a6c84SAndroid Build Coastguard Worker bc_vec_grow(v, 1);
1019*cf5a6c84SAndroid Build Coastguard Worker
1020*cf5a6c84SAndroid Build Coastguard Worker ptr = v->v + v->size * idx;
1021*cf5a6c84SAndroid Build Coastguard Worker
1022*cf5a6c84SAndroid Build Coastguard Worker memmove(ptr + v->size, ptr, v->size * (v->len++ - idx));
1023*cf5a6c84SAndroid Build Coastguard Worker memmove(ptr, data, v->size);
1024*cf5a6c84SAndroid Build Coastguard Worker }
1025*cf5a6c84SAndroid Build Coastguard Worker }
1026*cf5a6c84SAndroid Build Coastguard Worker
bc_vec_string(BcVec * v,size_t len,char * str)1027*cf5a6c84SAndroid Build Coastguard Worker void bc_vec_string(BcVec *v, size_t len, char *str) {
1028*cf5a6c84SAndroid Build Coastguard Worker
1029*cf5a6c84SAndroid Build Coastguard Worker bc_vec_npop(v, v->len);
1030*cf5a6c84SAndroid Build Coastguard Worker bc_vec_expand(v, len + 1);
1031*cf5a6c84SAndroid Build Coastguard Worker memcpy(v->v, str, len);
1032*cf5a6c84SAndroid Build Coastguard Worker v->len = len;
1033*cf5a6c84SAndroid Build Coastguard Worker
1034*cf5a6c84SAndroid Build Coastguard Worker bc_vec_pushByte(v, '\0');
1035*cf5a6c84SAndroid Build Coastguard Worker }
1036*cf5a6c84SAndroid Build Coastguard Worker
bc_vec_concat(BcVec * v,char * str)1037*cf5a6c84SAndroid Build Coastguard Worker void bc_vec_concat(BcVec *v, char *str) {
1038*cf5a6c84SAndroid Build Coastguard Worker unsigned long len;
1039*cf5a6c84SAndroid Build Coastguard Worker
1040*cf5a6c84SAndroid Build Coastguard Worker if (!v->len) bc_vec_pushByte(v, '\0');
1041*cf5a6c84SAndroid Build Coastguard Worker
1042*cf5a6c84SAndroid Build Coastguard Worker len = strlen(str);
1043*cf5a6c84SAndroid Build Coastguard Worker bc_vec_grow(v, len);
1044*cf5a6c84SAndroid Build Coastguard Worker strcpy(v->v+v->len-1, str);
1045*cf5a6c84SAndroid Build Coastguard Worker v->len += len;
1046*cf5a6c84SAndroid Build Coastguard Worker }
1047*cf5a6c84SAndroid Build Coastguard Worker
bc_vec_empty(BcVec * v)1048*cf5a6c84SAndroid Build Coastguard Worker void bc_vec_empty(BcVec *v) {
1049*cf5a6c84SAndroid Build Coastguard Worker bc_vec_npop(v, v->len);
1050*cf5a6c84SAndroid Build Coastguard Worker bc_vec_pushByte(v, '\0');
1051*cf5a6c84SAndroid Build Coastguard Worker }
1052*cf5a6c84SAndroid Build Coastguard Worker
bc_vec_item(BcVec * v,size_t idx)1053*cf5a6c84SAndroid Build Coastguard Worker void* bc_vec_item(BcVec *v, size_t idx) {
1054*cf5a6c84SAndroid Build Coastguard Worker return v->v + v->size * idx;
1055*cf5a6c84SAndroid Build Coastguard Worker }
1056*cf5a6c84SAndroid Build Coastguard Worker
bc_vec_item_rev(BcVec * v,size_t idx)1057*cf5a6c84SAndroid Build Coastguard Worker void* bc_vec_item_rev(BcVec *v, size_t idx) {
1058*cf5a6c84SAndroid Build Coastguard Worker return v->v + v->size * (v->len - idx - 1);
1059*cf5a6c84SAndroid Build Coastguard Worker }
1060*cf5a6c84SAndroid Build Coastguard Worker
bc_vec_free(void * vec)1061*cf5a6c84SAndroid Build Coastguard Worker void bc_vec_free(void *vec) {
1062*cf5a6c84SAndroid Build Coastguard Worker BcVec *v = (BcVec*) vec;
1063*cf5a6c84SAndroid Build Coastguard Worker bc_vec_npop(v, v->len);
1064*cf5a6c84SAndroid Build Coastguard Worker free(v->v);
1065*cf5a6c84SAndroid Build Coastguard Worker }
1066*cf5a6c84SAndroid Build Coastguard Worker
bc_map_find(BcVec * v,struct str_len * ptr)1067*cf5a6c84SAndroid Build Coastguard Worker static size_t bc_map_find(BcVec *v, struct str_len *ptr) {
1068*cf5a6c84SAndroid Build Coastguard Worker
1069*cf5a6c84SAndroid Build Coastguard Worker size_t low = 0, high = v->len;
1070*cf5a6c84SAndroid Build Coastguard Worker
1071*cf5a6c84SAndroid Build Coastguard Worker while (low < high) {
1072*cf5a6c84SAndroid Build Coastguard Worker
1073*cf5a6c84SAndroid Build Coastguard Worker size_t mid = (low + high) / 2;
1074*cf5a6c84SAndroid Build Coastguard Worker struct str_len *id = bc_vec_item(v, mid);
1075*cf5a6c84SAndroid Build Coastguard Worker int result = bc_id_cmp(ptr, id);
1076*cf5a6c84SAndroid Build Coastguard Worker
1077*cf5a6c84SAndroid Build Coastguard Worker if (!result) return mid;
1078*cf5a6c84SAndroid Build Coastguard Worker else if (result < 0) high = mid;
1079*cf5a6c84SAndroid Build Coastguard Worker else low = mid + 1;
1080*cf5a6c84SAndroid Build Coastguard Worker }
1081*cf5a6c84SAndroid Build Coastguard Worker
1082*cf5a6c84SAndroid Build Coastguard Worker return low;
1083*cf5a6c84SAndroid Build Coastguard Worker }
1084*cf5a6c84SAndroid Build Coastguard Worker
bc_map_insert(BcVec * v,struct str_len * ptr,size_t * i)1085*cf5a6c84SAndroid Build Coastguard Worker int bc_map_insert(BcVec *v, struct str_len *ptr, size_t *i) {
1086*cf5a6c84SAndroid Build Coastguard Worker
1087*cf5a6c84SAndroid Build Coastguard Worker *i = bc_map_find(v, ptr);
1088*cf5a6c84SAndroid Build Coastguard Worker
1089*cf5a6c84SAndroid Build Coastguard Worker if (*i == v->len) bc_vec_push(v, ptr);
1090*cf5a6c84SAndroid Build Coastguard Worker else if (!bc_id_cmp(ptr, bc_vec_item(v, *i))) return 0;
1091*cf5a6c84SAndroid Build Coastguard Worker else bc_vec_pushAt(v, ptr, *i);
1092*cf5a6c84SAndroid Build Coastguard Worker
1093*cf5a6c84SAndroid Build Coastguard Worker return 1;
1094*cf5a6c84SAndroid Build Coastguard Worker }
1095*cf5a6c84SAndroid Build Coastguard Worker
bc_map_index(BcVec * v,struct str_len * ptr)1096*cf5a6c84SAndroid Build Coastguard Worker size_t bc_map_index(BcVec *v, struct str_len *ptr) {
1097*cf5a6c84SAndroid Build Coastguard Worker size_t i = bc_map_find(v, ptr);
1098*cf5a6c84SAndroid Build Coastguard Worker if (i >= v->len) return SIZE_MAX;
1099*cf5a6c84SAndroid Build Coastguard Worker return bc_id_cmp(ptr, bc_vec_item(v, i)) ? SIZE_MAX : i;
1100*cf5a6c84SAndroid Build Coastguard Worker }
1101*cf5a6c84SAndroid Build Coastguard Worker
bc_read_binary(char * buf,size_t size)1102*cf5a6c84SAndroid Build Coastguard Worker static int bc_read_binary(char *buf, size_t size) {
1103*cf5a6c84SAndroid Build Coastguard Worker
1104*cf5a6c84SAndroid Build Coastguard Worker size_t i;
1105*cf5a6c84SAndroid Build Coastguard Worker
1106*cf5a6c84SAndroid Build Coastguard Worker for (i = 0; i < size; ++i)
1107*cf5a6c84SAndroid Build Coastguard Worker if ((buf[i]<' ' && !isspace(buf[i])) || buf[i]>'~') return 1;
1108*cf5a6c84SAndroid Build Coastguard Worker
1109*cf5a6c84SAndroid Build Coastguard Worker return 0;
1110*cf5a6c84SAndroid Build Coastguard Worker }
1111*cf5a6c84SAndroid Build Coastguard Worker
bc_read_chars(BcVec * vec,char * prompt)1112*cf5a6c84SAndroid Build Coastguard Worker BcStatus bc_read_chars(BcVec *vec, char *prompt) {
1113*cf5a6c84SAndroid Build Coastguard Worker
1114*cf5a6c84SAndroid Build Coastguard Worker int i;
1115*cf5a6c84SAndroid Build Coastguard Worker signed char c = 0;
1116*cf5a6c84SAndroid Build Coastguard Worker
1117*cf5a6c84SAndroid Build Coastguard Worker bc_vec_npop(vec, vec->len);
1118*cf5a6c84SAndroid Build Coastguard Worker
1119*cf5a6c84SAndroid Build Coastguard Worker if (BC_TTYIN && !FLAG(s)) {
1120*cf5a6c84SAndroid Build Coastguard Worker fputs(prompt, stderr);
1121*cf5a6c84SAndroid Build Coastguard Worker fflush(stderr);
1122*cf5a6c84SAndroid Build Coastguard Worker }
1123*cf5a6c84SAndroid Build Coastguard Worker
1124*cf5a6c84SAndroid Build Coastguard Worker while (!TT.sig && c != '\n') {
1125*cf5a6c84SAndroid Build Coastguard Worker
1126*cf5a6c84SAndroid Build Coastguard Worker i = fgetc(stdin);
1127*cf5a6c84SAndroid Build Coastguard Worker
1128*cf5a6c84SAndroid Build Coastguard Worker if (i == EOF) {
1129*cf5a6c84SAndroid Build Coastguard Worker
1130*cf5a6c84SAndroid Build Coastguard Worker if (errno == EINTR) {
1131*cf5a6c84SAndroid Build Coastguard Worker
1132*cf5a6c84SAndroid Build Coastguard Worker if (TT.sig == SIGTERM || TT.sig == SIGQUIT) return BC_STATUS_SIGNAL;
1133*cf5a6c84SAndroid Build Coastguard Worker
1134*cf5a6c84SAndroid Build Coastguard Worker TT.sig = 0;
1135*cf5a6c84SAndroid Build Coastguard Worker
1136*cf5a6c84SAndroid Build Coastguard Worker if (BC_TTYIN) {
1137*cf5a6c84SAndroid Build Coastguard Worker fputs(bc_program_ready_msg, stderr);
1138*cf5a6c84SAndroid Build Coastguard Worker if (!FLAG(s)) fputs(prompt, stderr);
1139*cf5a6c84SAndroid Build Coastguard Worker fflush(stderr);
1140*cf5a6c84SAndroid Build Coastguard Worker }
1141*cf5a6c84SAndroid Build Coastguard Worker else return BC_STATUS_SIGNAL;
1142*cf5a6c84SAndroid Build Coastguard Worker
1143*cf5a6c84SAndroid Build Coastguard Worker continue;
1144*cf5a6c84SAndroid Build Coastguard Worker }
1145*cf5a6c84SAndroid Build Coastguard Worker
1146*cf5a6c84SAndroid Build Coastguard Worker bc_vec_pushByte(vec, '\0');
1147*cf5a6c84SAndroid Build Coastguard Worker return BC_STATUS_EOF;
1148*cf5a6c84SAndroid Build Coastguard Worker }
1149*cf5a6c84SAndroid Build Coastguard Worker
1150*cf5a6c84SAndroid Build Coastguard Worker c = (signed char) i;
1151*cf5a6c84SAndroid Build Coastguard Worker bc_vec_push(vec, &c);
1152*cf5a6c84SAndroid Build Coastguard Worker }
1153*cf5a6c84SAndroid Build Coastguard Worker
1154*cf5a6c84SAndroid Build Coastguard Worker bc_vec_pushByte(vec, '\0');
1155*cf5a6c84SAndroid Build Coastguard Worker
1156*cf5a6c84SAndroid Build Coastguard Worker return TT.sig ? BC_STATUS_SIGNAL : BC_STATUS_SUCCESS;
1157*cf5a6c84SAndroid Build Coastguard Worker }
1158*cf5a6c84SAndroid Build Coastguard Worker
bc_read_line(BcVec * vec,char * prompt)1159*cf5a6c84SAndroid Build Coastguard Worker BcStatus bc_read_line(BcVec *vec, char *prompt) {
1160*cf5a6c84SAndroid Build Coastguard Worker
1161*cf5a6c84SAndroid Build Coastguard Worker BcStatus s;
1162*cf5a6c84SAndroid Build Coastguard Worker
1163*cf5a6c84SAndroid Build Coastguard Worker // We are about to output to stderr, so flush stdout to
1164*cf5a6c84SAndroid Build Coastguard Worker // make sure that we don't get the outputs mixed up.
1165*cf5a6c84SAndroid Build Coastguard Worker fflush(stdout);
1166*cf5a6c84SAndroid Build Coastguard Worker
1167*cf5a6c84SAndroid Build Coastguard Worker s = bc_read_chars(vec, prompt);
1168*cf5a6c84SAndroid Build Coastguard Worker if (s && s != BC_STATUS_EOF) return s;
1169*cf5a6c84SAndroid Build Coastguard Worker if (bc_read_binary(vec->v, vec->len - 1))
1170*cf5a6c84SAndroid Build Coastguard Worker return bc_vm_verr(BC_ERROR_VM_BIN_FILE, "<stdin>");
1171*cf5a6c84SAndroid Build Coastguard Worker
1172*cf5a6c84SAndroid Build Coastguard Worker return BC_STATUS_SUCCESS;
1173*cf5a6c84SAndroid Build Coastguard Worker }
1174*cf5a6c84SAndroid Build Coastguard Worker
bc_read_file(char * path,char ** buf)1175*cf5a6c84SAndroid Build Coastguard Worker BcStatus bc_read_file(char *path, char **buf) {
1176*cf5a6c84SAndroid Build Coastguard Worker
1177*cf5a6c84SAndroid Build Coastguard Worker BcError e = BC_ERROR_VM_IO_ERR;
1178*cf5a6c84SAndroid Build Coastguard Worker FILE *f;
1179*cf5a6c84SAndroid Build Coastguard Worker size_t size, read;
1180*cf5a6c84SAndroid Build Coastguard Worker long res;
1181*cf5a6c84SAndroid Build Coastguard Worker struct stat pstat;
1182*cf5a6c84SAndroid Build Coastguard Worker
1183*cf5a6c84SAndroid Build Coastguard Worker f = fopen(path, "r");
1184*cf5a6c84SAndroid Build Coastguard Worker if (!f) return bc_vm_verr(BC_ERROR_EXEC_FILE_ERR, path);
1185*cf5a6c84SAndroid Build Coastguard Worker if (fstat(fileno(f), &pstat) == -1) goto malloc_err;
1186*cf5a6c84SAndroid Build Coastguard Worker
1187*cf5a6c84SAndroid Build Coastguard Worker if (S_ISDIR(pstat.st_mode)) {
1188*cf5a6c84SAndroid Build Coastguard Worker e = BC_ERROR_VM_PATH_DIR;
1189*cf5a6c84SAndroid Build Coastguard Worker goto malloc_err;
1190*cf5a6c84SAndroid Build Coastguard Worker }
1191*cf5a6c84SAndroid Build Coastguard Worker
1192*cf5a6c84SAndroid Build Coastguard Worker if (fseek(f, 0, SEEK_END) == -1) goto malloc_err;
1193*cf5a6c84SAndroid Build Coastguard Worker res = ftell(f);
1194*cf5a6c84SAndroid Build Coastguard Worker if (res < 0) goto malloc_err;
1195*cf5a6c84SAndroid Build Coastguard Worker if (fseek(f, 0, SEEK_SET) == -1) goto malloc_err;
1196*cf5a6c84SAndroid Build Coastguard Worker
1197*cf5a6c84SAndroid Build Coastguard Worker size = (size_t) res;
1198*cf5a6c84SAndroid Build Coastguard Worker *buf = xmalloc(size + 1);
1199*cf5a6c84SAndroid Build Coastguard Worker
1200*cf5a6c84SAndroid Build Coastguard Worker read = fread(*buf, 1, size, f);
1201*cf5a6c84SAndroid Build Coastguard Worker if (read != size) goto read_err;
1202*cf5a6c84SAndroid Build Coastguard Worker
1203*cf5a6c84SAndroid Build Coastguard Worker (*buf)[size] = '\0';
1204*cf5a6c84SAndroid Build Coastguard Worker
1205*cf5a6c84SAndroid Build Coastguard Worker if (bc_read_binary(*buf, size)) {
1206*cf5a6c84SAndroid Build Coastguard Worker e = BC_ERROR_VM_BIN_FILE;
1207*cf5a6c84SAndroid Build Coastguard Worker goto read_err;
1208*cf5a6c84SAndroid Build Coastguard Worker }
1209*cf5a6c84SAndroid Build Coastguard Worker
1210*cf5a6c84SAndroid Build Coastguard Worker fclose(f);
1211*cf5a6c84SAndroid Build Coastguard Worker
1212*cf5a6c84SAndroid Build Coastguard Worker return BC_STATUS_SUCCESS;
1213*cf5a6c84SAndroid Build Coastguard Worker
1214*cf5a6c84SAndroid Build Coastguard Worker read_err:
1215*cf5a6c84SAndroid Build Coastguard Worker free(*buf);
1216*cf5a6c84SAndroid Build Coastguard Worker malloc_err:
1217*cf5a6c84SAndroid Build Coastguard Worker fclose(f);
1218*cf5a6c84SAndroid Build Coastguard Worker return bc_vm_verr(e, path);
1219*cf5a6c84SAndroid Build Coastguard Worker }
1220*cf5a6c84SAndroid Build Coastguard Worker
bc_num_setToZero(BcNum * n,size_t scale)1221*cf5a6c84SAndroid Build Coastguard Worker static void bc_num_setToZero(BcNum *n, size_t scale) {
1222*cf5a6c84SAndroid Build Coastguard Worker n->len = 0;
1223*cf5a6c84SAndroid Build Coastguard Worker n->neg = 0;
1224*cf5a6c84SAndroid Build Coastguard Worker n->rdx = scale;
1225*cf5a6c84SAndroid Build Coastguard Worker }
1226*cf5a6c84SAndroid Build Coastguard Worker
bc_num_one(BcNum * n)1227*cf5a6c84SAndroid Build Coastguard Worker void bc_num_one(BcNum *n) {
1228*cf5a6c84SAndroid Build Coastguard Worker bc_num_setToZero(n, 0);
1229*cf5a6c84SAndroid Build Coastguard Worker n->len = 1;
1230*cf5a6c84SAndroid Build Coastguard Worker n->num[0] = 1;
1231*cf5a6c84SAndroid Build Coastguard Worker }
1232*cf5a6c84SAndroid Build Coastguard Worker
bc_num_ten(BcNum * n)1233*cf5a6c84SAndroid Build Coastguard Worker void bc_num_ten(BcNum *n) {
1234*cf5a6c84SAndroid Build Coastguard Worker bc_num_setToZero(n, 0);
1235*cf5a6c84SAndroid Build Coastguard Worker n->len = 2;
1236*cf5a6c84SAndroid Build Coastguard Worker n->num[0] = 0;
1237*cf5a6c84SAndroid Build Coastguard Worker n->num[1] = 1;
1238*cf5a6c84SAndroid Build Coastguard Worker }
1239*cf5a6c84SAndroid Build Coastguard Worker
bc_num_log10(size_t i)1240*cf5a6c84SAndroid Build Coastguard Worker static size_t bc_num_log10(size_t i) {
1241*cf5a6c84SAndroid Build Coastguard Worker size_t len;
1242*cf5a6c84SAndroid Build Coastguard Worker for (len = 1; i; i /= 10, ++len);
1243*cf5a6c84SAndroid Build Coastguard Worker return len;
1244*cf5a6c84SAndroid Build Coastguard Worker }
1245*cf5a6c84SAndroid Build Coastguard Worker
bc_num_subArrays(signed char * a,signed char * b,size_t len)1246*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_num_subArrays(signed char *a, signed char *b, size_t len)
1247*cf5a6c84SAndroid Build Coastguard Worker {
1248*cf5a6c84SAndroid Build Coastguard Worker size_t i, j;
1249*cf5a6c84SAndroid Build Coastguard Worker for (i = 0; !TT.sig && i < len; ++i) {
1250*cf5a6c84SAndroid Build Coastguard Worker for (a[i] -= b[i], j = 0; !TT.sig && a[i + j] < 0;) {
1251*cf5a6c84SAndroid Build Coastguard Worker a[i + j++] += 10;
1252*cf5a6c84SAndroid Build Coastguard Worker a[i + j] -= 1;
1253*cf5a6c84SAndroid Build Coastguard Worker }
1254*cf5a6c84SAndroid Build Coastguard Worker }
1255*cf5a6c84SAndroid Build Coastguard Worker return TT.sig ? BC_STATUS_SIGNAL : BC_STATUS_SUCCESS;
1256*cf5a6c84SAndroid Build Coastguard Worker }
1257*cf5a6c84SAndroid Build Coastguard Worker
bc_num_compare(signed char * a,signed char * b,size_t len)1258*cf5a6c84SAndroid Build Coastguard Worker static ssize_t bc_num_compare(signed char *a, signed char *b, size_t len)
1259*cf5a6c84SAndroid Build Coastguard Worker {
1260*cf5a6c84SAndroid Build Coastguard Worker size_t i;
1261*cf5a6c84SAndroid Build Coastguard Worker int c = 0;
1262*cf5a6c84SAndroid Build Coastguard Worker
1263*cf5a6c84SAndroid Build Coastguard Worker for (i = len - 1; !TT.sig && i < len && !(c = a[i] - b[i]); --i);
1264*cf5a6c84SAndroid Build Coastguard Worker return BC_NUM_NEG(i + 1, c < 0);
1265*cf5a6c84SAndroid Build Coastguard Worker }
1266*cf5a6c84SAndroid Build Coastguard Worker
bc_num_cmp(BcNum * a,BcNum * b)1267*cf5a6c84SAndroid Build Coastguard Worker ssize_t bc_num_cmp(BcNum *a, BcNum *b) {
1268*cf5a6c84SAndroid Build Coastguard Worker
1269*cf5a6c84SAndroid Build Coastguard Worker size_t i, min, a_int, b_int, diff;
1270*cf5a6c84SAndroid Build Coastguard Worker signed char *max_num, *min_num;
1271*cf5a6c84SAndroid Build Coastguard Worker int a_max, neg = 0;
1272*cf5a6c84SAndroid Build Coastguard Worker ssize_t cmp;
1273*cf5a6c84SAndroid Build Coastguard Worker
1274*cf5a6c84SAndroid Build Coastguard Worker if (a == b) return 0;
1275*cf5a6c84SAndroid Build Coastguard Worker if (!a->len) return BC_NUM_NEG(b->len != 0, !b->neg);
1276*cf5a6c84SAndroid Build Coastguard Worker if (!b->len) return BC_NUM_CMP_ZERO(a);
1277*cf5a6c84SAndroid Build Coastguard Worker if (a->neg) {
1278*cf5a6c84SAndroid Build Coastguard Worker if (b->neg) neg = 1;
1279*cf5a6c84SAndroid Build Coastguard Worker else return -1;
1280*cf5a6c84SAndroid Build Coastguard Worker } else if (b->neg) return 1;
1281*cf5a6c84SAndroid Build Coastguard Worker
1282*cf5a6c84SAndroid Build Coastguard Worker a_int = BC_NUM_INT(a);
1283*cf5a6c84SAndroid Build Coastguard Worker b_int = BC_NUM_INT(b);
1284*cf5a6c84SAndroid Build Coastguard Worker a_int -= b_int;
1285*cf5a6c84SAndroid Build Coastguard Worker a_max = (a->rdx > b->rdx);
1286*cf5a6c84SAndroid Build Coastguard Worker
1287*cf5a6c84SAndroid Build Coastguard Worker if (a_int) return neg ? -((ssize_t) a_int) : (ssize_t) a_int;
1288*cf5a6c84SAndroid Build Coastguard Worker
1289*cf5a6c84SAndroid Build Coastguard Worker if (a_max) {
1290*cf5a6c84SAndroid Build Coastguard Worker min = b->rdx;
1291*cf5a6c84SAndroid Build Coastguard Worker diff = a->rdx - b->rdx;
1292*cf5a6c84SAndroid Build Coastguard Worker max_num = a->num + diff;
1293*cf5a6c84SAndroid Build Coastguard Worker min_num = b->num;
1294*cf5a6c84SAndroid Build Coastguard Worker } else {
1295*cf5a6c84SAndroid Build Coastguard Worker min = a->rdx;
1296*cf5a6c84SAndroid Build Coastguard Worker diff = b->rdx - a->rdx;
1297*cf5a6c84SAndroid Build Coastguard Worker max_num = b->num + diff;
1298*cf5a6c84SAndroid Build Coastguard Worker min_num = a->num;
1299*cf5a6c84SAndroid Build Coastguard Worker }
1300*cf5a6c84SAndroid Build Coastguard Worker
1301*cf5a6c84SAndroid Build Coastguard Worker cmp = bc_num_compare(max_num, min_num, b_int + min);
1302*cf5a6c84SAndroid Build Coastguard Worker if (cmp) return BC_NUM_NEG(cmp, (!a_max) != neg);
1303*cf5a6c84SAndroid Build Coastguard Worker
1304*cf5a6c84SAndroid Build Coastguard Worker for (max_num -= diff, i = diff - 1; !TT.sig && i < diff; --i) {
1305*cf5a6c84SAndroid Build Coastguard Worker if (max_num[i]) return BC_NUM_NEG(1, (!a_max) != neg);
1306*cf5a6c84SAndroid Build Coastguard Worker }
1307*cf5a6c84SAndroid Build Coastguard Worker
1308*cf5a6c84SAndroid Build Coastguard Worker return 0;
1309*cf5a6c84SAndroid Build Coastguard Worker }
1310*cf5a6c84SAndroid Build Coastguard Worker
bc_num_clean(BcNum * n)1311*cf5a6c84SAndroid Build Coastguard Worker static void bc_num_clean(BcNum *n) {
1312*cf5a6c84SAndroid Build Coastguard Worker while (n->len && !n->num[n->len - 1]) --n->len;
1313*cf5a6c84SAndroid Build Coastguard Worker if (!n->len) n->neg = 0;
1314*cf5a6c84SAndroid Build Coastguard Worker else if (n->len < n->rdx) n->len = n->rdx;
1315*cf5a6c84SAndroid Build Coastguard Worker }
1316*cf5a6c84SAndroid Build Coastguard Worker
bc_num_truncate(BcNum * n,size_t places)1317*cf5a6c84SAndroid Build Coastguard Worker void bc_num_truncate(BcNum *n, size_t places) {
1318*cf5a6c84SAndroid Build Coastguard Worker
1319*cf5a6c84SAndroid Build Coastguard Worker if (!places) return;
1320*cf5a6c84SAndroid Build Coastguard Worker
1321*cf5a6c84SAndroid Build Coastguard Worker n->rdx -= places;
1322*cf5a6c84SAndroid Build Coastguard Worker
1323*cf5a6c84SAndroid Build Coastguard Worker if (n->len) {
1324*cf5a6c84SAndroid Build Coastguard Worker n->len -= places;
1325*cf5a6c84SAndroid Build Coastguard Worker memmove(n->num, n->num + places, n->len);
1326*cf5a6c84SAndroid Build Coastguard Worker bc_num_clean(n);
1327*cf5a6c84SAndroid Build Coastguard Worker }
1328*cf5a6c84SAndroid Build Coastguard Worker }
1329*cf5a6c84SAndroid Build Coastguard Worker
bc_num_extend(BcNum * n,size_t places)1330*cf5a6c84SAndroid Build Coastguard Worker static void bc_num_extend(BcNum *n, size_t places) {
1331*cf5a6c84SAndroid Build Coastguard Worker
1332*cf5a6c84SAndroid Build Coastguard Worker size_t len = n->len + places;
1333*cf5a6c84SAndroid Build Coastguard Worker
1334*cf5a6c84SAndroid Build Coastguard Worker if (!places) return;
1335*cf5a6c84SAndroid Build Coastguard Worker
1336*cf5a6c84SAndroid Build Coastguard Worker if (n->cap < len) bc_num_expand(n, len);
1337*cf5a6c84SAndroid Build Coastguard Worker
1338*cf5a6c84SAndroid Build Coastguard Worker memmove(n->num + places, n->num, n->len);
1339*cf5a6c84SAndroid Build Coastguard Worker memset(n->num, 0, places);
1340*cf5a6c84SAndroid Build Coastguard Worker
1341*cf5a6c84SAndroid Build Coastguard Worker if (n->len) n->len += places;
1342*cf5a6c84SAndroid Build Coastguard Worker
1343*cf5a6c84SAndroid Build Coastguard Worker n->rdx += places;
1344*cf5a6c84SAndroid Build Coastguard Worker }
1345*cf5a6c84SAndroid Build Coastguard Worker
bc_num_retireMul(BcNum * n,size_t scale,int neg1,int neg2)1346*cf5a6c84SAndroid Build Coastguard Worker static void bc_num_retireMul(BcNum *n, size_t scale, int neg1, int neg2) {
1347*cf5a6c84SAndroid Build Coastguard Worker
1348*cf5a6c84SAndroid Build Coastguard Worker if (n->rdx < scale) bc_num_extend(n, scale - n->rdx);
1349*cf5a6c84SAndroid Build Coastguard Worker else bc_num_truncate(n, n->rdx - scale);
1350*cf5a6c84SAndroid Build Coastguard Worker
1351*cf5a6c84SAndroid Build Coastguard Worker bc_num_clean(n);
1352*cf5a6c84SAndroid Build Coastguard Worker if (n->len) n->neg = (!neg1 != !neg2);
1353*cf5a6c84SAndroid Build Coastguard Worker }
1354*cf5a6c84SAndroid Build Coastguard Worker
bc_num_split(BcNum * n,size_t idx,BcNum * a,BcNum * b)1355*cf5a6c84SAndroid Build Coastguard Worker static void bc_num_split(BcNum *n, size_t idx, BcNum *a, BcNum *b) {
1356*cf5a6c84SAndroid Build Coastguard Worker
1357*cf5a6c84SAndroid Build Coastguard Worker if (idx < n->len) {
1358*cf5a6c84SAndroid Build Coastguard Worker
1359*cf5a6c84SAndroid Build Coastguard Worker b->len = n->len - idx;
1360*cf5a6c84SAndroid Build Coastguard Worker a->len = idx;
1361*cf5a6c84SAndroid Build Coastguard Worker a->rdx = b->rdx = 0;
1362*cf5a6c84SAndroid Build Coastguard Worker
1363*cf5a6c84SAndroid Build Coastguard Worker memcpy(b->num, n->num + idx, b->len);
1364*cf5a6c84SAndroid Build Coastguard Worker memcpy(a->num, n->num, idx);
1365*cf5a6c84SAndroid Build Coastguard Worker
1366*cf5a6c84SAndroid Build Coastguard Worker bc_num_clean(b);
1367*cf5a6c84SAndroid Build Coastguard Worker }
1368*cf5a6c84SAndroid Build Coastguard Worker else bc_num_copy(a, n);
1369*cf5a6c84SAndroid Build Coastguard Worker
1370*cf5a6c84SAndroid Build Coastguard Worker bc_num_clean(a);
1371*cf5a6c84SAndroid Build Coastguard Worker }
1372*cf5a6c84SAndroid Build Coastguard Worker
bc_num_shift(BcNum * n,size_t places)1373*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_num_shift(BcNum *n, size_t places) {
1374*cf5a6c84SAndroid Build Coastguard Worker
1375*cf5a6c84SAndroid Build Coastguard Worker if (!places || !n->len) return BC_STATUS_SUCCESS;
1376*cf5a6c84SAndroid Build Coastguard Worker if (places + n->len > BC_MAX_NUM)
1377*cf5a6c84SAndroid Build Coastguard Worker return bc_vm_verr(BC_ERROR_MATH_OVERFLOW, "shifted left too far");
1378*cf5a6c84SAndroid Build Coastguard Worker
1379*cf5a6c84SAndroid Build Coastguard Worker if (n->rdx >= places) n->rdx -= places;
1380*cf5a6c84SAndroid Build Coastguard Worker else {
1381*cf5a6c84SAndroid Build Coastguard Worker bc_num_extend(n, places - n->rdx);
1382*cf5a6c84SAndroid Build Coastguard Worker n->rdx = 0;
1383*cf5a6c84SAndroid Build Coastguard Worker }
1384*cf5a6c84SAndroid Build Coastguard Worker
1385*cf5a6c84SAndroid Build Coastguard Worker bc_num_clean(n);
1386*cf5a6c84SAndroid Build Coastguard Worker
1387*cf5a6c84SAndroid Build Coastguard Worker return BC_STATUS_SUCCESS;
1388*cf5a6c84SAndroid Build Coastguard Worker }
1389*cf5a6c84SAndroid Build Coastguard Worker
bc_num_inv(BcNum * a,BcNum * b,size_t scale)1390*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_num_inv(BcNum *a, BcNum *b, size_t scale) {
1391*cf5a6c84SAndroid Build Coastguard Worker
1392*cf5a6c84SAndroid Build Coastguard Worker BcNum one;
1393*cf5a6c84SAndroid Build Coastguard Worker signed char num[2];
1394*cf5a6c84SAndroid Build Coastguard Worker
1395*cf5a6c84SAndroid Build Coastguard Worker one.cap = 2;
1396*cf5a6c84SAndroid Build Coastguard Worker one.num = num;
1397*cf5a6c84SAndroid Build Coastguard Worker bc_num_one(&one);
1398*cf5a6c84SAndroid Build Coastguard Worker
1399*cf5a6c84SAndroid Build Coastguard Worker return bc_num_div(&one, a, b, scale);
1400*cf5a6c84SAndroid Build Coastguard Worker }
1401*cf5a6c84SAndroid Build Coastguard Worker
bc_num_addDigit(signed char * num,unsigned int d,unsigned int c)1402*cf5a6c84SAndroid Build Coastguard Worker static unsigned int bc_num_addDigit(signed char *num, unsigned int d, unsigned int c)
1403*cf5a6c84SAndroid Build Coastguard Worker {
1404*cf5a6c84SAndroid Build Coastguard Worker d += c;
1405*cf5a6c84SAndroid Build Coastguard Worker *num = d % 10;
1406*cf5a6c84SAndroid Build Coastguard Worker return d / 10;
1407*cf5a6c84SAndroid Build Coastguard Worker }
1408*cf5a6c84SAndroid Build Coastguard Worker
bc_num_a(BcNum * a,BcNum * b,BcNum * c,size_t sub)1409*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_num_a(BcNum *a, BcNum *b, BcNum *c, size_t sub) {
1410*cf5a6c84SAndroid Build Coastguard Worker
1411*cf5a6c84SAndroid Build Coastguard Worker signed char *ptr, *ptr_a, *ptr_b, *ptr_c;
1412*cf5a6c84SAndroid Build Coastguard Worker size_t i, max, min_rdx, min_int, diff, a_int, b_int;
1413*cf5a6c84SAndroid Build Coastguard Worker unsigned int carry;
1414*cf5a6c84SAndroid Build Coastguard Worker
1415*cf5a6c84SAndroid Build Coastguard Worker // Because this function doesn't need to use scale (per the bc spec),
1416*cf5a6c84SAndroid Build Coastguard Worker // I am hijacking it to say whether it's doing an add or a subtract.
1417*cf5a6c84SAndroid Build Coastguard Worker
1418*cf5a6c84SAndroid Build Coastguard Worker if (!a->len) {
1419*cf5a6c84SAndroid Build Coastguard Worker bc_num_copy(c, b);
1420*cf5a6c84SAndroid Build Coastguard Worker if (sub && c->len) c->neg = !c->neg;
1421*cf5a6c84SAndroid Build Coastguard Worker return BC_STATUS_SUCCESS;
1422*cf5a6c84SAndroid Build Coastguard Worker }
1423*cf5a6c84SAndroid Build Coastguard Worker if (!b->len) {
1424*cf5a6c84SAndroid Build Coastguard Worker bc_num_copy(c, a);
1425*cf5a6c84SAndroid Build Coastguard Worker return BC_STATUS_SUCCESS;
1426*cf5a6c84SAndroid Build Coastguard Worker }
1427*cf5a6c84SAndroid Build Coastguard Worker
1428*cf5a6c84SAndroid Build Coastguard Worker c->neg = a->neg;
1429*cf5a6c84SAndroid Build Coastguard Worker c->rdx = maxof(a->rdx, b->rdx);
1430*cf5a6c84SAndroid Build Coastguard Worker min_rdx = minof(a->rdx, b->rdx);
1431*cf5a6c84SAndroid Build Coastguard Worker
1432*cf5a6c84SAndroid Build Coastguard Worker if (a->rdx > b->rdx) {
1433*cf5a6c84SAndroid Build Coastguard Worker diff = a->rdx - b->rdx;
1434*cf5a6c84SAndroid Build Coastguard Worker ptr = a->num;
1435*cf5a6c84SAndroid Build Coastguard Worker ptr_a = a->num + diff;
1436*cf5a6c84SAndroid Build Coastguard Worker ptr_b = b->num;
1437*cf5a6c84SAndroid Build Coastguard Worker }
1438*cf5a6c84SAndroid Build Coastguard Worker else {
1439*cf5a6c84SAndroid Build Coastguard Worker diff = b->rdx - a->rdx;
1440*cf5a6c84SAndroid Build Coastguard Worker ptr = b->num;
1441*cf5a6c84SAndroid Build Coastguard Worker ptr_a = a->num;
1442*cf5a6c84SAndroid Build Coastguard Worker ptr_b = b->num + diff;
1443*cf5a6c84SAndroid Build Coastguard Worker }
1444*cf5a6c84SAndroid Build Coastguard Worker
1445*cf5a6c84SAndroid Build Coastguard Worker for (ptr_c = c->num, i = 0; i < diff; ++i) ptr_c[i] = ptr[i];
1446*cf5a6c84SAndroid Build Coastguard Worker
1447*cf5a6c84SAndroid Build Coastguard Worker c->len = diff;
1448*cf5a6c84SAndroid Build Coastguard Worker ptr_c += diff;
1449*cf5a6c84SAndroid Build Coastguard Worker a_int = BC_NUM_INT(a);
1450*cf5a6c84SAndroid Build Coastguard Worker b_int = BC_NUM_INT(b);
1451*cf5a6c84SAndroid Build Coastguard Worker
1452*cf5a6c84SAndroid Build Coastguard Worker if (a_int > b_int) {
1453*cf5a6c84SAndroid Build Coastguard Worker min_int = b_int;
1454*cf5a6c84SAndroid Build Coastguard Worker max = a_int;
1455*cf5a6c84SAndroid Build Coastguard Worker ptr = ptr_a;
1456*cf5a6c84SAndroid Build Coastguard Worker }
1457*cf5a6c84SAndroid Build Coastguard Worker else {
1458*cf5a6c84SAndroid Build Coastguard Worker min_int = a_int;
1459*cf5a6c84SAndroid Build Coastguard Worker max = b_int;
1460*cf5a6c84SAndroid Build Coastguard Worker ptr = ptr_b;
1461*cf5a6c84SAndroid Build Coastguard Worker }
1462*cf5a6c84SAndroid Build Coastguard Worker
1463*cf5a6c84SAndroid Build Coastguard Worker for (carry = 0, i = 0; !TT.sig && i < min_rdx + min_int; ++i) {
1464*cf5a6c84SAndroid Build Coastguard Worker unsigned int in = (unsigned int) (ptr_a[i] + ptr_b[i]);
1465*cf5a6c84SAndroid Build Coastguard Worker carry = bc_num_addDigit(ptr_c + i, in, carry);
1466*cf5a6c84SAndroid Build Coastguard Worker }
1467*cf5a6c84SAndroid Build Coastguard Worker
1468*cf5a6c84SAndroid Build Coastguard Worker for (; !TT.sig && i < max + min_rdx; ++i)
1469*cf5a6c84SAndroid Build Coastguard Worker carry = bc_num_addDigit(ptr_c + i, (unsigned int) ptr[i], carry);
1470*cf5a6c84SAndroid Build Coastguard Worker
1471*cf5a6c84SAndroid Build Coastguard Worker c->len += i;
1472*cf5a6c84SAndroid Build Coastguard Worker
1473*cf5a6c84SAndroid Build Coastguard Worker if (carry) c->num[c->len++] = carry;
1474*cf5a6c84SAndroid Build Coastguard Worker
1475*cf5a6c84SAndroid Build Coastguard Worker return TT.sig ? BC_STATUS_SIGNAL : BC_STATUS_SUCCESS;
1476*cf5a6c84SAndroid Build Coastguard Worker }
1477*cf5a6c84SAndroid Build Coastguard Worker
bc_num_s(BcNum * a,BcNum * b,BcNum * c,size_t sub)1478*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_num_s(BcNum *a, BcNum *b, BcNum *c, size_t sub) {
1479*cf5a6c84SAndroid Build Coastguard Worker
1480*cf5a6c84SAndroid Build Coastguard Worker BcStatus s;
1481*cf5a6c84SAndroid Build Coastguard Worker ssize_t cmp;
1482*cf5a6c84SAndroid Build Coastguard Worker BcNum *minuend, *subtrahend;
1483*cf5a6c84SAndroid Build Coastguard Worker size_t start;
1484*cf5a6c84SAndroid Build Coastguard Worker int aneg, bneg, neg;
1485*cf5a6c84SAndroid Build Coastguard Worker
1486*cf5a6c84SAndroid Build Coastguard Worker // Because this function doesn't need to use scale (per the bc spec),
1487*cf5a6c84SAndroid Build Coastguard Worker // I am hijacking it to say whether it's doing an add or a subtract.
1488*cf5a6c84SAndroid Build Coastguard Worker
1489*cf5a6c84SAndroid Build Coastguard Worker if (!a->len) {
1490*cf5a6c84SAndroid Build Coastguard Worker bc_num_copy(c, b);
1491*cf5a6c84SAndroid Build Coastguard Worker if (sub && c->len) c->neg = !c->neg;
1492*cf5a6c84SAndroid Build Coastguard Worker return BC_STATUS_SUCCESS;
1493*cf5a6c84SAndroid Build Coastguard Worker }
1494*cf5a6c84SAndroid Build Coastguard Worker if (!b->len) {
1495*cf5a6c84SAndroid Build Coastguard Worker bc_num_copy(c, a);
1496*cf5a6c84SAndroid Build Coastguard Worker return BC_STATUS_SUCCESS;
1497*cf5a6c84SAndroid Build Coastguard Worker }
1498*cf5a6c84SAndroid Build Coastguard Worker
1499*cf5a6c84SAndroid Build Coastguard Worker aneg = a->neg;
1500*cf5a6c84SAndroid Build Coastguard Worker bneg = b->neg;
1501*cf5a6c84SAndroid Build Coastguard Worker a->neg = b->neg = 0;
1502*cf5a6c84SAndroid Build Coastguard Worker
1503*cf5a6c84SAndroid Build Coastguard Worker cmp = bc_num_cmp(a, b);
1504*cf5a6c84SAndroid Build Coastguard Worker
1505*cf5a6c84SAndroid Build Coastguard Worker a->neg = aneg;
1506*cf5a6c84SAndroid Build Coastguard Worker b->neg = bneg;
1507*cf5a6c84SAndroid Build Coastguard Worker
1508*cf5a6c84SAndroid Build Coastguard Worker if (!cmp) {
1509*cf5a6c84SAndroid Build Coastguard Worker bc_num_setToZero(c, maxof(a->rdx, b->rdx));
1510*cf5a6c84SAndroid Build Coastguard Worker return BC_STATUS_SUCCESS;
1511*cf5a6c84SAndroid Build Coastguard Worker }
1512*cf5a6c84SAndroid Build Coastguard Worker
1513*cf5a6c84SAndroid Build Coastguard Worker if (cmp > 0) {
1514*cf5a6c84SAndroid Build Coastguard Worker neg = a->neg;
1515*cf5a6c84SAndroid Build Coastguard Worker minuend = a;
1516*cf5a6c84SAndroid Build Coastguard Worker subtrahend = b;
1517*cf5a6c84SAndroid Build Coastguard Worker }
1518*cf5a6c84SAndroid Build Coastguard Worker else {
1519*cf5a6c84SAndroid Build Coastguard Worker neg = b->neg;
1520*cf5a6c84SAndroid Build Coastguard Worker if (sub) neg = !neg;
1521*cf5a6c84SAndroid Build Coastguard Worker minuend = b;
1522*cf5a6c84SAndroid Build Coastguard Worker subtrahend = a;
1523*cf5a6c84SAndroid Build Coastguard Worker }
1524*cf5a6c84SAndroid Build Coastguard Worker
1525*cf5a6c84SAndroid Build Coastguard Worker bc_num_copy(c, minuend);
1526*cf5a6c84SAndroid Build Coastguard Worker c->neg = neg;
1527*cf5a6c84SAndroid Build Coastguard Worker
1528*cf5a6c84SAndroid Build Coastguard Worker if (c->rdx < subtrahend->rdx) {
1529*cf5a6c84SAndroid Build Coastguard Worker bc_num_extend(c, subtrahend->rdx - c->rdx);
1530*cf5a6c84SAndroid Build Coastguard Worker start = 0;
1531*cf5a6c84SAndroid Build Coastguard Worker }
1532*cf5a6c84SAndroid Build Coastguard Worker else start = c->rdx - subtrahend->rdx;
1533*cf5a6c84SAndroid Build Coastguard Worker
1534*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_subArrays(c->num + start, subtrahend->num, subtrahend->len);
1535*cf5a6c84SAndroid Build Coastguard Worker
1536*cf5a6c84SAndroid Build Coastguard Worker bc_num_clean(c);
1537*cf5a6c84SAndroid Build Coastguard Worker
1538*cf5a6c84SAndroid Build Coastguard Worker return s;
1539*cf5a6c84SAndroid Build Coastguard Worker }
1540*cf5a6c84SAndroid Build Coastguard Worker
bc_num_k(BcNum * a,BcNum * b,BcNum * c)1541*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_num_k(BcNum *a, BcNum *b, BcNum *c) {
1542*cf5a6c84SAndroid Build Coastguard Worker
1543*cf5a6c84SAndroid Build Coastguard Worker BcStatus s;
1544*cf5a6c84SAndroid Build Coastguard Worker size_t max = maxof(a->len, b->len), max2 = (max + 1) / 2;
1545*cf5a6c84SAndroid Build Coastguard Worker BcNum l1, h1, l2, h2, m2, m1, z0, z1, z2, temp;
1546*cf5a6c84SAndroid Build Coastguard Worker int aone = BC_NUM_ONE(a);
1547*cf5a6c84SAndroid Build Coastguard Worker
1548*cf5a6c84SAndroid Build Coastguard Worker // This is here because the function is recursive.
1549*cf5a6c84SAndroid Build Coastguard Worker if (TT.sig) return BC_STATUS_SIGNAL;
1550*cf5a6c84SAndroid Build Coastguard Worker if (!a->len || !b->len) {
1551*cf5a6c84SAndroid Build Coastguard Worker bc_num_setToZero(c, 0);
1552*cf5a6c84SAndroid Build Coastguard Worker return BC_STATUS_SUCCESS;
1553*cf5a6c84SAndroid Build Coastguard Worker }
1554*cf5a6c84SAndroid Build Coastguard Worker if (aone || BC_NUM_ONE(b)) {
1555*cf5a6c84SAndroid Build Coastguard Worker bc_num_copy(c, aone ? b : a);
1556*cf5a6c84SAndroid Build Coastguard Worker return BC_STATUS_SUCCESS;
1557*cf5a6c84SAndroid Build Coastguard Worker }
1558*cf5a6c84SAndroid Build Coastguard Worker
1559*cf5a6c84SAndroid Build Coastguard Worker // check karatsuba length
1560*cf5a6c84SAndroid Build Coastguard Worker if (a->len + b->len < 32 || a->len < 32 || b->len < 32)
1561*cf5a6c84SAndroid Build Coastguard Worker {
1562*cf5a6c84SAndroid Build Coastguard Worker size_t i, j, len;
1563*cf5a6c84SAndroid Build Coastguard Worker unsigned int carry;
1564*cf5a6c84SAndroid Build Coastguard Worker signed char *ptr_c;
1565*cf5a6c84SAndroid Build Coastguard Worker
1566*cf5a6c84SAndroid Build Coastguard Worker bc_num_expand(c, a->len + b->len + 1);
1567*cf5a6c84SAndroid Build Coastguard Worker
1568*cf5a6c84SAndroid Build Coastguard Worker ptr_c = c->num;
1569*cf5a6c84SAndroid Build Coastguard Worker memset(ptr_c, 0, c->cap);
1570*cf5a6c84SAndroid Build Coastguard Worker c->len = len = 0;
1571*cf5a6c84SAndroid Build Coastguard Worker
1572*cf5a6c84SAndroid Build Coastguard Worker for (i = 0; !TT.sig && i < b->len; ++i) {
1573*cf5a6c84SAndroid Build Coastguard Worker
1574*cf5a6c84SAndroid Build Coastguard Worker signed char *ptr = ptr_c + i;
1575*cf5a6c84SAndroid Build Coastguard Worker
1576*cf5a6c84SAndroid Build Coastguard Worker carry = 0;
1577*cf5a6c84SAndroid Build Coastguard Worker
1578*cf5a6c84SAndroid Build Coastguard Worker for (j = 0; !TT.sig && j < a->len; ++j) {
1579*cf5a6c84SAndroid Build Coastguard Worker unsigned int in = (char) ptr[j];
1580*cf5a6c84SAndroid Build Coastguard Worker in += ((unsigned int) a->num[j]) * ((unsigned int) b->num[i]);
1581*cf5a6c84SAndroid Build Coastguard Worker carry = bc_num_addDigit(ptr + j, in, carry);
1582*cf5a6c84SAndroid Build Coastguard Worker }
1583*cf5a6c84SAndroid Build Coastguard Worker // todo: is this typecast useless?
1584*cf5a6c84SAndroid Build Coastguard Worker ptr[j] += (signed) carry;
1585*cf5a6c84SAndroid Build Coastguard Worker len = maxof(len, i + j + (carry != 0));
1586*cf5a6c84SAndroid Build Coastguard Worker }
1587*cf5a6c84SAndroid Build Coastguard Worker
1588*cf5a6c84SAndroid Build Coastguard Worker c->len = len;
1589*cf5a6c84SAndroid Build Coastguard Worker
1590*cf5a6c84SAndroid Build Coastguard Worker return TT.sig ? BC_STATUS_SIGNAL : BC_STATUS_SUCCESS;
1591*cf5a6c84SAndroid Build Coastguard Worker }
1592*cf5a6c84SAndroid Build Coastguard Worker
1593*cf5a6c84SAndroid Build Coastguard Worker bc_num_init(&l1, max);
1594*cf5a6c84SAndroid Build Coastguard Worker bc_num_init(&h1, max);
1595*cf5a6c84SAndroid Build Coastguard Worker bc_num_init(&l2, max);
1596*cf5a6c84SAndroid Build Coastguard Worker bc_num_init(&h2, max);
1597*cf5a6c84SAndroid Build Coastguard Worker bc_num_init(&m1, max);
1598*cf5a6c84SAndroid Build Coastguard Worker bc_num_init(&m2, max);
1599*cf5a6c84SAndroid Build Coastguard Worker bc_num_init(&z0, max);
1600*cf5a6c84SAndroid Build Coastguard Worker bc_num_init(&z1, max);
1601*cf5a6c84SAndroid Build Coastguard Worker bc_num_init(&z2, max);
1602*cf5a6c84SAndroid Build Coastguard Worker bc_num_init(&temp, max + max);
1603*cf5a6c84SAndroid Build Coastguard Worker
1604*cf5a6c84SAndroid Build Coastguard Worker bc_num_split(a, max2, &l1, &h1);
1605*cf5a6c84SAndroid Build Coastguard Worker bc_num_split(b, max2, &l2, &h2);
1606*cf5a6c84SAndroid Build Coastguard Worker
1607*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_add(&h1, &l1, &m1, 0);
1608*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
1609*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_add(&h2, &l2, &m2, 0);
1610*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
1611*cf5a6c84SAndroid Build Coastguard Worker
1612*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_k(&h1, &h2, &z0);
1613*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
1614*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_k(&m1, &m2, &z1);
1615*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
1616*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_k(&l1, &l2, &z2);
1617*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
1618*cf5a6c84SAndroid Build Coastguard Worker
1619*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_sub(&z1, &z0, &temp, 0);
1620*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
1621*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_sub(&temp, &z2, &z1, 0);
1622*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
1623*cf5a6c84SAndroid Build Coastguard Worker
1624*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_shift(&z0, max2 * 2);
1625*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
1626*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_shift(&z1, max2);
1627*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
1628*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_add(&z0, &z1, &temp, 0);
1629*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
1630*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_add(&temp, &z2, c, 0);
1631*cf5a6c84SAndroid Build Coastguard Worker
1632*cf5a6c84SAndroid Build Coastguard Worker err:
1633*cf5a6c84SAndroid Build Coastguard Worker bc_num_free(&temp);
1634*cf5a6c84SAndroid Build Coastguard Worker bc_num_free(&z2);
1635*cf5a6c84SAndroid Build Coastguard Worker bc_num_free(&z1);
1636*cf5a6c84SAndroid Build Coastguard Worker bc_num_free(&z0);
1637*cf5a6c84SAndroid Build Coastguard Worker bc_num_free(&m2);
1638*cf5a6c84SAndroid Build Coastguard Worker bc_num_free(&m1);
1639*cf5a6c84SAndroid Build Coastguard Worker bc_num_free(&h2);
1640*cf5a6c84SAndroid Build Coastguard Worker bc_num_free(&l2);
1641*cf5a6c84SAndroid Build Coastguard Worker bc_num_free(&h1);
1642*cf5a6c84SAndroid Build Coastguard Worker bc_num_free(&l1);
1643*cf5a6c84SAndroid Build Coastguard Worker return s;
1644*cf5a6c84SAndroid Build Coastguard Worker }
1645*cf5a6c84SAndroid Build Coastguard Worker
bc_num_m(BcNum * a,BcNum * b,BcNum * c,size_t scale)1646*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_num_m(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
1647*cf5a6c84SAndroid Build Coastguard Worker
1648*cf5a6c84SAndroid Build Coastguard Worker BcStatus s;
1649*cf5a6c84SAndroid Build Coastguard Worker BcNum cpa, cpb;
1650*cf5a6c84SAndroid Build Coastguard Worker size_t maxrdx = maxof(a->rdx, b->rdx);
1651*cf5a6c84SAndroid Build Coastguard Worker
1652*cf5a6c84SAndroid Build Coastguard Worker scale = maxof(scale, a->rdx);
1653*cf5a6c84SAndroid Build Coastguard Worker scale = maxof(scale, b->rdx);
1654*cf5a6c84SAndroid Build Coastguard Worker scale = minof(a->rdx + b->rdx, scale);
1655*cf5a6c84SAndroid Build Coastguard Worker maxrdx = maxof(maxrdx, scale);
1656*cf5a6c84SAndroid Build Coastguard Worker
1657*cf5a6c84SAndroid Build Coastguard Worker bc_num_createCopy(&cpa, a);
1658*cf5a6c84SAndroid Build Coastguard Worker bc_num_createCopy(&cpb, b);
1659*cf5a6c84SAndroid Build Coastguard Worker
1660*cf5a6c84SAndroid Build Coastguard Worker cpa.neg = cpb.neg = 0;
1661*cf5a6c84SAndroid Build Coastguard Worker
1662*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_shift(&cpa, maxrdx);
1663*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
1664*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_shift(&cpb, maxrdx);
1665*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
1666*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_k(&cpa, &cpb, c);
1667*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
1668*cf5a6c84SAndroid Build Coastguard Worker
1669*cf5a6c84SAndroid Build Coastguard Worker maxrdx += scale;
1670*cf5a6c84SAndroid Build Coastguard Worker bc_num_expand(c, c->len + maxrdx);
1671*cf5a6c84SAndroid Build Coastguard Worker
1672*cf5a6c84SAndroid Build Coastguard Worker if (c->len < maxrdx) {
1673*cf5a6c84SAndroid Build Coastguard Worker memset(c->num + c->len, 0, c->cap - c->len);
1674*cf5a6c84SAndroid Build Coastguard Worker c->len += maxrdx;
1675*cf5a6c84SAndroid Build Coastguard Worker }
1676*cf5a6c84SAndroid Build Coastguard Worker
1677*cf5a6c84SAndroid Build Coastguard Worker c->rdx = maxrdx;
1678*cf5a6c84SAndroid Build Coastguard Worker bc_num_retireMul(c, scale, a->neg, b->neg);
1679*cf5a6c84SAndroid Build Coastguard Worker
1680*cf5a6c84SAndroid Build Coastguard Worker err:
1681*cf5a6c84SAndroid Build Coastguard Worker bc_num_free(&cpb);
1682*cf5a6c84SAndroid Build Coastguard Worker bc_num_free(&cpa);
1683*cf5a6c84SAndroid Build Coastguard Worker return s;
1684*cf5a6c84SAndroid Build Coastguard Worker }
1685*cf5a6c84SAndroid Build Coastguard Worker
bc_num_d(BcNum * a,BcNum * b,BcNum * c,size_t scale)1686*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_num_d(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
1687*cf5a6c84SAndroid Build Coastguard Worker
1688*cf5a6c84SAndroid Build Coastguard Worker BcStatus s = BC_STATUS_SUCCESS;
1689*cf5a6c84SAndroid Build Coastguard Worker signed char *n, *p, q;
1690*cf5a6c84SAndroid Build Coastguard Worker size_t len, end, i;
1691*cf5a6c84SAndroid Build Coastguard Worker BcNum cp;
1692*cf5a6c84SAndroid Build Coastguard Worker int zero = 1;
1693*cf5a6c84SAndroid Build Coastguard Worker
1694*cf5a6c84SAndroid Build Coastguard Worker if (!b->len) return bc_vm_err(BC_ERROR_MATH_DIVIDE_BY_ZERO);
1695*cf5a6c84SAndroid Build Coastguard Worker if (!a->len) {
1696*cf5a6c84SAndroid Build Coastguard Worker bc_num_setToZero(c, scale);
1697*cf5a6c84SAndroid Build Coastguard Worker return BC_STATUS_SUCCESS;
1698*cf5a6c84SAndroid Build Coastguard Worker }
1699*cf5a6c84SAndroid Build Coastguard Worker if (BC_NUM_ONE(b)) {
1700*cf5a6c84SAndroid Build Coastguard Worker bc_num_copy(c, a);
1701*cf5a6c84SAndroid Build Coastguard Worker bc_num_retireMul(c, scale, a->neg, b->neg);
1702*cf5a6c84SAndroid Build Coastguard Worker return BC_STATUS_SUCCESS;
1703*cf5a6c84SAndroid Build Coastguard Worker }
1704*cf5a6c84SAndroid Build Coastguard Worker
1705*cf5a6c84SAndroid Build Coastguard Worker bc_num_init(&cp, bc_num_mulReq(a, b, scale));
1706*cf5a6c84SAndroid Build Coastguard Worker bc_num_copy(&cp, a);
1707*cf5a6c84SAndroid Build Coastguard Worker len = b->len;
1708*cf5a6c84SAndroid Build Coastguard Worker
1709*cf5a6c84SAndroid Build Coastguard Worker if (len > cp.len) {
1710*cf5a6c84SAndroid Build Coastguard Worker bc_num_expand(&cp, len + 2);
1711*cf5a6c84SAndroid Build Coastguard Worker bc_num_extend(&cp, len - cp.len);
1712*cf5a6c84SAndroid Build Coastguard Worker }
1713*cf5a6c84SAndroid Build Coastguard Worker
1714*cf5a6c84SAndroid Build Coastguard Worker if (b->rdx > cp.rdx) bc_num_extend(&cp, b->rdx - cp.rdx);
1715*cf5a6c84SAndroid Build Coastguard Worker cp.rdx -= b->rdx;
1716*cf5a6c84SAndroid Build Coastguard Worker if (scale > cp.rdx) bc_num_extend(&cp, scale - cp.rdx);
1717*cf5a6c84SAndroid Build Coastguard Worker
1718*cf5a6c84SAndroid Build Coastguard Worker if (b->rdx == b->len) {
1719*cf5a6c84SAndroid Build Coastguard Worker for (i = 0; zero && i < len; ++i) zero = !b->num[len - i - 1];
1720*cf5a6c84SAndroid Build Coastguard Worker len -= i - 1;
1721*cf5a6c84SAndroid Build Coastguard Worker }
1722*cf5a6c84SAndroid Build Coastguard Worker
1723*cf5a6c84SAndroid Build Coastguard Worker if (cp.cap == cp.len) bc_num_expand(&cp, cp.len + 1);
1724*cf5a6c84SAndroid Build Coastguard Worker
1725*cf5a6c84SAndroid Build Coastguard Worker // We want an extra zero in front to make things simpler.
1726*cf5a6c84SAndroid Build Coastguard Worker cp.num[cp.len++] = 0;
1727*cf5a6c84SAndroid Build Coastguard Worker end = cp.len - len;
1728*cf5a6c84SAndroid Build Coastguard Worker
1729*cf5a6c84SAndroid Build Coastguard Worker bc_num_expand(c, cp.len);
1730*cf5a6c84SAndroid Build Coastguard Worker
1731*cf5a6c84SAndroid Build Coastguard Worker memset(c->num + end, 0, c->cap - end);
1732*cf5a6c84SAndroid Build Coastguard Worker c->rdx = cp.rdx;
1733*cf5a6c84SAndroid Build Coastguard Worker c->len = cp.len;
1734*cf5a6c84SAndroid Build Coastguard Worker p = b->num;
1735*cf5a6c84SAndroid Build Coastguard Worker
1736*cf5a6c84SAndroid Build Coastguard Worker for (i = end - 1; !TT.sig && !s && i < end; --i) {
1737*cf5a6c84SAndroid Build Coastguard Worker n = cp.num + i;
1738*cf5a6c84SAndroid Build Coastguard Worker for (q = 0; !s && (n[len] || bc_num_compare(n, p, len) >= 0); ++q)
1739*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_subArrays(n, p, len);
1740*cf5a6c84SAndroid Build Coastguard Worker c->num[i] = q;
1741*cf5a6c84SAndroid Build Coastguard Worker }
1742*cf5a6c84SAndroid Build Coastguard Worker
1743*cf5a6c84SAndroid Build Coastguard Worker if (!s) bc_num_retireMul(c, scale, a->neg, b->neg);
1744*cf5a6c84SAndroid Build Coastguard Worker bc_num_free(&cp);
1745*cf5a6c84SAndroid Build Coastguard Worker
1746*cf5a6c84SAndroid Build Coastguard Worker return s;
1747*cf5a6c84SAndroid Build Coastguard Worker }
1748*cf5a6c84SAndroid Build Coastguard Worker
bc_num_r(BcNum * a,BcNum * b,BcNum * c,BcNum * d,size_t scale,size_t ts)1749*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_num_r(BcNum *a, BcNum *b, BcNum *c, BcNum *d, size_t scale,
1750*cf5a6c84SAndroid Build Coastguard Worker size_t ts)
1751*cf5a6c84SAndroid Build Coastguard Worker {
1752*cf5a6c84SAndroid Build Coastguard Worker BcStatus s;
1753*cf5a6c84SAndroid Build Coastguard Worker BcNum temp;
1754*cf5a6c84SAndroid Build Coastguard Worker int neg;
1755*cf5a6c84SAndroid Build Coastguard Worker
1756*cf5a6c84SAndroid Build Coastguard Worker if (!b->len) return bc_vm_err(BC_ERROR_MATH_DIVIDE_BY_ZERO);
1757*cf5a6c84SAndroid Build Coastguard Worker if (!a->len) {
1758*cf5a6c84SAndroid Build Coastguard Worker bc_num_setToZero(c, ts);
1759*cf5a6c84SAndroid Build Coastguard Worker bc_num_setToZero(d, ts);
1760*cf5a6c84SAndroid Build Coastguard Worker return BC_STATUS_SUCCESS;
1761*cf5a6c84SAndroid Build Coastguard Worker }
1762*cf5a6c84SAndroid Build Coastguard Worker
1763*cf5a6c84SAndroid Build Coastguard Worker bc_num_init(&temp, d->cap);
1764*cf5a6c84SAndroid Build Coastguard Worker bc_num_d(a, b, c, scale);
1765*cf5a6c84SAndroid Build Coastguard Worker
1766*cf5a6c84SAndroid Build Coastguard Worker if (scale) scale = ts;
1767*cf5a6c84SAndroid Build Coastguard Worker
1768*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_m(c, b, &temp, scale);
1769*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
1770*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_sub(a, &temp, d, scale);
1771*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
1772*cf5a6c84SAndroid Build Coastguard Worker
1773*cf5a6c84SAndroid Build Coastguard Worker if (ts > d->rdx && d->len) bc_num_extend(d, ts - d->rdx);
1774*cf5a6c84SAndroid Build Coastguard Worker
1775*cf5a6c84SAndroid Build Coastguard Worker neg = d->neg;
1776*cf5a6c84SAndroid Build Coastguard Worker bc_num_retireMul(d, ts, a->neg, b->neg);
1777*cf5a6c84SAndroid Build Coastguard Worker d->neg = neg;
1778*cf5a6c84SAndroid Build Coastguard Worker
1779*cf5a6c84SAndroid Build Coastguard Worker err:
1780*cf5a6c84SAndroid Build Coastguard Worker bc_num_free(&temp);
1781*cf5a6c84SAndroid Build Coastguard Worker return s;
1782*cf5a6c84SAndroid Build Coastguard Worker }
1783*cf5a6c84SAndroid Build Coastguard Worker
bc_num_rem(BcNum * a,BcNum * b,BcNum * c,size_t scale)1784*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_num_rem(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
1785*cf5a6c84SAndroid Build Coastguard Worker
1786*cf5a6c84SAndroid Build Coastguard Worker BcStatus s;
1787*cf5a6c84SAndroid Build Coastguard Worker BcNum c1;
1788*cf5a6c84SAndroid Build Coastguard Worker size_t ts = maxof(scale + b->rdx, a->rdx), len = bc_num_mulReq(a, b, ts);
1789*cf5a6c84SAndroid Build Coastguard Worker
1790*cf5a6c84SAndroid Build Coastguard Worker bc_num_init(&c1, len);
1791*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_r(a, b, &c1, c, scale, ts);
1792*cf5a6c84SAndroid Build Coastguard Worker bc_num_free(&c1);
1793*cf5a6c84SAndroid Build Coastguard Worker
1794*cf5a6c84SAndroid Build Coastguard Worker return s;
1795*cf5a6c84SAndroid Build Coastguard Worker }
1796*cf5a6c84SAndroid Build Coastguard Worker
bc_num_p(BcNum * a,BcNum * b,BcNum * c,size_t scale)1797*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_num_p(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
1798*cf5a6c84SAndroid Build Coastguard Worker
1799*cf5a6c84SAndroid Build Coastguard Worker BcStatus s = BC_STATUS_SUCCESS;
1800*cf5a6c84SAndroid Build Coastguard Worker BcNum copy;
1801*cf5a6c84SAndroid Build Coastguard Worker unsigned long pow = 0;
1802*cf5a6c84SAndroid Build Coastguard Worker size_t i, powrdx, resrdx;
1803*cf5a6c84SAndroid Build Coastguard Worker int neg, zero;
1804*cf5a6c84SAndroid Build Coastguard Worker
1805*cf5a6c84SAndroid Build Coastguard Worker if (b->rdx) return bc_vm_err(BC_ERROR_MATH_NON_INTEGER);
1806*cf5a6c84SAndroid Build Coastguard Worker
1807*cf5a6c84SAndroid Build Coastguard Worker if (!b->len) {
1808*cf5a6c84SAndroid Build Coastguard Worker bc_num_one(c);
1809*cf5a6c84SAndroid Build Coastguard Worker return BC_STATUS_SUCCESS;
1810*cf5a6c84SAndroid Build Coastguard Worker }
1811*cf5a6c84SAndroid Build Coastguard Worker if (!a->len) {
1812*cf5a6c84SAndroid Build Coastguard Worker if (b->neg) return bc_vm_err(BC_ERROR_MATH_DIVIDE_BY_ZERO);
1813*cf5a6c84SAndroid Build Coastguard Worker bc_num_setToZero(c, scale);
1814*cf5a6c84SAndroid Build Coastguard Worker return BC_STATUS_SUCCESS;
1815*cf5a6c84SAndroid Build Coastguard Worker }
1816*cf5a6c84SAndroid Build Coastguard Worker if (BC_NUM_ONE(b)) {
1817*cf5a6c84SAndroid Build Coastguard Worker if (!b->neg) bc_num_copy(c, a);
1818*cf5a6c84SAndroid Build Coastguard Worker else s = bc_num_inv(a, c, scale);
1819*cf5a6c84SAndroid Build Coastguard Worker return s;
1820*cf5a6c84SAndroid Build Coastguard Worker }
1821*cf5a6c84SAndroid Build Coastguard Worker
1822*cf5a6c84SAndroid Build Coastguard Worker neg = b->neg;
1823*cf5a6c84SAndroid Build Coastguard Worker b->neg = 0;
1824*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_ulong(b, &pow);
1825*cf5a6c84SAndroid Build Coastguard Worker b->neg = neg;
1826*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
1827*cf5a6c84SAndroid Build Coastguard Worker
1828*cf5a6c84SAndroid Build Coastguard Worker bc_num_createCopy(©, a);
1829*cf5a6c84SAndroid Build Coastguard Worker
1830*cf5a6c84SAndroid Build Coastguard Worker if (!neg) scale = minof(a->rdx * pow, maxof(scale, a->rdx));
1831*cf5a6c84SAndroid Build Coastguard Worker
1832*cf5a6c84SAndroid Build Coastguard Worker for (powrdx = a->rdx; !TT.sig && !(pow & 1); pow >>= 1) {
1833*cf5a6c84SAndroid Build Coastguard Worker powrdx <<= 1;
1834*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_mul(©, ©, ©, powrdx);
1835*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
1836*cf5a6c84SAndroid Build Coastguard Worker }
1837*cf5a6c84SAndroid Build Coastguard Worker
1838*cf5a6c84SAndroid Build Coastguard Worker if (TT.sig) {
1839*cf5a6c84SAndroid Build Coastguard Worker s = BC_STATUS_SIGNAL;
1840*cf5a6c84SAndroid Build Coastguard Worker goto err;
1841*cf5a6c84SAndroid Build Coastguard Worker }
1842*cf5a6c84SAndroid Build Coastguard Worker
1843*cf5a6c84SAndroid Build Coastguard Worker bc_num_copy(c, ©);
1844*cf5a6c84SAndroid Build Coastguard Worker resrdx = powrdx;
1845*cf5a6c84SAndroid Build Coastguard Worker
1846*cf5a6c84SAndroid Build Coastguard Worker while (!TT.sig && (pow >>= 1)) {
1847*cf5a6c84SAndroid Build Coastguard Worker
1848*cf5a6c84SAndroid Build Coastguard Worker powrdx <<= 1;
1849*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_mul(©, ©, ©, powrdx);
1850*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
1851*cf5a6c84SAndroid Build Coastguard Worker
1852*cf5a6c84SAndroid Build Coastguard Worker if (pow & 1) {
1853*cf5a6c84SAndroid Build Coastguard Worker resrdx += powrdx;
1854*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_mul(c, ©, c, resrdx);
1855*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
1856*cf5a6c84SAndroid Build Coastguard Worker }
1857*cf5a6c84SAndroid Build Coastguard Worker }
1858*cf5a6c84SAndroid Build Coastguard Worker
1859*cf5a6c84SAndroid Build Coastguard Worker if (neg) {
1860*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_inv(c, c, scale);
1861*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
1862*cf5a6c84SAndroid Build Coastguard Worker }
1863*cf5a6c84SAndroid Build Coastguard Worker
1864*cf5a6c84SAndroid Build Coastguard Worker if (TT.sig) {
1865*cf5a6c84SAndroid Build Coastguard Worker s = BC_STATUS_SIGNAL;
1866*cf5a6c84SAndroid Build Coastguard Worker goto err;
1867*cf5a6c84SAndroid Build Coastguard Worker }
1868*cf5a6c84SAndroid Build Coastguard Worker
1869*cf5a6c84SAndroid Build Coastguard Worker if (c->rdx > scale) bc_num_truncate(c, c->rdx - scale);
1870*cf5a6c84SAndroid Build Coastguard Worker
1871*cf5a6c84SAndroid Build Coastguard Worker // We can't use bc_num_clean() here.
1872*cf5a6c84SAndroid Build Coastguard Worker for (zero = 1, i = 0; zero && i < c->len; ++i) zero = !c->num[i];
1873*cf5a6c84SAndroid Build Coastguard Worker if (zero) bc_num_setToZero(c, scale);
1874*cf5a6c84SAndroid Build Coastguard Worker
1875*cf5a6c84SAndroid Build Coastguard Worker err:
1876*cf5a6c84SAndroid Build Coastguard Worker bc_num_free(©);
1877*cf5a6c84SAndroid Build Coastguard Worker return s;
1878*cf5a6c84SAndroid Build Coastguard Worker }
1879*cf5a6c84SAndroid Build Coastguard Worker
bc_num_binary(BcNum * a,BcNum * b,BcNum * c,size_t scale,BcNumBinaryOp op,size_t req)1880*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale,
1881*cf5a6c84SAndroid Build Coastguard Worker BcNumBinaryOp op, size_t req)
1882*cf5a6c84SAndroid Build Coastguard Worker {
1883*cf5a6c84SAndroid Build Coastguard Worker BcStatus s;
1884*cf5a6c84SAndroid Build Coastguard Worker BcNum num2, *ptr_a, *ptr_b;
1885*cf5a6c84SAndroid Build Coastguard Worker int init = 0;
1886*cf5a6c84SAndroid Build Coastguard Worker
1887*cf5a6c84SAndroid Build Coastguard Worker if (c == a) {
1888*cf5a6c84SAndroid Build Coastguard Worker ptr_a = &num2;
1889*cf5a6c84SAndroid Build Coastguard Worker memcpy(ptr_a, c, sizeof(BcNum));
1890*cf5a6c84SAndroid Build Coastguard Worker init = 1;
1891*cf5a6c84SAndroid Build Coastguard Worker }
1892*cf5a6c84SAndroid Build Coastguard Worker else ptr_a = a;
1893*cf5a6c84SAndroid Build Coastguard Worker
1894*cf5a6c84SAndroid Build Coastguard Worker if (c == b) {
1895*cf5a6c84SAndroid Build Coastguard Worker ptr_b = &num2;
1896*cf5a6c84SAndroid Build Coastguard Worker if (c != a) {
1897*cf5a6c84SAndroid Build Coastguard Worker memcpy(ptr_b, c, sizeof(BcNum));
1898*cf5a6c84SAndroid Build Coastguard Worker init = 1;
1899*cf5a6c84SAndroid Build Coastguard Worker }
1900*cf5a6c84SAndroid Build Coastguard Worker }
1901*cf5a6c84SAndroid Build Coastguard Worker else ptr_b = b;
1902*cf5a6c84SAndroid Build Coastguard Worker
1903*cf5a6c84SAndroid Build Coastguard Worker if (init) bc_num_init(c, req);
1904*cf5a6c84SAndroid Build Coastguard Worker else bc_num_expand(c, req);
1905*cf5a6c84SAndroid Build Coastguard Worker
1906*cf5a6c84SAndroid Build Coastguard Worker s = op(ptr_a, ptr_b, c, scale);
1907*cf5a6c84SAndroid Build Coastguard Worker
1908*cf5a6c84SAndroid Build Coastguard Worker if (init) bc_num_free(&num2);
1909*cf5a6c84SAndroid Build Coastguard Worker
1910*cf5a6c84SAndroid Build Coastguard Worker return s;
1911*cf5a6c84SAndroid Build Coastguard Worker }
1912*cf5a6c84SAndroid Build Coastguard Worker
bc_num_parseChar(char c,size_t base_t)1913*cf5a6c84SAndroid Build Coastguard Worker static unsigned long bc_num_parseChar(char c, size_t base_t) {
1914*cf5a6c84SAndroid Build Coastguard Worker
1915*cf5a6c84SAndroid Build Coastguard Worker if (isupper(c)) {
1916*cf5a6c84SAndroid Build Coastguard Worker c += 10 - 'A';
1917*cf5a6c84SAndroid Build Coastguard Worker if (c >= base_t) c = base_t - 1;
1918*cf5a6c84SAndroid Build Coastguard Worker } else c -= '0';
1919*cf5a6c84SAndroid Build Coastguard Worker
1920*cf5a6c84SAndroid Build Coastguard Worker return c;
1921*cf5a6c84SAndroid Build Coastguard Worker }
1922*cf5a6c84SAndroid Build Coastguard Worker
bc_num_parseBase(BcNum * n,char * val,BcNum * base,size_t base_t)1923*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_num_parseBase(BcNum *n, char *val,
1924*cf5a6c84SAndroid Build Coastguard Worker BcNum *base, size_t base_t)
1925*cf5a6c84SAndroid Build Coastguard Worker {
1926*cf5a6c84SAndroid Build Coastguard Worker BcStatus s = BC_STATUS_SUCCESS;
1927*cf5a6c84SAndroid Build Coastguard Worker BcNum temp, mult, result;
1928*cf5a6c84SAndroid Build Coastguard Worker signed char c = 0;
1929*cf5a6c84SAndroid Build Coastguard Worker int zero = 1;
1930*cf5a6c84SAndroid Build Coastguard Worker unsigned long v;
1931*cf5a6c84SAndroid Build Coastguard Worker size_t i, digits, len = strlen(val);
1932*cf5a6c84SAndroid Build Coastguard Worker
1933*cf5a6c84SAndroid Build Coastguard Worker for (i = 0; zero && i < len; ++i) zero = (val[i] == '.' || val[i] == '0');
1934*cf5a6c84SAndroid Build Coastguard Worker if (zero) return BC_STATUS_SUCCESS;
1935*cf5a6c84SAndroid Build Coastguard Worker
1936*cf5a6c84SAndroid Build Coastguard Worker bc_num_init(&temp, BC_NUM_LONG_LOG10);
1937*cf5a6c84SAndroid Build Coastguard Worker bc_num_init(&mult, BC_NUM_LONG_LOG10);
1938*cf5a6c84SAndroid Build Coastguard Worker
1939*cf5a6c84SAndroid Build Coastguard Worker for (i = 0; i < len && (c = val[i]) && c != '.'; ++i) {
1940*cf5a6c84SAndroid Build Coastguard Worker
1941*cf5a6c84SAndroid Build Coastguard Worker v = bc_num_parseChar(c, base_t);
1942*cf5a6c84SAndroid Build Coastguard Worker
1943*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_mul(n, base, &mult, 0);
1944*cf5a6c84SAndroid Build Coastguard Worker if (s) goto int_err;
1945*cf5a6c84SAndroid Build Coastguard Worker bc_num_ulong2num(&temp, v);
1946*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_add(&mult, &temp, n, 0);
1947*cf5a6c84SAndroid Build Coastguard Worker if (s) goto int_err;
1948*cf5a6c84SAndroid Build Coastguard Worker }
1949*cf5a6c84SAndroid Build Coastguard Worker
1950*cf5a6c84SAndroid Build Coastguard Worker if (i == len && !(c = val[i])) goto int_err;
1951*cf5a6c84SAndroid Build Coastguard Worker
1952*cf5a6c84SAndroid Build Coastguard Worker bc_num_init(&result, base->len);
1953*cf5a6c84SAndroid Build Coastguard Worker bc_num_one(&mult);
1954*cf5a6c84SAndroid Build Coastguard Worker
1955*cf5a6c84SAndroid Build Coastguard Worker for (i += 1, digits = 0; i < len && (c = val[i]); ++i, ++digits) {
1956*cf5a6c84SAndroid Build Coastguard Worker
1957*cf5a6c84SAndroid Build Coastguard Worker v = bc_num_parseChar(c, base_t);
1958*cf5a6c84SAndroid Build Coastguard Worker
1959*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_mul(&result, base, &result, 0);
1960*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
1961*cf5a6c84SAndroid Build Coastguard Worker bc_num_ulong2num(&temp, v);
1962*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_add(&result, &temp, &result, 0);
1963*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
1964*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_mul(&mult, base, &mult, 0);
1965*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
1966*cf5a6c84SAndroid Build Coastguard Worker }
1967*cf5a6c84SAndroid Build Coastguard Worker
1968*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_div(&result, &mult, &result, digits);
1969*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
1970*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_add(n, &result, n, digits);
1971*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
1972*cf5a6c84SAndroid Build Coastguard Worker
1973*cf5a6c84SAndroid Build Coastguard Worker if (n->len) {
1974*cf5a6c84SAndroid Build Coastguard Worker if (n->rdx < digits) bc_num_extend(n, digits - n->rdx);
1975*cf5a6c84SAndroid Build Coastguard Worker }
1976*cf5a6c84SAndroid Build Coastguard Worker else bc_num_setToZero(n, 0);
1977*cf5a6c84SAndroid Build Coastguard Worker
1978*cf5a6c84SAndroid Build Coastguard Worker
1979*cf5a6c84SAndroid Build Coastguard Worker err:
1980*cf5a6c84SAndroid Build Coastguard Worker bc_num_free(&result);
1981*cf5a6c84SAndroid Build Coastguard Worker int_err:
1982*cf5a6c84SAndroid Build Coastguard Worker bc_num_free(&mult);
1983*cf5a6c84SAndroid Build Coastguard Worker bc_num_free(&temp);
1984*cf5a6c84SAndroid Build Coastguard Worker return s;
1985*cf5a6c84SAndroid Build Coastguard Worker }
1986*cf5a6c84SAndroid Build Coastguard Worker
bc_num_printNewline()1987*cf5a6c84SAndroid Build Coastguard Worker static void bc_num_printNewline() {
1988*cf5a6c84SAndroid Build Coastguard Worker if (TT.nchars >= TT.line_len - 1) {
1989*cf5a6c84SAndroid Build Coastguard Worker putchar('\\');
1990*cf5a6c84SAndroid Build Coastguard Worker putchar('\n');
1991*cf5a6c84SAndroid Build Coastguard Worker TT.nchars = 0;
1992*cf5a6c84SAndroid Build Coastguard Worker }
1993*cf5a6c84SAndroid Build Coastguard Worker }
1994*cf5a6c84SAndroid Build Coastguard Worker
bc_num_printDigits(size_t n,size_t len,int rdx)1995*cf5a6c84SAndroid Build Coastguard Worker static void bc_num_printDigits(size_t n, size_t len, int rdx) {
1996*cf5a6c84SAndroid Build Coastguard Worker
1997*cf5a6c84SAndroid Build Coastguard Worker size_t exp, pow;
1998*cf5a6c84SAndroid Build Coastguard Worker
1999*cf5a6c84SAndroid Build Coastguard Worker bc_num_printNewline();
2000*cf5a6c84SAndroid Build Coastguard Worker putchar(rdx ? '.' : ' ');
2001*cf5a6c84SAndroid Build Coastguard Worker ++TT.nchars;
2002*cf5a6c84SAndroid Build Coastguard Worker
2003*cf5a6c84SAndroid Build Coastguard Worker bc_num_printNewline();
2004*cf5a6c84SAndroid Build Coastguard Worker for (exp = 0, pow = 1; exp < len - 1; ++exp, pow *= 10);
2005*cf5a6c84SAndroid Build Coastguard Worker
2006*cf5a6c84SAndroid Build Coastguard Worker for (exp = 0; exp < len; pow /= 10, ++TT.nchars, ++exp) {
2007*cf5a6c84SAndroid Build Coastguard Worker size_t dig;
2008*cf5a6c84SAndroid Build Coastguard Worker bc_num_printNewline();
2009*cf5a6c84SAndroid Build Coastguard Worker dig = n / pow;
2010*cf5a6c84SAndroid Build Coastguard Worker n -= dig * pow;
2011*cf5a6c84SAndroid Build Coastguard Worker putchar(((char) dig) + '0');
2012*cf5a6c84SAndroid Build Coastguard Worker }
2013*cf5a6c84SAndroid Build Coastguard Worker }
2014*cf5a6c84SAndroid Build Coastguard Worker
bc_num_printHex(size_t n,size_t len,int rdx)2015*cf5a6c84SAndroid Build Coastguard Worker static void bc_num_printHex(size_t n, size_t len, int rdx) {
2016*cf5a6c84SAndroid Build Coastguard Worker
2017*cf5a6c84SAndroid Build Coastguard Worker if (rdx) {
2018*cf5a6c84SAndroid Build Coastguard Worker bc_num_printNewline();
2019*cf5a6c84SAndroid Build Coastguard Worker putchar('.');
2020*cf5a6c84SAndroid Build Coastguard Worker TT.nchars += 1;
2021*cf5a6c84SAndroid Build Coastguard Worker }
2022*cf5a6c84SAndroid Build Coastguard Worker
2023*cf5a6c84SAndroid Build Coastguard Worker bc_num_printNewline();
2024*cf5a6c84SAndroid Build Coastguard Worker putchar(bc_num_hex_digits[n]);
2025*cf5a6c84SAndroid Build Coastguard Worker TT.nchars += len;
2026*cf5a6c84SAndroid Build Coastguard Worker }
2027*cf5a6c84SAndroid Build Coastguard Worker
bc_num_printDecimal(BcNum * n)2028*cf5a6c84SAndroid Build Coastguard Worker static void bc_num_printDecimal(BcNum *n) {
2029*cf5a6c84SAndroid Build Coastguard Worker
2030*cf5a6c84SAndroid Build Coastguard Worker size_t i, rdx = n->rdx - 1;
2031*cf5a6c84SAndroid Build Coastguard Worker
2032*cf5a6c84SAndroid Build Coastguard Worker if (n->neg) putchar('-');
2033*cf5a6c84SAndroid Build Coastguard Worker TT.nchars += n->neg;
2034*cf5a6c84SAndroid Build Coastguard Worker
2035*cf5a6c84SAndroid Build Coastguard Worker for (i = n->len - 1; i < n->len; --i)
2036*cf5a6c84SAndroid Build Coastguard Worker bc_num_printHex((size_t) n->num[i], 1, i == rdx);
2037*cf5a6c84SAndroid Build Coastguard Worker }
2038*cf5a6c84SAndroid Build Coastguard Worker
bc_num_printNum(BcNum * n,BcNum * base,size_t len,BcNumDigitOp print)2039*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_num_printNum(BcNum *n, BcNum *base,
2040*cf5a6c84SAndroid Build Coastguard Worker size_t len, BcNumDigitOp print)
2041*cf5a6c84SAndroid Build Coastguard Worker {
2042*cf5a6c84SAndroid Build Coastguard Worker BcStatus s;
2043*cf5a6c84SAndroid Build Coastguard Worker BcVec stack;
2044*cf5a6c84SAndroid Build Coastguard Worker BcNum intp, fracp, digit, frac_len;
2045*cf5a6c84SAndroid Build Coastguard Worker unsigned long dig, *ptr;
2046*cf5a6c84SAndroid Build Coastguard Worker size_t i;
2047*cf5a6c84SAndroid Build Coastguard Worker int radix;
2048*cf5a6c84SAndroid Build Coastguard Worker
2049*cf5a6c84SAndroid Build Coastguard Worker if (!n->len) {
2050*cf5a6c84SAndroid Build Coastguard Worker print(0, len, 0);
2051*cf5a6c84SAndroid Build Coastguard Worker return BC_STATUS_SUCCESS;
2052*cf5a6c84SAndroid Build Coastguard Worker }
2053*cf5a6c84SAndroid Build Coastguard Worker
2054*cf5a6c84SAndroid Build Coastguard Worker bc_vec_init(&stack, sizeof(unsigned long), NULL);
2055*cf5a6c84SAndroid Build Coastguard Worker bc_num_init(&fracp, n->rdx);
2056*cf5a6c84SAndroid Build Coastguard Worker bc_num_init(&digit, len);
2057*cf5a6c84SAndroid Build Coastguard Worker bc_num_init(&frac_len, BC_NUM_INT(n));
2058*cf5a6c84SAndroid Build Coastguard Worker bc_num_one(&frac_len);
2059*cf5a6c84SAndroid Build Coastguard Worker bc_num_createCopy(&intp, n);
2060*cf5a6c84SAndroid Build Coastguard Worker
2061*cf5a6c84SAndroid Build Coastguard Worker bc_num_truncate(&intp, intp.rdx);
2062*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_sub(n, &intp, &fracp, 0);
2063*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
2064*cf5a6c84SAndroid Build Coastguard Worker
2065*cf5a6c84SAndroid Build Coastguard Worker while (intp.len) {
2066*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_divmod(&intp, base, &intp, &digit, 0);
2067*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
2068*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_ulong(&digit, &dig);
2069*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
2070*cf5a6c84SAndroid Build Coastguard Worker bc_vec_push(&stack, &dig);
2071*cf5a6c84SAndroid Build Coastguard Worker }
2072*cf5a6c84SAndroid Build Coastguard Worker
2073*cf5a6c84SAndroid Build Coastguard Worker for (i = 0; i < stack.len; ++i) {
2074*cf5a6c84SAndroid Build Coastguard Worker ptr = bc_vec_item_rev(&stack, i);
2075*cf5a6c84SAndroid Build Coastguard Worker print(*ptr, len, 0);
2076*cf5a6c84SAndroid Build Coastguard Worker }
2077*cf5a6c84SAndroid Build Coastguard Worker
2078*cf5a6c84SAndroid Build Coastguard Worker if (!n->rdx) goto err;
2079*cf5a6c84SAndroid Build Coastguard Worker
2080*cf5a6c84SAndroid Build Coastguard Worker for (radix = 1; frac_len.len <= n->rdx; radix = 0) {
2081*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_mul(&fracp, base, &fracp, n->rdx);
2082*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
2083*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_ulong(&fracp, &dig);
2084*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
2085*cf5a6c84SAndroid Build Coastguard Worker bc_num_ulong2num(&intp, dig);
2086*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_sub(&fracp, &intp, &fracp, 0);
2087*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
2088*cf5a6c84SAndroid Build Coastguard Worker print(dig, len, radix);
2089*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_mul(&frac_len, base, &frac_len, 0);
2090*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
2091*cf5a6c84SAndroid Build Coastguard Worker }
2092*cf5a6c84SAndroid Build Coastguard Worker
2093*cf5a6c84SAndroid Build Coastguard Worker err:
2094*cf5a6c84SAndroid Build Coastguard Worker bc_num_free(&frac_len);
2095*cf5a6c84SAndroid Build Coastguard Worker bc_num_free(&digit);
2096*cf5a6c84SAndroid Build Coastguard Worker bc_num_free(&fracp);
2097*cf5a6c84SAndroid Build Coastguard Worker bc_num_free(&intp);
2098*cf5a6c84SAndroid Build Coastguard Worker bc_vec_free(&stack);
2099*cf5a6c84SAndroid Build Coastguard Worker return s;
2100*cf5a6c84SAndroid Build Coastguard Worker }
2101*cf5a6c84SAndroid Build Coastguard Worker
bc_num_printBase(BcNum * n,BcNum * base,size_t base_t)2102*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_num_printBase(BcNum *n, BcNum *base, size_t base_t) {
2103*cf5a6c84SAndroid Build Coastguard Worker
2104*cf5a6c84SAndroid Build Coastguard Worker BcStatus s;
2105*cf5a6c84SAndroid Build Coastguard Worker size_t width;
2106*cf5a6c84SAndroid Build Coastguard Worker BcNumDigitOp print;
2107*cf5a6c84SAndroid Build Coastguard Worker int neg = n->neg;
2108*cf5a6c84SAndroid Build Coastguard Worker
2109*cf5a6c84SAndroid Build Coastguard Worker if (neg) putchar('-');
2110*cf5a6c84SAndroid Build Coastguard Worker TT.nchars += neg;
2111*cf5a6c84SAndroid Build Coastguard Worker
2112*cf5a6c84SAndroid Build Coastguard Worker n->neg = 0;
2113*cf5a6c84SAndroid Build Coastguard Worker
2114*cf5a6c84SAndroid Build Coastguard Worker if (base_t <= 16) {
2115*cf5a6c84SAndroid Build Coastguard Worker width = 1;
2116*cf5a6c84SAndroid Build Coastguard Worker print = bc_num_printHex;
2117*cf5a6c84SAndroid Build Coastguard Worker } else {
2118*cf5a6c84SAndroid Build Coastguard Worker width = bc_num_log10(base_t - 1) - 1;
2119*cf5a6c84SAndroid Build Coastguard Worker print = bc_num_printDigits;
2120*cf5a6c84SAndroid Build Coastguard Worker }
2121*cf5a6c84SAndroid Build Coastguard Worker
2122*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_printNum(n, base, width, print);
2123*cf5a6c84SAndroid Build Coastguard Worker n->neg = neg;
2124*cf5a6c84SAndroid Build Coastguard Worker
2125*cf5a6c84SAndroid Build Coastguard Worker return s;
2126*cf5a6c84SAndroid Build Coastguard Worker }
2127*cf5a6c84SAndroid Build Coastguard Worker
bc_num_setup(BcNum * n,signed char * num,size_t cap)2128*cf5a6c84SAndroid Build Coastguard Worker void bc_num_setup(BcNum *n, signed char *num, size_t cap) {
2129*cf5a6c84SAndroid Build Coastguard Worker n->num = num;
2130*cf5a6c84SAndroid Build Coastguard Worker n->cap = cap;
2131*cf5a6c84SAndroid Build Coastguard Worker n->rdx = n->len = 0;
2132*cf5a6c84SAndroid Build Coastguard Worker n->neg = 0;
2133*cf5a6c84SAndroid Build Coastguard Worker }
2134*cf5a6c84SAndroid Build Coastguard Worker
bc_num_init(BcNum * n,size_t req)2135*cf5a6c84SAndroid Build Coastguard Worker void bc_num_init(BcNum *n, size_t req) {
2136*cf5a6c84SAndroid Build Coastguard Worker req = req >= BC_NUM_DEF_SIZE ? req : BC_NUM_DEF_SIZE;
2137*cf5a6c84SAndroid Build Coastguard Worker bc_num_setup(n, xmalloc(req), req);
2138*cf5a6c84SAndroid Build Coastguard Worker }
2139*cf5a6c84SAndroid Build Coastguard Worker
bc_num_expand(BcNum * n,size_t req)2140*cf5a6c84SAndroid Build Coastguard Worker void bc_num_expand(BcNum *n, size_t req) {
2141*cf5a6c84SAndroid Build Coastguard Worker req = req >= BC_NUM_DEF_SIZE ? req : BC_NUM_DEF_SIZE;
2142*cf5a6c84SAndroid Build Coastguard Worker if (req > n->cap) {
2143*cf5a6c84SAndroid Build Coastguard Worker n->num = xrealloc(n->num, req);
2144*cf5a6c84SAndroid Build Coastguard Worker n->cap = req;
2145*cf5a6c84SAndroid Build Coastguard Worker }
2146*cf5a6c84SAndroid Build Coastguard Worker }
2147*cf5a6c84SAndroid Build Coastguard Worker
bc_num_free(void * num)2148*cf5a6c84SAndroid Build Coastguard Worker void bc_num_free(void *num) {
2149*cf5a6c84SAndroid Build Coastguard Worker free(((BcNum*) num)->num);
2150*cf5a6c84SAndroid Build Coastguard Worker }
2151*cf5a6c84SAndroid Build Coastguard Worker
bc_num_copy(BcNum * d,BcNum * s)2152*cf5a6c84SAndroid Build Coastguard Worker void bc_num_copy(BcNum *d, BcNum *s) {
2153*cf5a6c84SAndroid Build Coastguard Worker if (d == s) return;
2154*cf5a6c84SAndroid Build Coastguard Worker bc_num_expand(d, s->len);
2155*cf5a6c84SAndroid Build Coastguard Worker d->len = s->len;
2156*cf5a6c84SAndroid Build Coastguard Worker d->neg = s->neg;
2157*cf5a6c84SAndroid Build Coastguard Worker d->rdx = s->rdx;
2158*cf5a6c84SAndroid Build Coastguard Worker memcpy(d->num, s->num, d->len);
2159*cf5a6c84SAndroid Build Coastguard Worker }
2160*cf5a6c84SAndroid Build Coastguard Worker
bc_num_createCopy(BcNum * d,BcNum * s)2161*cf5a6c84SAndroid Build Coastguard Worker void bc_num_createCopy(BcNum *d, BcNum *s) {
2162*cf5a6c84SAndroid Build Coastguard Worker bc_num_init(d, s->len);
2163*cf5a6c84SAndroid Build Coastguard Worker bc_num_copy(d, s);
2164*cf5a6c84SAndroid Build Coastguard Worker }
2165*cf5a6c84SAndroid Build Coastguard Worker
bc_num_createFromUlong(BcNum * n,unsigned long val)2166*cf5a6c84SAndroid Build Coastguard Worker void bc_num_createFromUlong(BcNum *n, unsigned long val) {
2167*cf5a6c84SAndroid Build Coastguard Worker bc_num_init(n, BC_NUM_LONG_LOG10);
2168*cf5a6c84SAndroid Build Coastguard Worker bc_num_ulong2num(n, val);
2169*cf5a6c84SAndroid Build Coastguard Worker }
2170*cf5a6c84SAndroid Build Coastguard Worker
bc_num_parse(BcNum * n,char * val,BcNum * base,size_t base_t,int letter)2171*cf5a6c84SAndroid Build Coastguard Worker BcStatus bc_num_parse(BcNum *n, char *val,
2172*cf5a6c84SAndroid Build Coastguard Worker BcNum *base, size_t base_t, int letter)
2173*cf5a6c84SAndroid Build Coastguard Worker {
2174*cf5a6c84SAndroid Build Coastguard Worker BcStatus s = BC_STATUS_SUCCESS;
2175*cf5a6c84SAndroid Build Coastguard Worker
2176*cf5a6c84SAndroid Build Coastguard Worker if (letter) bc_num_ulong2num(n, bc_num_parseChar(val[0], 'Z'+11));
2177*cf5a6c84SAndroid Build Coastguard Worker else if (base_t == 10) {
2178*cf5a6c84SAndroid Build Coastguard Worker size_t len, i;
2179*cf5a6c84SAndroid Build Coastguard Worker char *ptr;
2180*cf5a6c84SAndroid Build Coastguard Worker int zero = 1;
2181*cf5a6c84SAndroid Build Coastguard Worker
2182*cf5a6c84SAndroid Build Coastguard Worker while (*val == '0') val++;
2183*cf5a6c84SAndroid Build Coastguard Worker
2184*cf5a6c84SAndroid Build Coastguard Worker len = strlen(val);
2185*cf5a6c84SAndroid Build Coastguard Worker if (len) {
2186*cf5a6c84SAndroid Build Coastguard Worker for (i = 0; zero && i < len; ++i) zero = (val[i] == '0') || val[i] == '.';
2187*cf5a6c84SAndroid Build Coastguard Worker bc_num_expand(n, len);
2188*cf5a6c84SAndroid Build Coastguard Worker }
2189*cf5a6c84SAndroid Build Coastguard Worker ptr = strchr(val, '.');
2190*cf5a6c84SAndroid Build Coastguard Worker n->rdx = ptr ? (val + len) - (ptr + 1) : 0;
2191*cf5a6c84SAndroid Build Coastguard Worker
2192*cf5a6c84SAndroid Build Coastguard Worker if (!zero) {
2193*cf5a6c84SAndroid Build Coastguard Worker for (i = len - 1; i < len; ++n->len, --i) {
2194*cf5a6c84SAndroid Build Coastguard Worker
2195*cf5a6c84SAndroid Build Coastguard Worker char c = val[i];
2196*cf5a6c84SAndroid Build Coastguard Worker
2197*cf5a6c84SAndroid Build Coastguard Worker if (c == '.') n->len -= 1;
2198*cf5a6c84SAndroid Build Coastguard Worker else {
2199*cf5a6c84SAndroid Build Coastguard Worker if (isupper(c)) c = '9';
2200*cf5a6c84SAndroid Build Coastguard Worker n->num[n->len] = c - '0';
2201*cf5a6c84SAndroid Build Coastguard Worker }
2202*cf5a6c84SAndroid Build Coastguard Worker }
2203*cf5a6c84SAndroid Build Coastguard Worker }
2204*cf5a6c84SAndroid Build Coastguard Worker } else s = bc_num_parseBase(n, val, base, base_t);
2205*cf5a6c84SAndroid Build Coastguard Worker
2206*cf5a6c84SAndroid Build Coastguard Worker return s;
2207*cf5a6c84SAndroid Build Coastguard Worker }
2208*cf5a6c84SAndroid Build Coastguard Worker
bc_num_ulong(BcNum * n,unsigned long * result)2209*cf5a6c84SAndroid Build Coastguard Worker BcStatus bc_num_ulong(BcNum *n, unsigned long *result) {
2210*cf5a6c84SAndroid Build Coastguard Worker
2211*cf5a6c84SAndroid Build Coastguard Worker size_t i;
2212*cf5a6c84SAndroid Build Coastguard Worker unsigned long r;
2213*cf5a6c84SAndroid Build Coastguard Worker
2214*cf5a6c84SAndroid Build Coastguard Worker *result = 0;
2215*cf5a6c84SAndroid Build Coastguard Worker
2216*cf5a6c84SAndroid Build Coastguard Worker if (n->neg) return bc_vm_err(BC_ERROR_MATH_NEGATIVE);
2217*cf5a6c84SAndroid Build Coastguard Worker
2218*cf5a6c84SAndroid Build Coastguard Worker for (r = 0, i = n->len; i > n->rdx;) {
2219*cf5a6c84SAndroid Build Coastguard Worker
2220*cf5a6c84SAndroid Build Coastguard Worker unsigned long prev = r * 10;
2221*cf5a6c84SAndroid Build Coastguard Worker
2222*cf5a6c84SAndroid Build Coastguard Worker if (prev == SIZE_MAX || prev / 10 != r)
2223*cf5a6c84SAndroid Build Coastguard Worker return bc_vm_err(BC_ERROR_MATH_OVERFLOW);
2224*cf5a6c84SAndroid Build Coastguard Worker
2225*cf5a6c84SAndroid Build Coastguard Worker r = prev + ((char) n->num[--i]);
2226*cf5a6c84SAndroid Build Coastguard Worker
2227*cf5a6c84SAndroid Build Coastguard Worker if (r == SIZE_MAX || r < prev) return bc_vm_err(BC_ERROR_MATH_OVERFLOW);
2228*cf5a6c84SAndroid Build Coastguard Worker }
2229*cf5a6c84SAndroid Build Coastguard Worker
2230*cf5a6c84SAndroid Build Coastguard Worker *result = r;
2231*cf5a6c84SAndroid Build Coastguard Worker
2232*cf5a6c84SAndroid Build Coastguard Worker return BC_STATUS_SUCCESS;
2233*cf5a6c84SAndroid Build Coastguard Worker }
2234*cf5a6c84SAndroid Build Coastguard Worker
bc_num_ulong2num(BcNum * n,unsigned long val)2235*cf5a6c84SAndroid Build Coastguard Worker void bc_num_ulong2num(BcNum *n, unsigned long val) {
2236*cf5a6c84SAndroid Build Coastguard Worker
2237*cf5a6c84SAndroid Build Coastguard Worker size_t len;
2238*cf5a6c84SAndroid Build Coastguard Worker signed char *ptr;
2239*cf5a6c84SAndroid Build Coastguard Worker unsigned long i;
2240*cf5a6c84SAndroid Build Coastguard Worker
2241*cf5a6c84SAndroid Build Coastguard Worker bc_num_setToZero(n, 0);
2242*cf5a6c84SAndroid Build Coastguard Worker
2243*cf5a6c84SAndroid Build Coastguard Worker if (!val) return;
2244*cf5a6c84SAndroid Build Coastguard Worker
2245*cf5a6c84SAndroid Build Coastguard Worker len = bc_num_log10(ULONG_MAX);
2246*cf5a6c84SAndroid Build Coastguard Worker bc_num_expand(n, len);
2247*cf5a6c84SAndroid Build Coastguard Worker for (ptr = n->num, i = 0; val; ++i, ++n->len, val /= 10) ptr[i] = val % 10;
2248*cf5a6c84SAndroid Build Coastguard Worker }
2249*cf5a6c84SAndroid Build Coastguard Worker
bc_num_addReq(BcNum * a,BcNum * b,size_t scale)2250*cf5a6c84SAndroid Build Coastguard Worker size_t bc_num_addReq(BcNum *a, BcNum *b, size_t scale) {
2251*cf5a6c84SAndroid Build Coastguard Worker return maxof(a->rdx, b->rdx) + maxof(BC_NUM_INT(a), BC_NUM_INT(b)) + 1;
2252*cf5a6c84SAndroid Build Coastguard Worker }
2253*cf5a6c84SAndroid Build Coastguard Worker
bc_num_mulReq(BcNum * a,BcNum * b,size_t scale)2254*cf5a6c84SAndroid Build Coastguard Worker size_t bc_num_mulReq(BcNum *a, BcNum *b, size_t scale) {
2255*cf5a6c84SAndroid Build Coastguard Worker return BC_NUM_INT(a) + BC_NUM_INT(b) + maxof(scale, a->rdx + b->rdx) + 1;
2256*cf5a6c84SAndroid Build Coastguard Worker }
2257*cf5a6c84SAndroid Build Coastguard Worker
bc_num_powReq(BcNum * a,BcNum * b,size_t scale)2258*cf5a6c84SAndroid Build Coastguard Worker size_t bc_num_powReq(BcNum *a, BcNum *b, size_t scale) {
2259*cf5a6c84SAndroid Build Coastguard Worker return a->len + b->len + 1;
2260*cf5a6c84SAndroid Build Coastguard Worker }
2261*cf5a6c84SAndroid Build Coastguard Worker
bc_num_add(BcNum * a,BcNum * b,BcNum * c,size_t scale)2262*cf5a6c84SAndroid Build Coastguard Worker BcStatus bc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
2263*cf5a6c84SAndroid Build Coastguard Worker BcNumBinaryOp op = (!a->neg == !b->neg) ? bc_num_a : bc_num_s;
2264*cf5a6c84SAndroid Build Coastguard Worker return bc_num_binary(a, b, c, 0, op, bc_num_addReq(a, b, scale));
2265*cf5a6c84SAndroid Build Coastguard Worker }
2266*cf5a6c84SAndroid Build Coastguard Worker
bc_num_sub(BcNum * a,BcNum * b,BcNum * c,size_t scale)2267*cf5a6c84SAndroid Build Coastguard Worker BcStatus bc_num_sub(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
2268*cf5a6c84SAndroid Build Coastguard Worker BcNumBinaryOp op = (!a->neg == !b->neg) ? bc_num_s : bc_num_a;
2269*cf5a6c84SAndroid Build Coastguard Worker return bc_num_binary(a, b, c, 1, op, bc_num_addReq(a, b, scale));
2270*cf5a6c84SAndroid Build Coastguard Worker }
2271*cf5a6c84SAndroid Build Coastguard Worker
bc_num_mul(BcNum * a,BcNum * b,BcNum * c,size_t scale)2272*cf5a6c84SAndroid Build Coastguard Worker BcStatus bc_num_mul(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
2273*cf5a6c84SAndroid Build Coastguard Worker return bc_num_binary(a, b, c, scale, bc_num_m, bc_num_mulReq(a, b, scale));
2274*cf5a6c84SAndroid Build Coastguard Worker }
2275*cf5a6c84SAndroid Build Coastguard Worker
bc_num_div(BcNum * a,BcNum * b,BcNum * c,size_t scale)2276*cf5a6c84SAndroid Build Coastguard Worker BcStatus bc_num_div(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
2277*cf5a6c84SAndroid Build Coastguard Worker return bc_num_binary(a, b, c, scale, bc_num_d, bc_num_mulReq(a, b, scale));
2278*cf5a6c84SAndroid Build Coastguard Worker }
2279*cf5a6c84SAndroid Build Coastguard Worker
bc_num_mod(BcNum * a,BcNum * b,BcNum * c,size_t scale)2280*cf5a6c84SAndroid Build Coastguard Worker BcStatus bc_num_mod(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
2281*cf5a6c84SAndroid Build Coastguard Worker return bc_num_binary(a, b, c, scale, bc_num_rem, bc_num_mulReq(a, b, scale));
2282*cf5a6c84SAndroid Build Coastguard Worker }
2283*cf5a6c84SAndroid Build Coastguard Worker
bc_num_pow(BcNum * a,BcNum * b,BcNum * c,size_t scale)2284*cf5a6c84SAndroid Build Coastguard Worker BcStatus bc_num_pow(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
2285*cf5a6c84SAndroid Build Coastguard Worker return bc_num_binary(a, b, c, scale, bc_num_p, a->len + b->len + 1);
2286*cf5a6c84SAndroid Build Coastguard Worker }
2287*cf5a6c84SAndroid Build Coastguard Worker
bc_num_sqrt(BcNum * a,BcNum * b,size_t scale)2288*cf5a6c84SAndroid Build Coastguard Worker BcStatus bc_num_sqrt(BcNum *a, BcNum *b, size_t scale) {
2289*cf5a6c84SAndroid Build Coastguard Worker
2290*cf5a6c84SAndroid Build Coastguard Worker BcStatus s = BC_STATUS_SUCCESS;
2291*cf5a6c84SAndroid Build Coastguard Worker BcNum num1, num2, half, f, fprime, *x0, *x1, *temp;
2292*cf5a6c84SAndroid Build Coastguard Worker size_t pow, len, digs, digs1, resrdx, times = 0;
2293*cf5a6c84SAndroid Build Coastguard Worker ssize_t cmp = 1, cmp1 = SSIZE_MAX, cmp2 = SSIZE_MAX;
2294*cf5a6c84SAndroid Build Coastguard Worker signed char half_digs[2];
2295*cf5a6c84SAndroid Build Coastguard Worker
2296*cf5a6c84SAndroid Build Coastguard Worker bc_num_init(b, maxof(scale, a->rdx) + ((BC_NUM_INT(a) + 1) >> 1) + 1);
2297*cf5a6c84SAndroid Build Coastguard Worker
2298*cf5a6c84SAndroid Build Coastguard Worker if (!a->len) {
2299*cf5a6c84SAndroid Build Coastguard Worker bc_num_setToZero(b, scale);
2300*cf5a6c84SAndroid Build Coastguard Worker return BC_STATUS_SUCCESS;
2301*cf5a6c84SAndroid Build Coastguard Worker }
2302*cf5a6c84SAndroid Build Coastguard Worker if (a->neg) return bc_vm_err(BC_ERROR_MATH_NEGATIVE);
2303*cf5a6c84SAndroid Build Coastguard Worker if (BC_NUM_ONE(a)) {
2304*cf5a6c84SAndroid Build Coastguard Worker bc_num_one(b);
2305*cf5a6c84SAndroid Build Coastguard Worker bc_num_extend(b, scale);
2306*cf5a6c84SAndroid Build Coastguard Worker return BC_STATUS_SUCCESS;
2307*cf5a6c84SAndroid Build Coastguard Worker }
2308*cf5a6c84SAndroid Build Coastguard Worker
2309*cf5a6c84SAndroid Build Coastguard Worker scale = maxof(scale, a->rdx) + 1;
2310*cf5a6c84SAndroid Build Coastguard Worker len = a->len + scale;
2311*cf5a6c84SAndroid Build Coastguard Worker
2312*cf5a6c84SAndroid Build Coastguard Worker bc_num_init(&num1, len);
2313*cf5a6c84SAndroid Build Coastguard Worker bc_num_init(&num2, len);
2314*cf5a6c84SAndroid Build Coastguard Worker bc_num_setup(&half, half_digs, sizeof(half_digs));
2315*cf5a6c84SAndroid Build Coastguard Worker
2316*cf5a6c84SAndroid Build Coastguard Worker bc_num_one(&half);
2317*cf5a6c84SAndroid Build Coastguard Worker half.num[0] = 5;
2318*cf5a6c84SAndroid Build Coastguard Worker half.rdx = 1;
2319*cf5a6c84SAndroid Build Coastguard Worker
2320*cf5a6c84SAndroid Build Coastguard Worker bc_num_init(&f, len);
2321*cf5a6c84SAndroid Build Coastguard Worker bc_num_init(&fprime, len);
2322*cf5a6c84SAndroid Build Coastguard Worker
2323*cf5a6c84SAndroid Build Coastguard Worker x0 = &num1;
2324*cf5a6c84SAndroid Build Coastguard Worker x1 = &num2;
2325*cf5a6c84SAndroid Build Coastguard Worker
2326*cf5a6c84SAndroid Build Coastguard Worker bc_num_one(x0);
2327*cf5a6c84SAndroid Build Coastguard Worker pow = BC_NUM_INT(a);
2328*cf5a6c84SAndroid Build Coastguard Worker
2329*cf5a6c84SAndroid Build Coastguard Worker if (pow) {
2330*cf5a6c84SAndroid Build Coastguard Worker
2331*cf5a6c84SAndroid Build Coastguard Worker if (pow & 1) x0->num[0] = 2;
2332*cf5a6c84SAndroid Build Coastguard Worker else x0->num[0] = 6;
2333*cf5a6c84SAndroid Build Coastguard Worker
2334*cf5a6c84SAndroid Build Coastguard Worker pow -= 2 - (pow & 1);
2335*cf5a6c84SAndroid Build Coastguard Worker
2336*cf5a6c84SAndroid Build Coastguard Worker bc_num_extend(x0, pow);
2337*cf5a6c84SAndroid Build Coastguard Worker
2338*cf5a6c84SAndroid Build Coastguard Worker // Make sure to move the radix back.
2339*cf5a6c84SAndroid Build Coastguard Worker x0->rdx -= pow;
2340*cf5a6c84SAndroid Build Coastguard Worker }
2341*cf5a6c84SAndroid Build Coastguard Worker
2342*cf5a6c84SAndroid Build Coastguard Worker x0->rdx = digs = digs1 = 0;
2343*cf5a6c84SAndroid Build Coastguard Worker resrdx = scale + 2;
2344*cf5a6c84SAndroid Build Coastguard Worker len = BC_NUM_INT(x0) + resrdx - 1;
2345*cf5a6c84SAndroid Build Coastguard Worker
2346*cf5a6c84SAndroid Build Coastguard Worker while (!TT.sig && (cmp || digs < len)) {
2347*cf5a6c84SAndroid Build Coastguard Worker
2348*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_div(a, x0, &f, resrdx);
2349*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
2350*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_add(x0, &f, &fprime, resrdx);
2351*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
2352*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_mul(&fprime, &half, x1, resrdx);
2353*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
2354*cf5a6c84SAndroid Build Coastguard Worker
2355*cf5a6c84SAndroid Build Coastguard Worker cmp = bc_num_cmp(x1, x0);
2356*cf5a6c84SAndroid Build Coastguard Worker digs = x1->len - (unsigned long long) llabs(cmp);
2357*cf5a6c84SAndroid Build Coastguard Worker
2358*cf5a6c84SAndroid Build Coastguard Worker if (cmp == cmp2 && digs == digs1) times += 1;
2359*cf5a6c84SAndroid Build Coastguard Worker else times = 0;
2360*cf5a6c84SAndroid Build Coastguard Worker
2361*cf5a6c84SAndroid Build Coastguard Worker resrdx += times > 4;
2362*cf5a6c84SAndroid Build Coastguard Worker
2363*cf5a6c84SAndroid Build Coastguard Worker cmp2 = cmp1;
2364*cf5a6c84SAndroid Build Coastguard Worker cmp1 = cmp;
2365*cf5a6c84SAndroid Build Coastguard Worker digs1 = digs;
2366*cf5a6c84SAndroid Build Coastguard Worker
2367*cf5a6c84SAndroid Build Coastguard Worker temp = x0;
2368*cf5a6c84SAndroid Build Coastguard Worker x0 = x1;
2369*cf5a6c84SAndroid Build Coastguard Worker x1 = temp;
2370*cf5a6c84SAndroid Build Coastguard Worker }
2371*cf5a6c84SAndroid Build Coastguard Worker
2372*cf5a6c84SAndroid Build Coastguard Worker if (TT.sig) {
2373*cf5a6c84SAndroid Build Coastguard Worker s = BC_STATUS_SIGNAL;
2374*cf5a6c84SAndroid Build Coastguard Worker goto err;
2375*cf5a6c84SAndroid Build Coastguard Worker }
2376*cf5a6c84SAndroid Build Coastguard Worker
2377*cf5a6c84SAndroid Build Coastguard Worker bc_num_copy(b, x0);
2378*cf5a6c84SAndroid Build Coastguard Worker scale -= 1;
2379*cf5a6c84SAndroid Build Coastguard Worker if (b->rdx > scale) bc_num_truncate(b, b->rdx - scale);
2380*cf5a6c84SAndroid Build Coastguard Worker
2381*cf5a6c84SAndroid Build Coastguard Worker err:
2382*cf5a6c84SAndroid Build Coastguard Worker bc_num_free(&fprime);
2383*cf5a6c84SAndroid Build Coastguard Worker bc_num_free(&f);
2384*cf5a6c84SAndroid Build Coastguard Worker bc_num_free(&num2);
2385*cf5a6c84SAndroid Build Coastguard Worker bc_num_free(&num1);
2386*cf5a6c84SAndroid Build Coastguard Worker return s;
2387*cf5a6c84SAndroid Build Coastguard Worker }
2388*cf5a6c84SAndroid Build Coastguard Worker
bc_num_divmod(BcNum * a,BcNum * b,BcNum * c,BcNum * d,size_t scale)2389*cf5a6c84SAndroid Build Coastguard Worker BcStatus bc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d, size_t scale) {
2390*cf5a6c84SAndroid Build Coastguard Worker
2391*cf5a6c84SAndroid Build Coastguard Worker BcStatus s;
2392*cf5a6c84SAndroid Build Coastguard Worker BcNum num2, *ptr_a;
2393*cf5a6c84SAndroid Build Coastguard Worker int init = 0;
2394*cf5a6c84SAndroid Build Coastguard Worker size_t ts = maxof(scale + b->rdx, a->rdx), len = bc_num_mulReq(a, b, ts);
2395*cf5a6c84SAndroid Build Coastguard Worker
2396*cf5a6c84SAndroid Build Coastguard Worker if (c == a) {
2397*cf5a6c84SAndroid Build Coastguard Worker memcpy(&num2, c, sizeof(BcNum));
2398*cf5a6c84SAndroid Build Coastguard Worker ptr_a = &num2;
2399*cf5a6c84SAndroid Build Coastguard Worker bc_num_init(c, len);
2400*cf5a6c84SAndroid Build Coastguard Worker init = 1;
2401*cf5a6c84SAndroid Build Coastguard Worker }
2402*cf5a6c84SAndroid Build Coastguard Worker else {
2403*cf5a6c84SAndroid Build Coastguard Worker ptr_a = a;
2404*cf5a6c84SAndroid Build Coastguard Worker bc_num_expand(c, len);
2405*cf5a6c84SAndroid Build Coastguard Worker }
2406*cf5a6c84SAndroid Build Coastguard Worker
2407*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_r(ptr_a, b, c, d, scale, ts);
2408*cf5a6c84SAndroid Build Coastguard Worker
2409*cf5a6c84SAndroid Build Coastguard Worker if (init) bc_num_free(&num2);
2410*cf5a6c84SAndroid Build Coastguard Worker
2411*cf5a6c84SAndroid Build Coastguard Worker return s;
2412*cf5a6c84SAndroid Build Coastguard Worker }
2413*cf5a6c84SAndroid Build Coastguard Worker
bc_id_cmp(struct str_len * e1,struct str_len * e2)2414*cf5a6c84SAndroid Build Coastguard Worker int bc_id_cmp(struct str_len *e1, struct str_len *e2) {
2415*cf5a6c84SAndroid Build Coastguard Worker return strcmp(e1->str, e2->str);
2416*cf5a6c84SAndroid Build Coastguard Worker }
2417*cf5a6c84SAndroid Build Coastguard Worker
bc_id_free(void * id)2418*cf5a6c84SAndroid Build Coastguard Worker void bc_id_free(void *id) {
2419*cf5a6c84SAndroid Build Coastguard Worker free(((struct str_len *)id)->str);
2420*cf5a6c84SAndroid Build Coastguard Worker }
2421*cf5a6c84SAndroid Build Coastguard Worker
bc_string_free(void * string)2422*cf5a6c84SAndroid Build Coastguard Worker void bc_string_free(void *string) {
2423*cf5a6c84SAndroid Build Coastguard Worker free(*((char**) string));
2424*cf5a6c84SAndroid Build Coastguard Worker }
2425*cf5a6c84SAndroid Build Coastguard Worker
bc_func_insert(BcFunc * f,char * name,BcType type,size_t line)2426*cf5a6c84SAndroid Build Coastguard Worker BcStatus bc_func_insert(BcFunc *f, char *name, BcType type, size_t line) {
2427*cf5a6c84SAndroid Build Coastguard Worker
2428*cf5a6c84SAndroid Build Coastguard Worker struct str_len a;
2429*cf5a6c84SAndroid Build Coastguard Worker size_t i;
2430*cf5a6c84SAndroid Build Coastguard Worker
2431*cf5a6c84SAndroid Build Coastguard Worker for (i = 0; i < f->autos.len; ++i) {
2432*cf5a6c84SAndroid Build Coastguard Worker struct str_len *id = bc_vec_item(&f->autos, i);
2433*cf5a6c84SAndroid Build Coastguard Worker if (!strcmp(name, id->str) && type == (BcType) id->len)
2434*cf5a6c84SAndroid Build Coastguard Worker return bc_vm_error(BC_ERROR_PARSE_DUP_LOCAL, line, name);
2435*cf5a6c84SAndroid Build Coastguard Worker }
2436*cf5a6c84SAndroid Build Coastguard Worker
2437*cf5a6c84SAndroid Build Coastguard Worker a.len = type;
2438*cf5a6c84SAndroid Build Coastguard Worker a.str = name;
2439*cf5a6c84SAndroid Build Coastguard Worker
2440*cf5a6c84SAndroid Build Coastguard Worker bc_vec_push(&f->autos, &a);
2441*cf5a6c84SAndroid Build Coastguard Worker
2442*cf5a6c84SAndroid Build Coastguard Worker return BC_STATUS_SUCCESS;
2443*cf5a6c84SAndroid Build Coastguard Worker }
2444*cf5a6c84SAndroid Build Coastguard Worker
bc_func_init(BcFunc * f,char * name)2445*cf5a6c84SAndroid Build Coastguard Worker void bc_func_init(BcFunc *f, char *name) {
2446*cf5a6c84SAndroid Build Coastguard Worker bc_vec_init(&f->code, sizeof(char), NULL);
2447*cf5a6c84SAndroid Build Coastguard Worker bc_vec_init(&f->strs, sizeof(char*), bc_string_free);
2448*cf5a6c84SAndroid Build Coastguard Worker bc_vec_init(&f->consts, sizeof(char*), bc_string_free);
2449*cf5a6c84SAndroid Build Coastguard Worker bc_vec_init(&f->autos, sizeof(struct str_len), bc_id_free);
2450*cf5a6c84SAndroid Build Coastguard Worker bc_vec_init(&f->labels, sizeof(size_t), NULL);
2451*cf5a6c84SAndroid Build Coastguard Worker f->nparams = 0;
2452*cf5a6c84SAndroid Build Coastguard Worker f->voidfn = 0;
2453*cf5a6c84SAndroid Build Coastguard Worker f->name = name;
2454*cf5a6c84SAndroid Build Coastguard Worker }
2455*cf5a6c84SAndroid Build Coastguard Worker
bc_func_reset(BcFunc * f)2456*cf5a6c84SAndroid Build Coastguard Worker void bc_func_reset(BcFunc *f) {
2457*cf5a6c84SAndroid Build Coastguard Worker bc_vec_npop(&f->code, f->code.len);
2458*cf5a6c84SAndroid Build Coastguard Worker bc_vec_npop(&f->strs, f->strs.len);
2459*cf5a6c84SAndroid Build Coastguard Worker bc_vec_npop(&f->consts, f->consts.len);
2460*cf5a6c84SAndroid Build Coastguard Worker bc_vec_npop(&f->autos, f->autos.len);
2461*cf5a6c84SAndroid Build Coastguard Worker bc_vec_npop(&f->labels, f->labels.len);
2462*cf5a6c84SAndroid Build Coastguard Worker f->nparams = 0;
2463*cf5a6c84SAndroid Build Coastguard Worker f->voidfn = 0;
2464*cf5a6c84SAndroid Build Coastguard Worker }
2465*cf5a6c84SAndroid Build Coastguard Worker
bc_func_free(void * func)2466*cf5a6c84SAndroid Build Coastguard Worker void bc_func_free(void *func) {
2467*cf5a6c84SAndroid Build Coastguard Worker BcFunc *f = (BcFunc*) func;
2468*cf5a6c84SAndroid Build Coastguard Worker bc_vec_free(&f->code);
2469*cf5a6c84SAndroid Build Coastguard Worker bc_vec_free(&f->strs);
2470*cf5a6c84SAndroid Build Coastguard Worker bc_vec_free(&f->consts);
2471*cf5a6c84SAndroid Build Coastguard Worker bc_vec_free(&f->autos);
2472*cf5a6c84SAndroid Build Coastguard Worker bc_vec_free(&f->labels);
2473*cf5a6c84SAndroid Build Coastguard Worker }
2474*cf5a6c84SAndroid Build Coastguard Worker
bc_array_init(BcVec * a,int nums)2475*cf5a6c84SAndroid Build Coastguard Worker void bc_array_init(BcVec *a, int nums) {
2476*cf5a6c84SAndroid Build Coastguard Worker if (nums) bc_vec_init(a, sizeof(BcNum), bc_num_free);
2477*cf5a6c84SAndroid Build Coastguard Worker else bc_vec_init(a, sizeof(BcVec), bc_vec_free);
2478*cf5a6c84SAndroid Build Coastguard Worker bc_array_expand(a, 1);
2479*cf5a6c84SAndroid Build Coastguard Worker }
2480*cf5a6c84SAndroid Build Coastguard Worker
bc_array_copy(BcVec * d,BcVec * s)2481*cf5a6c84SAndroid Build Coastguard Worker void bc_array_copy(BcVec *d, BcVec *s) {
2482*cf5a6c84SAndroid Build Coastguard Worker
2483*cf5a6c84SAndroid Build Coastguard Worker size_t i;
2484*cf5a6c84SAndroid Build Coastguard Worker
2485*cf5a6c84SAndroid Build Coastguard Worker bc_vec_npop(d, d->len);
2486*cf5a6c84SAndroid Build Coastguard Worker bc_vec_expand(d, s->cap);
2487*cf5a6c84SAndroid Build Coastguard Worker d->len = s->len;
2488*cf5a6c84SAndroid Build Coastguard Worker
2489*cf5a6c84SAndroid Build Coastguard Worker for (i = 0; i < s->len; ++i) {
2490*cf5a6c84SAndroid Build Coastguard Worker BcNum *dnum = bc_vec_item(d, i), *snum = bc_vec_item(s, i);
2491*cf5a6c84SAndroid Build Coastguard Worker bc_num_createCopy(dnum, snum);
2492*cf5a6c84SAndroid Build Coastguard Worker }
2493*cf5a6c84SAndroid Build Coastguard Worker }
2494*cf5a6c84SAndroid Build Coastguard Worker
bc_array_expand(BcVec * a,size_t len)2495*cf5a6c84SAndroid Build Coastguard Worker void bc_array_expand(BcVec *a, size_t len) {
2496*cf5a6c84SAndroid Build Coastguard Worker
2497*cf5a6c84SAndroid Build Coastguard Worker if (a->size == sizeof(BcNum) && a->dtor == bc_num_free) {
2498*cf5a6c84SAndroid Build Coastguard Worker BcNum n;
2499*cf5a6c84SAndroid Build Coastguard Worker while (len > a->len) {
2500*cf5a6c84SAndroid Build Coastguard Worker bc_num_init(&n, BC_NUM_DEF_SIZE);
2501*cf5a6c84SAndroid Build Coastguard Worker bc_vec_push(a, &n);
2502*cf5a6c84SAndroid Build Coastguard Worker }
2503*cf5a6c84SAndroid Build Coastguard Worker }
2504*cf5a6c84SAndroid Build Coastguard Worker else {
2505*cf5a6c84SAndroid Build Coastguard Worker BcVec v;
2506*cf5a6c84SAndroid Build Coastguard Worker while (len > a->len) {
2507*cf5a6c84SAndroid Build Coastguard Worker bc_array_init(&v, 1);
2508*cf5a6c84SAndroid Build Coastguard Worker bc_vec_push(a, &v);
2509*cf5a6c84SAndroid Build Coastguard Worker }
2510*cf5a6c84SAndroid Build Coastguard Worker }
2511*cf5a6c84SAndroid Build Coastguard Worker }
2512*cf5a6c84SAndroid Build Coastguard Worker
bc_result_free(void * result)2513*cf5a6c84SAndroid Build Coastguard Worker void bc_result_free(void *result) {
2514*cf5a6c84SAndroid Build Coastguard Worker
2515*cf5a6c84SAndroid Build Coastguard Worker BcResult *r = (BcResult*) result;
2516*cf5a6c84SAndroid Build Coastguard Worker
2517*cf5a6c84SAndroid Build Coastguard Worker switch (r->t) {
2518*cf5a6c84SAndroid Build Coastguard Worker
2519*cf5a6c84SAndroid Build Coastguard Worker case BC_RESULT_TEMP:
2520*cf5a6c84SAndroid Build Coastguard Worker case BC_RESULT_IBASE:
2521*cf5a6c84SAndroid Build Coastguard Worker case BC_RESULT_SCALE:
2522*cf5a6c84SAndroid Build Coastguard Worker case BC_RESULT_OBASE:
2523*cf5a6c84SAndroid Build Coastguard Worker {
2524*cf5a6c84SAndroid Build Coastguard Worker bc_num_free(&r->d.n);
2525*cf5a6c84SAndroid Build Coastguard Worker break;
2526*cf5a6c84SAndroid Build Coastguard Worker }
2527*cf5a6c84SAndroid Build Coastguard Worker
2528*cf5a6c84SAndroid Build Coastguard Worker case BC_RESULT_VAR:
2529*cf5a6c84SAndroid Build Coastguard Worker case BC_RESULT_ARRAY:
2530*cf5a6c84SAndroid Build Coastguard Worker case BC_RESULT_ARRAY_ELEM:
2531*cf5a6c84SAndroid Build Coastguard Worker {
2532*cf5a6c84SAndroid Build Coastguard Worker free(r->d.id.str);
2533*cf5a6c84SAndroid Build Coastguard Worker break;
2534*cf5a6c84SAndroid Build Coastguard Worker }
2535*cf5a6c84SAndroid Build Coastguard Worker
2536*cf5a6c84SAndroid Build Coastguard Worker case BC_RESULT_STR:
2537*cf5a6c84SAndroid Build Coastguard Worker case BC_RESULT_CONSTANT:
2538*cf5a6c84SAndroid Build Coastguard Worker case BC_RESULT_VOID:
2539*cf5a6c84SAndroid Build Coastguard Worker case BC_RESULT_ONE:
2540*cf5a6c84SAndroid Build Coastguard Worker case BC_RESULT_LAST:
2541*cf5a6c84SAndroid Build Coastguard Worker {
2542*cf5a6c84SAndroid Build Coastguard Worker // Do nothing.
2543*cf5a6c84SAndroid Build Coastguard Worker break;
2544*cf5a6c84SAndroid Build Coastguard Worker }
2545*cf5a6c84SAndroid Build Coastguard Worker }
2546*cf5a6c84SAndroid Build Coastguard Worker }
2547*cf5a6c84SAndroid Build Coastguard Worker
bc_lex_invalidChar(BcLex * l,char c)2548*cf5a6c84SAndroid Build Coastguard Worker BcStatus bc_lex_invalidChar(BcLex *l, char c) {
2549*cf5a6c84SAndroid Build Coastguard Worker l->t = BC_LEX_INVALID;
2550*cf5a6c84SAndroid Build Coastguard Worker return bc_lex_verr(l, BC_ERROR_PARSE_CHAR, c);
2551*cf5a6c84SAndroid Build Coastguard Worker }
2552*cf5a6c84SAndroid Build Coastguard Worker
bc_lex_lineComment(BcLex * l)2553*cf5a6c84SAndroid Build Coastguard Worker void bc_lex_lineComment(BcLex *l) {
2554*cf5a6c84SAndroid Build Coastguard Worker l->t = BC_LEX_WHITESPACE;
2555*cf5a6c84SAndroid Build Coastguard Worker while (l->i < l->len && l->buf[l->i] != '\n') ++l->i;
2556*cf5a6c84SAndroid Build Coastguard Worker }
2557*cf5a6c84SAndroid Build Coastguard Worker
bc_lex_comment(BcLex * l)2558*cf5a6c84SAndroid Build Coastguard Worker BcStatus bc_lex_comment(BcLex *l) {
2559*cf5a6c84SAndroid Build Coastguard Worker
2560*cf5a6c84SAndroid Build Coastguard Worker size_t i, nlines = 0;
2561*cf5a6c84SAndroid Build Coastguard Worker char *buf = l->buf;
2562*cf5a6c84SAndroid Build Coastguard Worker int end = 0;
2563*cf5a6c84SAndroid Build Coastguard Worker char c;
2564*cf5a6c84SAndroid Build Coastguard Worker
2565*cf5a6c84SAndroid Build Coastguard Worker l->t = BC_LEX_WHITESPACE;
2566*cf5a6c84SAndroid Build Coastguard Worker
2567*cf5a6c84SAndroid Build Coastguard Worker for (i = ++l->i; !end; i += !end) {
2568*cf5a6c84SAndroid Build Coastguard Worker
2569*cf5a6c84SAndroid Build Coastguard Worker for (; (c = buf[i]) && c != '*'; ++i) nlines += (c == '\n');
2570*cf5a6c84SAndroid Build Coastguard Worker
2571*cf5a6c84SAndroid Build Coastguard Worker if (!c || buf[i + 1] == '\0') {
2572*cf5a6c84SAndroid Build Coastguard Worker l->i = i;
2573*cf5a6c84SAndroid Build Coastguard Worker return bc_lex_err(l, BC_ERROR_PARSE_COMMENT);
2574*cf5a6c84SAndroid Build Coastguard Worker }
2575*cf5a6c84SAndroid Build Coastguard Worker
2576*cf5a6c84SAndroid Build Coastguard Worker end = buf[i + 1] == '/';
2577*cf5a6c84SAndroid Build Coastguard Worker }
2578*cf5a6c84SAndroid Build Coastguard Worker
2579*cf5a6c84SAndroid Build Coastguard Worker l->i = i + 2;
2580*cf5a6c84SAndroid Build Coastguard Worker l->line += nlines;
2581*cf5a6c84SAndroid Build Coastguard Worker
2582*cf5a6c84SAndroid Build Coastguard Worker return BC_STATUS_SUCCESS;
2583*cf5a6c84SAndroid Build Coastguard Worker }
2584*cf5a6c84SAndroid Build Coastguard Worker
bc_lex_whitespace(BcLex * l)2585*cf5a6c84SAndroid Build Coastguard Worker void bc_lex_whitespace(BcLex *l) {
2586*cf5a6c84SAndroid Build Coastguard Worker char c;
2587*cf5a6c84SAndroid Build Coastguard Worker l->t = BC_LEX_WHITESPACE;
2588*cf5a6c84SAndroid Build Coastguard Worker for (c = l->buf[l->i]; c != '\n' && isspace(c); c = l->buf[++l->i]);
2589*cf5a6c84SAndroid Build Coastguard Worker }
2590*cf5a6c84SAndroid Build Coastguard Worker
bc_lex_number(BcLex * l,char start)2591*cf5a6c84SAndroid Build Coastguard Worker BcStatus bc_lex_number(BcLex *l, char start) {
2592*cf5a6c84SAndroid Build Coastguard Worker
2593*cf5a6c84SAndroid Build Coastguard Worker char *buf = l->buf + l->i;
2594*cf5a6c84SAndroid Build Coastguard Worker size_t i;
2595*cf5a6c84SAndroid Build Coastguard Worker char last_valid, c;
2596*cf5a6c84SAndroid Build Coastguard Worker int last_pt, pt = (start == '.');
2597*cf5a6c84SAndroid Build Coastguard Worker
2598*cf5a6c84SAndroid Build Coastguard Worker l->t = BC_LEX_NUMBER;
2599*cf5a6c84SAndroid Build Coastguard Worker last_valid = 'Z';
2600*cf5a6c84SAndroid Build Coastguard Worker
2601*cf5a6c84SAndroid Build Coastguard Worker bc_vec_npop(&l->str, l->str.len);
2602*cf5a6c84SAndroid Build Coastguard Worker bc_vec_push(&l->str, &start);
2603*cf5a6c84SAndroid Build Coastguard Worker
2604*cf5a6c84SAndroid Build Coastguard Worker for (i = 0; (c = buf[i]) && (BC_LEX_NUM_CHAR(c, last_valid, pt) ||
2605*cf5a6c84SAndroid Build Coastguard Worker (c == '\\' && buf[i + 1] == '\n')); ++i)
2606*cf5a6c84SAndroid Build Coastguard Worker {
2607*cf5a6c84SAndroid Build Coastguard Worker if (c == '\\') {
2608*cf5a6c84SAndroid Build Coastguard Worker
2609*cf5a6c84SAndroid Build Coastguard Worker if (buf[i + 1] == '\n') {
2610*cf5a6c84SAndroid Build Coastguard Worker
2611*cf5a6c84SAndroid Build Coastguard Worker i += 2;
2612*cf5a6c84SAndroid Build Coastguard Worker
2613*cf5a6c84SAndroid Build Coastguard Worker // Make sure to eat whitespace at the beginning of the line.
2614*cf5a6c84SAndroid Build Coastguard Worker while(isspace(buf[i]) && buf[i] != '\n') ++i;
2615*cf5a6c84SAndroid Build Coastguard Worker
2616*cf5a6c84SAndroid Build Coastguard Worker c = buf[i];
2617*cf5a6c84SAndroid Build Coastguard Worker
2618*cf5a6c84SAndroid Build Coastguard Worker if (!BC_LEX_NUM_CHAR(c, last_valid, pt)) break;
2619*cf5a6c84SAndroid Build Coastguard Worker }
2620*cf5a6c84SAndroid Build Coastguard Worker else break;
2621*cf5a6c84SAndroid Build Coastguard Worker }
2622*cf5a6c84SAndroid Build Coastguard Worker
2623*cf5a6c84SAndroid Build Coastguard Worker last_pt = (c == '.');
2624*cf5a6c84SAndroid Build Coastguard Worker if (pt && last_pt) break;
2625*cf5a6c84SAndroid Build Coastguard Worker pt = pt || last_pt;
2626*cf5a6c84SAndroid Build Coastguard Worker
2627*cf5a6c84SAndroid Build Coastguard Worker bc_vec_push(&l->str, &c);
2628*cf5a6c84SAndroid Build Coastguard Worker }
2629*cf5a6c84SAndroid Build Coastguard Worker
2630*cf5a6c84SAndroid Build Coastguard Worker if (l->str.len - pt > BC_MAX_NUM)
2631*cf5a6c84SAndroid Build Coastguard Worker return bc_lex_verr(l, BC_ERROR_EXEC_NUM_LEN, BC_MAX_NUM);
2632*cf5a6c84SAndroid Build Coastguard Worker
2633*cf5a6c84SAndroid Build Coastguard Worker bc_vec_pushByte(&l->str, '\0');
2634*cf5a6c84SAndroid Build Coastguard Worker l->i += i;
2635*cf5a6c84SAndroid Build Coastguard Worker
2636*cf5a6c84SAndroid Build Coastguard Worker return BC_STATUS_SUCCESS;
2637*cf5a6c84SAndroid Build Coastguard Worker }
2638*cf5a6c84SAndroid Build Coastguard Worker
bc_lex_name(BcLex * l)2639*cf5a6c84SAndroid Build Coastguard Worker BcStatus bc_lex_name(BcLex *l) {
2640*cf5a6c84SAndroid Build Coastguard Worker
2641*cf5a6c84SAndroid Build Coastguard Worker size_t i = 0;
2642*cf5a6c84SAndroid Build Coastguard Worker char *buf = l->buf + l->i - 1;
2643*cf5a6c84SAndroid Build Coastguard Worker char c = buf[i];
2644*cf5a6c84SAndroid Build Coastguard Worker
2645*cf5a6c84SAndroid Build Coastguard Worker l->t = BC_LEX_NAME;
2646*cf5a6c84SAndroid Build Coastguard Worker
2647*cf5a6c84SAndroid Build Coastguard Worker while ((c >= 'a' && c <= 'z') || isdigit(c) || c == '_') c = buf[++i];
2648*cf5a6c84SAndroid Build Coastguard Worker
2649*cf5a6c84SAndroid Build Coastguard Worker if (i > BC_MAX_NAME)
2650*cf5a6c84SAndroid Build Coastguard Worker return bc_lex_verr(l, BC_ERROR_EXEC_NAME_LEN, BC_MAX_NAME);
2651*cf5a6c84SAndroid Build Coastguard Worker
2652*cf5a6c84SAndroid Build Coastguard Worker bc_vec_string(&l->str, i, buf);
2653*cf5a6c84SAndroid Build Coastguard Worker
2654*cf5a6c84SAndroid Build Coastguard Worker // Increment the index. We minus 1 because it has already been incremented.
2655*cf5a6c84SAndroid Build Coastguard Worker l->i += i - 1;
2656*cf5a6c84SAndroid Build Coastguard Worker
2657*cf5a6c84SAndroid Build Coastguard Worker return BC_STATUS_SUCCESS;
2658*cf5a6c84SAndroid Build Coastguard Worker }
2659*cf5a6c84SAndroid Build Coastguard Worker
bc_lex_init(BcLex * l)2660*cf5a6c84SAndroid Build Coastguard Worker void bc_lex_init(BcLex *l) {
2661*cf5a6c84SAndroid Build Coastguard Worker bc_vec_init(&l->str, sizeof(char), NULL);
2662*cf5a6c84SAndroid Build Coastguard Worker }
2663*cf5a6c84SAndroid Build Coastguard Worker
bc_lex_file(BcLex * l,char * file)2664*cf5a6c84SAndroid Build Coastguard Worker void bc_lex_file(BcLex *l, char *file) {
2665*cf5a6c84SAndroid Build Coastguard Worker l->line = 1;
2666*cf5a6c84SAndroid Build Coastguard Worker TT.file = file;
2667*cf5a6c84SAndroid Build Coastguard Worker }
2668*cf5a6c84SAndroid Build Coastguard Worker
bc_lex_next(BcLex * l)2669*cf5a6c84SAndroid Build Coastguard Worker BcStatus bc_lex_next(BcLex *l) {
2670*cf5a6c84SAndroid Build Coastguard Worker
2671*cf5a6c84SAndroid Build Coastguard Worker BcStatus s;
2672*cf5a6c84SAndroid Build Coastguard Worker
2673*cf5a6c84SAndroid Build Coastguard Worker l->last = l->t;
2674*cf5a6c84SAndroid Build Coastguard Worker l->line += (l->i != 0 && l->buf[l->i - 1] == '\n');
2675*cf5a6c84SAndroid Build Coastguard Worker
2676*cf5a6c84SAndroid Build Coastguard Worker if (l->last == BC_LEX_EOF) return bc_lex_err(l, BC_ERROR_PARSE_EOF);
2677*cf5a6c84SAndroid Build Coastguard Worker
2678*cf5a6c84SAndroid Build Coastguard Worker l->t = BC_LEX_EOF;
2679*cf5a6c84SAndroid Build Coastguard Worker
2680*cf5a6c84SAndroid Build Coastguard Worker if (l->i == l->len) return BC_STATUS_SUCCESS;
2681*cf5a6c84SAndroid Build Coastguard Worker
2682*cf5a6c84SAndroid Build Coastguard Worker // Loop until failure or we don't have whitespace. This
2683*cf5a6c84SAndroid Build Coastguard Worker // is so the parser doesn't get inundated with whitespace.
2684*cf5a6c84SAndroid Build Coastguard Worker do {
2685*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_token(l);
2686*cf5a6c84SAndroid Build Coastguard Worker } while (!s && l->t == BC_LEX_WHITESPACE);
2687*cf5a6c84SAndroid Build Coastguard Worker
2688*cf5a6c84SAndroid Build Coastguard Worker return s;
2689*cf5a6c84SAndroid Build Coastguard Worker }
2690*cf5a6c84SAndroid Build Coastguard Worker
bc_lex_text(BcLex * l,char * text)2691*cf5a6c84SAndroid Build Coastguard Worker BcStatus bc_lex_text(BcLex *l, char *text) {
2692*cf5a6c84SAndroid Build Coastguard Worker l->buf = text;
2693*cf5a6c84SAndroid Build Coastguard Worker l->i = 0;
2694*cf5a6c84SAndroid Build Coastguard Worker l->len = strlen(text);
2695*cf5a6c84SAndroid Build Coastguard Worker l->t = l->last = BC_LEX_INVALID;
2696*cf5a6c84SAndroid Build Coastguard Worker return bc_lex_next(l);
2697*cf5a6c84SAndroid Build Coastguard Worker }
2698*cf5a6c84SAndroid Build Coastguard Worker
bc_lex_identifier(BcLex * l)2699*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_lex_identifier(BcLex *l) {
2700*cf5a6c84SAndroid Build Coastguard Worker
2701*cf5a6c84SAndroid Build Coastguard Worker BcStatus s;
2702*cf5a6c84SAndroid Build Coastguard Worker size_t i;
2703*cf5a6c84SAndroid Build Coastguard Worker char *buf = l->buf + l->i - 1;
2704*cf5a6c84SAndroid Build Coastguard Worker
2705*cf5a6c84SAndroid Build Coastguard Worker for (i = 0; i < bc_lex_kws_len; ++i) {
2706*cf5a6c84SAndroid Build Coastguard Worker
2707*cf5a6c84SAndroid Build Coastguard Worker BcLexKeyword *kw = bc_lex_kws + i;
2708*cf5a6c84SAndroid Build Coastguard Worker size_t len = BC_LEX_KW_LEN(kw);
2709*cf5a6c84SAndroid Build Coastguard Worker
2710*cf5a6c84SAndroid Build Coastguard Worker if (!strncmp(buf, kw->name, len) && !isalnum(buf[len]) && buf[len] != '_')
2711*cf5a6c84SAndroid Build Coastguard Worker {
2712*cf5a6c84SAndroid Build Coastguard Worker l->t = BC_LEX_KEY_AUTO + (BcLexType) i;
2713*cf5a6c84SAndroid Build Coastguard Worker
2714*cf5a6c84SAndroid Build Coastguard Worker if (!BC_LEX_KW_POSIX(kw)) {
2715*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_vposixErr(l, BC_ERROR_POSIX_KW, kw->name);
2716*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
2717*cf5a6c84SAndroid Build Coastguard Worker }
2718*cf5a6c84SAndroid Build Coastguard Worker
2719*cf5a6c84SAndroid Build Coastguard Worker // We minus 1 because the index has already been incremented.
2720*cf5a6c84SAndroid Build Coastguard Worker l->i += len - 1;
2721*cf5a6c84SAndroid Build Coastguard Worker return BC_STATUS_SUCCESS;
2722*cf5a6c84SAndroid Build Coastguard Worker }
2723*cf5a6c84SAndroid Build Coastguard Worker }
2724*cf5a6c84SAndroid Build Coastguard Worker
2725*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_name(l);
2726*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
2727*cf5a6c84SAndroid Build Coastguard Worker
2728*cf5a6c84SAndroid Build Coastguard Worker if (l->str.len - 1 > 1) s = bc_lex_vposixErr(l, BC_ERROR_POSIX_NAME_LEN, buf);
2729*cf5a6c84SAndroid Build Coastguard Worker
2730*cf5a6c84SAndroid Build Coastguard Worker return s;
2731*cf5a6c84SAndroid Build Coastguard Worker }
2732*cf5a6c84SAndroid Build Coastguard Worker
bc_lex_string(BcLex * l)2733*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_lex_string(BcLex *l) {
2734*cf5a6c84SAndroid Build Coastguard Worker
2735*cf5a6c84SAndroid Build Coastguard Worker size_t len, nlines = 0, i = l->i;
2736*cf5a6c84SAndroid Build Coastguard Worker char *buf = l->buf;
2737*cf5a6c84SAndroid Build Coastguard Worker char c;
2738*cf5a6c84SAndroid Build Coastguard Worker
2739*cf5a6c84SAndroid Build Coastguard Worker l->t = BC_LEX_STR;
2740*cf5a6c84SAndroid Build Coastguard Worker
2741*cf5a6c84SAndroid Build Coastguard Worker for (; (c = buf[i]) && c != '"'; ++i) nlines += c == '\n';
2742*cf5a6c84SAndroid Build Coastguard Worker
2743*cf5a6c84SAndroid Build Coastguard Worker if (c == '\0') {
2744*cf5a6c84SAndroid Build Coastguard Worker l->i = i;
2745*cf5a6c84SAndroid Build Coastguard Worker return bc_lex_err(l, BC_ERROR_PARSE_STRING);
2746*cf5a6c84SAndroid Build Coastguard Worker }
2747*cf5a6c84SAndroid Build Coastguard Worker
2748*cf5a6c84SAndroid Build Coastguard Worker len = i - l->i;
2749*cf5a6c84SAndroid Build Coastguard Worker
2750*cf5a6c84SAndroid Build Coastguard Worker if (len > BC_MAX_STRING)
2751*cf5a6c84SAndroid Build Coastguard Worker return bc_lex_verr(l, BC_ERROR_EXEC_STRING_LEN, BC_MAX_STRING);
2752*cf5a6c84SAndroid Build Coastguard Worker
2753*cf5a6c84SAndroid Build Coastguard Worker bc_vec_string(&l->str, len, l->buf + l->i);
2754*cf5a6c84SAndroid Build Coastguard Worker
2755*cf5a6c84SAndroid Build Coastguard Worker l->i = i + 1;
2756*cf5a6c84SAndroid Build Coastguard Worker l->line += nlines;
2757*cf5a6c84SAndroid Build Coastguard Worker
2758*cf5a6c84SAndroid Build Coastguard Worker return BC_STATUS_SUCCESS;
2759*cf5a6c84SAndroid Build Coastguard Worker }
2760*cf5a6c84SAndroid Build Coastguard Worker
bc_lex_assign(BcLex * l,BcLexType with,BcLexType without)2761*cf5a6c84SAndroid Build Coastguard Worker static void bc_lex_assign(BcLex *l, BcLexType with, BcLexType without) {
2762*cf5a6c84SAndroid Build Coastguard Worker if (l->buf[l->i] == '=') {
2763*cf5a6c84SAndroid Build Coastguard Worker ++l->i;
2764*cf5a6c84SAndroid Build Coastguard Worker l->t = with;
2765*cf5a6c84SAndroid Build Coastguard Worker }
2766*cf5a6c84SAndroid Build Coastguard Worker else l->t = without;
2767*cf5a6c84SAndroid Build Coastguard Worker }
2768*cf5a6c84SAndroid Build Coastguard Worker
bc_lex_token(BcLex * l)2769*cf5a6c84SAndroid Build Coastguard Worker BcStatus bc_lex_token(BcLex *l) {
2770*cf5a6c84SAndroid Build Coastguard Worker
2771*cf5a6c84SAndroid Build Coastguard Worker BcStatus s = BC_STATUS_SUCCESS;
2772*cf5a6c84SAndroid Build Coastguard Worker char c = l->buf[l->i++], c2;
2773*cf5a6c84SAndroid Build Coastguard Worker
2774*cf5a6c84SAndroid Build Coastguard Worker // This is the workhorse of the lexer.
2775*cf5a6c84SAndroid Build Coastguard Worker switch (c) {
2776*cf5a6c84SAndroid Build Coastguard Worker
2777*cf5a6c84SAndroid Build Coastguard Worker case '\0':
2778*cf5a6c84SAndroid Build Coastguard Worker case '\n':
2779*cf5a6c84SAndroid Build Coastguard Worker {
2780*cf5a6c84SAndroid Build Coastguard Worker l->t = !c ? BC_LEX_EOF : BC_LEX_NLINE;
2781*cf5a6c84SAndroid Build Coastguard Worker break;
2782*cf5a6c84SAndroid Build Coastguard Worker }
2783*cf5a6c84SAndroid Build Coastguard Worker
2784*cf5a6c84SAndroid Build Coastguard Worker case '\t':
2785*cf5a6c84SAndroid Build Coastguard Worker case '\v':
2786*cf5a6c84SAndroid Build Coastguard Worker case '\f':
2787*cf5a6c84SAndroid Build Coastguard Worker case '\r':
2788*cf5a6c84SAndroid Build Coastguard Worker case ' ':
2789*cf5a6c84SAndroid Build Coastguard Worker {
2790*cf5a6c84SAndroid Build Coastguard Worker bc_lex_whitespace(l);
2791*cf5a6c84SAndroid Build Coastguard Worker break;
2792*cf5a6c84SAndroid Build Coastguard Worker }
2793*cf5a6c84SAndroid Build Coastguard Worker
2794*cf5a6c84SAndroid Build Coastguard Worker case '!':
2795*cf5a6c84SAndroid Build Coastguard Worker {
2796*cf5a6c84SAndroid Build Coastguard Worker bc_lex_assign(l, BC_LEX_OP_REL_NE, BC_LEX_OP_BOOL_NOT);
2797*cf5a6c84SAndroid Build Coastguard Worker
2798*cf5a6c84SAndroid Build Coastguard Worker if (l->t == BC_LEX_OP_BOOL_NOT) {
2799*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_vposixErr(l, BC_ERROR_POSIX_BOOL, "!");
2800*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
2801*cf5a6c84SAndroid Build Coastguard Worker }
2802*cf5a6c84SAndroid Build Coastguard Worker
2803*cf5a6c84SAndroid Build Coastguard Worker break;
2804*cf5a6c84SAndroid Build Coastguard Worker }
2805*cf5a6c84SAndroid Build Coastguard Worker
2806*cf5a6c84SAndroid Build Coastguard Worker case '"':
2807*cf5a6c84SAndroid Build Coastguard Worker {
2808*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_string(l);
2809*cf5a6c84SAndroid Build Coastguard Worker break;
2810*cf5a6c84SAndroid Build Coastguard Worker }
2811*cf5a6c84SAndroid Build Coastguard Worker
2812*cf5a6c84SAndroid Build Coastguard Worker case '#':
2813*cf5a6c84SAndroid Build Coastguard Worker {
2814*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_posixErr(l, BC_ERROR_POSIX_COMMENT);
2815*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
2816*cf5a6c84SAndroid Build Coastguard Worker
2817*cf5a6c84SAndroid Build Coastguard Worker bc_lex_lineComment(l);
2818*cf5a6c84SAndroid Build Coastguard Worker
2819*cf5a6c84SAndroid Build Coastguard Worker break;
2820*cf5a6c84SAndroid Build Coastguard Worker }
2821*cf5a6c84SAndroid Build Coastguard Worker
2822*cf5a6c84SAndroid Build Coastguard Worker case '%':
2823*cf5a6c84SAndroid Build Coastguard Worker {
2824*cf5a6c84SAndroid Build Coastguard Worker bc_lex_assign(l, BC_LEX_OP_ASSIGN_MODULUS, BC_LEX_OP_MODULUS);
2825*cf5a6c84SAndroid Build Coastguard Worker break;
2826*cf5a6c84SAndroid Build Coastguard Worker }
2827*cf5a6c84SAndroid Build Coastguard Worker
2828*cf5a6c84SAndroid Build Coastguard Worker case '&':
2829*cf5a6c84SAndroid Build Coastguard Worker {
2830*cf5a6c84SAndroid Build Coastguard Worker c2 = l->buf[l->i];
2831*cf5a6c84SAndroid Build Coastguard Worker if (c2 == '&') {
2832*cf5a6c84SAndroid Build Coastguard Worker
2833*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_vposixErr(l, BC_ERROR_POSIX_BOOL, "&&");
2834*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
2835*cf5a6c84SAndroid Build Coastguard Worker
2836*cf5a6c84SAndroid Build Coastguard Worker ++l->i;
2837*cf5a6c84SAndroid Build Coastguard Worker l->t = BC_LEX_OP_BOOL_AND;
2838*cf5a6c84SAndroid Build Coastguard Worker }
2839*cf5a6c84SAndroid Build Coastguard Worker else s = bc_lex_invalidChar(l, c);
2840*cf5a6c84SAndroid Build Coastguard Worker
2841*cf5a6c84SAndroid Build Coastguard Worker break;
2842*cf5a6c84SAndroid Build Coastguard Worker }
2843*cf5a6c84SAndroid Build Coastguard Worker case '(':
2844*cf5a6c84SAndroid Build Coastguard Worker case ')':
2845*cf5a6c84SAndroid Build Coastguard Worker {
2846*cf5a6c84SAndroid Build Coastguard Worker l->t = (BcLexType) (c - '(' + BC_LEX_LPAREN);
2847*cf5a6c84SAndroid Build Coastguard Worker break;
2848*cf5a6c84SAndroid Build Coastguard Worker }
2849*cf5a6c84SAndroid Build Coastguard Worker
2850*cf5a6c84SAndroid Build Coastguard Worker case '*':
2851*cf5a6c84SAndroid Build Coastguard Worker {
2852*cf5a6c84SAndroid Build Coastguard Worker bc_lex_assign(l, BC_LEX_OP_ASSIGN_MULTIPLY, BC_LEX_OP_MULTIPLY);
2853*cf5a6c84SAndroid Build Coastguard Worker break;
2854*cf5a6c84SAndroid Build Coastguard Worker }
2855*cf5a6c84SAndroid Build Coastguard Worker
2856*cf5a6c84SAndroid Build Coastguard Worker case '+':
2857*cf5a6c84SAndroid Build Coastguard Worker {
2858*cf5a6c84SAndroid Build Coastguard Worker c2 = l->buf[l->i];
2859*cf5a6c84SAndroid Build Coastguard Worker if (c2 == '+') {
2860*cf5a6c84SAndroid Build Coastguard Worker ++l->i;
2861*cf5a6c84SAndroid Build Coastguard Worker l->t = BC_LEX_OP_INC;
2862*cf5a6c84SAndroid Build Coastguard Worker }
2863*cf5a6c84SAndroid Build Coastguard Worker else bc_lex_assign(l, BC_LEX_OP_ASSIGN_PLUS, BC_LEX_OP_PLUS);
2864*cf5a6c84SAndroid Build Coastguard Worker break;
2865*cf5a6c84SAndroid Build Coastguard Worker }
2866*cf5a6c84SAndroid Build Coastguard Worker
2867*cf5a6c84SAndroid Build Coastguard Worker case ',':
2868*cf5a6c84SAndroid Build Coastguard Worker {
2869*cf5a6c84SAndroid Build Coastguard Worker l->t = BC_LEX_COMMA;
2870*cf5a6c84SAndroid Build Coastguard Worker break;
2871*cf5a6c84SAndroid Build Coastguard Worker }
2872*cf5a6c84SAndroid Build Coastguard Worker
2873*cf5a6c84SAndroid Build Coastguard Worker case '-':
2874*cf5a6c84SAndroid Build Coastguard Worker {
2875*cf5a6c84SAndroid Build Coastguard Worker c2 = l->buf[l->i];
2876*cf5a6c84SAndroid Build Coastguard Worker if (c2 == '-') {
2877*cf5a6c84SAndroid Build Coastguard Worker ++l->i;
2878*cf5a6c84SAndroid Build Coastguard Worker l->t = BC_LEX_OP_DEC;
2879*cf5a6c84SAndroid Build Coastguard Worker }
2880*cf5a6c84SAndroid Build Coastguard Worker else bc_lex_assign(l, BC_LEX_OP_ASSIGN_MINUS, BC_LEX_OP_MINUS);
2881*cf5a6c84SAndroid Build Coastguard Worker break;
2882*cf5a6c84SAndroid Build Coastguard Worker }
2883*cf5a6c84SAndroid Build Coastguard Worker
2884*cf5a6c84SAndroid Build Coastguard Worker case '.':
2885*cf5a6c84SAndroid Build Coastguard Worker {
2886*cf5a6c84SAndroid Build Coastguard Worker c2 = l->buf[l->i];
2887*cf5a6c84SAndroid Build Coastguard Worker if (BC_LEX_NUM_CHAR(c2, 'Z', 1)) s = bc_lex_number(l, c);
2888*cf5a6c84SAndroid Build Coastguard Worker else {
2889*cf5a6c84SAndroid Build Coastguard Worker l->t = BC_LEX_KEY_LAST;
2890*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_posixErr(l, BC_ERROR_POSIX_DOT);
2891*cf5a6c84SAndroid Build Coastguard Worker }
2892*cf5a6c84SAndroid Build Coastguard Worker break;
2893*cf5a6c84SAndroid Build Coastguard Worker }
2894*cf5a6c84SAndroid Build Coastguard Worker
2895*cf5a6c84SAndroid Build Coastguard Worker case '/':
2896*cf5a6c84SAndroid Build Coastguard Worker {
2897*cf5a6c84SAndroid Build Coastguard Worker c2 = l->buf[l->i];
2898*cf5a6c84SAndroid Build Coastguard Worker if (c2 =='*') s = bc_lex_comment(l);
2899*cf5a6c84SAndroid Build Coastguard Worker else bc_lex_assign(l, BC_LEX_OP_ASSIGN_DIVIDE, BC_LEX_OP_DIVIDE);
2900*cf5a6c84SAndroid Build Coastguard Worker break;
2901*cf5a6c84SAndroid Build Coastguard Worker }
2902*cf5a6c84SAndroid Build Coastguard Worker
2903*cf5a6c84SAndroid Build Coastguard Worker case '0':
2904*cf5a6c84SAndroid Build Coastguard Worker case '1':
2905*cf5a6c84SAndroid Build Coastguard Worker case '2':
2906*cf5a6c84SAndroid Build Coastguard Worker case '3':
2907*cf5a6c84SAndroid Build Coastguard Worker case '4':
2908*cf5a6c84SAndroid Build Coastguard Worker case '5':
2909*cf5a6c84SAndroid Build Coastguard Worker case '6':
2910*cf5a6c84SAndroid Build Coastguard Worker case '7':
2911*cf5a6c84SAndroid Build Coastguard Worker case '8':
2912*cf5a6c84SAndroid Build Coastguard Worker case '9':
2913*cf5a6c84SAndroid Build Coastguard Worker case 'A':
2914*cf5a6c84SAndroid Build Coastguard Worker case 'B':
2915*cf5a6c84SAndroid Build Coastguard Worker case 'C':
2916*cf5a6c84SAndroid Build Coastguard Worker case 'D':
2917*cf5a6c84SAndroid Build Coastguard Worker case 'E':
2918*cf5a6c84SAndroid Build Coastguard Worker case 'F':
2919*cf5a6c84SAndroid Build Coastguard Worker // Apparently, GNU bc (and maybe others) allows any uppercase letter as a
2920*cf5a6c84SAndroid Build Coastguard Worker // number. When single digits, they act like the ones above. When multi-
2921*cf5a6c84SAndroid Build Coastguard Worker // digit, any letter above the input base is automatically set to the
2922*cf5a6c84SAndroid Build Coastguard Worker // biggest allowable digit in the input base.
2923*cf5a6c84SAndroid Build Coastguard Worker case 'G':
2924*cf5a6c84SAndroid Build Coastguard Worker case 'H':
2925*cf5a6c84SAndroid Build Coastguard Worker case 'I':
2926*cf5a6c84SAndroid Build Coastguard Worker case 'J':
2927*cf5a6c84SAndroid Build Coastguard Worker case 'K':
2928*cf5a6c84SAndroid Build Coastguard Worker case 'L':
2929*cf5a6c84SAndroid Build Coastguard Worker case 'M':
2930*cf5a6c84SAndroid Build Coastguard Worker case 'N':
2931*cf5a6c84SAndroid Build Coastguard Worker case 'O':
2932*cf5a6c84SAndroid Build Coastguard Worker case 'P':
2933*cf5a6c84SAndroid Build Coastguard Worker case 'Q':
2934*cf5a6c84SAndroid Build Coastguard Worker case 'R':
2935*cf5a6c84SAndroid Build Coastguard Worker case 'S':
2936*cf5a6c84SAndroid Build Coastguard Worker case 'T':
2937*cf5a6c84SAndroid Build Coastguard Worker case 'U':
2938*cf5a6c84SAndroid Build Coastguard Worker case 'V':
2939*cf5a6c84SAndroid Build Coastguard Worker case 'W':
2940*cf5a6c84SAndroid Build Coastguard Worker case 'X':
2941*cf5a6c84SAndroid Build Coastguard Worker case 'Y':
2942*cf5a6c84SAndroid Build Coastguard Worker case 'Z':
2943*cf5a6c84SAndroid Build Coastguard Worker {
2944*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_number(l, c);
2945*cf5a6c84SAndroid Build Coastguard Worker break;
2946*cf5a6c84SAndroid Build Coastguard Worker }
2947*cf5a6c84SAndroid Build Coastguard Worker
2948*cf5a6c84SAndroid Build Coastguard Worker case ';':
2949*cf5a6c84SAndroid Build Coastguard Worker {
2950*cf5a6c84SAndroid Build Coastguard Worker l->t = BC_LEX_SCOLON;
2951*cf5a6c84SAndroid Build Coastguard Worker break;
2952*cf5a6c84SAndroid Build Coastguard Worker }
2953*cf5a6c84SAndroid Build Coastguard Worker
2954*cf5a6c84SAndroid Build Coastguard Worker case '<':
2955*cf5a6c84SAndroid Build Coastguard Worker {
2956*cf5a6c84SAndroid Build Coastguard Worker bc_lex_assign(l, BC_LEX_OP_REL_LE, BC_LEX_OP_REL_LT);
2957*cf5a6c84SAndroid Build Coastguard Worker break;
2958*cf5a6c84SAndroid Build Coastguard Worker }
2959*cf5a6c84SAndroid Build Coastguard Worker
2960*cf5a6c84SAndroid Build Coastguard Worker case '=':
2961*cf5a6c84SAndroid Build Coastguard Worker {
2962*cf5a6c84SAndroid Build Coastguard Worker bc_lex_assign(l, BC_LEX_OP_REL_EQ, BC_LEX_OP_ASSIGN);
2963*cf5a6c84SAndroid Build Coastguard Worker break;
2964*cf5a6c84SAndroid Build Coastguard Worker }
2965*cf5a6c84SAndroid Build Coastguard Worker
2966*cf5a6c84SAndroid Build Coastguard Worker case '>':
2967*cf5a6c84SAndroid Build Coastguard Worker {
2968*cf5a6c84SAndroid Build Coastguard Worker bc_lex_assign(l, BC_LEX_OP_REL_GE, BC_LEX_OP_REL_GT);
2969*cf5a6c84SAndroid Build Coastguard Worker break;
2970*cf5a6c84SAndroid Build Coastguard Worker }
2971*cf5a6c84SAndroid Build Coastguard Worker
2972*cf5a6c84SAndroid Build Coastguard Worker case '[':
2973*cf5a6c84SAndroid Build Coastguard Worker case ']':
2974*cf5a6c84SAndroid Build Coastguard Worker {
2975*cf5a6c84SAndroid Build Coastguard Worker l->t = (BcLexType) (c - '[' + BC_LEX_LBRACKET);
2976*cf5a6c84SAndroid Build Coastguard Worker break;
2977*cf5a6c84SAndroid Build Coastguard Worker }
2978*cf5a6c84SAndroid Build Coastguard Worker
2979*cf5a6c84SAndroid Build Coastguard Worker case '\\':
2980*cf5a6c84SAndroid Build Coastguard Worker {
2981*cf5a6c84SAndroid Build Coastguard Worker if (l->buf[l->i] == '\n') {
2982*cf5a6c84SAndroid Build Coastguard Worker l->t = BC_LEX_WHITESPACE;
2983*cf5a6c84SAndroid Build Coastguard Worker ++l->i;
2984*cf5a6c84SAndroid Build Coastguard Worker }
2985*cf5a6c84SAndroid Build Coastguard Worker else s = bc_lex_invalidChar(l, c);
2986*cf5a6c84SAndroid Build Coastguard Worker break;
2987*cf5a6c84SAndroid Build Coastguard Worker }
2988*cf5a6c84SAndroid Build Coastguard Worker
2989*cf5a6c84SAndroid Build Coastguard Worker case '^':
2990*cf5a6c84SAndroid Build Coastguard Worker {
2991*cf5a6c84SAndroid Build Coastguard Worker bc_lex_assign(l, BC_LEX_OP_ASSIGN_POWER, BC_LEX_OP_POWER);
2992*cf5a6c84SAndroid Build Coastguard Worker break;
2993*cf5a6c84SAndroid Build Coastguard Worker }
2994*cf5a6c84SAndroid Build Coastguard Worker
2995*cf5a6c84SAndroid Build Coastguard Worker case 'a':
2996*cf5a6c84SAndroid Build Coastguard Worker case 'b':
2997*cf5a6c84SAndroid Build Coastguard Worker case 'c':
2998*cf5a6c84SAndroid Build Coastguard Worker case 'd':
2999*cf5a6c84SAndroid Build Coastguard Worker case 'e':
3000*cf5a6c84SAndroid Build Coastguard Worker case 'f':
3001*cf5a6c84SAndroid Build Coastguard Worker case 'g':
3002*cf5a6c84SAndroid Build Coastguard Worker case 'h':
3003*cf5a6c84SAndroid Build Coastguard Worker case 'i':
3004*cf5a6c84SAndroid Build Coastguard Worker case 'j':
3005*cf5a6c84SAndroid Build Coastguard Worker case 'k':
3006*cf5a6c84SAndroid Build Coastguard Worker case 'l':
3007*cf5a6c84SAndroid Build Coastguard Worker case 'm':
3008*cf5a6c84SAndroid Build Coastguard Worker case 'n':
3009*cf5a6c84SAndroid Build Coastguard Worker case 'o':
3010*cf5a6c84SAndroid Build Coastguard Worker case 'p':
3011*cf5a6c84SAndroid Build Coastguard Worker case 'q':
3012*cf5a6c84SAndroid Build Coastguard Worker case 'r':
3013*cf5a6c84SAndroid Build Coastguard Worker case 's':
3014*cf5a6c84SAndroid Build Coastguard Worker case 't':
3015*cf5a6c84SAndroid Build Coastguard Worker case 'u':
3016*cf5a6c84SAndroid Build Coastguard Worker case 'v':
3017*cf5a6c84SAndroid Build Coastguard Worker case 'w':
3018*cf5a6c84SAndroid Build Coastguard Worker case 'x':
3019*cf5a6c84SAndroid Build Coastguard Worker case 'y':
3020*cf5a6c84SAndroid Build Coastguard Worker case 'z':
3021*cf5a6c84SAndroid Build Coastguard Worker {
3022*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_identifier(l);
3023*cf5a6c84SAndroid Build Coastguard Worker break;
3024*cf5a6c84SAndroid Build Coastguard Worker }
3025*cf5a6c84SAndroid Build Coastguard Worker
3026*cf5a6c84SAndroid Build Coastguard Worker case '{':
3027*cf5a6c84SAndroid Build Coastguard Worker case '}':
3028*cf5a6c84SAndroid Build Coastguard Worker {
3029*cf5a6c84SAndroid Build Coastguard Worker l->t = (BcLexType) (c - '{' + BC_LEX_LBRACE);
3030*cf5a6c84SAndroid Build Coastguard Worker break;
3031*cf5a6c84SAndroid Build Coastguard Worker }
3032*cf5a6c84SAndroid Build Coastguard Worker
3033*cf5a6c84SAndroid Build Coastguard Worker case '|':
3034*cf5a6c84SAndroid Build Coastguard Worker {
3035*cf5a6c84SAndroid Build Coastguard Worker c2 = l->buf[l->i];
3036*cf5a6c84SAndroid Build Coastguard Worker
3037*cf5a6c84SAndroid Build Coastguard Worker if (c2 == '|') {
3038*cf5a6c84SAndroid Build Coastguard Worker
3039*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_vposixErr(l, BC_ERROR_POSIX_BOOL, "||");
3040*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
3041*cf5a6c84SAndroid Build Coastguard Worker
3042*cf5a6c84SAndroid Build Coastguard Worker ++l->i;
3043*cf5a6c84SAndroid Build Coastguard Worker l->t = BC_LEX_OP_BOOL_OR;
3044*cf5a6c84SAndroid Build Coastguard Worker }
3045*cf5a6c84SAndroid Build Coastguard Worker else s = bc_lex_invalidChar(l, c);
3046*cf5a6c84SAndroid Build Coastguard Worker
3047*cf5a6c84SAndroid Build Coastguard Worker break;
3048*cf5a6c84SAndroid Build Coastguard Worker }
3049*cf5a6c84SAndroid Build Coastguard Worker
3050*cf5a6c84SAndroid Build Coastguard Worker default:
3051*cf5a6c84SAndroid Build Coastguard Worker {
3052*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_invalidChar(l, c);
3053*cf5a6c84SAndroid Build Coastguard Worker break;
3054*cf5a6c84SAndroid Build Coastguard Worker }
3055*cf5a6c84SAndroid Build Coastguard Worker }
3056*cf5a6c84SAndroid Build Coastguard Worker
3057*cf5a6c84SAndroid Build Coastguard Worker return s;
3058*cf5a6c84SAndroid Build Coastguard Worker }
3059*cf5a6c84SAndroid Build Coastguard Worker
bc_parse_updateFunc(BcParse * p,size_t fidx)3060*cf5a6c84SAndroid Build Coastguard Worker void bc_parse_updateFunc(BcParse *p, size_t fidx) {
3061*cf5a6c84SAndroid Build Coastguard Worker p->fidx = fidx;
3062*cf5a6c84SAndroid Build Coastguard Worker p->func = bc_vec_item(&p->prog->fns, fidx);
3063*cf5a6c84SAndroid Build Coastguard Worker }
3064*cf5a6c84SAndroid Build Coastguard Worker
bc_parse_pushName(BcParse * p,char * name)3065*cf5a6c84SAndroid Build Coastguard Worker void bc_parse_pushName(BcParse *p, char *name) {
3066*cf5a6c84SAndroid Build Coastguard Worker bc_vec_npush(&p->func->code, strlen(name), name);
3067*cf5a6c84SAndroid Build Coastguard Worker bc_parse_push(p, UCHAR_MAX);
3068*cf5a6c84SAndroid Build Coastguard Worker }
3069*cf5a6c84SAndroid Build Coastguard Worker
bc_parse_pushIndex(BcParse * p,size_t idx)3070*cf5a6c84SAndroid Build Coastguard Worker void bc_parse_pushIndex(BcParse *p, size_t idx) {
3071*cf5a6c84SAndroid Build Coastguard Worker bc_vec_pushIndex(&p->func->code, idx);
3072*cf5a6c84SAndroid Build Coastguard Worker }
3073*cf5a6c84SAndroid Build Coastguard Worker
bc_parse_addId(BcParse * p,char inst)3074*cf5a6c84SAndroid Build Coastguard Worker void bc_parse_addId(BcParse *p, char inst) {
3075*cf5a6c84SAndroid Build Coastguard Worker
3076*cf5a6c84SAndroid Build Coastguard Worker BcFunc *f = p->func;
3077*cf5a6c84SAndroid Build Coastguard Worker BcVec *v = inst == BC_INST_NUM ? &f->consts : &f->strs;
3078*cf5a6c84SAndroid Build Coastguard Worker size_t idx = v->len;
3079*cf5a6c84SAndroid Build Coastguard Worker char *str = xstrdup(p->l.str.v);
3080*cf5a6c84SAndroid Build Coastguard Worker
3081*cf5a6c84SAndroid Build Coastguard Worker bc_vec_push(v, &str);
3082*cf5a6c84SAndroid Build Coastguard Worker bc_parse_updateFunc(p, p->fidx);
3083*cf5a6c84SAndroid Build Coastguard Worker bc_parse_push(p, inst);
3084*cf5a6c84SAndroid Build Coastguard Worker bc_parse_pushIndex(p, idx);
3085*cf5a6c84SAndroid Build Coastguard Worker }
3086*cf5a6c84SAndroid Build Coastguard Worker
bc_parse_text(BcParse * p,char * text)3087*cf5a6c84SAndroid Build Coastguard Worker BcStatus bc_parse_text(BcParse *p, char *text) {
3088*cf5a6c84SAndroid Build Coastguard Worker // Make sure the pointer isn't invalidated.
3089*cf5a6c84SAndroid Build Coastguard Worker p->func = bc_vec_item(&p->prog->fns, p->fidx);
3090*cf5a6c84SAndroid Build Coastguard Worker return bc_lex_text(&p->l, text);
3091*cf5a6c84SAndroid Build Coastguard Worker }
3092*cf5a6c84SAndroid Build Coastguard Worker
bc_parse_reset(BcParse * p,BcStatus s)3093*cf5a6c84SAndroid Build Coastguard Worker BcStatus bc_parse_reset(BcParse *p, BcStatus s) {
3094*cf5a6c84SAndroid Build Coastguard Worker
3095*cf5a6c84SAndroid Build Coastguard Worker if (p->fidx != BC_PROG_MAIN) {
3096*cf5a6c84SAndroid Build Coastguard Worker bc_func_reset(p->func);
3097*cf5a6c84SAndroid Build Coastguard Worker bc_parse_updateFunc(p, BC_PROG_MAIN);
3098*cf5a6c84SAndroid Build Coastguard Worker }
3099*cf5a6c84SAndroid Build Coastguard Worker
3100*cf5a6c84SAndroid Build Coastguard Worker p->l.i = p->l.len;
3101*cf5a6c84SAndroid Build Coastguard Worker p->l.t = BC_LEX_EOF;
3102*cf5a6c84SAndroid Build Coastguard Worker p->auto_part = 0;
3103*cf5a6c84SAndroid Build Coastguard Worker
3104*cf5a6c84SAndroid Build Coastguard Worker bc_vec_npop(&p->flags, p->flags.len - 1);
3105*cf5a6c84SAndroid Build Coastguard Worker bc_vec_npop(&p->exits, p->exits.len);
3106*cf5a6c84SAndroid Build Coastguard Worker bc_vec_npop(&p->conds, p->conds.len);
3107*cf5a6c84SAndroid Build Coastguard Worker bc_vec_npop(&p->ops, p->ops.len);
3108*cf5a6c84SAndroid Build Coastguard Worker
3109*cf5a6c84SAndroid Build Coastguard Worker return bc_program_reset(p->prog, s);
3110*cf5a6c84SAndroid Build Coastguard Worker }
3111*cf5a6c84SAndroid Build Coastguard Worker
bc_parse_free(BcParse * p)3112*cf5a6c84SAndroid Build Coastguard Worker void bc_parse_free(BcParse *p) {
3113*cf5a6c84SAndroid Build Coastguard Worker bc_vec_free(&p->flags);
3114*cf5a6c84SAndroid Build Coastguard Worker bc_vec_free(&p->exits);
3115*cf5a6c84SAndroid Build Coastguard Worker bc_vec_free(&p->conds);
3116*cf5a6c84SAndroid Build Coastguard Worker bc_vec_free(&p->ops);
3117*cf5a6c84SAndroid Build Coastguard Worker bc_vec_free(&p->l.str);
3118*cf5a6c84SAndroid Build Coastguard Worker }
3119*cf5a6c84SAndroid Build Coastguard Worker
bc_parse_init(BcParse * p,BcProgram * prog,size_t func)3120*cf5a6c84SAndroid Build Coastguard Worker void bc_parse_init(BcParse *p, BcProgram *prog, size_t func)
3121*cf5a6c84SAndroid Build Coastguard Worker {
3122*cf5a6c84SAndroid Build Coastguard Worker uint16_t flag = 0;
3123*cf5a6c84SAndroid Build Coastguard Worker bc_vec_init(&p->flags, sizeof(uint16_t), NULL);
3124*cf5a6c84SAndroid Build Coastguard Worker bc_vec_push(&p->flags, &flag);
3125*cf5a6c84SAndroid Build Coastguard Worker bc_vec_init(&p->exits, sizeof(BcInstPtr), NULL);
3126*cf5a6c84SAndroid Build Coastguard Worker bc_vec_init(&p->conds, sizeof(size_t), NULL);
3127*cf5a6c84SAndroid Build Coastguard Worker bc_vec_init(&p->ops, sizeof(BcLexType), NULL);
3128*cf5a6c84SAndroid Build Coastguard Worker
3129*cf5a6c84SAndroid Build Coastguard Worker bc_lex_init(&p->l);
3130*cf5a6c84SAndroid Build Coastguard Worker
3131*cf5a6c84SAndroid Build Coastguard Worker p->prog = prog;
3132*cf5a6c84SAndroid Build Coastguard Worker p->auto_part = 0;
3133*cf5a6c84SAndroid Build Coastguard Worker bc_parse_updateFunc(p, func);
3134*cf5a6c84SAndroid Build Coastguard Worker }
3135*cf5a6c84SAndroid Build Coastguard Worker
3136*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_parse_else(BcParse *p);
3137*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_parse_stmt(BcParse *p);
3138*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_parse_expr_err(BcParse *p, uint8_t flags, BcParseNext next);
3139*cf5a6c84SAndroid Build Coastguard Worker
bc_parse_inst_isLeaf(BcInst t)3140*cf5a6c84SAndroid Build Coastguard Worker static int bc_parse_inst_isLeaf(BcInst t) {
3141*cf5a6c84SAndroid Build Coastguard Worker return (t >= BC_INST_NUM && t <= BC_INST_ABS) ||
3142*cf5a6c84SAndroid Build Coastguard Worker t == BC_INST_INC_POST || t == BC_INST_DEC_POST;
3143*cf5a6c84SAndroid Build Coastguard Worker }
3144*cf5a6c84SAndroid Build Coastguard Worker
bc_parse_isDelimiter(BcParse * p)3145*cf5a6c84SAndroid Build Coastguard Worker static int bc_parse_isDelimiter(BcParse *p) {
3146*cf5a6c84SAndroid Build Coastguard Worker
3147*cf5a6c84SAndroid Build Coastguard Worker BcLexType t = p->l.t;
3148*cf5a6c84SAndroid Build Coastguard Worker int good = 0;
3149*cf5a6c84SAndroid Build Coastguard Worker
3150*cf5a6c84SAndroid Build Coastguard Worker if (BC_PARSE_DELIMITER(t)) return 1;
3151*cf5a6c84SAndroid Build Coastguard Worker
3152*cf5a6c84SAndroid Build Coastguard Worker if (t == BC_LEX_KEY_ELSE) {
3153*cf5a6c84SAndroid Build Coastguard Worker
3154*cf5a6c84SAndroid Build Coastguard Worker size_t i;
3155*cf5a6c84SAndroid Build Coastguard Worker uint16_t *fptr = NULL, flags = BC_PARSE_FLAG_ELSE;
3156*cf5a6c84SAndroid Build Coastguard Worker
3157*cf5a6c84SAndroid Build Coastguard Worker for (i = 0; i < p->flags.len && BC_PARSE_BLOCK_STMT(flags); ++i) {
3158*cf5a6c84SAndroid Build Coastguard Worker fptr = bc_vec_item_rev(&p->flags, i);
3159*cf5a6c84SAndroid Build Coastguard Worker flags = *fptr;
3160*cf5a6c84SAndroid Build Coastguard Worker if ((flags & BC_PARSE_FLAG_BRACE) && p->l.last != BC_LEX_RBRACE)
3161*cf5a6c84SAndroid Build Coastguard Worker return 0;
3162*cf5a6c84SAndroid Build Coastguard Worker }
3163*cf5a6c84SAndroid Build Coastguard Worker
3164*cf5a6c84SAndroid Build Coastguard Worker good = ((flags & BC_PARSE_FLAG_IF) != 0);
3165*cf5a6c84SAndroid Build Coastguard Worker }
3166*cf5a6c84SAndroid Build Coastguard Worker else if (t == BC_LEX_RBRACE) {
3167*cf5a6c84SAndroid Build Coastguard Worker
3168*cf5a6c84SAndroid Build Coastguard Worker size_t i;
3169*cf5a6c84SAndroid Build Coastguard Worker
3170*cf5a6c84SAndroid Build Coastguard Worker for (i = 0; !good && i < p->flags.len; ++i) {
3171*cf5a6c84SAndroid Build Coastguard Worker uint16_t *fptr = bc_vec_item_rev(&p->flags, i);
3172*cf5a6c84SAndroid Build Coastguard Worker good = (((*fptr) & BC_PARSE_FLAG_BRACE) != 0);
3173*cf5a6c84SAndroid Build Coastguard Worker }
3174*cf5a6c84SAndroid Build Coastguard Worker }
3175*cf5a6c84SAndroid Build Coastguard Worker
3176*cf5a6c84SAndroid Build Coastguard Worker return good;
3177*cf5a6c84SAndroid Build Coastguard Worker }
3178*cf5a6c84SAndroid Build Coastguard Worker
bc_parse_setLabel(BcParse * p)3179*cf5a6c84SAndroid Build Coastguard Worker static void bc_parse_setLabel(BcParse *p) {
3180*cf5a6c84SAndroid Build Coastguard Worker
3181*cf5a6c84SAndroid Build Coastguard Worker BcFunc *func = p->func;
3182*cf5a6c84SAndroid Build Coastguard Worker BcInstPtr *ip = bc_vec_top(&p->exits);
3183*cf5a6c84SAndroid Build Coastguard Worker size_t *label;
3184*cf5a6c84SAndroid Build Coastguard Worker
3185*cf5a6c84SAndroid Build Coastguard Worker label = bc_vec_item(&func->labels, ip->idx);
3186*cf5a6c84SAndroid Build Coastguard Worker *label = func->code.len;
3187*cf5a6c84SAndroid Build Coastguard Worker
3188*cf5a6c84SAndroid Build Coastguard Worker bc_vec_pop(&p->exits);
3189*cf5a6c84SAndroid Build Coastguard Worker }
3190*cf5a6c84SAndroid Build Coastguard Worker
bc_parse_createLabel(BcParse * p,size_t idx)3191*cf5a6c84SAndroid Build Coastguard Worker static void bc_parse_createLabel(BcParse *p, size_t idx) {
3192*cf5a6c84SAndroid Build Coastguard Worker bc_vec_push(&p->func->labels, &idx);
3193*cf5a6c84SAndroid Build Coastguard Worker }
3194*cf5a6c84SAndroid Build Coastguard Worker
bc_parse_createCondLabel(BcParse * p,size_t idx)3195*cf5a6c84SAndroid Build Coastguard Worker static void bc_parse_createCondLabel(BcParse *p, size_t idx) {
3196*cf5a6c84SAndroid Build Coastguard Worker bc_parse_createLabel(p, p->func->code.len);
3197*cf5a6c84SAndroid Build Coastguard Worker bc_vec_push(&p->conds, &idx);
3198*cf5a6c84SAndroid Build Coastguard Worker }
3199*cf5a6c84SAndroid Build Coastguard Worker
bc_parse_createExitLabel(BcParse * p,size_t idx,int loop)3200*cf5a6c84SAndroid Build Coastguard Worker static void bc_parse_createExitLabel(BcParse *p, size_t idx, int loop) {
3201*cf5a6c84SAndroid Build Coastguard Worker
3202*cf5a6c84SAndroid Build Coastguard Worker BcInstPtr ip;
3203*cf5a6c84SAndroid Build Coastguard Worker
3204*cf5a6c84SAndroid Build Coastguard Worker ip.func = loop;
3205*cf5a6c84SAndroid Build Coastguard Worker ip.idx = idx;
3206*cf5a6c84SAndroid Build Coastguard Worker ip.len = 0;
3207*cf5a6c84SAndroid Build Coastguard Worker
3208*cf5a6c84SAndroid Build Coastguard Worker bc_vec_push(&p->exits, &ip);
3209*cf5a6c84SAndroid Build Coastguard Worker bc_parse_createLabel(p, SIZE_MAX);
3210*cf5a6c84SAndroid Build Coastguard Worker }
3211*cf5a6c84SAndroid Build Coastguard Worker
bc_parse_addFunc(BcParse * p,char * name)3212*cf5a6c84SAndroid Build Coastguard Worker static size_t bc_parse_addFunc(BcParse *p, char *name) {
3213*cf5a6c84SAndroid Build Coastguard Worker
3214*cf5a6c84SAndroid Build Coastguard Worker size_t idx = bc_program_insertFunc(p->prog, name);
3215*cf5a6c84SAndroid Build Coastguard Worker
3216*cf5a6c84SAndroid Build Coastguard Worker // Make sure that this pointer was not invalidated.
3217*cf5a6c84SAndroid Build Coastguard Worker p->func = bc_vec_item(&p->prog->fns, p->fidx);
3218*cf5a6c84SAndroid Build Coastguard Worker
3219*cf5a6c84SAndroid Build Coastguard Worker return idx;
3220*cf5a6c84SAndroid Build Coastguard Worker }
3221*cf5a6c84SAndroid Build Coastguard Worker
bc_parse_operator(BcParse * p,BcLexType type,size_t start,size_t * nexprs)3222*cf5a6c84SAndroid Build Coastguard Worker static void bc_parse_operator(BcParse *p, BcLexType type,
3223*cf5a6c84SAndroid Build Coastguard Worker size_t start, size_t *nexprs)
3224*cf5a6c84SAndroid Build Coastguard Worker {
3225*cf5a6c84SAndroid Build Coastguard Worker BcLexType t;
3226*cf5a6c84SAndroid Build Coastguard Worker char l, r = BC_PARSE_OP_PREC(type);
3227*cf5a6c84SAndroid Build Coastguard Worker char left = BC_PARSE_OP_LEFT(type);
3228*cf5a6c84SAndroid Build Coastguard Worker
3229*cf5a6c84SAndroid Build Coastguard Worker while (p->ops.len > start) {
3230*cf5a6c84SAndroid Build Coastguard Worker
3231*cf5a6c84SAndroid Build Coastguard Worker t = BC_PARSE_TOP_OP(p);
3232*cf5a6c84SAndroid Build Coastguard Worker if (t == BC_LEX_LPAREN) break;
3233*cf5a6c84SAndroid Build Coastguard Worker
3234*cf5a6c84SAndroid Build Coastguard Worker l = BC_PARSE_OP_PREC(t);
3235*cf5a6c84SAndroid Build Coastguard Worker if (l >= r && (l != r || !left)) break;
3236*cf5a6c84SAndroid Build Coastguard Worker
3237*cf5a6c84SAndroid Build Coastguard Worker bc_parse_push(p, BC_PARSE_TOKEN_INST(t));
3238*cf5a6c84SAndroid Build Coastguard Worker bc_vec_pop(&p->ops);
3239*cf5a6c84SAndroid Build Coastguard Worker *nexprs -= !BC_PARSE_OP_PREFIX(t);
3240*cf5a6c84SAndroid Build Coastguard Worker }
3241*cf5a6c84SAndroid Build Coastguard Worker
3242*cf5a6c84SAndroid Build Coastguard Worker bc_vec_push(&p->ops, &type);
3243*cf5a6c84SAndroid Build Coastguard Worker }
3244*cf5a6c84SAndroid Build Coastguard Worker
bc_parse_rightParen(BcParse * p,size_t ops_bgn,size_t * nexs)3245*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_parse_rightParen(BcParse *p, size_t ops_bgn, size_t *nexs) {
3246*cf5a6c84SAndroid Build Coastguard Worker
3247*cf5a6c84SAndroid Build Coastguard Worker BcLexType top;
3248*cf5a6c84SAndroid Build Coastguard Worker
3249*cf5a6c84SAndroid Build Coastguard Worker if (p->ops.len <= ops_bgn) return bc_parse_err(p, BC_ERROR_PARSE_EXPR);
3250*cf5a6c84SAndroid Build Coastguard Worker
3251*cf5a6c84SAndroid Build Coastguard Worker while ((top = BC_PARSE_TOP_OP(p)) != BC_LEX_LPAREN) {
3252*cf5a6c84SAndroid Build Coastguard Worker
3253*cf5a6c84SAndroid Build Coastguard Worker bc_parse_push(p, BC_PARSE_TOKEN_INST(top));
3254*cf5a6c84SAndroid Build Coastguard Worker
3255*cf5a6c84SAndroid Build Coastguard Worker bc_vec_pop(&p->ops);
3256*cf5a6c84SAndroid Build Coastguard Worker *nexs -= !BC_PARSE_OP_PREFIX(top);
3257*cf5a6c84SAndroid Build Coastguard Worker
3258*cf5a6c84SAndroid Build Coastguard Worker if (p->ops.len <= ops_bgn) return bc_parse_err(p, BC_ERROR_PARSE_EXPR);
3259*cf5a6c84SAndroid Build Coastguard Worker }
3260*cf5a6c84SAndroid Build Coastguard Worker
3261*cf5a6c84SAndroid Build Coastguard Worker bc_vec_pop(&p->ops);
3262*cf5a6c84SAndroid Build Coastguard Worker
3263*cf5a6c84SAndroid Build Coastguard Worker return bc_lex_next(&p->l);
3264*cf5a6c84SAndroid Build Coastguard Worker }
3265*cf5a6c84SAndroid Build Coastguard Worker
bc_parse_params(BcParse * p,uint8_t flags)3266*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_parse_params(BcParse *p, uint8_t flags) {
3267*cf5a6c84SAndroid Build Coastguard Worker
3268*cf5a6c84SAndroid Build Coastguard Worker BcStatus s;
3269*cf5a6c84SAndroid Build Coastguard Worker int comma = 0;
3270*cf5a6c84SAndroid Build Coastguard Worker size_t nparams;
3271*cf5a6c84SAndroid Build Coastguard Worker
3272*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
3273*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
3274*cf5a6c84SAndroid Build Coastguard Worker
3275*cf5a6c84SAndroid Build Coastguard Worker for (nparams = 0; p->l.t != BC_LEX_RPAREN; ++nparams) {
3276*cf5a6c84SAndroid Build Coastguard Worker
3277*cf5a6c84SAndroid Build Coastguard Worker flags = (flags & ~(BC_PARSE_PRINT | BC_PARSE_REL)) | BC_PARSE_ARRAY;
3278*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_expr_status(p, flags, bc_parse_next_param);
3279*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
3280*cf5a6c84SAndroid Build Coastguard Worker
3281*cf5a6c84SAndroid Build Coastguard Worker comma = p->l.t == BC_LEX_COMMA;
3282*cf5a6c84SAndroid Build Coastguard Worker if (comma) {
3283*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
3284*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
3285*cf5a6c84SAndroid Build Coastguard Worker }
3286*cf5a6c84SAndroid Build Coastguard Worker }
3287*cf5a6c84SAndroid Build Coastguard Worker
3288*cf5a6c84SAndroid Build Coastguard Worker if (comma) return bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
3289*cf5a6c84SAndroid Build Coastguard Worker bc_parse_push(p, BC_INST_CALL);
3290*cf5a6c84SAndroid Build Coastguard Worker bc_parse_pushIndex(p, nparams);
3291*cf5a6c84SAndroid Build Coastguard Worker
3292*cf5a6c84SAndroid Build Coastguard Worker return BC_STATUS_SUCCESS;
3293*cf5a6c84SAndroid Build Coastguard Worker }
3294*cf5a6c84SAndroid Build Coastguard Worker
bc_parse_call(BcParse * p,char * name,uint8_t flags)3295*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_parse_call(BcParse *p, char *name, uint8_t flags) {
3296*cf5a6c84SAndroid Build Coastguard Worker
3297*cf5a6c84SAndroid Build Coastguard Worker BcStatus s;
3298*cf5a6c84SAndroid Build Coastguard Worker struct str_len id;
3299*cf5a6c84SAndroid Build Coastguard Worker size_t idx;
3300*cf5a6c84SAndroid Build Coastguard Worker
3301*cf5a6c84SAndroid Build Coastguard Worker id.str = name;
3302*cf5a6c84SAndroid Build Coastguard Worker
3303*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_params(p, flags);
3304*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
3305*cf5a6c84SAndroid Build Coastguard Worker
3306*cf5a6c84SAndroid Build Coastguard Worker if (p->l.t != BC_LEX_RPAREN) {
3307*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
3308*cf5a6c84SAndroid Build Coastguard Worker goto err;
3309*cf5a6c84SAndroid Build Coastguard Worker }
3310*cf5a6c84SAndroid Build Coastguard Worker
3311*cf5a6c84SAndroid Build Coastguard Worker idx = bc_map_index(&p->prog->fn_map, &id);
3312*cf5a6c84SAndroid Build Coastguard Worker
3313*cf5a6c84SAndroid Build Coastguard Worker if (idx == SIZE_MAX) {
3314*cf5a6c84SAndroid Build Coastguard Worker bc_parse_addFunc(p, name);
3315*cf5a6c84SAndroid Build Coastguard Worker idx = bc_map_index(&p->prog->fn_map, &id);
3316*cf5a6c84SAndroid Build Coastguard Worker } else free(name);
3317*cf5a6c84SAndroid Build Coastguard Worker
3318*cf5a6c84SAndroid Build Coastguard Worker bc_parse_pushIndex(p,
3319*cf5a6c84SAndroid Build Coastguard Worker ((struct str_len *)bc_vec_item(&p->prog->fn_map, idx))->len);
3320*cf5a6c84SAndroid Build Coastguard Worker
3321*cf5a6c84SAndroid Build Coastguard Worker return bc_lex_next(&p->l);
3322*cf5a6c84SAndroid Build Coastguard Worker
3323*cf5a6c84SAndroid Build Coastguard Worker err:
3324*cf5a6c84SAndroid Build Coastguard Worker free(name);
3325*cf5a6c84SAndroid Build Coastguard Worker return s;
3326*cf5a6c84SAndroid Build Coastguard Worker }
3327*cf5a6c84SAndroid Build Coastguard Worker
bc_parse_name(BcParse * p,BcInst * type,uint8_t flags)3328*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_parse_name(BcParse *p, BcInst *type, uint8_t flags) {
3329*cf5a6c84SAndroid Build Coastguard Worker
3330*cf5a6c84SAndroid Build Coastguard Worker BcStatus s;
3331*cf5a6c84SAndroid Build Coastguard Worker char *name;
3332*cf5a6c84SAndroid Build Coastguard Worker
3333*cf5a6c84SAndroid Build Coastguard Worker name = xstrdup(p->l.str.v);
3334*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
3335*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
3336*cf5a6c84SAndroid Build Coastguard Worker
3337*cf5a6c84SAndroid Build Coastguard Worker if (p->l.t == BC_LEX_LBRACKET) {
3338*cf5a6c84SAndroid Build Coastguard Worker
3339*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
3340*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
3341*cf5a6c84SAndroid Build Coastguard Worker
3342*cf5a6c84SAndroid Build Coastguard Worker if (p->l.t == BC_LEX_RBRACKET) {
3343*cf5a6c84SAndroid Build Coastguard Worker
3344*cf5a6c84SAndroid Build Coastguard Worker if (!(flags & BC_PARSE_ARRAY)) {
3345*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_err(p, BC_ERROR_PARSE_EXPR);
3346*cf5a6c84SAndroid Build Coastguard Worker goto err;
3347*cf5a6c84SAndroid Build Coastguard Worker }
3348*cf5a6c84SAndroid Build Coastguard Worker
3349*cf5a6c84SAndroid Build Coastguard Worker *type = BC_INST_ARRAY;
3350*cf5a6c84SAndroid Build Coastguard Worker }
3351*cf5a6c84SAndroid Build Coastguard Worker else {
3352*cf5a6c84SAndroid Build Coastguard Worker
3353*cf5a6c84SAndroid Build Coastguard Worker *type = BC_INST_ARRAY_ELEM;
3354*cf5a6c84SAndroid Build Coastguard Worker
3355*cf5a6c84SAndroid Build Coastguard Worker flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL);
3356*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_expr_status(p, flags, bc_parse_next_elem);
3357*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
3358*cf5a6c84SAndroid Build Coastguard Worker
3359*cf5a6c84SAndroid Build Coastguard Worker if (p->l.t != BC_LEX_RBRACKET) {
3360*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
3361*cf5a6c84SAndroid Build Coastguard Worker goto err;
3362*cf5a6c84SAndroid Build Coastguard Worker }
3363*cf5a6c84SAndroid Build Coastguard Worker }
3364*cf5a6c84SAndroid Build Coastguard Worker
3365*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
3366*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
3367*cf5a6c84SAndroid Build Coastguard Worker
3368*cf5a6c84SAndroid Build Coastguard Worker bc_parse_push(p, *type);
3369*cf5a6c84SAndroid Build Coastguard Worker bc_parse_pushName(p, name);
3370*cf5a6c84SAndroid Build Coastguard Worker }
3371*cf5a6c84SAndroid Build Coastguard Worker else if (p->l.t == BC_LEX_LPAREN) {
3372*cf5a6c84SAndroid Build Coastguard Worker
3373*cf5a6c84SAndroid Build Coastguard Worker if (flags & BC_PARSE_NOCALL) {
3374*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
3375*cf5a6c84SAndroid Build Coastguard Worker goto err;
3376*cf5a6c84SAndroid Build Coastguard Worker }
3377*cf5a6c84SAndroid Build Coastguard Worker
3378*cf5a6c84SAndroid Build Coastguard Worker *type = BC_INST_CALL;
3379*cf5a6c84SAndroid Build Coastguard Worker
3380*cf5a6c84SAndroid Build Coastguard Worker // Return early because bc_parse_call() frees the name.
3381*cf5a6c84SAndroid Build Coastguard Worker return bc_parse_call(p, name, flags);
3382*cf5a6c84SAndroid Build Coastguard Worker }
3383*cf5a6c84SAndroid Build Coastguard Worker else {
3384*cf5a6c84SAndroid Build Coastguard Worker *type = BC_INST_VAR;
3385*cf5a6c84SAndroid Build Coastguard Worker bc_parse_push(p, BC_INST_VAR);
3386*cf5a6c84SAndroid Build Coastguard Worker bc_parse_pushName(p, name);
3387*cf5a6c84SAndroid Build Coastguard Worker }
3388*cf5a6c84SAndroid Build Coastguard Worker
3389*cf5a6c84SAndroid Build Coastguard Worker err:
3390*cf5a6c84SAndroid Build Coastguard Worker free(name);
3391*cf5a6c84SAndroid Build Coastguard Worker return s;
3392*cf5a6c84SAndroid Build Coastguard Worker }
3393*cf5a6c84SAndroid Build Coastguard Worker
bc_parse_read(BcParse * p)3394*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_parse_read(BcParse *p) {
3395*cf5a6c84SAndroid Build Coastguard Worker
3396*cf5a6c84SAndroid Build Coastguard Worker BcStatus s;
3397*cf5a6c84SAndroid Build Coastguard Worker
3398*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
3399*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
3400*cf5a6c84SAndroid Build Coastguard Worker if (p->l.t != BC_LEX_LPAREN) return bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
3401*cf5a6c84SAndroid Build Coastguard Worker
3402*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
3403*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
3404*cf5a6c84SAndroid Build Coastguard Worker if (p->l.t != BC_LEX_RPAREN) return bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
3405*cf5a6c84SAndroid Build Coastguard Worker
3406*cf5a6c84SAndroid Build Coastguard Worker bc_parse_push(p, BC_INST_READ);
3407*cf5a6c84SAndroid Build Coastguard Worker
3408*cf5a6c84SAndroid Build Coastguard Worker return bc_lex_next(&p->l);
3409*cf5a6c84SAndroid Build Coastguard Worker }
3410*cf5a6c84SAndroid Build Coastguard Worker
bc_parse_builtin(BcParse * p,BcLexType type,uint8_t flags,BcInst * prev)3411*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_parse_builtin(BcParse *p, BcLexType type,
3412*cf5a6c84SAndroid Build Coastguard Worker uint8_t flags, BcInst *prev)
3413*cf5a6c84SAndroid Build Coastguard Worker {
3414*cf5a6c84SAndroid Build Coastguard Worker BcStatus s;
3415*cf5a6c84SAndroid Build Coastguard Worker
3416*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
3417*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
3418*cf5a6c84SAndroid Build Coastguard Worker if (p->l.t != BC_LEX_LPAREN) return bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
3419*cf5a6c84SAndroid Build Coastguard Worker
3420*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
3421*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
3422*cf5a6c84SAndroid Build Coastguard Worker
3423*cf5a6c84SAndroid Build Coastguard Worker flags = (flags & ~(BC_PARSE_PRINT | BC_PARSE_REL));
3424*cf5a6c84SAndroid Build Coastguard Worker if (type == BC_LEX_KEY_LENGTH) flags |= BC_PARSE_ARRAY;
3425*cf5a6c84SAndroid Build Coastguard Worker
3426*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_expr_status(p, flags, bc_parse_next_rel);
3427*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
3428*cf5a6c84SAndroid Build Coastguard Worker
3429*cf5a6c84SAndroid Build Coastguard Worker if (p->l.t != BC_LEX_RPAREN) return bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
3430*cf5a6c84SAndroid Build Coastguard Worker
3431*cf5a6c84SAndroid Build Coastguard Worker *prev = type - BC_LEX_KEY_LENGTH + BC_INST_LENGTH;
3432*cf5a6c84SAndroid Build Coastguard Worker bc_parse_push(p, *prev);
3433*cf5a6c84SAndroid Build Coastguard Worker
3434*cf5a6c84SAndroid Build Coastguard Worker return bc_lex_next(&p->l);
3435*cf5a6c84SAndroid Build Coastguard Worker }
3436*cf5a6c84SAndroid Build Coastguard Worker
bc_parse_scale(BcParse * p,BcInst * type,uint8_t flags)3437*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_parse_scale(BcParse *p, BcInst *type, uint8_t flags) {
3438*cf5a6c84SAndroid Build Coastguard Worker
3439*cf5a6c84SAndroid Build Coastguard Worker BcStatus s;
3440*cf5a6c84SAndroid Build Coastguard Worker
3441*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
3442*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
3443*cf5a6c84SAndroid Build Coastguard Worker
3444*cf5a6c84SAndroid Build Coastguard Worker if (p->l.t != BC_LEX_LPAREN) {
3445*cf5a6c84SAndroid Build Coastguard Worker *type = BC_INST_SCALE;
3446*cf5a6c84SAndroid Build Coastguard Worker bc_parse_push(p, BC_INST_SCALE);
3447*cf5a6c84SAndroid Build Coastguard Worker return BC_STATUS_SUCCESS;
3448*cf5a6c84SAndroid Build Coastguard Worker }
3449*cf5a6c84SAndroid Build Coastguard Worker
3450*cf5a6c84SAndroid Build Coastguard Worker *type = BC_INST_SCALE_FUNC;
3451*cf5a6c84SAndroid Build Coastguard Worker flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL);
3452*cf5a6c84SAndroid Build Coastguard Worker
3453*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
3454*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
3455*cf5a6c84SAndroid Build Coastguard Worker
3456*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_expr_status(p, flags, bc_parse_next_rel);
3457*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
3458*cf5a6c84SAndroid Build Coastguard Worker if (p->l.t != BC_LEX_RPAREN) return bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
3459*cf5a6c84SAndroid Build Coastguard Worker
3460*cf5a6c84SAndroid Build Coastguard Worker bc_parse_push(p, BC_INST_SCALE_FUNC);
3461*cf5a6c84SAndroid Build Coastguard Worker
3462*cf5a6c84SAndroid Build Coastguard Worker return bc_lex_next(&p->l);
3463*cf5a6c84SAndroid Build Coastguard Worker }
3464*cf5a6c84SAndroid Build Coastguard Worker
bc_parse_incdec(BcParse * p,BcInst * prev,size_t * nexs,uint8_t flags)3465*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_parse_incdec(BcParse *p, BcInst *prev,
3466*cf5a6c84SAndroid Build Coastguard Worker size_t *nexs, uint8_t flags)
3467*cf5a6c84SAndroid Build Coastguard Worker {
3468*cf5a6c84SAndroid Build Coastguard Worker BcStatus s;
3469*cf5a6c84SAndroid Build Coastguard Worker BcLexType type;
3470*cf5a6c84SAndroid Build Coastguard Worker char inst;
3471*cf5a6c84SAndroid Build Coastguard Worker BcInst etype = *prev;
3472*cf5a6c84SAndroid Build Coastguard Worker BcLexType last = p->l.last;
3473*cf5a6c84SAndroid Build Coastguard Worker
3474*cf5a6c84SAndroid Build Coastguard Worker if (last == BC_LEX_OP_INC || last == BC_LEX_OP_DEC || last == BC_LEX_RPAREN)
3475*cf5a6c84SAndroid Build Coastguard Worker return s = bc_parse_err(p, BC_ERROR_PARSE_ASSIGN);
3476*cf5a6c84SAndroid Build Coastguard Worker
3477*cf5a6c84SAndroid Build Coastguard Worker if (BC_PARSE_INST_VAR(etype)) {
3478*cf5a6c84SAndroid Build Coastguard Worker *prev = inst = BC_INST_INC_POST + (p->l.t != BC_LEX_OP_INC);
3479*cf5a6c84SAndroid Build Coastguard Worker bc_parse_push(p, inst);
3480*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
3481*cf5a6c84SAndroid Build Coastguard Worker }
3482*cf5a6c84SAndroid Build Coastguard Worker else {
3483*cf5a6c84SAndroid Build Coastguard Worker
3484*cf5a6c84SAndroid Build Coastguard Worker *prev = inst = BC_INST_INC_PRE + (p->l.t != BC_LEX_OP_INC);
3485*cf5a6c84SAndroid Build Coastguard Worker
3486*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
3487*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
3488*cf5a6c84SAndroid Build Coastguard Worker type = p->l.t;
3489*cf5a6c84SAndroid Build Coastguard Worker
3490*cf5a6c84SAndroid Build Coastguard Worker // Because we parse the next part of the expression
3491*cf5a6c84SAndroid Build Coastguard Worker // right here, we need to increment this.
3492*cf5a6c84SAndroid Build Coastguard Worker *nexs = *nexs + 1;
3493*cf5a6c84SAndroid Build Coastguard Worker
3494*cf5a6c84SAndroid Build Coastguard Worker if (type == BC_LEX_NAME)
3495*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_name(p, prev, flags | BC_PARSE_NOCALL);
3496*cf5a6c84SAndroid Build Coastguard Worker else if (type >= BC_LEX_KEY_LAST && type <= BC_LEX_KEY_OBASE) {
3497*cf5a6c84SAndroid Build Coastguard Worker bc_parse_push(p, type - BC_LEX_KEY_LAST + BC_INST_LAST);
3498*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
3499*cf5a6c84SAndroid Build Coastguard Worker }
3500*cf5a6c84SAndroid Build Coastguard Worker else if (type == BC_LEX_KEY_SCALE) {
3501*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
3502*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
3503*cf5a6c84SAndroid Build Coastguard Worker if (p->l.t == BC_LEX_LPAREN) s = bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
3504*cf5a6c84SAndroid Build Coastguard Worker else bc_parse_push(p, BC_INST_SCALE);
3505*cf5a6c84SAndroid Build Coastguard Worker }
3506*cf5a6c84SAndroid Build Coastguard Worker else s = bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
3507*cf5a6c84SAndroid Build Coastguard Worker
3508*cf5a6c84SAndroid Build Coastguard Worker if (!s) bc_parse_push(p, inst);
3509*cf5a6c84SAndroid Build Coastguard Worker }
3510*cf5a6c84SAndroid Build Coastguard Worker
3511*cf5a6c84SAndroid Build Coastguard Worker return s;
3512*cf5a6c84SAndroid Build Coastguard Worker }
3513*cf5a6c84SAndroid Build Coastguard Worker
bc_parse_minus(BcParse * p,BcInst * prev,size_t ops_bgn,int rparen,int bin_last,size_t * nexprs)3514*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_parse_minus(BcParse *p, BcInst *prev, size_t ops_bgn,
3515*cf5a6c84SAndroid Build Coastguard Worker int rparen, int bin_last, size_t *nexprs)
3516*cf5a6c84SAndroid Build Coastguard Worker {
3517*cf5a6c84SAndroid Build Coastguard Worker BcStatus s;
3518*cf5a6c84SAndroid Build Coastguard Worker BcLexType type;
3519*cf5a6c84SAndroid Build Coastguard Worker
3520*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
3521*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
3522*cf5a6c84SAndroid Build Coastguard Worker
3523*cf5a6c84SAndroid Build Coastguard Worker type = BC_PARSE_LEAF(*prev, bin_last, rparen) ? BC_LEX_OP_MINUS : BC_LEX_NEG;
3524*cf5a6c84SAndroid Build Coastguard Worker *prev = BC_PARSE_TOKEN_INST(type);
3525*cf5a6c84SAndroid Build Coastguard Worker
3526*cf5a6c84SAndroid Build Coastguard Worker // We can just push onto the op stack because this is the largest
3527*cf5a6c84SAndroid Build Coastguard Worker // precedence operator that gets pushed. Inc/dec does not.
3528*cf5a6c84SAndroid Build Coastguard Worker if (type != BC_LEX_OP_MINUS) bc_vec_push(&p->ops, &type);
3529*cf5a6c84SAndroid Build Coastguard Worker else bc_parse_operator(p, type, ops_bgn, nexprs);
3530*cf5a6c84SAndroid Build Coastguard Worker
3531*cf5a6c84SAndroid Build Coastguard Worker return s;
3532*cf5a6c84SAndroid Build Coastguard Worker }
3533*cf5a6c84SAndroid Build Coastguard Worker
bc_parse_str(BcParse * p,char inst)3534*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_parse_str(BcParse *p, char inst) {
3535*cf5a6c84SAndroid Build Coastguard Worker bc_parse_string(p);
3536*cf5a6c84SAndroid Build Coastguard Worker bc_parse_push(p, inst);
3537*cf5a6c84SAndroid Build Coastguard Worker return bc_lex_next(&p->l);
3538*cf5a6c84SAndroid Build Coastguard Worker }
3539*cf5a6c84SAndroid Build Coastguard Worker
bc_parse_print(BcParse * p)3540*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_parse_print(BcParse *p) {
3541*cf5a6c84SAndroid Build Coastguard Worker
3542*cf5a6c84SAndroid Build Coastguard Worker BcStatus s;
3543*cf5a6c84SAndroid Build Coastguard Worker BcLexType t;
3544*cf5a6c84SAndroid Build Coastguard Worker int comma = 0;
3545*cf5a6c84SAndroid Build Coastguard Worker
3546*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
3547*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
3548*cf5a6c84SAndroid Build Coastguard Worker
3549*cf5a6c84SAndroid Build Coastguard Worker t = p->l.t;
3550*cf5a6c84SAndroid Build Coastguard Worker
3551*cf5a6c84SAndroid Build Coastguard Worker if (bc_parse_isDelimiter(p)) return bc_parse_err(p, BC_ERROR_PARSE_PRINT);
3552*cf5a6c84SAndroid Build Coastguard Worker
3553*cf5a6c84SAndroid Build Coastguard Worker do {
3554*cf5a6c84SAndroid Build Coastguard Worker if (t == BC_LEX_STR) s = bc_parse_str(p, BC_INST_PRINT_POP);
3555*cf5a6c84SAndroid Build Coastguard Worker else {
3556*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_expr_status(p, 0, bc_parse_next_print);
3557*cf5a6c84SAndroid Build Coastguard Worker if (!s) bc_parse_push(p, BC_INST_PRINT_POP);
3558*cf5a6c84SAndroid Build Coastguard Worker }
3559*cf5a6c84SAndroid Build Coastguard Worker
3560*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
3561*cf5a6c84SAndroid Build Coastguard Worker
3562*cf5a6c84SAndroid Build Coastguard Worker comma = (p->l.t == BC_LEX_COMMA);
3563*cf5a6c84SAndroid Build Coastguard Worker
3564*cf5a6c84SAndroid Build Coastguard Worker if (comma) s = bc_lex_next(&p->l);
3565*cf5a6c84SAndroid Build Coastguard Worker else {
3566*cf5a6c84SAndroid Build Coastguard Worker if (!bc_parse_isDelimiter(p))
3567*cf5a6c84SAndroid Build Coastguard Worker return bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
3568*cf5a6c84SAndroid Build Coastguard Worker else break;
3569*cf5a6c84SAndroid Build Coastguard Worker }
3570*cf5a6c84SAndroid Build Coastguard Worker
3571*cf5a6c84SAndroid Build Coastguard Worker t = p->l.t;
3572*cf5a6c84SAndroid Build Coastguard Worker } while (!s);
3573*cf5a6c84SAndroid Build Coastguard Worker
3574*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
3575*cf5a6c84SAndroid Build Coastguard Worker if (comma) return bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
3576*cf5a6c84SAndroid Build Coastguard Worker
3577*cf5a6c84SAndroid Build Coastguard Worker return s;
3578*cf5a6c84SAndroid Build Coastguard Worker }
3579*cf5a6c84SAndroid Build Coastguard Worker
bc_parse_return(BcParse * p)3580*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_parse_return(BcParse *p) {
3581*cf5a6c84SAndroid Build Coastguard Worker
3582*cf5a6c84SAndroid Build Coastguard Worker BcStatus s;
3583*cf5a6c84SAndroid Build Coastguard Worker BcLexType t;
3584*cf5a6c84SAndroid Build Coastguard Worker int paren;
3585*cf5a6c84SAndroid Build Coastguard Worker char inst = BC_INST_RET0;
3586*cf5a6c84SAndroid Build Coastguard Worker
3587*cf5a6c84SAndroid Build Coastguard Worker if (!BC_PARSE_FUNC(p)) return bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
3588*cf5a6c84SAndroid Build Coastguard Worker
3589*cf5a6c84SAndroid Build Coastguard Worker if (p->func->voidfn) inst = BC_INST_RET_VOID;
3590*cf5a6c84SAndroid Build Coastguard Worker
3591*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
3592*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
3593*cf5a6c84SAndroid Build Coastguard Worker
3594*cf5a6c84SAndroid Build Coastguard Worker t = p->l.t;
3595*cf5a6c84SAndroid Build Coastguard Worker paren = t == BC_LEX_LPAREN;
3596*cf5a6c84SAndroid Build Coastguard Worker
3597*cf5a6c84SAndroid Build Coastguard Worker if (bc_parse_isDelimiter(p)) bc_parse_push(p, inst);
3598*cf5a6c84SAndroid Build Coastguard Worker else {
3599*cf5a6c84SAndroid Build Coastguard Worker
3600*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_expr_err(p, 0, bc_parse_next_expr);
3601*cf5a6c84SAndroid Build Coastguard Worker if (s && s != BC_STATUS_EMPTY_EXPR) return s;
3602*cf5a6c84SAndroid Build Coastguard Worker else if (s == BC_STATUS_EMPTY_EXPR) {
3603*cf5a6c84SAndroid Build Coastguard Worker bc_parse_push(p, inst);
3604*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
3605*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
3606*cf5a6c84SAndroid Build Coastguard Worker }
3607*cf5a6c84SAndroid Build Coastguard Worker
3608*cf5a6c84SAndroid Build Coastguard Worker if (!paren || p->l.last != BC_LEX_RPAREN) {
3609*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_posixErr(p, BC_ERROR_POSIX_RET);
3610*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
3611*cf5a6c84SAndroid Build Coastguard Worker }
3612*cf5a6c84SAndroid Build Coastguard Worker else if (p->func->voidfn)
3613*cf5a6c84SAndroid Build Coastguard Worker return bc_parse_verr(p, BC_ERROR_PARSE_RET_VOID, p->func->name);
3614*cf5a6c84SAndroid Build Coastguard Worker
3615*cf5a6c84SAndroid Build Coastguard Worker bc_parse_push(p, BC_INST_RET);
3616*cf5a6c84SAndroid Build Coastguard Worker }
3617*cf5a6c84SAndroid Build Coastguard Worker
3618*cf5a6c84SAndroid Build Coastguard Worker return s;
3619*cf5a6c84SAndroid Build Coastguard Worker }
3620*cf5a6c84SAndroid Build Coastguard Worker
bc_parse_endBody(BcParse * p,int brace)3621*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_parse_endBody(BcParse *p, int brace) {
3622*cf5a6c84SAndroid Build Coastguard Worker
3623*cf5a6c84SAndroid Build Coastguard Worker BcStatus s = BC_STATUS_SUCCESS;
3624*cf5a6c84SAndroid Build Coastguard Worker int has_brace, new_else = 0;
3625*cf5a6c84SAndroid Build Coastguard Worker
3626*cf5a6c84SAndroid Build Coastguard Worker if (p->flags.len <= 1) return bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
3627*cf5a6c84SAndroid Build Coastguard Worker
3628*cf5a6c84SAndroid Build Coastguard Worker if (brace) {
3629*cf5a6c84SAndroid Build Coastguard Worker if (p->l.t == BC_LEX_RBRACE) {
3630*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
3631*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
3632*cf5a6c84SAndroid Build Coastguard Worker if (!bc_parse_isDelimiter(p))
3633*cf5a6c84SAndroid Build Coastguard Worker return bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
3634*cf5a6c84SAndroid Build Coastguard Worker }
3635*cf5a6c84SAndroid Build Coastguard Worker else return bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
3636*cf5a6c84SAndroid Build Coastguard Worker }
3637*cf5a6c84SAndroid Build Coastguard Worker
3638*cf5a6c84SAndroid Build Coastguard Worker has_brace = (BC_PARSE_BRACE(p) != 0);
3639*cf5a6c84SAndroid Build Coastguard Worker
3640*cf5a6c84SAndroid Build Coastguard Worker do {
3641*cf5a6c84SAndroid Build Coastguard Worker size_t len = p->flags.len;
3642*cf5a6c84SAndroid Build Coastguard Worker int loop;
3643*cf5a6c84SAndroid Build Coastguard Worker
3644*cf5a6c84SAndroid Build Coastguard Worker if (has_brace && !brace) return bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
3645*cf5a6c84SAndroid Build Coastguard Worker
3646*cf5a6c84SAndroid Build Coastguard Worker loop = BC_PARSE_LOOP_INNER(p) != 0;
3647*cf5a6c84SAndroid Build Coastguard Worker
3648*cf5a6c84SAndroid Build Coastguard Worker if (loop || BC_PARSE_ELSE(p)) {
3649*cf5a6c84SAndroid Build Coastguard Worker
3650*cf5a6c84SAndroid Build Coastguard Worker if (loop) {
3651*cf5a6c84SAndroid Build Coastguard Worker
3652*cf5a6c84SAndroid Build Coastguard Worker size_t *label = bc_vec_top(&p->conds);
3653*cf5a6c84SAndroid Build Coastguard Worker
3654*cf5a6c84SAndroid Build Coastguard Worker bc_parse_push(p, BC_INST_JUMP);
3655*cf5a6c84SAndroid Build Coastguard Worker bc_parse_pushIndex(p, *label);
3656*cf5a6c84SAndroid Build Coastguard Worker
3657*cf5a6c84SAndroid Build Coastguard Worker bc_vec_pop(&p->conds);
3658*cf5a6c84SAndroid Build Coastguard Worker }
3659*cf5a6c84SAndroid Build Coastguard Worker
3660*cf5a6c84SAndroid Build Coastguard Worker bc_parse_setLabel(p);
3661*cf5a6c84SAndroid Build Coastguard Worker bc_vec_pop(&p->flags);
3662*cf5a6c84SAndroid Build Coastguard Worker }
3663*cf5a6c84SAndroid Build Coastguard Worker else if (BC_PARSE_FUNC_INNER(p)) {
3664*cf5a6c84SAndroid Build Coastguard Worker BcInst inst = (p->func->voidfn ? BC_INST_RET_VOID : BC_INST_RET0);
3665*cf5a6c84SAndroid Build Coastguard Worker bc_parse_push(p, inst);
3666*cf5a6c84SAndroid Build Coastguard Worker bc_parse_updateFunc(p, BC_PROG_MAIN);
3667*cf5a6c84SAndroid Build Coastguard Worker bc_vec_pop(&p->flags);
3668*cf5a6c84SAndroid Build Coastguard Worker }
3669*cf5a6c84SAndroid Build Coastguard Worker else if (BC_PARSE_BRACE(p) && !BC_PARSE_IF(p)) bc_vec_pop(&p->flags);
3670*cf5a6c84SAndroid Build Coastguard Worker
3671*cf5a6c84SAndroid Build Coastguard Worker // This needs to be last to parse nested if's properly.
3672*cf5a6c84SAndroid Build Coastguard Worker if (BC_PARSE_IF(p) && (len == p->flags.len || !BC_PARSE_BRACE(p))) {
3673*cf5a6c84SAndroid Build Coastguard Worker
3674*cf5a6c84SAndroid Build Coastguard Worker while (p->l.t == BC_LEX_NLINE) {
3675*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
3676*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
3677*cf5a6c84SAndroid Build Coastguard Worker }
3678*cf5a6c84SAndroid Build Coastguard Worker
3679*cf5a6c84SAndroid Build Coastguard Worker bc_vec_pop(&p->flags);
3680*cf5a6c84SAndroid Build Coastguard Worker *(BC_PARSE_TOP_FLAG_PTR(p)) |= BC_PARSE_FLAG_IF_END;
3681*cf5a6c84SAndroid Build Coastguard Worker
3682*cf5a6c84SAndroid Build Coastguard Worker new_else = (p->l.t == BC_LEX_KEY_ELSE);
3683*cf5a6c84SAndroid Build Coastguard Worker if (new_else) s = bc_parse_else(p);
3684*cf5a6c84SAndroid Build Coastguard Worker else if (!has_brace && (!BC_PARSE_IF_END(p) || brace))
3685*cf5a6c84SAndroid Build Coastguard Worker bc_parse_noElse(p);
3686*cf5a6c84SAndroid Build Coastguard Worker }
3687*cf5a6c84SAndroid Build Coastguard Worker
3688*cf5a6c84SAndroid Build Coastguard Worker if (brace && has_brace) brace = 0;
3689*cf5a6c84SAndroid Build Coastguard Worker
3690*cf5a6c84SAndroid Build Coastguard Worker } while (p->flags.len > 1 && !new_else && (!BC_PARSE_IF_END(p) || brace) &&
3691*cf5a6c84SAndroid Build Coastguard Worker !(has_brace = (BC_PARSE_BRACE(p) != 0)));
3692*cf5a6c84SAndroid Build Coastguard Worker
3693*cf5a6c84SAndroid Build Coastguard Worker if (!s && p->flags.len == 1 && brace)
3694*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
3695*cf5a6c84SAndroid Build Coastguard Worker else if (brace && BC_PARSE_BRACE(p)) {
3696*cf5a6c84SAndroid Build Coastguard Worker uint16_t flags = BC_PARSE_TOP_FLAG(p);
3697*cf5a6c84SAndroid Build Coastguard Worker if (!(flags & (BC_PARSE_FLAG_FUNC_INNER | BC_PARSE_FLAG_LOOP_INNER)) &&
3698*cf5a6c84SAndroid Build Coastguard Worker !(flags & (BC_PARSE_FLAG_IF | BC_PARSE_FLAG_ELSE)) &&
3699*cf5a6c84SAndroid Build Coastguard Worker !(flags & (BC_PARSE_FLAG_IF_END)))
3700*cf5a6c84SAndroid Build Coastguard Worker {
3701*cf5a6c84SAndroid Build Coastguard Worker bc_vec_pop(&p->flags);
3702*cf5a6c84SAndroid Build Coastguard Worker }
3703*cf5a6c84SAndroid Build Coastguard Worker }
3704*cf5a6c84SAndroid Build Coastguard Worker
3705*cf5a6c84SAndroid Build Coastguard Worker return s;
3706*cf5a6c84SAndroid Build Coastguard Worker }
3707*cf5a6c84SAndroid Build Coastguard Worker
bc_parse_startBody(BcParse * p,uint16_t flags)3708*cf5a6c84SAndroid Build Coastguard Worker static void bc_parse_startBody(BcParse *p, uint16_t flags) {
3709*cf5a6c84SAndroid Build Coastguard Worker flags |= (BC_PARSE_TOP_FLAG(p) & (BC_PARSE_FLAG_FUNC | BC_PARSE_FLAG_LOOP));
3710*cf5a6c84SAndroid Build Coastguard Worker flags |= BC_PARSE_FLAG_BODY;
3711*cf5a6c84SAndroid Build Coastguard Worker bc_vec_push(&p->flags, &flags);
3712*cf5a6c84SAndroid Build Coastguard Worker }
3713*cf5a6c84SAndroid Build Coastguard Worker
bc_parse_noElse(BcParse * p)3714*cf5a6c84SAndroid Build Coastguard Worker void bc_parse_noElse(BcParse *p) {
3715*cf5a6c84SAndroid Build Coastguard Worker uint16_t *flag_ptr = BC_PARSE_TOP_FLAG_PTR(p);
3716*cf5a6c84SAndroid Build Coastguard Worker *flag_ptr = (*flag_ptr & ~(BC_PARSE_FLAG_IF_END));
3717*cf5a6c84SAndroid Build Coastguard Worker bc_parse_setLabel(p);
3718*cf5a6c84SAndroid Build Coastguard Worker }
3719*cf5a6c84SAndroid Build Coastguard Worker
bc_parse_if(BcParse * p)3720*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_parse_if(BcParse *p) {
3721*cf5a6c84SAndroid Build Coastguard Worker
3722*cf5a6c84SAndroid Build Coastguard Worker BcStatus s;
3723*cf5a6c84SAndroid Build Coastguard Worker size_t idx;
3724*cf5a6c84SAndroid Build Coastguard Worker
3725*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
3726*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
3727*cf5a6c84SAndroid Build Coastguard Worker if (p->l.t != BC_LEX_LPAREN) return bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
3728*cf5a6c84SAndroid Build Coastguard Worker
3729*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
3730*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
3731*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_expr_status(p, BC_PARSE_REL, bc_parse_next_rel);
3732*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
3733*cf5a6c84SAndroid Build Coastguard Worker if (p->l.t != BC_LEX_RPAREN) return bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
3734*cf5a6c84SAndroid Build Coastguard Worker
3735*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
3736*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
3737*cf5a6c84SAndroid Build Coastguard Worker bc_parse_push(p, BC_INST_JUMP_ZERO);
3738*cf5a6c84SAndroid Build Coastguard Worker
3739*cf5a6c84SAndroid Build Coastguard Worker idx = p->func->labels.len;
3740*cf5a6c84SAndroid Build Coastguard Worker
3741*cf5a6c84SAndroid Build Coastguard Worker bc_parse_pushIndex(p, idx);
3742*cf5a6c84SAndroid Build Coastguard Worker bc_parse_createExitLabel(p, idx, 0);
3743*cf5a6c84SAndroid Build Coastguard Worker bc_parse_startBody(p, BC_PARSE_FLAG_IF);
3744*cf5a6c84SAndroid Build Coastguard Worker
3745*cf5a6c84SAndroid Build Coastguard Worker return BC_STATUS_SUCCESS;
3746*cf5a6c84SAndroid Build Coastguard Worker }
3747*cf5a6c84SAndroid Build Coastguard Worker
bc_parse_else(BcParse * p)3748*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_parse_else(BcParse *p) {
3749*cf5a6c84SAndroid Build Coastguard Worker
3750*cf5a6c84SAndroid Build Coastguard Worker size_t idx = p->func->labels.len;
3751*cf5a6c84SAndroid Build Coastguard Worker
3752*cf5a6c84SAndroid Build Coastguard Worker if (!BC_PARSE_IF_END(p)) return bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
3753*cf5a6c84SAndroid Build Coastguard Worker
3754*cf5a6c84SAndroid Build Coastguard Worker bc_parse_push(p, BC_INST_JUMP);
3755*cf5a6c84SAndroid Build Coastguard Worker bc_parse_pushIndex(p, idx);
3756*cf5a6c84SAndroid Build Coastguard Worker
3757*cf5a6c84SAndroid Build Coastguard Worker bc_parse_noElse(p);
3758*cf5a6c84SAndroid Build Coastguard Worker
3759*cf5a6c84SAndroid Build Coastguard Worker bc_parse_createExitLabel(p, idx, 0);
3760*cf5a6c84SAndroid Build Coastguard Worker bc_parse_startBody(p, BC_PARSE_FLAG_ELSE);
3761*cf5a6c84SAndroid Build Coastguard Worker
3762*cf5a6c84SAndroid Build Coastguard Worker return bc_lex_next(&p->l);
3763*cf5a6c84SAndroid Build Coastguard Worker }
3764*cf5a6c84SAndroid Build Coastguard Worker
bc_parse_while(BcParse * p)3765*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_parse_while(BcParse *p) {
3766*cf5a6c84SAndroid Build Coastguard Worker
3767*cf5a6c84SAndroid Build Coastguard Worker BcStatus s;
3768*cf5a6c84SAndroid Build Coastguard Worker size_t idx;
3769*cf5a6c84SAndroid Build Coastguard Worker
3770*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
3771*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
3772*cf5a6c84SAndroid Build Coastguard Worker if (p->l.t != BC_LEX_LPAREN) return bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
3773*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
3774*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
3775*cf5a6c84SAndroid Build Coastguard Worker
3776*cf5a6c84SAndroid Build Coastguard Worker bc_parse_createCondLabel(p, p->func->labels.len);
3777*cf5a6c84SAndroid Build Coastguard Worker
3778*cf5a6c84SAndroid Build Coastguard Worker idx = p->func->labels.len;
3779*cf5a6c84SAndroid Build Coastguard Worker
3780*cf5a6c84SAndroid Build Coastguard Worker bc_parse_createExitLabel(p, idx, 1);
3781*cf5a6c84SAndroid Build Coastguard Worker
3782*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_expr_status(p, BC_PARSE_REL, bc_parse_next_rel);
3783*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
3784*cf5a6c84SAndroid Build Coastguard Worker if (p->l.t != BC_LEX_RPAREN) return bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
3785*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
3786*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
3787*cf5a6c84SAndroid Build Coastguard Worker
3788*cf5a6c84SAndroid Build Coastguard Worker bc_parse_push(p, BC_INST_JUMP_ZERO);
3789*cf5a6c84SAndroid Build Coastguard Worker bc_parse_pushIndex(p, idx);
3790*cf5a6c84SAndroid Build Coastguard Worker bc_parse_startBody(p, BC_PARSE_FLAG_LOOP | BC_PARSE_FLAG_LOOP_INNER);
3791*cf5a6c84SAndroid Build Coastguard Worker
3792*cf5a6c84SAndroid Build Coastguard Worker return BC_STATUS_SUCCESS;
3793*cf5a6c84SAndroid Build Coastguard Worker }
3794*cf5a6c84SAndroid Build Coastguard Worker
bc_parse_for(BcParse * p)3795*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_parse_for(BcParse *p) {
3796*cf5a6c84SAndroid Build Coastguard Worker
3797*cf5a6c84SAndroid Build Coastguard Worker BcStatus s;
3798*cf5a6c84SAndroid Build Coastguard Worker size_t cond_idx, exit_idx, body_idx, update_idx;
3799*cf5a6c84SAndroid Build Coastguard Worker
3800*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
3801*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
3802*cf5a6c84SAndroid Build Coastguard Worker if (p->l.t != BC_LEX_LPAREN) return bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
3803*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
3804*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
3805*cf5a6c84SAndroid Build Coastguard Worker
3806*cf5a6c84SAndroid Build Coastguard Worker if (p->l.t != BC_LEX_SCOLON) {
3807*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_expr_status(p, 0, bc_parse_next_for);
3808*cf5a6c84SAndroid Build Coastguard Worker if (!s) bc_parse_push(p, BC_INST_POP);
3809*cf5a6c84SAndroid Build Coastguard Worker }
3810*cf5a6c84SAndroid Build Coastguard Worker else s = bc_parse_posixErr(p, BC_ERROR_POSIX_FOR1);
3811*cf5a6c84SAndroid Build Coastguard Worker
3812*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
3813*cf5a6c84SAndroid Build Coastguard Worker if (p->l.t != BC_LEX_SCOLON) return bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
3814*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
3815*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
3816*cf5a6c84SAndroid Build Coastguard Worker
3817*cf5a6c84SAndroid Build Coastguard Worker cond_idx = p->func->labels.len;
3818*cf5a6c84SAndroid Build Coastguard Worker update_idx = cond_idx + 1;
3819*cf5a6c84SAndroid Build Coastguard Worker body_idx = update_idx + 1;
3820*cf5a6c84SAndroid Build Coastguard Worker exit_idx = body_idx + 1;
3821*cf5a6c84SAndroid Build Coastguard Worker
3822*cf5a6c84SAndroid Build Coastguard Worker bc_parse_createLabel(p, p->func->code.len);
3823*cf5a6c84SAndroid Build Coastguard Worker
3824*cf5a6c84SAndroid Build Coastguard Worker if (p->l.t != BC_LEX_SCOLON)
3825*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_expr_status(p, BC_PARSE_REL, bc_parse_next_for);
3826*cf5a6c84SAndroid Build Coastguard Worker else {
3827*cf5a6c84SAndroid Build Coastguard Worker
3828*cf5a6c84SAndroid Build Coastguard Worker // Set this for the next call to bc_parse_number.
3829*cf5a6c84SAndroid Build Coastguard Worker // This is safe to set because the current token
3830*cf5a6c84SAndroid Build Coastguard Worker // is a semicolon, which has no string requirement.
3831*cf5a6c84SAndroid Build Coastguard Worker bc_vec_string(&p->l.str, strlen(bc_parse_const1), bc_parse_const1);
3832*cf5a6c84SAndroid Build Coastguard Worker bc_parse_number(p);
3833*cf5a6c84SAndroid Build Coastguard Worker
3834*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_posixErr(p, BC_ERROR_POSIX_FOR2);
3835*cf5a6c84SAndroid Build Coastguard Worker }
3836*cf5a6c84SAndroid Build Coastguard Worker
3837*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
3838*cf5a6c84SAndroid Build Coastguard Worker if (p->l.t != BC_LEX_SCOLON) return bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
3839*cf5a6c84SAndroid Build Coastguard Worker
3840*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
3841*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
3842*cf5a6c84SAndroid Build Coastguard Worker
3843*cf5a6c84SAndroid Build Coastguard Worker bc_parse_push(p, BC_INST_JUMP_ZERO);
3844*cf5a6c84SAndroid Build Coastguard Worker bc_parse_pushIndex(p, exit_idx);
3845*cf5a6c84SAndroid Build Coastguard Worker bc_parse_push(p, BC_INST_JUMP);
3846*cf5a6c84SAndroid Build Coastguard Worker bc_parse_pushIndex(p, body_idx);
3847*cf5a6c84SAndroid Build Coastguard Worker
3848*cf5a6c84SAndroid Build Coastguard Worker bc_parse_createCondLabel(p, update_idx);
3849*cf5a6c84SAndroid Build Coastguard Worker
3850*cf5a6c84SAndroid Build Coastguard Worker if (p->l.t != BC_LEX_RPAREN) {
3851*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_expr_status(p, 0, bc_parse_next_rel);
3852*cf5a6c84SAndroid Build Coastguard Worker if (!s) bc_parse_push(p, BC_INST_POP);
3853*cf5a6c84SAndroid Build Coastguard Worker }
3854*cf5a6c84SAndroid Build Coastguard Worker else s = bc_parse_posixErr(p, BC_ERROR_POSIX_FOR3);
3855*cf5a6c84SAndroid Build Coastguard Worker
3856*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
3857*cf5a6c84SAndroid Build Coastguard Worker
3858*cf5a6c84SAndroid Build Coastguard Worker if (p->l.t != BC_LEX_RPAREN) return bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
3859*cf5a6c84SAndroid Build Coastguard Worker bc_parse_push(p, BC_INST_JUMP);
3860*cf5a6c84SAndroid Build Coastguard Worker bc_parse_pushIndex(p, cond_idx);
3861*cf5a6c84SAndroid Build Coastguard Worker bc_parse_createLabel(p, p->func->code.len);
3862*cf5a6c84SAndroid Build Coastguard Worker
3863*cf5a6c84SAndroid Build Coastguard Worker bc_parse_createExitLabel(p, exit_idx, 1);
3864*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
3865*cf5a6c84SAndroid Build Coastguard Worker if (!s) bc_parse_startBody(p, BC_PARSE_FLAG_LOOP | BC_PARSE_FLAG_LOOP_INNER);
3866*cf5a6c84SAndroid Build Coastguard Worker
3867*cf5a6c84SAndroid Build Coastguard Worker return s;
3868*cf5a6c84SAndroid Build Coastguard Worker }
3869*cf5a6c84SAndroid Build Coastguard Worker
bc_parse_loopExit(BcParse * p,BcLexType type)3870*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_parse_loopExit(BcParse *p, BcLexType type) {
3871*cf5a6c84SAndroid Build Coastguard Worker
3872*cf5a6c84SAndroid Build Coastguard Worker size_t i;
3873*cf5a6c84SAndroid Build Coastguard Worker BcInstPtr *ip;
3874*cf5a6c84SAndroid Build Coastguard Worker
3875*cf5a6c84SAndroid Build Coastguard Worker if (!BC_PARSE_LOOP(p)) return bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
3876*cf5a6c84SAndroid Build Coastguard Worker
3877*cf5a6c84SAndroid Build Coastguard Worker if (type == BC_LEX_KEY_BREAK) {
3878*cf5a6c84SAndroid Build Coastguard Worker
3879*cf5a6c84SAndroid Build Coastguard Worker if (!p->exits.len) return bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
3880*cf5a6c84SAndroid Build Coastguard Worker
3881*cf5a6c84SAndroid Build Coastguard Worker i = p->exits.len - 1;
3882*cf5a6c84SAndroid Build Coastguard Worker ip = bc_vec_item(&p->exits, i);
3883*cf5a6c84SAndroid Build Coastguard Worker
3884*cf5a6c84SAndroid Build Coastguard Worker while (!ip->func && i < p->exits.len) ip = bc_vec_item(&p->exits, i--);
3885*cf5a6c84SAndroid Build Coastguard Worker if (i >= p->exits.len && !ip->func)
3886*cf5a6c84SAndroid Build Coastguard Worker return bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
3887*cf5a6c84SAndroid Build Coastguard Worker
3888*cf5a6c84SAndroid Build Coastguard Worker i = ip->idx;
3889*cf5a6c84SAndroid Build Coastguard Worker }
3890*cf5a6c84SAndroid Build Coastguard Worker else i = *((size_t*) bc_vec_top(&p->conds));
3891*cf5a6c84SAndroid Build Coastguard Worker
3892*cf5a6c84SAndroid Build Coastguard Worker bc_parse_push(p, BC_INST_JUMP);
3893*cf5a6c84SAndroid Build Coastguard Worker bc_parse_pushIndex(p, i);
3894*cf5a6c84SAndroid Build Coastguard Worker
3895*cf5a6c84SAndroid Build Coastguard Worker return bc_lex_next(&p->l);
3896*cf5a6c84SAndroid Build Coastguard Worker }
3897*cf5a6c84SAndroid Build Coastguard Worker
bc_parse_func(BcParse * p)3898*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_parse_func(BcParse *p) {
3899*cf5a6c84SAndroid Build Coastguard Worker
3900*cf5a6c84SAndroid Build Coastguard Worker BcStatus s;
3901*cf5a6c84SAndroid Build Coastguard Worker int comma = 0, voidfn;
3902*cf5a6c84SAndroid Build Coastguard Worker uint16_t flags;
3903*cf5a6c84SAndroid Build Coastguard Worker char *name;
3904*cf5a6c84SAndroid Build Coastguard Worker size_t idx;
3905*cf5a6c84SAndroid Build Coastguard Worker
3906*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
3907*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
3908*cf5a6c84SAndroid Build Coastguard Worker
3909*cf5a6c84SAndroid Build Coastguard Worker if (p->l.t != BC_LEX_NAME) return bc_parse_err(p, BC_ERROR_PARSE_FUNC);
3910*cf5a6c84SAndroid Build Coastguard Worker
3911*cf5a6c84SAndroid Build Coastguard Worker voidfn = (!FLAG(s) && !FLAG(w) && p->l.t == BC_LEX_NAME &&
3912*cf5a6c84SAndroid Build Coastguard Worker !strcmp(p->l.str.v, "void"));
3913*cf5a6c84SAndroid Build Coastguard Worker
3914*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
3915*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
3916*cf5a6c84SAndroid Build Coastguard Worker
3917*cf5a6c84SAndroid Build Coastguard Worker voidfn = (voidfn && p->l.t == BC_LEX_NAME);
3918*cf5a6c84SAndroid Build Coastguard Worker
3919*cf5a6c84SAndroid Build Coastguard Worker if (voidfn) {
3920*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
3921*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
3922*cf5a6c84SAndroid Build Coastguard Worker }
3923*cf5a6c84SAndroid Build Coastguard Worker
3924*cf5a6c84SAndroid Build Coastguard Worker if (p->l.t != BC_LEX_LPAREN) return bc_parse_err(p, BC_ERROR_PARSE_FUNC);
3925*cf5a6c84SAndroid Build Coastguard Worker
3926*cf5a6c84SAndroid Build Coastguard Worker name = xstrdup(p->l.str.v);
3927*cf5a6c84SAndroid Build Coastguard Worker idx = bc_program_insertFunc(p->prog, name);
3928*cf5a6c84SAndroid Build Coastguard Worker bc_parse_updateFunc(p, idx);
3929*cf5a6c84SAndroid Build Coastguard Worker p->func->voidfn = voidfn;
3930*cf5a6c84SAndroid Build Coastguard Worker
3931*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
3932*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
3933*cf5a6c84SAndroid Build Coastguard Worker
3934*cf5a6c84SAndroid Build Coastguard Worker while (p->l.t != BC_LEX_RPAREN) {
3935*cf5a6c84SAndroid Build Coastguard Worker
3936*cf5a6c84SAndroid Build Coastguard Worker BcType t = BC_TYPE_VAR;
3937*cf5a6c84SAndroid Build Coastguard Worker
3938*cf5a6c84SAndroid Build Coastguard Worker if (p->l.t != BC_LEX_NAME) return bc_parse_err(p, BC_ERROR_PARSE_FUNC);
3939*cf5a6c84SAndroid Build Coastguard Worker
3940*cf5a6c84SAndroid Build Coastguard Worker ++p->func->nparams;
3941*cf5a6c84SAndroid Build Coastguard Worker
3942*cf5a6c84SAndroid Build Coastguard Worker name = xstrdup(p->l.str.v);
3943*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
3944*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
3945*cf5a6c84SAndroid Build Coastguard Worker
3946*cf5a6c84SAndroid Build Coastguard Worker if (p->l.t == BC_LEX_LBRACKET) {
3947*cf5a6c84SAndroid Build Coastguard Worker
3948*cf5a6c84SAndroid Build Coastguard Worker if (t == BC_TYPE_VAR) t = BC_TYPE_ARRAY;
3949*cf5a6c84SAndroid Build Coastguard Worker
3950*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
3951*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
3952*cf5a6c84SAndroid Build Coastguard Worker
3953*cf5a6c84SAndroid Build Coastguard Worker if (p->l.t != BC_LEX_RBRACKET) {
3954*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_err(p, BC_ERROR_PARSE_FUNC);
3955*cf5a6c84SAndroid Build Coastguard Worker goto err;
3956*cf5a6c84SAndroid Build Coastguard Worker }
3957*cf5a6c84SAndroid Build Coastguard Worker
3958*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
3959*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
3960*cf5a6c84SAndroid Build Coastguard Worker }
3961*cf5a6c84SAndroid Build Coastguard Worker
3962*cf5a6c84SAndroid Build Coastguard Worker comma = p->l.t == BC_LEX_COMMA;
3963*cf5a6c84SAndroid Build Coastguard Worker if (comma) {
3964*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
3965*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
3966*cf5a6c84SAndroid Build Coastguard Worker }
3967*cf5a6c84SAndroid Build Coastguard Worker
3968*cf5a6c84SAndroid Build Coastguard Worker s = bc_func_insert(p->func, name, t, p->l.line);
3969*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
3970*cf5a6c84SAndroid Build Coastguard Worker }
3971*cf5a6c84SAndroid Build Coastguard Worker
3972*cf5a6c84SAndroid Build Coastguard Worker if (comma) return bc_parse_err(p, BC_ERROR_PARSE_FUNC);
3973*cf5a6c84SAndroid Build Coastguard Worker
3974*cf5a6c84SAndroid Build Coastguard Worker flags = BC_PARSE_FLAG_FUNC | BC_PARSE_FLAG_FUNC_INNER | BC_PARSE_FLAG_BODY;
3975*cf5a6c84SAndroid Build Coastguard Worker bc_parse_startBody(p, flags);
3976*cf5a6c84SAndroid Build Coastguard Worker
3977*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
3978*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
3979*cf5a6c84SAndroid Build Coastguard Worker
3980*cf5a6c84SAndroid Build Coastguard Worker if (p->l.t != BC_LEX_LBRACE) s = bc_parse_posixErr(p, BC_ERROR_POSIX_BRACE);
3981*cf5a6c84SAndroid Build Coastguard Worker
3982*cf5a6c84SAndroid Build Coastguard Worker return s;
3983*cf5a6c84SAndroid Build Coastguard Worker
3984*cf5a6c84SAndroid Build Coastguard Worker err:
3985*cf5a6c84SAndroid Build Coastguard Worker free(name);
3986*cf5a6c84SAndroid Build Coastguard Worker return s;
3987*cf5a6c84SAndroid Build Coastguard Worker }
3988*cf5a6c84SAndroid Build Coastguard Worker
bc_parse_auto(BcParse * p)3989*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_parse_auto(BcParse *p) {
3990*cf5a6c84SAndroid Build Coastguard Worker
3991*cf5a6c84SAndroid Build Coastguard Worker BcStatus s;
3992*cf5a6c84SAndroid Build Coastguard Worker int comma, one;
3993*cf5a6c84SAndroid Build Coastguard Worker char *name;
3994*cf5a6c84SAndroid Build Coastguard Worker
3995*cf5a6c84SAndroid Build Coastguard Worker if (!p->auto_part) return bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
3996*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
3997*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
3998*cf5a6c84SAndroid Build Coastguard Worker
3999*cf5a6c84SAndroid Build Coastguard Worker p->auto_part = comma = 0;
4000*cf5a6c84SAndroid Build Coastguard Worker one = p->l.t == BC_LEX_NAME;
4001*cf5a6c84SAndroid Build Coastguard Worker
4002*cf5a6c84SAndroid Build Coastguard Worker while (p->l.t == BC_LEX_NAME) {
4003*cf5a6c84SAndroid Build Coastguard Worker
4004*cf5a6c84SAndroid Build Coastguard Worker BcType t;
4005*cf5a6c84SAndroid Build Coastguard Worker
4006*cf5a6c84SAndroid Build Coastguard Worker name = xstrdup(p->l.str.v);
4007*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
4008*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
4009*cf5a6c84SAndroid Build Coastguard Worker
4010*cf5a6c84SAndroid Build Coastguard Worker if (p->l.t == BC_LEX_LBRACKET) {
4011*cf5a6c84SAndroid Build Coastguard Worker
4012*cf5a6c84SAndroid Build Coastguard Worker t = BC_TYPE_ARRAY;
4013*cf5a6c84SAndroid Build Coastguard Worker
4014*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
4015*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
4016*cf5a6c84SAndroid Build Coastguard Worker
4017*cf5a6c84SAndroid Build Coastguard Worker if (p->l.t != BC_LEX_RBRACKET) {
4018*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_err(p, BC_ERROR_PARSE_FUNC);
4019*cf5a6c84SAndroid Build Coastguard Worker goto err;
4020*cf5a6c84SAndroid Build Coastguard Worker }
4021*cf5a6c84SAndroid Build Coastguard Worker
4022*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
4023*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
4024*cf5a6c84SAndroid Build Coastguard Worker }
4025*cf5a6c84SAndroid Build Coastguard Worker else t = BC_TYPE_VAR;
4026*cf5a6c84SAndroid Build Coastguard Worker
4027*cf5a6c84SAndroid Build Coastguard Worker comma = p->l.t == BC_LEX_COMMA;
4028*cf5a6c84SAndroid Build Coastguard Worker if (comma) {
4029*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
4030*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
4031*cf5a6c84SAndroid Build Coastguard Worker }
4032*cf5a6c84SAndroid Build Coastguard Worker
4033*cf5a6c84SAndroid Build Coastguard Worker s = bc_func_insert(p->func, name, t, p->l.line);
4034*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
4035*cf5a6c84SAndroid Build Coastguard Worker }
4036*cf5a6c84SAndroid Build Coastguard Worker
4037*cf5a6c84SAndroid Build Coastguard Worker if (comma) return bc_parse_err(p, BC_ERROR_PARSE_FUNC);
4038*cf5a6c84SAndroid Build Coastguard Worker if (!one) return bc_parse_err(p, BC_ERROR_PARSE_NO_AUTO);
4039*cf5a6c84SAndroid Build Coastguard Worker if (!bc_parse_isDelimiter(p)) return bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
4040*cf5a6c84SAndroid Build Coastguard Worker
4041*cf5a6c84SAndroid Build Coastguard Worker return s;
4042*cf5a6c84SAndroid Build Coastguard Worker
4043*cf5a6c84SAndroid Build Coastguard Worker err:
4044*cf5a6c84SAndroid Build Coastguard Worker free(name);
4045*cf5a6c84SAndroid Build Coastguard Worker return s;
4046*cf5a6c84SAndroid Build Coastguard Worker }
4047*cf5a6c84SAndroid Build Coastguard Worker
bc_parse_body(BcParse * p,int brace)4048*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_parse_body(BcParse *p, int brace) {
4049*cf5a6c84SAndroid Build Coastguard Worker
4050*cf5a6c84SAndroid Build Coastguard Worker BcStatus s = BC_STATUS_SUCCESS;
4051*cf5a6c84SAndroid Build Coastguard Worker uint16_t *flag_ptr = BC_PARSE_TOP_FLAG_PTR(p);
4052*cf5a6c84SAndroid Build Coastguard Worker
4053*cf5a6c84SAndroid Build Coastguard Worker *flag_ptr &= ~(BC_PARSE_FLAG_BODY);
4054*cf5a6c84SAndroid Build Coastguard Worker
4055*cf5a6c84SAndroid Build Coastguard Worker if (*flag_ptr & BC_PARSE_FLAG_FUNC_INNER) {
4056*cf5a6c84SAndroid Build Coastguard Worker
4057*cf5a6c84SAndroid Build Coastguard Worker if (!brace) return bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
4058*cf5a6c84SAndroid Build Coastguard Worker
4059*cf5a6c84SAndroid Build Coastguard Worker p->auto_part = p->l.t != BC_LEX_KEY_AUTO;
4060*cf5a6c84SAndroid Build Coastguard Worker
4061*cf5a6c84SAndroid Build Coastguard Worker if (!p->auto_part) {
4062*cf5a6c84SAndroid Build Coastguard Worker
4063*cf5a6c84SAndroid Build Coastguard Worker // Make sure this is 1 to not get a parse error.
4064*cf5a6c84SAndroid Build Coastguard Worker p->auto_part = 1;
4065*cf5a6c84SAndroid Build Coastguard Worker
4066*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_auto(p);
4067*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
4068*cf5a6c84SAndroid Build Coastguard Worker }
4069*cf5a6c84SAndroid Build Coastguard Worker
4070*cf5a6c84SAndroid Build Coastguard Worker if (p->l.t == BC_LEX_NLINE) s = bc_lex_next(&p->l);
4071*cf5a6c84SAndroid Build Coastguard Worker }
4072*cf5a6c84SAndroid Build Coastguard Worker else {
4073*cf5a6c84SAndroid Build Coastguard Worker size_t len = p->flags.len;
4074*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_stmt(p);
4075*cf5a6c84SAndroid Build Coastguard Worker if (!s && !brace && !BC_PARSE_BODY(p) && len <= p->flags.len)
4076*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_endBody(p, 0);
4077*cf5a6c84SAndroid Build Coastguard Worker }
4078*cf5a6c84SAndroid Build Coastguard Worker
4079*cf5a6c84SAndroid Build Coastguard Worker return s;
4080*cf5a6c84SAndroid Build Coastguard Worker }
4081*cf5a6c84SAndroid Build Coastguard Worker
bc_parse_stmt(BcParse * p)4082*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_parse_stmt(BcParse *p) {
4083*cf5a6c84SAndroid Build Coastguard Worker
4084*cf5a6c84SAndroid Build Coastguard Worker BcStatus s = BC_STATUS_SUCCESS;
4085*cf5a6c84SAndroid Build Coastguard Worker size_t len;
4086*cf5a6c84SAndroid Build Coastguard Worker uint16_t flags;
4087*cf5a6c84SAndroid Build Coastguard Worker BcLexType type = p->l.t;
4088*cf5a6c84SAndroid Build Coastguard Worker
4089*cf5a6c84SAndroid Build Coastguard Worker if (type == BC_LEX_NLINE) return bc_lex_next(&p->l);
4090*cf5a6c84SAndroid Build Coastguard Worker if (type == BC_LEX_KEY_AUTO) return bc_parse_auto(p);
4091*cf5a6c84SAndroid Build Coastguard Worker
4092*cf5a6c84SAndroid Build Coastguard Worker p->auto_part = 0;
4093*cf5a6c84SAndroid Build Coastguard Worker
4094*cf5a6c84SAndroid Build Coastguard Worker if (type != BC_LEX_KEY_ELSE) {
4095*cf5a6c84SAndroid Build Coastguard Worker
4096*cf5a6c84SAndroid Build Coastguard Worker if (BC_PARSE_IF_END(p)) {
4097*cf5a6c84SAndroid Build Coastguard Worker bc_parse_noElse(p);
4098*cf5a6c84SAndroid Build Coastguard Worker if (p->flags.len > 1 && !BC_PARSE_BRACE(p))
4099*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_endBody(p, 0);
4100*cf5a6c84SAndroid Build Coastguard Worker return s;
4101*cf5a6c84SAndroid Build Coastguard Worker }
4102*cf5a6c84SAndroid Build Coastguard Worker else if (type == BC_LEX_LBRACE) {
4103*cf5a6c84SAndroid Build Coastguard Worker
4104*cf5a6c84SAndroid Build Coastguard Worker if (!BC_PARSE_BODY(p)) {
4105*cf5a6c84SAndroid Build Coastguard Worker bc_parse_startBody(p, BC_PARSE_FLAG_BRACE);
4106*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
4107*cf5a6c84SAndroid Build Coastguard Worker }
4108*cf5a6c84SAndroid Build Coastguard Worker else {
4109*cf5a6c84SAndroid Build Coastguard Worker *(BC_PARSE_TOP_FLAG_PTR(p)) |= BC_PARSE_FLAG_BRACE;
4110*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
4111*cf5a6c84SAndroid Build Coastguard Worker if (!s) s = bc_parse_body(p, 1);
4112*cf5a6c84SAndroid Build Coastguard Worker }
4113*cf5a6c84SAndroid Build Coastguard Worker
4114*cf5a6c84SAndroid Build Coastguard Worker return s;
4115*cf5a6c84SAndroid Build Coastguard Worker }
4116*cf5a6c84SAndroid Build Coastguard Worker else if (BC_PARSE_BODY(p) && !BC_PARSE_BRACE(p))
4117*cf5a6c84SAndroid Build Coastguard Worker return bc_parse_body(p, 0);
4118*cf5a6c84SAndroid Build Coastguard Worker }
4119*cf5a6c84SAndroid Build Coastguard Worker
4120*cf5a6c84SAndroid Build Coastguard Worker len = p->flags.len;
4121*cf5a6c84SAndroid Build Coastguard Worker flags = BC_PARSE_TOP_FLAG(p);
4122*cf5a6c84SAndroid Build Coastguard Worker
4123*cf5a6c84SAndroid Build Coastguard Worker switch (type) {
4124*cf5a6c84SAndroid Build Coastguard Worker
4125*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_OP_INC:
4126*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_OP_DEC:
4127*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_OP_MINUS:
4128*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_OP_BOOL_NOT:
4129*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_LPAREN:
4130*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_NAME:
4131*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_NUMBER:
4132*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_KEY_IBASE:
4133*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_KEY_LAST:
4134*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_KEY_LENGTH:
4135*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_KEY_OBASE:
4136*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_KEY_READ:
4137*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_KEY_SCALE:
4138*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_KEY_SQRT:
4139*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_KEY_ABS:
4140*cf5a6c84SAndroid Build Coastguard Worker {
4141*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_expr_status(p, BC_PARSE_PRINT, bc_parse_next_expr);
4142*cf5a6c84SAndroid Build Coastguard Worker break;
4143*cf5a6c84SAndroid Build Coastguard Worker }
4144*cf5a6c84SAndroid Build Coastguard Worker
4145*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_KEY_ELSE:
4146*cf5a6c84SAndroid Build Coastguard Worker {
4147*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_else(p);
4148*cf5a6c84SAndroid Build Coastguard Worker break;
4149*cf5a6c84SAndroid Build Coastguard Worker }
4150*cf5a6c84SAndroid Build Coastguard Worker
4151*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_SCOLON:
4152*cf5a6c84SAndroid Build Coastguard Worker {
4153*cf5a6c84SAndroid Build Coastguard Worker // Do nothing.
4154*cf5a6c84SAndroid Build Coastguard Worker break;
4155*cf5a6c84SAndroid Build Coastguard Worker }
4156*cf5a6c84SAndroid Build Coastguard Worker
4157*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_RBRACE:
4158*cf5a6c84SAndroid Build Coastguard Worker {
4159*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_endBody(p, 1);
4160*cf5a6c84SAndroid Build Coastguard Worker break;
4161*cf5a6c84SAndroid Build Coastguard Worker }
4162*cf5a6c84SAndroid Build Coastguard Worker
4163*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_STR:
4164*cf5a6c84SAndroid Build Coastguard Worker {
4165*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_str(p, BC_INST_PRINT_STR);
4166*cf5a6c84SAndroid Build Coastguard Worker break;
4167*cf5a6c84SAndroid Build Coastguard Worker }
4168*cf5a6c84SAndroid Build Coastguard Worker
4169*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_KEY_BREAK:
4170*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_KEY_CONTINUE:
4171*cf5a6c84SAndroid Build Coastguard Worker {
4172*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_loopExit(p, p->l.t);
4173*cf5a6c84SAndroid Build Coastguard Worker break;
4174*cf5a6c84SAndroid Build Coastguard Worker }
4175*cf5a6c84SAndroid Build Coastguard Worker
4176*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_KEY_FOR:
4177*cf5a6c84SAndroid Build Coastguard Worker {
4178*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_for(p);
4179*cf5a6c84SAndroid Build Coastguard Worker break;
4180*cf5a6c84SAndroid Build Coastguard Worker }
4181*cf5a6c84SAndroid Build Coastguard Worker
4182*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_KEY_HALT:
4183*cf5a6c84SAndroid Build Coastguard Worker {
4184*cf5a6c84SAndroid Build Coastguard Worker bc_parse_push(p, BC_INST_HALT);
4185*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
4186*cf5a6c84SAndroid Build Coastguard Worker break;
4187*cf5a6c84SAndroid Build Coastguard Worker }
4188*cf5a6c84SAndroid Build Coastguard Worker
4189*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_KEY_IF:
4190*cf5a6c84SAndroid Build Coastguard Worker {
4191*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_if(p);
4192*cf5a6c84SAndroid Build Coastguard Worker break;
4193*cf5a6c84SAndroid Build Coastguard Worker }
4194*cf5a6c84SAndroid Build Coastguard Worker
4195*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_KEY_LIMITS:
4196*cf5a6c84SAndroid Build Coastguard Worker {
4197*cf5a6c84SAndroid Build Coastguard Worker printf("BC_BASE_MAX = %lu\n", BC_MAX_OBASE);
4198*cf5a6c84SAndroid Build Coastguard Worker printf("BC_DIM_MAX = %lu\n", BC_MAX_DIM);
4199*cf5a6c84SAndroid Build Coastguard Worker printf("BC_SCALE_MAX = %lu\n", BC_MAX_SCALE);
4200*cf5a6c84SAndroid Build Coastguard Worker printf("BC_STRING_MAX = %lu\n", BC_MAX_STRING);
4201*cf5a6c84SAndroid Build Coastguard Worker printf("BC_NAME_MAX = %lu\n", BC_MAX_NAME);
4202*cf5a6c84SAndroid Build Coastguard Worker printf("BC_NUM_MAX = %lu\n", BC_MAX_NUM);
4203*cf5a6c84SAndroid Build Coastguard Worker printf("MAX Exponent = %lu\n", BC_MAX_EXP);
4204*cf5a6c84SAndroid Build Coastguard Worker printf("Number of vars = %lu\n", BC_MAX_VARS);
4205*cf5a6c84SAndroid Build Coastguard Worker
4206*cf5a6c84SAndroid Build Coastguard Worker s = bc_lex_next(&p->l);
4207*cf5a6c84SAndroid Build Coastguard Worker
4208*cf5a6c84SAndroid Build Coastguard Worker break;
4209*cf5a6c84SAndroid Build Coastguard Worker }
4210*cf5a6c84SAndroid Build Coastguard Worker
4211*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_KEY_PRINT:
4212*cf5a6c84SAndroid Build Coastguard Worker {
4213*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_print(p);
4214*cf5a6c84SAndroid Build Coastguard Worker break;
4215*cf5a6c84SAndroid Build Coastguard Worker }
4216*cf5a6c84SAndroid Build Coastguard Worker
4217*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_KEY_QUIT:
4218*cf5a6c84SAndroid Build Coastguard Worker {
4219*cf5a6c84SAndroid Build Coastguard Worker // Quit is a compile-time command. We don't exit directly,
4220*cf5a6c84SAndroid Build Coastguard Worker // so the vm can clean up. Limits do the same thing.
4221*cf5a6c84SAndroid Build Coastguard Worker s = BC_STATUS_QUIT;
4222*cf5a6c84SAndroid Build Coastguard Worker break;
4223*cf5a6c84SAndroid Build Coastguard Worker }
4224*cf5a6c84SAndroid Build Coastguard Worker
4225*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_KEY_RETURN:
4226*cf5a6c84SAndroid Build Coastguard Worker {
4227*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_return(p);
4228*cf5a6c84SAndroid Build Coastguard Worker break;
4229*cf5a6c84SAndroid Build Coastguard Worker }
4230*cf5a6c84SAndroid Build Coastguard Worker
4231*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_KEY_WHILE:
4232*cf5a6c84SAndroid Build Coastguard Worker {
4233*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_while(p);
4234*cf5a6c84SAndroid Build Coastguard Worker break;
4235*cf5a6c84SAndroid Build Coastguard Worker }
4236*cf5a6c84SAndroid Build Coastguard Worker
4237*cf5a6c84SAndroid Build Coastguard Worker default:
4238*cf5a6c84SAndroid Build Coastguard Worker {
4239*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
4240*cf5a6c84SAndroid Build Coastguard Worker break;
4241*cf5a6c84SAndroid Build Coastguard Worker }
4242*cf5a6c84SAndroid Build Coastguard Worker }
4243*cf5a6c84SAndroid Build Coastguard Worker
4244*cf5a6c84SAndroid Build Coastguard Worker if (!s && len == p->flags.len && flags == BC_PARSE_TOP_FLAG(p)) {
4245*cf5a6c84SAndroid Build Coastguard Worker if (!bc_parse_isDelimiter(p)) s = bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
4246*cf5a6c84SAndroid Build Coastguard Worker }
4247*cf5a6c84SAndroid Build Coastguard Worker
4248*cf5a6c84SAndroid Build Coastguard Worker // Make sure semicolons are eaten.
4249*cf5a6c84SAndroid Build Coastguard Worker while (!s && p->l.t == BC_LEX_SCOLON) s = bc_lex_next(&p->l);
4250*cf5a6c84SAndroid Build Coastguard Worker
4251*cf5a6c84SAndroid Build Coastguard Worker return s;
4252*cf5a6c84SAndroid Build Coastguard Worker }
4253*cf5a6c84SAndroid Build Coastguard Worker
bc_parse_parse(BcParse * p)4254*cf5a6c84SAndroid Build Coastguard Worker BcStatus bc_parse_parse(BcParse *p) {
4255*cf5a6c84SAndroid Build Coastguard Worker
4256*cf5a6c84SAndroid Build Coastguard Worker BcStatus s;
4257*cf5a6c84SAndroid Build Coastguard Worker
4258*cf5a6c84SAndroid Build Coastguard Worker if (p->l.t == BC_LEX_EOF) s = bc_parse_err(p, BC_ERROR_PARSE_EOF);
4259*cf5a6c84SAndroid Build Coastguard Worker else if (p->l.t == BC_LEX_KEY_DEFINE) {
4260*cf5a6c84SAndroid Build Coastguard Worker if (BC_PARSE_NO_EXEC(p)) return bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
4261*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_func(p);
4262*cf5a6c84SAndroid Build Coastguard Worker }
4263*cf5a6c84SAndroid Build Coastguard Worker else s = bc_parse_stmt(p);
4264*cf5a6c84SAndroid Build Coastguard Worker
4265*cf5a6c84SAndroid Build Coastguard Worker if ((s && s != BC_STATUS_QUIT) || TT.sig) s = bc_parse_reset(p, s);
4266*cf5a6c84SAndroid Build Coastguard Worker
4267*cf5a6c84SAndroid Build Coastguard Worker return s;
4268*cf5a6c84SAndroid Build Coastguard Worker }
4269*cf5a6c84SAndroid Build Coastguard Worker
bc_parse_expr_err(BcParse * p,uint8_t flags,BcParseNext next)4270*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_parse_expr_err(BcParse *p, uint8_t flags, BcParseNext next) {
4271*cf5a6c84SAndroid Build Coastguard Worker BcStatus s = BC_STATUS_SUCCESS;
4272*cf5a6c84SAndroid Build Coastguard Worker BcInst prev = BC_INST_PRINT;
4273*cf5a6c84SAndroid Build Coastguard Worker BcLexType top, t = p->l.t;
4274*cf5a6c84SAndroid Build Coastguard Worker size_t nexprs = 0, ops_bgn = p->ops.len;
4275*cf5a6c84SAndroid Build Coastguard Worker uint32_t i, nparens, nrelops;
4276*cf5a6c84SAndroid Build Coastguard Worker int pfirst, rprn, done, get_token, assign, bin_last, incdec;
4277*cf5a6c84SAndroid Build Coastguard Worker char valid[] = {0xfc, 0xff, 0xff, 0x67, 0xc0, 0x00, 0x7c, 0x0b};
4278*cf5a6c84SAndroid Build Coastguard Worker
4279*cf5a6c84SAndroid Build Coastguard Worker pfirst = p->l.t == BC_LEX_LPAREN;
4280*cf5a6c84SAndroid Build Coastguard Worker nparens = nrelops = 0;
4281*cf5a6c84SAndroid Build Coastguard Worker rprn = done = get_token = assign = incdec = 0;
4282*cf5a6c84SAndroid Build Coastguard Worker bin_last = 1;
4283*cf5a6c84SAndroid Build Coastguard Worker
4284*cf5a6c84SAndroid Build Coastguard Worker // We want to eat newlines if newlines are not a valid ending token.
4285*cf5a6c84SAndroid Build Coastguard Worker // This is for spacing in things like for loop headers.
4286*cf5a6c84SAndroid Build Coastguard Worker while (!s && (t = p->l.t) == BC_LEX_NLINE) s = bc_lex_next(&p->l);
4287*cf5a6c84SAndroid Build Coastguard Worker
4288*cf5a6c84SAndroid Build Coastguard Worker // Loop checking if token is valid in this expression
4289*cf5a6c84SAndroid Build Coastguard Worker for (; !TT.sig && !s && !done && (valid[t>>3] & (1<<(t&7))); t = p->l.t) {
4290*cf5a6c84SAndroid Build Coastguard Worker
4291*cf5a6c84SAndroid Build Coastguard Worker switch (t) {
4292*cf5a6c84SAndroid Build Coastguard Worker
4293*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_OP_INC:
4294*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_OP_DEC:
4295*cf5a6c84SAndroid Build Coastguard Worker {
4296*cf5a6c84SAndroid Build Coastguard Worker if (incdec) return bc_parse_err(p, BC_ERROR_PARSE_ASSIGN);
4297*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_incdec(p, &prev, &nexprs, flags);
4298*cf5a6c84SAndroid Build Coastguard Worker rprn = get_token = bin_last = 0;
4299*cf5a6c84SAndroid Build Coastguard Worker incdec = 1;
4300*cf5a6c84SAndroid Build Coastguard Worker break;
4301*cf5a6c84SAndroid Build Coastguard Worker }
4302*cf5a6c84SAndroid Build Coastguard Worker
4303*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_OP_MINUS:
4304*cf5a6c84SAndroid Build Coastguard Worker {
4305*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_minus(p, &prev, ops_bgn, rprn, bin_last, &nexprs);
4306*cf5a6c84SAndroid Build Coastguard Worker rprn = get_token = 0;
4307*cf5a6c84SAndroid Build Coastguard Worker bin_last = (prev == BC_INST_MINUS);
4308*cf5a6c84SAndroid Build Coastguard Worker if (bin_last) incdec = 0;
4309*cf5a6c84SAndroid Build Coastguard Worker break;
4310*cf5a6c84SAndroid Build Coastguard Worker }
4311*cf5a6c84SAndroid Build Coastguard Worker
4312*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_OP_ASSIGN_POWER:
4313*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_OP_ASSIGN_MULTIPLY:
4314*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_OP_ASSIGN_DIVIDE:
4315*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_OP_ASSIGN_MODULUS:
4316*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_OP_ASSIGN_PLUS:
4317*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_OP_ASSIGN_MINUS:
4318*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_OP_ASSIGN:
4319*cf5a6c84SAndroid Build Coastguard Worker {
4320*cf5a6c84SAndroid Build Coastguard Worker if (!BC_PARSE_INST_VAR(prev)) {
4321*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_err(p, BC_ERROR_PARSE_ASSIGN);
4322*cf5a6c84SAndroid Build Coastguard Worker break;
4323*cf5a6c84SAndroid Build Coastguard Worker }
4324*cf5a6c84SAndroid Build Coastguard Worker }
4325*cf5a6c84SAndroid Build Coastguard Worker // Fallthrough.
4326*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_OP_POWER:
4327*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_OP_MULTIPLY:
4328*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_OP_DIVIDE:
4329*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_OP_MODULUS:
4330*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_OP_PLUS:
4331*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_OP_REL_EQ:
4332*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_OP_REL_LE:
4333*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_OP_REL_GE:
4334*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_OP_REL_NE:
4335*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_OP_REL_LT:
4336*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_OP_REL_GT:
4337*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_OP_BOOL_NOT:
4338*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_OP_BOOL_OR:
4339*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_OP_BOOL_AND:
4340*cf5a6c84SAndroid Build Coastguard Worker {
4341*cf5a6c84SAndroid Build Coastguard Worker if (BC_PARSE_OP_PREFIX(t)) {
4342*cf5a6c84SAndroid Build Coastguard Worker if (!bin_last && !BC_PARSE_OP_PREFIX(p->l.last))
4343*cf5a6c84SAndroid Build Coastguard Worker return bc_parse_err(p, BC_ERROR_PARSE_EXPR);
4344*cf5a6c84SAndroid Build Coastguard Worker }
4345*cf5a6c84SAndroid Build Coastguard Worker else if (BC_PARSE_PREV_PREFIX(prev) || bin_last)
4346*cf5a6c84SAndroid Build Coastguard Worker return bc_parse_err(p, BC_ERROR_PARSE_EXPR);
4347*cf5a6c84SAndroid Build Coastguard Worker
4348*cf5a6c84SAndroid Build Coastguard Worker nrelops += (t >= BC_LEX_OP_REL_EQ && t <= BC_LEX_OP_REL_GT);
4349*cf5a6c84SAndroid Build Coastguard Worker prev = BC_PARSE_TOKEN_INST(t);
4350*cf5a6c84SAndroid Build Coastguard Worker bc_parse_operator(p, t, ops_bgn, &nexprs);
4351*cf5a6c84SAndroid Build Coastguard Worker rprn = incdec = 0;
4352*cf5a6c84SAndroid Build Coastguard Worker get_token = 1;
4353*cf5a6c84SAndroid Build Coastguard Worker bin_last = !BC_PARSE_OP_PREFIX(t);
4354*cf5a6c84SAndroid Build Coastguard Worker
4355*cf5a6c84SAndroid Build Coastguard Worker break;
4356*cf5a6c84SAndroid Build Coastguard Worker }
4357*cf5a6c84SAndroid Build Coastguard Worker
4358*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_LPAREN:
4359*cf5a6c84SAndroid Build Coastguard Worker {
4360*cf5a6c84SAndroid Build Coastguard Worker if (BC_PARSE_LEAF(prev, bin_last, rprn))
4361*cf5a6c84SAndroid Build Coastguard Worker return bc_parse_err(p, BC_ERROR_PARSE_EXPR);
4362*cf5a6c84SAndroid Build Coastguard Worker
4363*cf5a6c84SAndroid Build Coastguard Worker ++nparens;
4364*cf5a6c84SAndroid Build Coastguard Worker rprn = incdec = 0;
4365*cf5a6c84SAndroid Build Coastguard Worker get_token = 1;
4366*cf5a6c84SAndroid Build Coastguard Worker bc_vec_push(&p->ops, &t);
4367*cf5a6c84SAndroid Build Coastguard Worker
4368*cf5a6c84SAndroid Build Coastguard Worker break;
4369*cf5a6c84SAndroid Build Coastguard Worker }
4370*cf5a6c84SAndroid Build Coastguard Worker
4371*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_RPAREN:
4372*cf5a6c84SAndroid Build Coastguard Worker {
4373*cf5a6c84SAndroid Build Coastguard Worker // This needs to be a status. The error
4374*cf5a6c84SAndroid Build Coastguard Worker // is handled in bc_parse_expr_status().
4375*cf5a6c84SAndroid Build Coastguard Worker if (p->l.last == BC_LEX_LPAREN) return BC_STATUS_EMPTY_EXPR;
4376*cf5a6c84SAndroid Build Coastguard Worker
4377*cf5a6c84SAndroid Build Coastguard Worker if (bin_last || BC_PARSE_PREV_PREFIX(prev))
4378*cf5a6c84SAndroid Build Coastguard Worker return bc_parse_err(p, BC_ERROR_PARSE_EXPR);
4379*cf5a6c84SAndroid Build Coastguard Worker
4380*cf5a6c84SAndroid Build Coastguard Worker if (!nparens) {
4381*cf5a6c84SAndroid Build Coastguard Worker s = BC_STATUS_SUCCESS;
4382*cf5a6c84SAndroid Build Coastguard Worker done = 1;
4383*cf5a6c84SAndroid Build Coastguard Worker get_token = 0;
4384*cf5a6c84SAndroid Build Coastguard Worker break;
4385*cf5a6c84SAndroid Build Coastguard Worker }
4386*cf5a6c84SAndroid Build Coastguard Worker
4387*cf5a6c84SAndroid Build Coastguard Worker --nparens;
4388*cf5a6c84SAndroid Build Coastguard Worker rprn = 1;
4389*cf5a6c84SAndroid Build Coastguard Worker get_token = bin_last = incdec = 0;
4390*cf5a6c84SAndroid Build Coastguard Worker
4391*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_rightParen(p, ops_bgn, &nexprs);
4392*cf5a6c84SAndroid Build Coastguard Worker
4393*cf5a6c84SAndroid Build Coastguard Worker break;
4394*cf5a6c84SAndroid Build Coastguard Worker }
4395*cf5a6c84SAndroid Build Coastguard Worker
4396*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_NAME:
4397*cf5a6c84SAndroid Build Coastguard Worker {
4398*cf5a6c84SAndroid Build Coastguard Worker if (BC_PARSE_LEAF(prev, bin_last, rprn))
4399*cf5a6c84SAndroid Build Coastguard Worker return bc_parse_err(p, BC_ERROR_PARSE_EXPR);
4400*cf5a6c84SAndroid Build Coastguard Worker
4401*cf5a6c84SAndroid Build Coastguard Worker get_token = bin_last = 0;
4402*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_name(p, &prev, flags & ~BC_PARSE_NOCALL);
4403*cf5a6c84SAndroid Build Coastguard Worker rprn = (prev == BC_INST_CALL);
4404*cf5a6c84SAndroid Build Coastguard Worker ++nexprs;
4405*cf5a6c84SAndroid Build Coastguard Worker
4406*cf5a6c84SAndroid Build Coastguard Worker break;
4407*cf5a6c84SAndroid Build Coastguard Worker }
4408*cf5a6c84SAndroid Build Coastguard Worker
4409*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_NUMBER:
4410*cf5a6c84SAndroid Build Coastguard Worker {
4411*cf5a6c84SAndroid Build Coastguard Worker if (BC_PARSE_LEAF(prev, bin_last, rprn))
4412*cf5a6c84SAndroid Build Coastguard Worker return bc_parse_err(p, BC_ERROR_PARSE_EXPR);
4413*cf5a6c84SAndroid Build Coastguard Worker
4414*cf5a6c84SAndroid Build Coastguard Worker bc_parse_number(p);
4415*cf5a6c84SAndroid Build Coastguard Worker nexprs += 1;
4416*cf5a6c84SAndroid Build Coastguard Worker prev = BC_INST_NUM;
4417*cf5a6c84SAndroid Build Coastguard Worker get_token = 1;
4418*cf5a6c84SAndroid Build Coastguard Worker rprn = bin_last = 0;
4419*cf5a6c84SAndroid Build Coastguard Worker
4420*cf5a6c84SAndroid Build Coastguard Worker break;
4421*cf5a6c84SAndroid Build Coastguard Worker }
4422*cf5a6c84SAndroid Build Coastguard Worker
4423*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_KEY_IBASE:
4424*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_KEY_LAST:
4425*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_KEY_OBASE:
4426*cf5a6c84SAndroid Build Coastguard Worker {
4427*cf5a6c84SAndroid Build Coastguard Worker if (BC_PARSE_LEAF(prev, bin_last, rprn))
4428*cf5a6c84SAndroid Build Coastguard Worker return bc_parse_err(p, BC_ERROR_PARSE_EXPR);
4429*cf5a6c84SAndroid Build Coastguard Worker
4430*cf5a6c84SAndroid Build Coastguard Worker prev = (char) (t - BC_LEX_KEY_LAST + BC_INST_LAST);
4431*cf5a6c84SAndroid Build Coastguard Worker bc_parse_push(p, (char) prev);
4432*cf5a6c84SAndroid Build Coastguard Worker
4433*cf5a6c84SAndroid Build Coastguard Worker get_token = 1;
4434*cf5a6c84SAndroid Build Coastguard Worker rprn = bin_last = 0;
4435*cf5a6c84SAndroid Build Coastguard Worker ++nexprs;
4436*cf5a6c84SAndroid Build Coastguard Worker
4437*cf5a6c84SAndroid Build Coastguard Worker break;
4438*cf5a6c84SAndroid Build Coastguard Worker }
4439*cf5a6c84SAndroid Build Coastguard Worker
4440*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_KEY_LENGTH:
4441*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_KEY_SQRT:
4442*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_KEY_ABS:
4443*cf5a6c84SAndroid Build Coastguard Worker {
4444*cf5a6c84SAndroid Build Coastguard Worker if (BC_PARSE_LEAF(prev, bin_last, rprn))
4445*cf5a6c84SAndroid Build Coastguard Worker return bc_parse_err(p, BC_ERROR_PARSE_EXPR);
4446*cf5a6c84SAndroid Build Coastguard Worker
4447*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_builtin(p, t, flags, &prev);
4448*cf5a6c84SAndroid Build Coastguard Worker rprn = get_token = bin_last = incdec = 0;
4449*cf5a6c84SAndroid Build Coastguard Worker ++nexprs;
4450*cf5a6c84SAndroid Build Coastguard Worker
4451*cf5a6c84SAndroid Build Coastguard Worker break;
4452*cf5a6c84SAndroid Build Coastguard Worker }
4453*cf5a6c84SAndroid Build Coastguard Worker
4454*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_KEY_READ:
4455*cf5a6c84SAndroid Build Coastguard Worker {
4456*cf5a6c84SAndroid Build Coastguard Worker if (BC_PARSE_LEAF(prev, bin_last, rprn))
4457*cf5a6c84SAndroid Build Coastguard Worker return bc_parse_err(p, BC_ERROR_PARSE_EXPR);
4458*cf5a6c84SAndroid Build Coastguard Worker else if (flags & BC_PARSE_NOREAD)
4459*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_err(p, BC_ERROR_EXEC_REC_READ);
4460*cf5a6c84SAndroid Build Coastguard Worker else s = bc_parse_read(p);
4461*cf5a6c84SAndroid Build Coastguard Worker
4462*cf5a6c84SAndroid Build Coastguard Worker rprn = get_token = bin_last = incdec = 0;
4463*cf5a6c84SAndroid Build Coastguard Worker ++nexprs;
4464*cf5a6c84SAndroid Build Coastguard Worker prev = BC_INST_READ;
4465*cf5a6c84SAndroid Build Coastguard Worker
4466*cf5a6c84SAndroid Build Coastguard Worker break;
4467*cf5a6c84SAndroid Build Coastguard Worker }
4468*cf5a6c84SAndroid Build Coastguard Worker
4469*cf5a6c84SAndroid Build Coastguard Worker case BC_LEX_KEY_SCALE:
4470*cf5a6c84SAndroid Build Coastguard Worker {
4471*cf5a6c84SAndroid Build Coastguard Worker if (BC_PARSE_LEAF(prev, bin_last, rprn))
4472*cf5a6c84SAndroid Build Coastguard Worker return bc_parse_err(p, BC_ERROR_PARSE_EXPR);
4473*cf5a6c84SAndroid Build Coastguard Worker
4474*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_scale(p, &prev, flags);
4475*cf5a6c84SAndroid Build Coastguard Worker rprn = get_token = bin_last = 0;
4476*cf5a6c84SAndroid Build Coastguard Worker ++nexprs;
4477*cf5a6c84SAndroid Build Coastguard Worker
4478*cf5a6c84SAndroid Build Coastguard Worker break;
4479*cf5a6c84SAndroid Build Coastguard Worker }
4480*cf5a6c84SAndroid Build Coastguard Worker
4481*cf5a6c84SAndroid Build Coastguard Worker default:
4482*cf5a6c84SAndroid Build Coastguard Worker {
4483*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
4484*cf5a6c84SAndroid Build Coastguard Worker break;
4485*cf5a6c84SAndroid Build Coastguard Worker }
4486*cf5a6c84SAndroid Build Coastguard Worker }
4487*cf5a6c84SAndroid Build Coastguard Worker
4488*cf5a6c84SAndroid Build Coastguard Worker if (!s && get_token) s = bc_lex_next(&p->l);
4489*cf5a6c84SAndroid Build Coastguard Worker }
4490*cf5a6c84SAndroid Build Coastguard Worker
4491*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
4492*cf5a6c84SAndroid Build Coastguard Worker if (TT.sig) return BC_STATUS_SIGNAL;
4493*cf5a6c84SAndroid Build Coastguard Worker
4494*cf5a6c84SAndroid Build Coastguard Worker while (p->ops.len > ops_bgn) {
4495*cf5a6c84SAndroid Build Coastguard Worker
4496*cf5a6c84SAndroid Build Coastguard Worker top = BC_PARSE_TOP_OP(p);
4497*cf5a6c84SAndroid Build Coastguard Worker assign = top >= BC_LEX_OP_ASSIGN_POWER && top <= BC_LEX_OP_ASSIGN;
4498*cf5a6c84SAndroid Build Coastguard Worker
4499*cf5a6c84SAndroid Build Coastguard Worker if (top == BC_LEX_LPAREN || top == BC_LEX_RPAREN)
4500*cf5a6c84SAndroid Build Coastguard Worker return bc_parse_err(p, BC_ERROR_PARSE_EXPR);
4501*cf5a6c84SAndroid Build Coastguard Worker
4502*cf5a6c84SAndroid Build Coastguard Worker bc_parse_push(p, BC_PARSE_TOKEN_INST(top));
4503*cf5a6c84SAndroid Build Coastguard Worker
4504*cf5a6c84SAndroid Build Coastguard Worker nexprs -= !BC_PARSE_OP_PREFIX(top);
4505*cf5a6c84SAndroid Build Coastguard Worker bc_vec_pop(&p->ops);
4506*cf5a6c84SAndroid Build Coastguard Worker }
4507*cf5a6c84SAndroid Build Coastguard Worker
4508*cf5a6c84SAndroid Build Coastguard Worker if (nexprs != 1) return bc_parse_err(p, BC_ERROR_PARSE_EXPR);
4509*cf5a6c84SAndroid Build Coastguard Worker
4510*cf5a6c84SAndroid Build Coastguard Worker for (i = 0; i < next.len && t != next.tokens[i]; ++i);
4511*cf5a6c84SAndroid Build Coastguard Worker if (i == next.len && !bc_parse_isDelimiter(p))
4512*cf5a6c84SAndroid Build Coastguard Worker return bc_parse_err(p, BC_ERROR_PARSE_EXPR);
4513*cf5a6c84SAndroid Build Coastguard Worker
4514*cf5a6c84SAndroid Build Coastguard Worker if (!(flags & BC_PARSE_REL) && nrelops) {
4515*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_posixErr(p, BC_ERROR_POSIX_REL_POS);
4516*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
4517*cf5a6c84SAndroid Build Coastguard Worker }
4518*cf5a6c84SAndroid Build Coastguard Worker else if ((flags & BC_PARSE_REL) && nrelops > 1) {
4519*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_posixErr(p, BC_ERROR_POSIX_MULTIREL);
4520*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
4521*cf5a6c84SAndroid Build Coastguard Worker }
4522*cf5a6c84SAndroid Build Coastguard Worker
4523*cf5a6c84SAndroid Build Coastguard Worker if (flags & BC_PARSE_PRINT) {
4524*cf5a6c84SAndroid Build Coastguard Worker if (pfirst || !assign) bc_parse_push(p, BC_INST_PRINT);
4525*cf5a6c84SAndroid Build Coastguard Worker bc_parse_push(p, BC_INST_POP);
4526*cf5a6c84SAndroid Build Coastguard Worker }
4527*cf5a6c84SAndroid Build Coastguard Worker
4528*cf5a6c84SAndroid Build Coastguard Worker // We want to eat newlines if newlines are not a valid ending token.
4529*cf5a6c84SAndroid Build Coastguard Worker // This is for spacing in things like for loop headers.
4530*cf5a6c84SAndroid Build Coastguard Worker for (incdec = 1, i = 0; i < next.len && incdec; ++i)
4531*cf5a6c84SAndroid Build Coastguard Worker incdec = (next.tokens[i] != BC_LEX_NLINE);
4532*cf5a6c84SAndroid Build Coastguard Worker if (incdec) {
4533*cf5a6c84SAndroid Build Coastguard Worker while (!s && p->l.t == BC_LEX_NLINE) s = bc_lex_next(&p->l);
4534*cf5a6c84SAndroid Build Coastguard Worker }
4535*cf5a6c84SAndroid Build Coastguard Worker
4536*cf5a6c84SAndroid Build Coastguard Worker return s;
4537*cf5a6c84SAndroid Build Coastguard Worker }
4538*cf5a6c84SAndroid Build Coastguard Worker
bc_parse_expr_status(BcParse * p,uint8_t flags,BcParseNext next)4539*cf5a6c84SAndroid Build Coastguard Worker BcStatus bc_parse_expr_status(BcParse *p, uint8_t flags, BcParseNext next) {
4540*cf5a6c84SAndroid Build Coastguard Worker
4541*cf5a6c84SAndroid Build Coastguard Worker BcStatus s = bc_parse_expr_err(p, flags, next);
4542*cf5a6c84SAndroid Build Coastguard Worker
4543*cf5a6c84SAndroid Build Coastguard Worker if (s == BC_STATUS_EMPTY_EXPR) s = bc_parse_err(p, BC_ERROR_PARSE_EMPTY_EXPR);
4544*cf5a6c84SAndroid Build Coastguard Worker
4545*cf5a6c84SAndroid Build Coastguard Worker return s;
4546*cf5a6c84SAndroid Build Coastguard Worker }
4547*cf5a6c84SAndroid Build Coastguard Worker
bc_program_type_num(BcResult * r,BcNum * n)4548*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_program_type_num(BcResult *r, BcNum *n) {
4549*cf5a6c84SAndroid Build Coastguard Worker if (!BC_PROG_NUM(r, n)) return bc_vm_err(BC_ERROR_EXEC_TYPE);
4550*cf5a6c84SAndroid Build Coastguard Worker return BC_STATUS_SUCCESS;
4551*cf5a6c84SAndroid Build Coastguard Worker }
4552*cf5a6c84SAndroid Build Coastguard Worker
bc_program_type_match(BcResult * r,BcType t)4553*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_program_type_match(BcResult *r, BcType t) {
4554*cf5a6c84SAndroid Build Coastguard Worker if ((r->t != BC_RESULT_ARRAY) != (!t)) return bc_vm_err(BC_ERROR_EXEC_TYPE);
4555*cf5a6c84SAndroid Build Coastguard Worker return BC_STATUS_SUCCESS;
4556*cf5a6c84SAndroid Build Coastguard Worker }
4557*cf5a6c84SAndroid Build Coastguard Worker
bc_program_str(BcProgram * p,size_t idx,int str)4558*cf5a6c84SAndroid Build Coastguard Worker static char *bc_program_str(BcProgram *p, size_t idx, int str) {
4559*cf5a6c84SAndroid Build Coastguard Worker
4560*cf5a6c84SAndroid Build Coastguard Worker BcFunc *f;
4561*cf5a6c84SAndroid Build Coastguard Worker BcVec *v;
4562*cf5a6c84SAndroid Build Coastguard Worker size_t i;
4563*cf5a6c84SAndroid Build Coastguard Worker
4564*cf5a6c84SAndroid Build Coastguard Worker BcInstPtr *ip = bc_vec_item_rev(&p->stack, 0);
4565*cf5a6c84SAndroid Build Coastguard Worker i = ip->func;
4566*cf5a6c84SAndroid Build Coastguard Worker
4567*cf5a6c84SAndroid Build Coastguard Worker f = bc_vec_item(&p->fns, i);
4568*cf5a6c84SAndroid Build Coastguard Worker v = str ? &f->strs : &f->consts;
4569*cf5a6c84SAndroid Build Coastguard Worker
4570*cf5a6c84SAndroid Build Coastguard Worker return *((char**) bc_vec_item(v, idx));
4571*cf5a6c84SAndroid Build Coastguard Worker }
4572*cf5a6c84SAndroid Build Coastguard Worker
bc_program_index(char * code,size_t * bgn)4573*cf5a6c84SAndroid Build Coastguard Worker static size_t bc_program_index(char *code, size_t *bgn) {
4574*cf5a6c84SAndroid Build Coastguard Worker
4575*cf5a6c84SAndroid Build Coastguard Worker char amt = (char) code[(*bgn)++], i = 0;
4576*cf5a6c84SAndroid Build Coastguard Worker size_t res = 0;
4577*cf5a6c84SAndroid Build Coastguard Worker
4578*cf5a6c84SAndroid Build Coastguard Worker for (; i < amt; ++i, ++(*bgn)) {
4579*cf5a6c84SAndroid Build Coastguard Worker size_t temp = ((size_t) ((int) (char) code[*bgn]) & UCHAR_MAX);
4580*cf5a6c84SAndroid Build Coastguard Worker res |= (temp << (i * CHAR_BIT));
4581*cf5a6c84SAndroid Build Coastguard Worker }
4582*cf5a6c84SAndroid Build Coastguard Worker
4583*cf5a6c84SAndroid Build Coastguard Worker return res;
4584*cf5a6c84SAndroid Build Coastguard Worker }
4585*cf5a6c84SAndroid Build Coastguard Worker
bc_program_name(char * code,size_t * bgn)4586*cf5a6c84SAndroid Build Coastguard Worker static char *bc_program_name(char *code, size_t *bgn) {
4587*cf5a6c84SAndroid Build Coastguard Worker
4588*cf5a6c84SAndroid Build Coastguard Worker size_t i;
4589*cf5a6c84SAndroid Build Coastguard Worker char c;
4590*cf5a6c84SAndroid Build Coastguard Worker char *s;
4591*cf5a6c84SAndroid Build Coastguard Worker char *str = code + *bgn, *ptr = strchr(str, UCHAR_MAX);
4592*cf5a6c84SAndroid Build Coastguard Worker
4593*cf5a6c84SAndroid Build Coastguard Worker s = xmalloc(((unsigned long) ptr) - ((unsigned long) str) + 1);
4594*cf5a6c84SAndroid Build Coastguard Worker
4595*cf5a6c84SAndroid Build Coastguard Worker for (i = 0; (c = (char) code[(*bgn)++]) && c != UCHAR_MAX; ++i)
4596*cf5a6c84SAndroid Build Coastguard Worker s[i] = (char) c;
4597*cf5a6c84SAndroid Build Coastguard Worker
4598*cf5a6c84SAndroid Build Coastguard Worker s[i] = '\0';
4599*cf5a6c84SAndroid Build Coastguard Worker
4600*cf5a6c84SAndroid Build Coastguard Worker return s;
4601*cf5a6c84SAndroid Build Coastguard Worker }
4602*cf5a6c84SAndroid Build Coastguard Worker
bc_program_search(BcProgram * p,char * id,BcType type)4603*cf5a6c84SAndroid Build Coastguard Worker static BcVec* bc_program_search(BcProgram *p, char *id, BcType type) {
4604*cf5a6c84SAndroid Build Coastguard Worker
4605*cf5a6c84SAndroid Build Coastguard Worker struct str_len e, *ptr;
4606*cf5a6c84SAndroid Build Coastguard Worker BcVec *v, *map;
4607*cf5a6c84SAndroid Build Coastguard Worker size_t i;
4608*cf5a6c84SAndroid Build Coastguard Worker BcResultData data;
4609*cf5a6c84SAndroid Build Coastguard Worker int new, var = (type == BC_TYPE_VAR);
4610*cf5a6c84SAndroid Build Coastguard Worker
4611*cf5a6c84SAndroid Build Coastguard Worker v = var ? &p->vars : &p->arrs;
4612*cf5a6c84SAndroid Build Coastguard Worker map = var ? &p->var_map : &p->arr_map;
4613*cf5a6c84SAndroid Build Coastguard Worker
4614*cf5a6c84SAndroid Build Coastguard Worker e.str = id;
4615*cf5a6c84SAndroid Build Coastguard Worker e.len = v->len;
4616*cf5a6c84SAndroid Build Coastguard Worker new = bc_map_insert(map, &e, &i);
4617*cf5a6c84SAndroid Build Coastguard Worker
4618*cf5a6c84SAndroid Build Coastguard Worker if (new) {
4619*cf5a6c84SAndroid Build Coastguard Worker bc_array_init(&data.v, var);
4620*cf5a6c84SAndroid Build Coastguard Worker bc_vec_push(v, &data.v);
4621*cf5a6c84SAndroid Build Coastguard Worker }
4622*cf5a6c84SAndroid Build Coastguard Worker
4623*cf5a6c84SAndroid Build Coastguard Worker ptr = bc_vec_item(map, i);
4624*cf5a6c84SAndroid Build Coastguard Worker if (new) ptr->str = xstrdup(e.str);
4625*cf5a6c84SAndroid Build Coastguard Worker
4626*cf5a6c84SAndroid Build Coastguard Worker return bc_vec_item(v, ptr->len);
4627*cf5a6c84SAndroid Build Coastguard Worker }
4628*cf5a6c84SAndroid Build Coastguard Worker
bc_program_num(BcProgram * p,BcResult * r,BcNum ** num)4629*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_program_num(BcProgram *p, BcResult *r, BcNum **num) {
4630*cf5a6c84SAndroid Build Coastguard Worker
4631*cf5a6c84SAndroid Build Coastguard Worker BcStatus s = BC_STATUS_SUCCESS;
4632*cf5a6c84SAndroid Build Coastguard Worker BcNum *n = &r->d.n;
4633*cf5a6c84SAndroid Build Coastguard Worker
4634*cf5a6c84SAndroid Build Coastguard Worker switch (r->t) {
4635*cf5a6c84SAndroid Build Coastguard Worker
4636*cf5a6c84SAndroid Build Coastguard Worker case BC_RESULT_CONSTANT:
4637*cf5a6c84SAndroid Build Coastguard Worker {
4638*cf5a6c84SAndroid Build Coastguard Worker char *str = bc_program_str(p, r->d.id.len, 0);
4639*cf5a6c84SAndroid Build Coastguard Worker size_t len = strlen(str);
4640*cf5a6c84SAndroid Build Coastguard Worker
4641*cf5a6c84SAndroid Build Coastguard Worker bc_num_init(n, len);
4642*cf5a6c84SAndroid Build Coastguard Worker
4643*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_parse(n, str, &p->ib, p->ib_t, len == 1);
4644*cf5a6c84SAndroid Build Coastguard Worker
4645*cf5a6c84SAndroid Build Coastguard Worker if (s) {
4646*cf5a6c84SAndroid Build Coastguard Worker bc_num_free(n);
4647*cf5a6c84SAndroid Build Coastguard Worker return s;
4648*cf5a6c84SAndroid Build Coastguard Worker }
4649*cf5a6c84SAndroid Build Coastguard Worker
4650*cf5a6c84SAndroid Build Coastguard Worker r->t = BC_RESULT_TEMP;
4651*cf5a6c84SAndroid Build Coastguard Worker }
4652*cf5a6c84SAndroid Build Coastguard Worker // Fallthrough.
4653*cf5a6c84SAndroid Build Coastguard Worker case BC_RESULT_STR:
4654*cf5a6c84SAndroid Build Coastguard Worker case BC_RESULT_TEMP:
4655*cf5a6c84SAndroid Build Coastguard Worker case BC_RESULT_IBASE:
4656*cf5a6c84SAndroid Build Coastguard Worker case BC_RESULT_SCALE:
4657*cf5a6c84SAndroid Build Coastguard Worker case BC_RESULT_OBASE:
4658*cf5a6c84SAndroid Build Coastguard Worker {
4659*cf5a6c84SAndroid Build Coastguard Worker *num = n;
4660*cf5a6c84SAndroid Build Coastguard Worker break;
4661*cf5a6c84SAndroid Build Coastguard Worker }
4662*cf5a6c84SAndroid Build Coastguard Worker
4663*cf5a6c84SAndroid Build Coastguard Worker case BC_RESULT_VAR:
4664*cf5a6c84SAndroid Build Coastguard Worker case BC_RESULT_ARRAY:
4665*cf5a6c84SAndroid Build Coastguard Worker case BC_RESULT_ARRAY_ELEM:
4666*cf5a6c84SAndroid Build Coastguard Worker {
4667*cf5a6c84SAndroid Build Coastguard Worker BcVec *v;
4668*cf5a6c84SAndroid Build Coastguard Worker BcType type = (r->t == BC_RESULT_VAR) ? BC_TYPE_VAR : BC_TYPE_ARRAY;
4669*cf5a6c84SAndroid Build Coastguard Worker
4670*cf5a6c84SAndroid Build Coastguard Worker v = bc_program_search(p, r->d.id.str, type);
4671*cf5a6c84SAndroid Build Coastguard Worker
4672*cf5a6c84SAndroid Build Coastguard Worker if (r->t == BC_RESULT_ARRAY_ELEM) {
4673*cf5a6c84SAndroid Build Coastguard Worker
4674*cf5a6c84SAndroid Build Coastguard Worker size_t idx = r->d.id.len;
4675*cf5a6c84SAndroid Build Coastguard Worker
4676*cf5a6c84SAndroid Build Coastguard Worker v = bc_vec_top(v);
4677*cf5a6c84SAndroid Build Coastguard Worker
4678*cf5a6c84SAndroid Build Coastguard Worker if (v->len <= idx) bc_array_expand(v, idx + 1);
4679*cf5a6c84SAndroid Build Coastguard Worker *num = bc_vec_item(v, idx);
4680*cf5a6c84SAndroid Build Coastguard Worker }
4681*cf5a6c84SAndroid Build Coastguard Worker else *num = bc_vec_top(v);
4682*cf5a6c84SAndroid Build Coastguard Worker
4683*cf5a6c84SAndroid Build Coastguard Worker break;
4684*cf5a6c84SAndroid Build Coastguard Worker }
4685*cf5a6c84SAndroid Build Coastguard Worker
4686*cf5a6c84SAndroid Build Coastguard Worker case BC_RESULT_LAST:
4687*cf5a6c84SAndroid Build Coastguard Worker {
4688*cf5a6c84SAndroid Build Coastguard Worker *num = &p->last;
4689*cf5a6c84SAndroid Build Coastguard Worker break;
4690*cf5a6c84SAndroid Build Coastguard Worker }
4691*cf5a6c84SAndroid Build Coastguard Worker
4692*cf5a6c84SAndroid Build Coastguard Worker case BC_RESULT_ONE:
4693*cf5a6c84SAndroid Build Coastguard Worker {
4694*cf5a6c84SAndroid Build Coastguard Worker *num = &p->one;
4695*cf5a6c84SAndroid Build Coastguard Worker break;
4696*cf5a6c84SAndroid Build Coastguard Worker }
4697*cf5a6c84SAndroid Build Coastguard Worker
4698*cf5a6c84SAndroid Build Coastguard Worker case BC_RESULT_VOID:
4699*cf5a6c84SAndroid Build Coastguard Worker {
4700*cf5a6c84SAndroid Build Coastguard Worker s = bc_vm_err(BC_ERROR_EXEC_VOID_VAL);
4701*cf5a6c84SAndroid Build Coastguard Worker break;
4702*cf5a6c84SAndroid Build Coastguard Worker }
4703*cf5a6c84SAndroid Build Coastguard Worker }
4704*cf5a6c84SAndroid Build Coastguard Worker
4705*cf5a6c84SAndroid Build Coastguard Worker return s;
4706*cf5a6c84SAndroid Build Coastguard Worker }
4707*cf5a6c84SAndroid Build Coastguard Worker
bc_program_operand(BcProgram * p,BcResult ** r,BcNum ** n,size_t idx)4708*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_program_operand(BcProgram *p, BcResult **r,
4709*cf5a6c84SAndroid Build Coastguard Worker BcNum **n, size_t idx)
4710*cf5a6c84SAndroid Build Coastguard Worker {
4711*cf5a6c84SAndroid Build Coastguard Worker
4712*cf5a6c84SAndroid Build Coastguard Worker *r = bc_vec_item_rev(&p->results, idx);
4713*cf5a6c84SAndroid Build Coastguard Worker
4714*cf5a6c84SAndroid Build Coastguard Worker return bc_program_num(p, *r, n);
4715*cf5a6c84SAndroid Build Coastguard Worker }
4716*cf5a6c84SAndroid Build Coastguard Worker
bc_program_binPrep(BcProgram * p,BcResult ** l,BcNum ** ln,BcResult ** r,BcNum ** rn)4717*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_program_binPrep(BcProgram *p, BcResult **l, BcNum **ln,
4718*cf5a6c84SAndroid Build Coastguard Worker BcResult **r, BcNum **rn)
4719*cf5a6c84SAndroid Build Coastguard Worker {
4720*cf5a6c84SAndroid Build Coastguard Worker BcStatus s;
4721*cf5a6c84SAndroid Build Coastguard Worker BcResultType lt;
4722*cf5a6c84SAndroid Build Coastguard Worker
4723*cf5a6c84SAndroid Build Coastguard Worker s = bc_program_operand(p, l, ln, 1);
4724*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
4725*cf5a6c84SAndroid Build Coastguard Worker s = bc_program_operand(p, r, rn, 0);
4726*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
4727*cf5a6c84SAndroid Build Coastguard Worker
4728*cf5a6c84SAndroid Build Coastguard Worker lt = (*l)->t;
4729*cf5a6c84SAndroid Build Coastguard Worker
4730*cf5a6c84SAndroid Build Coastguard Worker // We run this again under these conditions in case any vector has been
4731*cf5a6c84SAndroid Build Coastguard Worker // reallocated out from under the BcNums or arrays we had.
4732*cf5a6c84SAndroid Build Coastguard Worker if (lt == (*r)->t && (lt == BC_RESULT_VAR || lt == BC_RESULT_ARRAY_ELEM))
4733*cf5a6c84SAndroid Build Coastguard Worker s = bc_program_num(p, *l, ln);
4734*cf5a6c84SAndroid Build Coastguard Worker
4735*cf5a6c84SAndroid Build Coastguard Worker if (lt == BC_RESULT_STR) return bc_vm_err(BC_ERROR_EXEC_TYPE);
4736*cf5a6c84SAndroid Build Coastguard Worker
4737*cf5a6c84SAndroid Build Coastguard Worker return s;
4738*cf5a6c84SAndroid Build Coastguard Worker }
4739*cf5a6c84SAndroid Build Coastguard Worker
bc_program_binOpPrep(BcProgram * p,BcResult ** l,BcNum ** ln,BcResult ** r,BcNum ** rn)4740*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_program_binOpPrep(BcProgram *p, BcResult **l, BcNum **ln,
4741*cf5a6c84SAndroid Build Coastguard Worker BcResult **r, BcNum **rn)
4742*cf5a6c84SAndroid Build Coastguard Worker {
4743*cf5a6c84SAndroid Build Coastguard Worker BcStatus s;
4744*cf5a6c84SAndroid Build Coastguard Worker
4745*cf5a6c84SAndroid Build Coastguard Worker s = bc_program_binPrep(p, l, ln, r, rn);
4746*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
4747*cf5a6c84SAndroid Build Coastguard Worker
4748*cf5a6c84SAndroid Build Coastguard Worker s = bc_program_type_num(*l, *ln);
4749*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
4750*cf5a6c84SAndroid Build Coastguard Worker
4751*cf5a6c84SAndroid Build Coastguard Worker return bc_program_type_num(*r, *rn);
4752*cf5a6c84SAndroid Build Coastguard Worker }
4753*cf5a6c84SAndroid Build Coastguard Worker
bc_program_assignPrep(BcProgram * p,BcResult ** l,BcNum ** ln,BcResult ** r,BcNum ** rn)4754*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_program_assignPrep(BcProgram *p, BcResult **l, BcNum **ln,
4755*cf5a6c84SAndroid Build Coastguard Worker BcResult **r, BcNum **rn)
4756*cf5a6c84SAndroid Build Coastguard Worker {
4757*cf5a6c84SAndroid Build Coastguard Worker BcStatus s;
4758*cf5a6c84SAndroid Build Coastguard Worker int good = 0;
4759*cf5a6c84SAndroid Build Coastguard Worker BcResultType lt;
4760*cf5a6c84SAndroid Build Coastguard Worker
4761*cf5a6c84SAndroid Build Coastguard Worker s = bc_program_binPrep(p, l, ln, r, rn);
4762*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
4763*cf5a6c84SAndroid Build Coastguard Worker
4764*cf5a6c84SAndroid Build Coastguard Worker lt = (*l)->t;
4765*cf5a6c84SAndroid Build Coastguard Worker
4766*cf5a6c84SAndroid Build Coastguard Worker if (lt == BC_RESULT_CONSTANT || lt == BC_RESULT_TEMP ||lt == BC_RESULT_ARRAY)
4767*cf5a6c84SAndroid Build Coastguard Worker return bc_vm_err(BC_ERROR_EXEC_TYPE);
4768*cf5a6c84SAndroid Build Coastguard Worker
4769*cf5a6c84SAndroid Build Coastguard Worker if (lt == BC_RESULT_ONE) return bc_vm_err(BC_ERROR_EXEC_TYPE);
4770*cf5a6c84SAndroid Build Coastguard Worker
4771*cf5a6c84SAndroid Build Coastguard Worker if (!good) s = bc_program_type_num(*r, *rn);
4772*cf5a6c84SAndroid Build Coastguard Worker
4773*cf5a6c84SAndroid Build Coastguard Worker return s;
4774*cf5a6c84SAndroid Build Coastguard Worker }
4775*cf5a6c84SAndroid Build Coastguard Worker
bc_program_binOpRetire(BcProgram * p,BcResult * r)4776*cf5a6c84SAndroid Build Coastguard Worker static void bc_program_binOpRetire(BcProgram *p, BcResult *r) {
4777*cf5a6c84SAndroid Build Coastguard Worker r->t = BC_RESULT_TEMP;
4778*cf5a6c84SAndroid Build Coastguard Worker bc_vec_pop(&p->results);
4779*cf5a6c84SAndroid Build Coastguard Worker bc_vec_pop(&p->results);
4780*cf5a6c84SAndroid Build Coastguard Worker bc_vec_push(&p->results, r);
4781*cf5a6c84SAndroid Build Coastguard Worker }
4782*cf5a6c84SAndroid Build Coastguard Worker
bc_program_prep(BcProgram * p,BcResult ** r,BcNum ** n)4783*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_program_prep(BcProgram *p, BcResult **r, BcNum **n) {
4784*cf5a6c84SAndroid Build Coastguard Worker
4785*cf5a6c84SAndroid Build Coastguard Worker BcStatus s;
4786*cf5a6c84SAndroid Build Coastguard Worker
4787*cf5a6c84SAndroid Build Coastguard Worker s = bc_program_operand(p, r, n, 0);
4788*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
4789*cf5a6c84SAndroid Build Coastguard Worker
4790*cf5a6c84SAndroid Build Coastguard Worker return bc_program_type_num(*r, *n);
4791*cf5a6c84SAndroid Build Coastguard Worker }
4792*cf5a6c84SAndroid Build Coastguard Worker
bc_program_retire(BcProgram * p,BcResult * r,BcResultType t)4793*cf5a6c84SAndroid Build Coastguard Worker static void bc_program_retire(BcProgram *p, BcResult *r, BcResultType t) {
4794*cf5a6c84SAndroid Build Coastguard Worker r->t = t;
4795*cf5a6c84SAndroid Build Coastguard Worker bc_vec_pop(&p->results);
4796*cf5a6c84SAndroid Build Coastguard Worker bc_vec_push(&p->results, r);
4797*cf5a6c84SAndroid Build Coastguard Worker }
4798*cf5a6c84SAndroid Build Coastguard Worker
bc_program_op(BcProgram * p,char inst)4799*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_program_op(BcProgram *p, char inst) {
4800*cf5a6c84SAndroid Build Coastguard Worker
4801*cf5a6c84SAndroid Build Coastguard Worker BcStatus s;
4802*cf5a6c84SAndroid Build Coastguard Worker BcResult *opd1, *opd2, res;
4803*cf5a6c84SAndroid Build Coastguard Worker BcNum *n1 = NULL, *n2 = NULL;
4804*cf5a6c84SAndroid Build Coastguard Worker size_t idx = inst - BC_INST_POWER;
4805*cf5a6c84SAndroid Build Coastguard Worker
4806*cf5a6c84SAndroid Build Coastguard Worker s = bc_program_binOpPrep(p, &opd1, &n1, &opd2, &n2);
4807*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
4808*cf5a6c84SAndroid Build Coastguard Worker bc_num_init(&res.d.n, bc_program_opReqs[idx](n1, n2, p->scale));
4809*cf5a6c84SAndroid Build Coastguard Worker
4810*cf5a6c84SAndroid Build Coastguard Worker s = bc_program_ops[idx](n1, n2, &res.d.n, p->scale);
4811*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
4812*cf5a6c84SAndroid Build Coastguard Worker bc_program_binOpRetire(p, &res);
4813*cf5a6c84SAndroid Build Coastguard Worker
4814*cf5a6c84SAndroid Build Coastguard Worker return s;
4815*cf5a6c84SAndroid Build Coastguard Worker
4816*cf5a6c84SAndroid Build Coastguard Worker err:
4817*cf5a6c84SAndroid Build Coastguard Worker bc_num_free(&res.d.n);
4818*cf5a6c84SAndroid Build Coastguard Worker return s;
4819*cf5a6c84SAndroid Build Coastguard Worker }
4820*cf5a6c84SAndroid Build Coastguard Worker
bc_program_read(BcProgram * p)4821*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_program_read(BcProgram *p) {
4822*cf5a6c84SAndroid Build Coastguard Worker
4823*cf5a6c84SAndroid Build Coastguard Worker BcStatus s;
4824*cf5a6c84SAndroid Build Coastguard Worker BcParse parse;
4825*cf5a6c84SAndroid Build Coastguard Worker BcVec buf;
4826*cf5a6c84SAndroid Build Coastguard Worker BcInstPtr ip;
4827*cf5a6c84SAndroid Build Coastguard Worker size_t i;
4828*cf5a6c84SAndroid Build Coastguard Worker char *file;
4829*cf5a6c84SAndroid Build Coastguard Worker BcFunc *f = bc_vec_item(&p->fns, BC_PROG_READ);
4830*cf5a6c84SAndroid Build Coastguard Worker
4831*cf5a6c84SAndroid Build Coastguard Worker for (i = 0; i < p->stack.len; ++i) {
4832*cf5a6c84SAndroid Build Coastguard Worker BcInstPtr *ip_ptr = bc_vec_item(&p->stack, i);
4833*cf5a6c84SAndroid Build Coastguard Worker if (ip_ptr->func == BC_PROG_READ)
4834*cf5a6c84SAndroid Build Coastguard Worker return bc_vm_err(BC_ERROR_EXEC_REC_READ);
4835*cf5a6c84SAndroid Build Coastguard Worker }
4836*cf5a6c84SAndroid Build Coastguard Worker
4837*cf5a6c84SAndroid Build Coastguard Worker file = TT.file;
4838*cf5a6c84SAndroid Build Coastguard Worker bc_lex_file(&parse.l, "<stdin>");
4839*cf5a6c84SAndroid Build Coastguard Worker bc_vec_npop(&f->code, f->code.len);
4840*cf5a6c84SAndroid Build Coastguard Worker bc_vec_init(&buf, sizeof(char), NULL);
4841*cf5a6c84SAndroid Build Coastguard Worker
4842*cf5a6c84SAndroid Build Coastguard Worker s = bc_read_line(&buf, "read> ");
4843*cf5a6c84SAndroid Build Coastguard Worker if (s) {
4844*cf5a6c84SAndroid Build Coastguard Worker if (s == BC_STATUS_EOF) s = bc_vm_err(BC_ERROR_EXEC_READ_EXPR);
4845*cf5a6c84SAndroid Build Coastguard Worker goto io_err;
4846*cf5a6c84SAndroid Build Coastguard Worker }
4847*cf5a6c84SAndroid Build Coastguard Worker
4848*cf5a6c84SAndroid Build Coastguard Worker bc_parse_init(&parse, p, BC_PROG_READ);
4849*cf5a6c84SAndroid Build Coastguard Worker
4850*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_text(&parse, buf.v);
4851*cf5a6c84SAndroid Build Coastguard Worker if (s) goto exec_err;
4852*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_expr_status(&parse, BC_PARSE_NOREAD, bc_parse_next_read);
4853*cf5a6c84SAndroid Build Coastguard Worker if (s) goto exec_err;
4854*cf5a6c84SAndroid Build Coastguard Worker
4855*cf5a6c84SAndroid Build Coastguard Worker if (parse.l.t != BC_LEX_NLINE && parse.l.t != BC_LEX_EOF) {
4856*cf5a6c84SAndroid Build Coastguard Worker s = bc_vm_err(BC_ERROR_EXEC_READ_EXPR);
4857*cf5a6c84SAndroid Build Coastguard Worker goto exec_err;
4858*cf5a6c84SAndroid Build Coastguard Worker }
4859*cf5a6c84SAndroid Build Coastguard Worker
4860*cf5a6c84SAndroid Build Coastguard Worker ip.func = BC_PROG_READ;
4861*cf5a6c84SAndroid Build Coastguard Worker ip.idx = 0;
4862*cf5a6c84SAndroid Build Coastguard Worker ip.len = p->results.len;
4863*cf5a6c84SAndroid Build Coastguard Worker
4864*cf5a6c84SAndroid Build Coastguard Worker // Update this pointer, just in case.
4865*cf5a6c84SAndroid Build Coastguard Worker f = bc_vec_item(&p->fns, BC_PROG_READ);
4866*cf5a6c84SAndroid Build Coastguard Worker
4867*cf5a6c84SAndroid Build Coastguard Worker bc_vec_pushByte(&f->code, BC_INST_RET);
4868*cf5a6c84SAndroid Build Coastguard Worker bc_vec_push(&p->stack, &ip);
4869*cf5a6c84SAndroid Build Coastguard Worker
4870*cf5a6c84SAndroid Build Coastguard Worker exec_err:
4871*cf5a6c84SAndroid Build Coastguard Worker bc_parse_free(&parse);
4872*cf5a6c84SAndroid Build Coastguard Worker io_err:
4873*cf5a6c84SAndroid Build Coastguard Worker bc_vec_free(&buf);
4874*cf5a6c84SAndroid Build Coastguard Worker TT.file = file;
4875*cf5a6c84SAndroid Build Coastguard Worker return s;
4876*cf5a6c84SAndroid Build Coastguard Worker }
4877*cf5a6c84SAndroid Build Coastguard Worker
bc_program_printChars(char * str)4878*cf5a6c84SAndroid Build Coastguard Worker static void bc_program_printChars(char *str) {
4879*cf5a6c84SAndroid Build Coastguard Worker char *nl;
4880*cf5a6c84SAndroid Build Coastguard Worker TT.nchars += printf("%s", str);
4881*cf5a6c84SAndroid Build Coastguard Worker nl = strrchr(str, '\n');
4882*cf5a6c84SAndroid Build Coastguard Worker if (nl) TT.nchars = strlen(nl + 1);
4883*cf5a6c84SAndroid Build Coastguard Worker }
4884*cf5a6c84SAndroid Build Coastguard Worker
4885*cf5a6c84SAndroid Build Coastguard Worker // Output, substituting escape sequences, see also unescape() in lib/
bc_program_printString(char * str)4886*cf5a6c84SAndroid Build Coastguard Worker static void bc_program_printString(char *str)
4887*cf5a6c84SAndroid Build Coastguard Worker {
4888*cf5a6c84SAndroid Build Coastguard Worker int i, c, idx;
4889*cf5a6c84SAndroid Build Coastguard Worker
4890*cf5a6c84SAndroid Build Coastguard Worker for (i = 0; str[i]; ++i, ++TT.nchars) {
4891*cf5a6c84SAndroid Build Coastguard Worker if ((c = str[i]) == '\\' && str[i+1]) {
4892*cf5a6c84SAndroid Build Coastguard Worker if ((idx = stridx("ab\\efnqrt", c = str[i+1])) >= 0) {
4893*cf5a6c84SAndroid Build Coastguard Worker if (c == 'n') TT.nchars = SIZE_MAX;
4894*cf5a6c84SAndroid Build Coastguard Worker c = "\a\b\\\\\f\n\"\r\t"[idx];
4895*cf5a6c84SAndroid Build Coastguard Worker }
4896*cf5a6c84SAndroid Build Coastguard Worker else putchar('\\');
4897*cf5a6c84SAndroid Build Coastguard Worker i++;
4898*cf5a6c84SAndroid Build Coastguard Worker }
4899*cf5a6c84SAndroid Build Coastguard Worker
4900*cf5a6c84SAndroid Build Coastguard Worker putchar(c);
4901*cf5a6c84SAndroid Build Coastguard Worker }
4902*cf5a6c84SAndroid Build Coastguard Worker }
4903*cf5a6c84SAndroid Build Coastguard Worker
bc_program_print(BcProgram * p,char inst,size_t idx)4904*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_program_print(BcProgram *p, char inst, size_t idx) {
4905*cf5a6c84SAndroid Build Coastguard Worker
4906*cf5a6c84SAndroid Build Coastguard Worker BcStatus s = BC_STATUS_SUCCESS;
4907*cf5a6c84SAndroid Build Coastguard Worker BcResult *r;
4908*cf5a6c84SAndroid Build Coastguard Worker char *str;
4909*cf5a6c84SAndroid Build Coastguard Worker BcNum *n = NULL;
4910*cf5a6c84SAndroid Build Coastguard Worker int pop = inst != BC_INST_PRINT;
4911*cf5a6c84SAndroid Build Coastguard Worker
4912*cf5a6c84SAndroid Build Coastguard Worker r = bc_vec_item_rev(&p->results, idx);
4913*cf5a6c84SAndroid Build Coastguard Worker
4914*cf5a6c84SAndroid Build Coastguard Worker if (r->t == BC_RESULT_VOID) {
4915*cf5a6c84SAndroid Build Coastguard Worker if (pop) return bc_vm_err(BC_ERROR_EXEC_VOID_VAL);
4916*cf5a6c84SAndroid Build Coastguard Worker return s;
4917*cf5a6c84SAndroid Build Coastguard Worker }
4918*cf5a6c84SAndroid Build Coastguard Worker
4919*cf5a6c84SAndroid Build Coastguard Worker s = bc_program_num(p, r, &n);
4920*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
4921*cf5a6c84SAndroid Build Coastguard Worker
4922*cf5a6c84SAndroid Build Coastguard Worker if (BC_PROG_NUM(r, n)) {
4923*cf5a6c84SAndroid Build Coastguard Worker bc_num_printNewline();
4924*cf5a6c84SAndroid Build Coastguard Worker
4925*cf5a6c84SAndroid Build Coastguard Worker if (!n->len) bc_num_printHex(0, 1, 0);
4926*cf5a6c84SAndroid Build Coastguard Worker else if (p->ob_t == 10) bc_num_printDecimal(n);
4927*cf5a6c84SAndroid Build Coastguard Worker else s = bc_num_printBase(n, &p->ob, p->ob_t);
4928*cf5a6c84SAndroid Build Coastguard Worker
4929*cf5a6c84SAndroid Build Coastguard Worker if (!s && !pop) {
4930*cf5a6c84SAndroid Build Coastguard Worker putchar('\n');
4931*cf5a6c84SAndroid Build Coastguard Worker TT.nchars = 0;
4932*cf5a6c84SAndroid Build Coastguard Worker }
4933*cf5a6c84SAndroid Build Coastguard Worker if (!s) bc_num_copy(&p->last, n);
4934*cf5a6c84SAndroid Build Coastguard Worker } else {
4935*cf5a6c84SAndroid Build Coastguard Worker
4936*cf5a6c84SAndroid Build Coastguard Worker size_t i = (r->t == BC_RESULT_STR) ? r->d.id.len : n->rdx;
4937*cf5a6c84SAndroid Build Coastguard Worker
4938*cf5a6c84SAndroid Build Coastguard Worker str = bc_program_str(p, i, 1);
4939*cf5a6c84SAndroid Build Coastguard Worker
4940*cf5a6c84SAndroid Build Coastguard Worker if (inst == BC_INST_PRINT_STR) bc_program_printChars(str);
4941*cf5a6c84SAndroid Build Coastguard Worker else {
4942*cf5a6c84SAndroid Build Coastguard Worker bc_program_printString(str);
4943*cf5a6c84SAndroid Build Coastguard Worker if (inst == BC_INST_PRINT) {
4944*cf5a6c84SAndroid Build Coastguard Worker putchar('\n');
4945*cf5a6c84SAndroid Build Coastguard Worker TT.nchars = 0;
4946*cf5a6c84SAndroid Build Coastguard Worker }
4947*cf5a6c84SAndroid Build Coastguard Worker }
4948*cf5a6c84SAndroid Build Coastguard Worker }
4949*cf5a6c84SAndroid Build Coastguard Worker
4950*cf5a6c84SAndroid Build Coastguard Worker if (!s && pop) bc_vec_pop(&p->results);
4951*cf5a6c84SAndroid Build Coastguard Worker
4952*cf5a6c84SAndroid Build Coastguard Worker return s;
4953*cf5a6c84SAndroid Build Coastguard Worker }
4954*cf5a6c84SAndroid Build Coastguard Worker
bc_program_negate(BcResult * r,BcNum * n)4955*cf5a6c84SAndroid Build Coastguard Worker void bc_program_negate(BcResult *r, BcNum *n) {
4956*cf5a6c84SAndroid Build Coastguard Worker BcNum *rn = &r->d.n;
4957*cf5a6c84SAndroid Build Coastguard Worker bc_num_copy(rn, n);
4958*cf5a6c84SAndroid Build Coastguard Worker if (rn->len) rn->neg = !rn->neg;
4959*cf5a6c84SAndroid Build Coastguard Worker }
4960*cf5a6c84SAndroid Build Coastguard Worker
bc_program_not(BcResult * r,BcNum * n)4961*cf5a6c84SAndroid Build Coastguard Worker void bc_program_not(BcResult *r, BcNum *n) {
4962*cf5a6c84SAndroid Build Coastguard Worker if (!BC_NUM_CMP_ZERO(n)) bc_num_one(&r->d.n);
4963*cf5a6c84SAndroid Build Coastguard Worker }
4964*cf5a6c84SAndroid Build Coastguard Worker
bc_program_unary(BcProgram * p,char inst)4965*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_program_unary(BcProgram *p, char inst) {
4966*cf5a6c84SAndroid Build Coastguard Worker
4967*cf5a6c84SAndroid Build Coastguard Worker BcStatus s;
4968*cf5a6c84SAndroid Build Coastguard Worker BcResult res, *ptr;
4969*cf5a6c84SAndroid Build Coastguard Worker BcNum *num = NULL;
4970*cf5a6c84SAndroid Build Coastguard Worker
4971*cf5a6c84SAndroid Build Coastguard Worker s = bc_program_prep(p, &ptr, &num);
4972*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
4973*cf5a6c84SAndroid Build Coastguard Worker
4974*cf5a6c84SAndroid Build Coastguard Worker bc_num_init(&res.d.n, num->len);
4975*cf5a6c84SAndroid Build Coastguard Worker bc_program_unarys[inst - BC_INST_NEG](&res, num);
4976*cf5a6c84SAndroid Build Coastguard Worker bc_program_retire(p, &res, BC_RESULT_TEMP);
4977*cf5a6c84SAndroid Build Coastguard Worker
4978*cf5a6c84SAndroid Build Coastguard Worker return s;
4979*cf5a6c84SAndroid Build Coastguard Worker }
4980*cf5a6c84SAndroid Build Coastguard Worker
bc_program_logical(BcProgram * p,char inst)4981*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_program_logical(BcProgram *p, char inst) {
4982*cf5a6c84SAndroid Build Coastguard Worker
4983*cf5a6c84SAndroid Build Coastguard Worker BcStatus s;
4984*cf5a6c84SAndroid Build Coastguard Worker BcResult *opd1, *opd2, res;
4985*cf5a6c84SAndroid Build Coastguard Worker BcNum *n1 = NULL, *n2 = NULL;
4986*cf5a6c84SAndroid Build Coastguard Worker int cond = 0;
4987*cf5a6c84SAndroid Build Coastguard Worker ssize_t cmp;
4988*cf5a6c84SAndroid Build Coastguard Worker
4989*cf5a6c84SAndroid Build Coastguard Worker s = bc_program_binOpPrep(p, &opd1, &n1, &opd2, &n2);
4990*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
4991*cf5a6c84SAndroid Build Coastguard Worker bc_num_init(&res.d.n, BC_NUM_DEF_SIZE);
4992*cf5a6c84SAndroid Build Coastguard Worker
4993*cf5a6c84SAndroid Build Coastguard Worker if (inst == BC_INST_BOOL_AND)
4994*cf5a6c84SAndroid Build Coastguard Worker cond = BC_NUM_CMP_ZERO(n1) && BC_NUM_CMP_ZERO(n2);
4995*cf5a6c84SAndroid Build Coastguard Worker else if (inst == BC_INST_BOOL_OR)
4996*cf5a6c84SAndroid Build Coastguard Worker cond = BC_NUM_CMP_ZERO(n1) || BC_NUM_CMP_ZERO(n2);
4997*cf5a6c84SAndroid Build Coastguard Worker else {
4998*cf5a6c84SAndroid Build Coastguard Worker
4999*cf5a6c84SAndroid Build Coastguard Worker cmp = bc_num_cmp(n1, n2);
5000*cf5a6c84SAndroid Build Coastguard Worker
5001*cf5a6c84SAndroid Build Coastguard Worker switch (inst) {
5002*cf5a6c84SAndroid Build Coastguard Worker
5003*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_REL_EQ:
5004*cf5a6c84SAndroid Build Coastguard Worker {
5005*cf5a6c84SAndroid Build Coastguard Worker cond = cmp == 0;
5006*cf5a6c84SAndroid Build Coastguard Worker break;
5007*cf5a6c84SAndroid Build Coastguard Worker }
5008*cf5a6c84SAndroid Build Coastguard Worker
5009*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_REL_LE:
5010*cf5a6c84SAndroid Build Coastguard Worker {
5011*cf5a6c84SAndroid Build Coastguard Worker cond = cmp <= 0;
5012*cf5a6c84SAndroid Build Coastguard Worker break;
5013*cf5a6c84SAndroid Build Coastguard Worker }
5014*cf5a6c84SAndroid Build Coastguard Worker
5015*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_REL_GE:
5016*cf5a6c84SAndroid Build Coastguard Worker {
5017*cf5a6c84SAndroid Build Coastguard Worker cond = cmp >= 0;
5018*cf5a6c84SAndroid Build Coastguard Worker break;
5019*cf5a6c84SAndroid Build Coastguard Worker }
5020*cf5a6c84SAndroid Build Coastguard Worker
5021*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_REL_NE:
5022*cf5a6c84SAndroid Build Coastguard Worker {
5023*cf5a6c84SAndroid Build Coastguard Worker cond = cmp != 0;
5024*cf5a6c84SAndroid Build Coastguard Worker break;
5025*cf5a6c84SAndroid Build Coastguard Worker }
5026*cf5a6c84SAndroid Build Coastguard Worker
5027*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_REL_LT:
5028*cf5a6c84SAndroid Build Coastguard Worker {
5029*cf5a6c84SAndroid Build Coastguard Worker cond = cmp < 0;
5030*cf5a6c84SAndroid Build Coastguard Worker break;
5031*cf5a6c84SAndroid Build Coastguard Worker }
5032*cf5a6c84SAndroid Build Coastguard Worker
5033*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_REL_GT:
5034*cf5a6c84SAndroid Build Coastguard Worker {
5035*cf5a6c84SAndroid Build Coastguard Worker cond = cmp > 0;
5036*cf5a6c84SAndroid Build Coastguard Worker break;
5037*cf5a6c84SAndroid Build Coastguard Worker }
5038*cf5a6c84SAndroid Build Coastguard Worker }
5039*cf5a6c84SAndroid Build Coastguard Worker }
5040*cf5a6c84SAndroid Build Coastguard Worker
5041*cf5a6c84SAndroid Build Coastguard Worker if (cond) bc_num_one(&res.d.n);
5042*cf5a6c84SAndroid Build Coastguard Worker
5043*cf5a6c84SAndroid Build Coastguard Worker bc_program_binOpRetire(p, &res);
5044*cf5a6c84SAndroid Build Coastguard Worker
5045*cf5a6c84SAndroid Build Coastguard Worker return s;
5046*cf5a6c84SAndroid Build Coastguard Worker }
5047*cf5a6c84SAndroid Build Coastguard Worker
bc_program_copyToVar(BcProgram * p,char * name,BcType t,int last)5048*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_program_copyToVar(BcProgram *p, char *name,
5049*cf5a6c84SAndroid Build Coastguard Worker BcType t, int last)
5050*cf5a6c84SAndroid Build Coastguard Worker {
5051*cf5a6c84SAndroid Build Coastguard Worker BcStatus s = BC_STATUS_SUCCESS;
5052*cf5a6c84SAndroid Build Coastguard Worker BcResult *ptr, r;
5053*cf5a6c84SAndroid Build Coastguard Worker BcVec *vec;
5054*cf5a6c84SAndroid Build Coastguard Worker BcNum *n = NULL;
5055*cf5a6c84SAndroid Build Coastguard Worker int var = (t == BC_TYPE_VAR);
5056*cf5a6c84SAndroid Build Coastguard Worker
5057*cf5a6c84SAndroid Build Coastguard Worker if (!last) {
5058*cf5a6c84SAndroid Build Coastguard Worker
5059*cf5a6c84SAndroid Build Coastguard Worker ptr = bc_vec_top(&p->results);
5060*cf5a6c84SAndroid Build Coastguard Worker
5061*cf5a6c84SAndroid Build Coastguard Worker if (ptr->t == BC_RESULT_VAR || ptr->t == BC_RESULT_ARRAY) {
5062*cf5a6c84SAndroid Build Coastguard Worker BcVec *v = bc_program_search(p, ptr->d.id.str, t);
5063*cf5a6c84SAndroid Build Coastguard Worker n = bc_vec_item_rev(v, 1);
5064*cf5a6c84SAndroid Build Coastguard Worker }
5065*cf5a6c84SAndroid Build Coastguard Worker else s = bc_program_num(p, ptr, &n);
5066*cf5a6c84SAndroid Build Coastguard Worker }
5067*cf5a6c84SAndroid Build Coastguard Worker else s = bc_program_operand(p, &ptr, &n, 0);
5068*cf5a6c84SAndroid Build Coastguard Worker
5069*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
5070*cf5a6c84SAndroid Build Coastguard Worker
5071*cf5a6c84SAndroid Build Coastguard Worker s = bc_program_type_match(ptr, t);
5072*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
5073*cf5a6c84SAndroid Build Coastguard Worker
5074*cf5a6c84SAndroid Build Coastguard Worker vec = bc_program_search(p, name, t);
5075*cf5a6c84SAndroid Build Coastguard Worker
5076*cf5a6c84SAndroid Build Coastguard Worker // Do this once more to make sure that pointers were not invalidated.
5077*cf5a6c84SAndroid Build Coastguard Worker vec = bc_program_search(p, name, t);
5078*cf5a6c84SAndroid Build Coastguard Worker
5079*cf5a6c84SAndroid Build Coastguard Worker if (var) bc_num_createCopy(&r.d.n, n);
5080*cf5a6c84SAndroid Build Coastguard Worker else {
5081*cf5a6c84SAndroid Build Coastguard Worker bc_array_init(&r.d.v, 1);
5082*cf5a6c84SAndroid Build Coastguard Worker bc_array_copy(&r.d.v, (BcVec *)n);
5083*cf5a6c84SAndroid Build Coastguard Worker }
5084*cf5a6c84SAndroid Build Coastguard Worker
5085*cf5a6c84SAndroid Build Coastguard Worker bc_vec_push(vec, &r.d);
5086*cf5a6c84SAndroid Build Coastguard Worker bc_vec_pop(&p->results);
5087*cf5a6c84SAndroid Build Coastguard Worker
5088*cf5a6c84SAndroid Build Coastguard Worker return s;
5089*cf5a6c84SAndroid Build Coastguard Worker }
5090*cf5a6c84SAndroid Build Coastguard Worker
bc_program_assign(BcProgram * p,char inst)5091*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_program_assign(BcProgram *p, char inst) {
5092*cf5a6c84SAndroid Build Coastguard Worker
5093*cf5a6c84SAndroid Build Coastguard Worker BcStatus s;
5094*cf5a6c84SAndroid Build Coastguard Worker BcResult *left, *right, res;
5095*cf5a6c84SAndroid Build Coastguard Worker BcNum *l = NULL, *r = NULL;
5096*cf5a6c84SAndroid Build Coastguard Worker int ib, sc;
5097*cf5a6c84SAndroid Build Coastguard Worker
5098*cf5a6c84SAndroid Build Coastguard Worker s = bc_program_assignPrep(p, &left, &l, &right, &r);
5099*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
5100*cf5a6c84SAndroid Build Coastguard Worker
5101*cf5a6c84SAndroid Build Coastguard Worker ib = (left->t == BC_RESULT_IBASE);
5102*cf5a6c84SAndroid Build Coastguard Worker sc = (left->t == BC_RESULT_SCALE);
5103*cf5a6c84SAndroid Build Coastguard Worker
5104*cf5a6c84SAndroid Build Coastguard Worker if (inst == BC_INST_ASSIGN) bc_num_copy(l, r);
5105*cf5a6c84SAndroid Build Coastguard Worker else {
5106*cf5a6c84SAndroid Build Coastguard Worker s = bc_program_ops[inst - BC_INST_ASSIGN_POWER](l, r, l, p->scale);
5107*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
5108*cf5a6c84SAndroid Build Coastguard Worker }
5109*cf5a6c84SAndroid Build Coastguard Worker
5110*cf5a6c84SAndroid Build Coastguard Worker if (ib || sc || left->t == BC_RESULT_OBASE) {
5111*cf5a6c84SAndroid Build Coastguard Worker
5112*cf5a6c84SAndroid Build Coastguard Worker size_t *ptr;
5113*cf5a6c84SAndroid Build Coastguard Worker unsigned long val, max, min;
5114*cf5a6c84SAndroid Build Coastguard Worker BcError e;
5115*cf5a6c84SAndroid Build Coastguard Worker
5116*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_ulong(l, &val);
5117*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
5118*cf5a6c84SAndroid Build Coastguard Worker e = left->t - BC_RESULT_IBASE + BC_ERROR_EXEC_IBASE;
5119*cf5a6c84SAndroid Build Coastguard Worker
5120*cf5a6c84SAndroid Build Coastguard Worker if (sc) {
5121*cf5a6c84SAndroid Build Coastguard Worker max = BC_MAX_SCALE;
5122*cf5a6c84SAndroid Build Coastguard Worker min = 0;
5123*cf5a6c84SAndroid Build Coastguard Worker ptr = &p->scale;
5124*cf5a6c84SAndroid Build Coastguard Worker }
5125*cf5a6c84SAndroid Build Coastguard Worker else {
5126*cf5a6c84SAndroid Build Coastguard Worker max = ib ? TT.max_ibase : BC_MAX_OBASE;
5127*cf5a6c84SAndroid Build Coastguard Worker min = 2;
5128*cf5a6c84SAndroid Build Coastguard Worker ptr = ib ? &p->ib_t : &p->ob_t;
5129*cf5a6c84SAndroid Build Coastguard Worker }
5130*cf5a6c84SAndroid Build Coastguard Worker
5131*cf5a6c84SAndroid Build Coastguard Worker if (val > max || val < min) return bc_vm_verr(e, min, max);
5132*cf5a6c84SAndroid Build Coastguard Worker if (!sc) bc_num_ulong2num(ib ? &p->ib : &p->ob, (unsigned long) val);
5133*cf5a6c84SAndroid Build Coastguard Worker
5134*cf5a6c84SAndroid Build Coastguard Worker *ptr = (size_t) val;
5135*cf5a6c84SAndroid Build Coastguard Worker s = BC_STATUS_SUCCESS;
5136*cf5a6c84SAndroid Build Coastguard Worker }
5137*cf5a6c84SAndroid Build Coastguard Worker
5138*cf5a6c84SAndroid Build Coastguard Worker bc_num_createCopy(&res.d.n, l);
5139*cf5a6c84SAndroid Build Coastguard Worker bc_program_binOpRetire(p, &res);
5140*cf5a6c84SAndroid Build Coastguard Worker
5141*cf5a6c84SAndroid Build Coastguard Worker return s;
5142*cf5a6c84SAndroid Build Coastguard Worker }
5143*cf5a6c84SAndroid Build Coastguard Worker
bc_program_pushVar(BcProgram * p,char * code,size_t * bgn)5144*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_program_pushVar(BcProgram *p, char *code, size_t *bgn) {
5145*cf5a6c84SAndroid Build Coastguard Worker
5146*cf5a6c84SAndroid Build Coastguard Worker BcStatus s = BC_STATUS_SUCCESS;
5147*cf5a6c84SAndroid Build Coastguard Worker BcResult r;
5148*cf5a6c84SAndroid Build Coastguard Worker char *name = bc_program_name(code, bgn);
5149*cf5a6c84SAndroid Build Coastguard Worker
5150*cf5a6c84SAndroid Build Coastguard Worker r.t = BC_RESULT_VAR;
5151*cf5a6c84SAndroid Build Coastguard Worker r.d.id.str = name;
5152*cf5a6c84SAndroid Build Coastguard Worker
5153*cf5a6c84SAndroid Build Coastguard Worker bc_vec_push(&p->results, &r);
5154*cf5a6c84SAndroid Build Coastguard Worker
5155*cf5a6c84SAndroid Build Coastguard Worker return s;
5156*cf5a6c84SAndroid Build Coastguard Worker }
5157*cf5a6c84SAndroid Build Coastguard Worker
bc_program_pushArray(BcProgram * p,char * code,size_t * bgn,char inst)5158*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_program_pushArray(BcProgram *p, char *code,
5159*cf5a6c84SAndroid Build Coastguard Worker size_t *bgn, char inst)
5160*cf5a6c84SAndroid Build Coastguard Worker {
5161*cf5a6c84SAndroid Build Coastguard Worker BcStatus s = BC_STATUS_SUCCESS;
5162*cf5a6c84SAndroid Build Coastguard Worker BcResult r;
5163*cf5a6c84SAndroid Build Coastguard Worker BcNum *num = NULL;
5164*cf5a6c84SAndroid Build Coastguard Worker
5165*cf5a6c84SAndroid Build Coastguard Worker r.d.id.str = bc_program_name(code, bgn);
5166*cf5a6c84SAndroid Build Coastguard Worker
5167*cf5a6c84SAndroid Build Coastguard Worker if (inst == BC_INST_ARRAY) {
5168*cf5a6c84SAndroid Build Coastguard Worker r.t = BC_RESULT_ARRAY;
5169*cf5a6c84SAndroid Build Coastguard Worker bc_vec_push(&p->results, &r);
5170*cf5a6c84SAndroid Build Coastguard Worker }
5171*cf5a6c84SAndroid Build Coastguard Worker else {
5172*cf5a6c84SAndroid Build Coastguard Worker
5173*cf5a6c84SAndroid Build Coastguard Worker BcResult *operand;
5174*cf5a6c84SAndroid Build Coastguard Worker unsigned long temp;
5175*cf5a6c84SAndroid Build Coastguard Worker
5176*cf5a6c84SAndroid Build Coastguard Worker s = bc_program_prep(p, &operand, &num);
5177*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
5178*cf5a6c84SAndroid Build Coastguard Worker s = bc_num_ulong(num, &temp);
5179*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
5180*cf5a6c84SAndroid Build Coastguard Worker
5181*cf5a6c84SAndroid Build Coastguard Worker if (temp > BC_MAX_DIM) {
5182*cf5a6c84SAndroid Build Coastguard Worker s = bc_vm_verr(BC_ERROR_EXEC_ARRAY_LEN, BC_MAX_DIM);
5183*cf5a6c84SAndroid Build Coastguard Worker goto err;
5184*cf5a6c84SAndroid Build Coastguard Worker }
5185*cf5a6c84SAndroid Build Coastguard Worker
5186*cf5a6c84SAndroid Build Coastguard Worker r.d.id.len = temp;
5187*cf5a6c84SAndroid Build Coastguard Worker bc_program_retire(p, &r, BC_RESULT_ARRAY_ELEM);
5188*cf5a6c84SAndroid Build Coastguard Worker }
5189*cf5a6c84SAndroid Build Coastguard Worker
5190*cf5a6c84SAndroid Build Coastguard Worker err:
5191*cf5a6c84SAndroid Build Coastguard Worker if (s) free(r.d.id.str);
5192*cf5a6c84SAndroid Build Coastguard Worker return s;
5193*cf5a6c84SAndroid Build Coastguard Worker }
5194*cf5a6c84SAndroid Build Coastguard Worker
bc_program_incdec(BcProgram * p,char inst)5195*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_program_incdec(BcProgram *p, char inst) {
5196*cf5a6c84SAndroid Build Coastguard Worker
5197*cf5a6c84SAndroid Build Coastguard Worker BcStatus s;
5198*cf5a6c84SAndroid Build Coastguard Worker BcResult *ptr, res, copy;
5199*cf5a6c84SAndroid Build Coastguard Worker BcNum *num = NULL;
5200*cf5a6c84SAndroid Build Coastguard Worker char inst2;
5201*cf5a6c84SAndroid Build Coastguard Worker
5202*cf5a6c84SAndroid Build Coastguard Worker s = bc_program_prep(p, &ptr, &num);
5203*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
5204*cf5a6c84SAndroid Build Coastguard Worker
5205*cf5a6c84SAndroid Build Coastguard Worker if (inst == BC_INST_INC_POST || inst == BC_INST_DEC_POST) {
5206*cf5a6c84SAndroid Build Coastguard Worker copy.t = BC_RESULT_TEMP;
5207*cf5a6c84SAndroid Build Coastguard Worker bc_num_createCopy(©.d.n, num);
5208*cf5a6c84SAndroid Build Coastguard Worker }
5209*cf5a6c84SAndroid Build Coastguard Worker
5210*cf5a6c84SAndroid Build Coastguard Worker res.t = BC_RESULT_ONE;
5211*cf5a6c84SAndroid Build Coastguard Worker inst2 = BC_INST_ASSIGN_PLUS + (inst & 0x01);
5212*cf5a6c84SAndroid Build Coastguard Worker
5213*cf5a6c84SAndroid Build Coastguard Worker bc_vec_push(&p->results, &res);
5214*cf5a6c84SAndroid Build Coastguard Worker bc_program_assign(p, inst2);
5215*cf5a6c84SAndroid Build Coastguard Worker
5216*cf5a6c84SAndroid Build Coastguard Worker if (inst == BC_INST_INC_POST || inst == BC_INST_DEC_POST) {
5217*cf5a6c84SAndroid Build Coastguard Worker bc_vec_pop(&p->results);
5218*cf5a6c84SAndroid Build Coastguard Worker bc_vec_push(&p->results, ©);
5219*cf5a6c84SAndroid Build Coastguard Worker }
5220*cf5a6c84SAndroid Build Coastguard Worker
5221*cf5a6c84SAndroid Build Coastguard Worker return s;
5222*cf5a6c84SAndroid Build Coastguard Worker }
5223*cf5a6c84SAndroid Build Coastguard Worker
bc_program_call(BcProgram * p,char * code,size_t * idx)5224*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_program_call(BcProgram *p, char *code,
5225*cf5a6c84SAndroid Build Coastguard Worker size_t *idx)
5226*cf5a6c84SAndroid Build Coastguard Worker {
5227*cf5a6c84SAndroid Build Coastguard Worker BcStatus s = BC_STATUS_SUCCESS;
5228*cf5a6c84SAndroid Build Coastguard Worker BcInstPtr ip;
5229*cf5a6c84SAndroid Build Coastguard Worker size_t i, nparams = bc_program_index(code, idx);
5230*cf5a6c84SAndroid Build Coastguard Worker BcFunc *f;
5231*cf5a6c84SAndroid Build Coastguard Worker BcVec *v;
5232*cf5a6c84SAndroid Build Coastguard Worker struct str_len *a;
5233*cf5a6c84SAndroid Build Coastguard Worker BcResultData param;
5234*cf5a6c84SAndroid Build Coastguard Worker BcResult *arg;
5235*cf5a6c84SAndroid Build Coastguard Worker
5236*cf5a6c84SAndroid Build Coastguard Worker ip.idx = 0;
5237*cf5a6c84SAndroid Build Coastguard Worker ip.func = bc_program_index(code, idx);
5238*cf5a6c84SAndroid Build Coastguard Worker f = bc_vec_item(&p->fns, ip.func);
5239*cf5a6c84SAndroid Build Coastguard Worker
5240*cf5a6c84SAndroid Build Coastguard Worker if (!f->code.len) return bc_vm_verr(BC_ERROR_EXEC_UNDEF_FUNC, f->name);
5241*cf5a6c84SAndroid Build Coastguard Worker if (nparams != f->nparams)
5242*cf5a6c84SAndroid Build Coastguard Worker return bc_vm_verr(BC_ERROR_EXEC_PARAMS, f->nparams, nparams);
5243*cf5a6c84SAndroid Build Coastguard Worker ip.len = p->results.len - nparams;
5244*cf5a6c84SAndroid Build Coastguard Worker
5245*cf5a6c84SAndroid Build Coastguard Worker for (i = 0; i < nparams; ++i) {
5246*cf5a6c84SAndroid Build Coastguard Worker
5247*cf5a6c84SAndroid Build Coastguard Worker size_t j;
5248*cf5a6c84SAndroid Build Coastguard Worker int last = 1;
5249*cf5a6c84SAndroid Build Coastguard Worker
5250*cf5a6c84SAndroid Build Coastguard Worker a = bc_vec_item(&f->autos, nparams - 1 - i);
5251*cf5a6c84SAndroid Build Coastguard Worker arg = bc_vec_top(&p->results);
5252*cf5a6c84SAndroid Build Coastguard Worker
5253*cf5a6c84SAndroid Build Coastguard Worker // If I have already pushed to a var, I need to make sure I
5254*cf5a6c84SAndroid Build Coastguard Worker // get the previous version, not the already pushed one.
5255*cf5a6c84SAndroid Build Coastguard Worker if (arg->t == BC_RESULT_VAR || arg->t == BC_RESULT_ARRAY) {
5256*cf5a6c84SAndroid Build Coastguard Worker for (j = 0; j < i && last; ++j) {
5257*cf5a6c84SAndroid Build Coastguard Worker struct str_len *id = bc_vec_item(&f->autos, nparams - 1 - j);
5258*cf5a6c84SAndroid Build Coastguard Worker last = strcmp(arg->d.id.str, id->str) ||
5259*cf5a6c84SAndroid Build Coastguard Worker (!id->len) != (arg->t == BC_RESULT_VAR);
5260*cf5a6c84SAndroid Build Coastguard Worker }
5261*cf5a6c84SAndroid Build Coastguard Worker }
5262*cf5a6c84SAndroid Build Coastguard Worker
5263*cf5a6c84SAndroid Build Coastguard Worker s = bc_program_copyToVar(p, a->str, a->len, last);
5264*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
5265*cf5a6c84SAndroid Build Coastguard Worker }
5266*cf5a6c84SAndroid Build Coastguard Worker
5267*cf5a6c84SAndroid Build Coastguard Worker for (; i < f->autos.len; ++i) {
5268*cf5a6c84SAndroid Build Coastguard Worker
5269*cf5a6c84SAndroid Build Coastguard Worker a = bc_vec_item(&f->autos, i);
5270*cf5a6c84SAndroid Build Coastguard Worker v = bc_program_search(p, a->str, a->len);
5271*cf5a6c84SAndroid Build Coastguard Worker
5272*cf5a6c84SAndroid Build Coastguard Worker if (a->len == BC_TYPE_VAR) {
5273*cf5a6c84SAndroid Build Coastguard Worker bc_num_init(¶m.n, BC_NUM_DEF_SIZE);
5274*cf5a6c84SAndroid Build Coastguard Worker bc_vec_push(v, ¶m.n);
5275*cf5a6c84SAndroid Build Coastguard Worker }
5276*cf5a6c84SAndroid Build Coastguard Worker else {
5277*cf5a6c84SAndroid Build Coastguard Worker bc_array_init(¶m.v, 1);
5278*cf5a6c84SAndroid Build Coastguard Worker bc_vec_push(v, ¶m.v);
5279*cf5a6c84SAndroid Build Coastguard Worker }
5280*cf5a6c84SAndroid Build Coastguard Worker }
5281*cf5a6c84SAndroid Build Coastguard Worker
5282*cf5a6c84SAndroid Build Coastguard Worker bc_vec_push(&p->stack, &ip);
5283*cf5a6c84SAndroid Build Coastguard Worker
5284*cf5a6c84SAndroid Build Coastguard Worker return BC_STATUS_SUCCESS;
5285*cf5a6c84SAndroid Build Coastguard Worker }
5286*cf5a6c84SAndroid Build Coastguard Worker
bc_program_return(BcProgram * p,char inst)5287*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_program_return(BcProgram *p, char inst) {
5288*cf5a6c84SAndroid Build Coastguard Worker
5289*cf5a6c84SAndroid Build Coastguard Worker BcStatus s;
5290*cf5a6c84SAndroid Build Coastguard Worker BcResult res;
5291*cf5a6c84SAndroid Build Coastguard Worker BcFunc *f;
5292*cf5a6c84SAndroid Build Coastguard Worker size_t i;
5293*cf5a6c84SAndroid Build Coastguard Worker BcInstPtr *ip = bc_vec_top(&p->stack);
5294*cf5a6c84SAndroid Build Coastguard Worker
5295*cf5a6c84SAndroid Build Coastguard Worker f = bc_vec_item(&p->fns, ip->func);
5296*cf5a6c84SAndroid Build Coastguard Worker res.t = BC_RESULT_TEMP;
5297*cf5a6c84SAndroid Build Coastguard Worker
5298*cf5a6c84SAndroid Build Coastguard Worker if (inst == BC_INST_RET) {
5299*cf5a6c84SAndroid Build Coastguard Worker
5300*cf5a6c84SAndroid Build Coastguard Worker BcNum *num = NULL;
5301*cf5a6c84SAndroid Build Coastguard Worker BcResult *operand;
5302*cf5a6c84SAndroid Build Coastguard Worker
5303*cf5a6c84SAndroid Build Coastguard Worker s = bc_program_operand(p, &operand, &num, 0);
5304*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
5305*cf5a6c84SAndroid Build Coastguard Worker
5306*cf5a6c84SAndroid Build Coastguard Worker bc_num_createCopy(&res.d.n, num);
5307*cf5a6c84SAndroid Build Coastguard Worker }
5308*cf5a6c84SAndroid Build Coastguard Worker else if (inst == BC_INST_RET_VOID) res.t = BC_RESULT_VOID;
5309*cf5a6c84SAndroid Build Coastguard Worker else bc_num_init(&res.d.n, BC_NUM_DEF_SIZE);
5310*cf5a6c84SAndroid Build Coastguard Worker
5311*cf5a6c84SAndroid Build Coastguard Worker // We need to pop arguments as well, so this takes that into account.
5312*cf5a6c84SAndroid Build Coastguard Worker for (i = 0; i < f->autos.len; ++i) {
5313*cf5a6c84SAndroid Build Coastguard Worker
5314*cf5a6c84SAndroid Build Coastguard Worker BcVec *v;
5315*cf5a6c84SAndroid Build Coastguard Worker struct str_len *a = bc_vec_item(&f->autos, i);
5316*cf5a6c84SAndroid Build Coastguard Worker
5317*cf5a6c84SAndroid Build Coastguard Worker v = bc_program_search(p, a->str, a->len);
5318*cf5a6c84SAndroid Build Coastguard Worker bc_vec_pop(v);
5319*cf5a6c84SAndroid Build Coastguard Worker }
5320*cf5a6c84SAndroid Build Coastguard Worker
5321*cf5a6c84SAndroid Build Coastguard Worker bc_vec_npop(&p->results, p->results.len - ip->len);
5322*cf5a6c84SAndroid Build Coastguard Worker bc_vec_push(&p->results, &res);
5323*cf5a6c84SAndroid Build Coastguard Worker bc_vec_pop(&p->stack);
5324*cf5a6c84SAndroid Build Coastguard Worker
5325*cf5a6c84SAndroid Build Coastguard Worker return BC_STATUS_SUCCESS;
5326*cf5a6c84SAndroid Build Coastguard Worker }
5327*cf5a6c84SAndroid Build Coastguard Worker
bc_program_scale(BcNum * n)5328*cf5a6c84SAndroid Build Coastguard Worker unsigned long bc_program_scale(BcNum *n) {
5329*cf5a6c84SAndroid Build Coastguard Worker return (unsigned long) n->rdx;
5330*cf5a6c84SAndroid Build Coastguard Worker }
5331*cf5a6c84SAndroid Build Coastguard Worker
bc_program_len(BcNum * n)5332*cf5a6c84SAndroid Build Coastguard Worker unsigned long bc_program_len(BcNum *n) {
5333*cf5a6c84SAndroid Build Coastguard Worker
5334*cf5a6c84SAndroid Build Coastguard Worker unsigned long len = n->len;
5335*cf5a6c84SAndroid Build Coastguard Worker size_t i;
5336*cf5a6c84SAndroid Build Coastguard Worker
5337*cf5a6c84SAndroid Build Coastguard Worker if (n->rdx != n->len) return len;
5338*cf5a6c84SAndroid Build Coastguard Worker for (i = n->len - 1; i < n->len && !n->num[i]; --len, --i);
5339*cf5a6c84SAndroid Build Coastguard Worker
5340*cf5a6c84SAndroid Build Coastguard Worker return len;
5341*cf5a6c84SAndroid Build Coastguard Worker }
5342*cf5a6c84SAndroid Build Coastguard Worker
bc_program_builtin(BcProgram * p,char inst)5343*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_program_builtin(BcProgram *p, char inst) {
5344*cf5a6c84SAndroid Build Coastguard Worker
5345*cf5a6c84SAndroid Build Coastguard Worker BcStatus s;
5346*cf5a6c84SAndroid Build Coastguard Worker BcResult *opnd;
5347*cf5a6c84SAndroid Build Coastguard Worker BcResult res;
5348*cf5a6c84SAndroid Build Coastguard Worker BcNum *num = NULL, *resn = &res.d.n;
5349*cf5a6c84SAndroid Build Coastguard Worker int len = (inst == BC_INST_LENGTH);
5350*cf5a6c84SAndroid Build Coastguard Worker
5351*cf5a6c84SAndroid Build Coastguard Worker s = bc_program_operand(p, &opnd, &num, 0);
5352*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
5353*cf5a6c84SAndroid Build Coastguard Worker
5354*cf5a6c84SAndroid Build Coastguard Worker if (inst == BC_INST_SQRT) s = bc_num_sqrt(num, resn, p->scale);
5355*cf5a6c84SAndroid Build Coastguard Worker else if (inst == BC_INST_ABS) {
5356*cf5a6c84SAndroid Build Coastguard Worker bc_num_createCopy(resn, num);
5357*cf5a6c84SAndroid Build Coastguard Worker resn->neg = 0;
5358*cf5a6c84SAndroid Build Coastguard Worker }
5359*cf5a6c84SAndroid Build Coastguard Worker else {
5360*cf5a6c84SAndroid Build Coastguard Worker
5361*cf5a6c84SAndroid Build Coastguard Worker unsigned long val = 0;
5362*cf5a6c84SAndroid Build Coastguard Worker
5363*cf5a6c84SAndroid Build Coastguard Worker if (len) {
5364*cf5a6c84SAndroid Build Coastguard Worker if (opnd->t == BC_RESULT_ARRAY)
5365*cf5a6c84SAndroid Build Coastguard Worker val = (unsigned long) ((BcVec*) num)->len;
5366*cf5a6c84SAndroid Build Coastguard Worker else val = bc_program_len(num);
5367*cf5a6c84SAndroid Build Coastguard Worker }
5368*cf5a6c84SAndroid Build Coastguard Worker else val = bc_program_scale(num);
5369*cf5a6c84SAndroid Build Coastguard Worker
5370*cf5a6c84SAndroid Build Coastguard Worker bc_num_createFromUlong(resn, val);
5371*cf5a6c84SAndroid Build Coastguard Worker }
5372*cf5a6c84SAndroid Build Coastguard Worker
5373*cf5a6c84SAndroid Build Coastguard Worker bc_program_retire(p, &res, BC_RESULT_TEMP);
5374*cf5a6c84SAndroid Build Coastguard Worker
5375*cf5a6c84SAndroid Build Coastguard Worker return s;
5376*cf5a6c84SAndroid Build Coastguard Worker }
5377*cf5a6c84SAndroid Build Coastguard Worker
bc_program_pushGlobal(BcProgram * p,char inst)5378*cf5a6c84SAndroid Build Coastguard Worker static void bc_program_pushGlobal(BcProgram *p, char inst) {
5379*cf5a6c84SAndroid Build Coastguard Worker
5380*cf5a6c84SAndroid Build Coastguard Worker BcResult res;
5381*cf5a6c84SAndroid Build Coastguard Worker unsigned long val;
5382*cf5a6c84SAndroid Build Coastguard Worker
5383*cf5a6c84SAndroid Build Coastguard Worker res.t = inst - BC_INST_IBASE + BC_RESULT_IBASE;
5384*cf5a6c84SAndroid Build Coastguard Worker if (inst == BC_INST_IBASE) val = (unsigned long) p->ib_t;
5385*cf5a6c84SAndroid Build Coastguard Worker else if (inst == BC_INST_SCALE) val = (unsigned long) p->scale;
5386*cf5a6c84SAndroid Build Coastguard Worker else val = (unsigned long) p->ob_t;
5387*cf5a6c84SAndroid Build Coastguard Worker
5388*cf5a6c84SAndroid Build Coastguard Worker bc_num_createFromUlong(&res.d.n, val);
5389*cf5a6c84SAndroid Build Coastguard Worker bc_vec_push(&p->results, &res);
5390*cf5a6c84SAndroid Build Coastguard Worker }
5391*cf5a6c84SAndroid Build Coastguard Worker
bc_program_free(BcProgram * p)5392*cf5a6c84SAndroid Build Coastguard Worker void bc_program_free(BcProgram *p) {
5393*cf5a6c84SAndroid Build Coastguard Worker bc_vec_free(&p->fns);
5394*cf5a6c84SAndroid Build Coastguard Worker bc_vec_free(&p->fn_map);
5395*cf5a6c84SAndroid Build Coastguard Worker bc_vec_free(&p->vars);
5396*cf5a6c84SAndroid Build Coastguard Worker bc_vec_free(&p->var_map);
5397*cf5a6c84SAndroid Build Coastguard Worker bc_vec_free(&p->arrs);
5398*cf5a6c84SAndroid Build Coastguard Worker bc_vec_free(&p->arr_map);
5399*cf5a6c84SAndroid Build Coastguard Worker bc_vec_free(&p->results);
5400*cf5a6c84SAndroid Build Coastguard Worker bc_vec_free(&p->stack);
5401*cf5a6c84SAndroid Build Coastguard Worker bc_num_free(&p->last);
5402*cf5a6c84SAndroid Build Coastguard Worker }
5403*cf5a6c84SAndroid Build Coastguard Worker
bc_program_init(BcProgram * p)5404*cf5a6c84SAndroid Build Coastguard Worker void bc_program_init(BcProgram *p) {
5405*cf5a6c84SAndroid Build Coastguard Worker
5406*cf5a6c84SAndroid Build Coastguard Worker BcInstPtr ip;
5407*cf5a6c84SAndroid Build Coastguard Worker
5408*cf5a6c84SAndroid Build Coastguard Worker memset(p, 0, sizeof(BcProgram));
5409*cf5a6c84SAndroid Build Coastguard Worker memset(&ip, 0, sizeof(BcInstPtr));
5410*cf5a6c84SAndroid Build Coastguard Worker
5411*cf5a6c84SAndroid Build Coastguard Worker bc_num_setup(&p->ib, p->ib_num, BC_NUM_LONG_LOG10);
5412*cf5a6c84SAndroid Build Coastguard Worker bc_num_ten(&p->ib);
5413*cf5a6c84SAndroid Build Coastguard Worker p->ib_t = 10;
5414*cf5a6c84SAndroid Build Coastguard Worker
5415*cf5a6c84SAndroid Build Coastguard Worker bc_num_setup(&p->ob, p->ob_num, BC_NUM_LONG_LOG10);
5416*cf5a6c84SAndroid Build Coastguard Worker bc_num_ten(&p->ob);
5417*cf5a6c84SAndroid Build Coastguard Worker p->ob_t = 10;
5418*cf5a6c84SAndroid Build Coastguard Worker
5419*cf5a6c84SAndroid Build Coastguard Worker bc_num_setup(&p->one, p->one_num, BC_PROG_ONE_CAP);
5420*cf5a6c84SAndroid Build Coastguard Worker bc_num_one(&p->one);
5421*cf5a6c84SAndroid Build Coastguard Worker bc_num_init(&p->last, BC_NUM_DEF_SIZE);
5422*cf5a6c84SAndroid Build Coastguard Worker
5423*cf5a6c84SAndroid Build Coastguard Worker bc_vec_init(&p->fns, sizeof(BcFunc), bc_func_free);
5424*cf5a6c84SAndroid Build Coastguard Worker bc_vec_init(&p->fn_map, sizeof(struct str_len), bc_id_free);
5425*cf5a6c84SAndroid Build Coastguard Worker bc_program_insertFunc(p, xstrdup(bc_func_main));
5426*cf5a6c84SAndroid Build Coastguard Worker bc_program_insertFunc(p, xstrdup(bc_func_read));
5427*cf5a6c84SAndroid Build Coastguard Worker
5428*cf5a6c84SAndroid Build Coastguard Worker bc_vec_init(&p->vars, sizeof(BcVec), bc_vec_free);
5429*cf5a6c84SAndroid Build Coastguard Worker bc_vec_init(&p->var_map, sizeof(struct str_len), bc_id_free);
5430*cf5a6c84SAndroid Build Coastguard Worker
5431*cf5a6c84SAndroid Build Coastguard Worker bc_vec_init(&p->arrs, sizeof(BcVec), bc_vec_free);
5432*cf5a6c84SAndroid Build Coastguard Worker bc_vec_init(&p->arr_map, sizeof(struct str_len), bc_id_free);
5433*cf5a6c84SAndroid Build Coastguard Worker
5434*cf5a6c84SAndroid Build Coastguard Worker bc_vec_init(&p->results, sizeof(BcResult), bc_result_free);
5435*cf5a6c84SAndroid Build Coastguard Worker bc_vec_init(&p->stack, sizeof(BcInstPtr), NULL);
5436*cf5a6c84SAndroid Build Coastguard Worker bc_vec_push(&p->stack, &ip);
5437*cf5a6c84SAndroid Build Coastguard Worker }
5438*cf5a6c84SAndroid Build Coastguard Worker
bc_program_addFunc(BcProgram * p,BcFunc * f,char * name)5439*cf5a6c84SAndroid Build Coastguard Worker void bc_program_addFunc(BcProgram *p, BcFunc *f, char *name) {
5440*cf5a6c84SAndroid Build Coastguard Worker bc_func_init(f, name);
5441*cf5a6c84SAndroid Build Coastguard Worker bc_vec_push(&p->fns, f);
5442*cf5a6c84SAndroid Build Coastguard Worker }
5443*cf5a6c84SAndroid Build Coastguard Worker
bc_program_insertFunc(BcProgram * p,char * name)5444*cf5a6c84SAndroid Build Coastguard Worker size_t bc_program_insertFunc(BcProgram *p, char *name) {
5445*cf5a6c84SAndroid Build Coastguard Worker
5446*cf5a6c84SAndroid Build Coastguard Worker struct str_len id;
5447*cf5a6c84SAndroid Build Coastguard Worker BcFunc f;
5448*cf5a6c84SAndroid Build Coastguard Worker int new;
5449*cf5a6c84SAndroid Build Coastguard Worker size_t idx;
5450*cf5a6c84SAndroid Build Coastguard Worker
5451*cf5a6c84SAndroid Build Coastguard Worker id.str = name;
5452*cf5a6c84SAndroid Build Coastguard Worker id.len = p->fns.len;
5453*cf5a6c84SAndroid Build Coastguard Worker
5454*cf5a6c84SAndroid Build Coastguard Worker new = bc_map_insert(&p->fn_map, &id, &idx);
5455*cf5a6c84SAndroid Build Coastguard Worker idx = ((struct BcVec *)bc_vec_item(&p->fn_map, idx))->len;
5456*cf5a6c84SAndroid Build Coastguard Worker
5457*cf5a6c84SAndroid Build Coastguard Worker if (!new) {
5458*cf5a6c84SAndroid Build Coastguard Worker BcFunc *func = bc_vec_item(&p->fns, idx);
5459*cf5a6c84SAndroid Build Coastguard Worker bc_func_reset(func);
5460*cf5a6c84SAndroid Build Coastguard Worker free(name);
5461*cf5a6c84SAndroid Build Coastguard Worker } else bc_program_addFunc(p, &f, name);
5462*cf5a6c84SAndroid Build Coastguard Worker
5463*cf5a6c84SAndroid Build Coastguard Worker return idx;
5464*cf5a6c84SAndroid Build Coastguard Worker }
5465*cf5a6c84SAndroid Build Coastguard Worker
bc_program_reset(BcProgram * p,BcStatus s)5466*cf5a6c84SAndroid Build Coastguard Worker BcStatus bc_program_reset(BcProgram *p, BcStatus s) {
5467*cf5a6c84SAndroid Build Coastguard Worker
5468*cf5a6c84SAndroid Build Coastguard Worker BcFunc *f;
5469*cf5a6c84SAndroid Build Coastguard Worker BcInstPtr *ip;
5470*cf5a6c84SAndroid Build Coastguard Worker
5471*cf5a6c84SAndroid Build Coastguard Worker bc_vec_npop(&p->stack, p->stack.len - 1);
5472*cf5a6c84SAndroid Build Coastguard Worker bc_vec_npop(&p->results, p->results.len);
5473*cf5a6c84SAndroid Build Coastguard Worker
5474*cf5a6c84SAndroid Build Coastguard Worker f = bc_vec_item(&p->fns, 0);
5475*cf5a6c84SAndroid Build Coastguard Worker ip = bc_vec_top(&p->stack);
5476*cf5a6c84SAndroid Build Coastguard Worker ip->idx = f->code.len;
5477*cf5a6c84SAndroid Build Coastguard Worker
5478*cf5a6c84SAndroid Build Coastguard Worker if (TT.sig == SIGTERM || TT.sig == SIGQUIT ||
5479*cf5a6c84SAndroid Build Coastguard Worker (!s && TT.sig == SIGINT && FLAG(i))) return BC_STATUS_QUIT;
5480*cf5a6c84SAndroid Build Coastguard Worker TT.sig = 0;
5481*cf5a6c84SAndroid Build Coastguard Worker
5482*cf5a6c84SAndroid Build Coastguard Worker if (!s || s == BC_STATUS_SIGNAL) {
5483*cf5a6c84SAndroid Build Coastguard Worker if (BC_TTYIN) {
5484*cf5a6c84SAndroid Build Coastguard Worker fputs(bc_program_ready_msg, stderr);
5485*cf5a6c84SAndroid Build Coastguard Worker fflush(stderr);
5486*cf5a6c84SAndroid Build Coastguard Worker s = BC_STATUS_SUCCESS;
5487*cf5a6c84SAndroid Build Coastguard Worker }
5488*cf5a6c84SAndroid Build Coastguard Worker else s = BC_STATUS_QUIT;
5489*cf5a6c84SAndroid Build Coastguard Worker }
5490*cf5a6c84SAndroid Build Coastguard Worker
5491*cf5a6c84SAndroid Build Coastguard Worker return s;
5492*cf5a6c84SAndroid Build Coastguard Worker }
5493*cf5a6c84SAndroid Build Coastguard Worker
bc_program_exec(BcProgram * p)5494*cf5a6c84SAndroid Build Coastguard Worker BcStatus bc_program_exec(BcProgram *p) {
5495*cf5a6c84SAndroid Build Coastguard Worker
5496*cf5a6c84SAndroid Build Coastguard Worker BcStatus s = BC_STATUS_SUCCESS;
5497*cf5a6c84SAndroid Build Coastguard Worker size_t idx;
5498*cf5a6c84SAndroid Build Coastguard Worker BcResult r, *ptr;
5499*cf5a6c84SAndroid Build Coastguard Worker BcInstPtr *ip = bc_vec_top(&p->stack);
5500*cf5a6c84SAndroid Build Coastguard Worker BcFunc *func = bc_vec_item(&p->fns, ip->func);
5501*cf5a6c84SAndroid Build Coastguard Worker char *code = func->code.v;
5502*cf5a6c84SAndroid Build Coastguard Worker int cond = 0;
5503*cf5a6c84SAndroid Build Coastguard Worker BcNum *num;
5504*cf5a6c84SAndroid Build Coastguard Worker
5505*cf5a6c84SAndroid Build Coastguard Worker while (!s && ip->idx < func->code.len) {
5506*cf5a6c84SAndroid Build Coastguard Worker
5507*cf5a6c84SAndroid Build Coastguard Worker char inst = (char) code[(ip->idx)++];
5508*cf5a6c84SAndroid Build Coastguard Worker
5509*cf5a6c84SAndroid Build Coastguard Worker switch (inst) {
5510*cf5a6c84SAndroid Build Coastguard Worker
5511*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_JUMP_ZERO:
5512*cf5a6c84SAndroid Build Coastguard Worker {
5513*cf5a6c84SAndroid Build Coastguard Worker s = bc_program_prep(p, &ptr, &num);
5514*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
5515*cf5a6c84SAndroid Build Coastguard Worker cond = !BC_NUM_CMP_ZERO(num);
5516*cf5a6c84SAndroid Build Coastguard Worker bc_vec_pop(&p->results);
5517*cf5a6c84SAndroid Build Coastguard Worker }
5518*cf5a6c84SAndroid Build Coastguard Worker // Fallthrough.
5519*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_JUMP:
5520*cf5a6c84SAndroid Build Coastguard Worker {
5521*cf5a6c84SAndroid Build Coastguard Worker size_t *addr;
5522*cf5a6c84SAndroid Build Coastguard Worker idx = bc_program_index(code, &ip->idx);
5523*cf5a6c84SAndroid Build Coastguard Worker addr = bc_vec_item(&func->labels, idx);
5524*cf5a6c84SAndroid Build Coastguard Worker if (inst == BC_INST_JUMP || cond) ip->idx = *addr;
5525*cf5a6c84SAndroid Build Coastguard Worker break;
5526*cf5a6c84SAndroid Build Coastguard Worker }
5527*cf5a6c84SAndroid Build Coastguard Worker
5528*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_CALL:
5529*cf5a6c84SAndroid Build Coastguard Worker {
5530*cf5a6c84SAndroid Build Coastguard Worker s = bc_program_call(p, code, &ip->idx);
5531*cf5a6c84SAndroid Build Coastguard Worker break;
5532*cf5a6c84SAndroid Build Coastguard Worker }
5533*cf5a6c84SAndroid Build Coastguard Worker
5534*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_INC_PRE:
5535*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_DEC_PRE:
5536*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_INC_POST:
5537*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_DEC_POST:
5538*cf5a6c84SAndroid Build Coastguard Worker {
5539*cf5a6c84SAndroid Build Coastguard Worker s = bc_program_incdec(p, inst);
5540*cf5a6c84SAndroid Build Coastguard Worker break;
5541*cf5a6c84SAndroid Build Coastguard Worker }
5542*cf5a6c84SAndroid Build Coastguard Worker
5543*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_HALT:
5544*cf5a6c84SAndroid Build Coastguard Worker {
5545*cf5a6c84SAndroid Build Coastguard Worker s = BC_STATUS_QUIT;
5546*cf5a6c84SAndroid Build Coastguard Worker break;
5547*cf5a6c84SAndroid Build Coastguard Worker }
5548*cf5a6c84SAndroid Build Coastguard Worker
5549*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_RET:
5550*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_RET0:
5551*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_RET_VOID:
5552*cf5a6c84SAndroid Build Coastguard Worker {
5553*cf5a6c84SAndroid Build Coastguard Worker s = bc_program_return(p, inst);
5554*cf5a6c84SAndroid Build Coastguard Worker break;
5555*cf5a6c84SAndroid Build Coastguard Worker }
5556*cf5a6c84SAndroid Build Coastguard Worker
5557*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_LAST:
5558*cf5a6c84SAndroid Build Coastguard Worker {
5559*cf5a6c84SAndroid Build Coastguard Worker r.t = BC_RESULT_LAST;
5560*cf5a6c84SAndroid Build Coastguard Worker bc_vec_push(&p->results, &r);
5561*cf5a6c84SAndroid Build Coastguard Worker break;
5562*cf5a6c84SAndroid Build Coastguard Worker }
5563*cf5a6c84SAndroid Build Coastguard Worker
5564*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_BOOL_OR:
5565*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_BOOL_AND:
5566*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_REL_EQ:
5567*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_REL_LE:
5568*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_REL_GE:
5569*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_REL_NE:
5570*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_REL_LT:
5571*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_REL_GT:
5572*cf5a6c84SAndroid Build Coastguard Worker {
5573*cf5a6c84SAndroid Build Coastguard Worker s = bc_program_logical(p, inst);
5574*cf5a6c84SAndroid Build Coastguard Worker break;
5575*cf5a6c84SAndroid Build Coastguard Worker }
5576*cf5a6c84SAndroid Build Coastguard Worker
5577*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_READ:
5578*cf5a6c84SAndroid Build Coastguard Worker {
5579*cf5a6c84SAndroid Build Coastguard Worker s = bc_program_read(p);
5580*cf5a6c84SAndroid Build Coastguard Worker break;
5581*cf5a6c84SAndroid Build Coastguard Worker }
5582*cf5a6c84SAndroid Build Coastguard Worker
5583*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_VAR:
5584*cf5a6c84SAndroid Build Coastguard Worker {
5585*cf5a6c84SAndroid Build Coastguard Worker s = bc_program_pushVar(p, code, &ip->idx);
5586*cf5a6c84SAndroid Build Coastguard Worker break;
5587*cf5a6c84SAndroid Build Coastguard Worker }
5588*cf5a6c84SAndroid Build Coastguard Worker
5589*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_ARRAY_ELEM:
5590*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_ARRAY:
5591*cf5a6c84SAndroid Build Coastguard Worker {
5592*cf5a6c84SAndroid Build Coastguard Worker s = bc_program_pushArray(p, code, &ip->idx, inst);
5593*cf5a6c84SAndroid Build Coastguard Worker break;
5594*cf5a6c84SAndroid Build Coastguard Worker }
5595*cf5a6c84SAndroid Build Coastguard Worker
5596*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_IBASE:
5597*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_SCALE:
5598*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_OBASE:
5599*cf5a6c84SAndroid Build Coastguard Worker {
5600*cf5a6c84SAndroid Build Coastguard Worker bc_program_pushGlobal(p, inst);
5601*cf5a6c84SAndroid Build Coastguard Worker break;
5602*cf5a6c84SAndroid Build Coastguard Worker }
5603*cf5a6c84SAndroid Build Coastguard Worker
5604*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_LENGTH:
5605*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_SCALE_FUNC:
5606*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_SQRT:
5607*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_ABS:
5608*cf5a6c84SAndroid Build Coastguard Worker {
5609*cf5a6c84SAndroid Build Coastguard Worker s = bc_program_builtin(p, inst);
5610*cf5a6c84SAndroid Build Coastguard Worker break;
5611*cf5a6c84SAndroid Build Coastguard Worker }
5612*cf5a6c84SAndroid Build Coastguard Worker
5613*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_NUM:
5614*cf5a6c84SAndroid Build Coastguard Worker {
5615*cf5a6c84SAndroid Build Coastguard Worker r.t = BC_RESULT_CONSTANT;
5616*cf5a6c84SAndroid Build Coastguard Worker r.d.id.len = bc_program_index(code, &ip->idx);
5617*cf5a6c84SAndroid Build Coastguard Worker bc_vec_push(&p->results, &r);
5618*cf5a6c84SAndroid Build Coastguard Worker break;
5619*cf5a6c84SAndroid Build Coastguard Worker }
5620*cf5a6c84SAndroid Build Coastguard Worker
5621*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_POP:
5622*cf5a6c84SAndroid Build Coastguard Worker {
5623*cf5a6c84SAndroid Build Coastguard Worker bc_vec_pop(&p->results);
5624*cf5a6c84SAndroid Build Coastguard Worker break;
5625*cf5a6c84SAndroid Build Coastguard Worker }
5626*cf5a6c84SAndroid Build Coastguard Worker
5627*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_PRINT:
5628*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_PRINT_POP:
5629*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_PRINT_STR:
5630*cf5a6c84SAndroid Build Coastguard Worker {
5631*cf5a6c84SAndroid Build Coastguard Worker s = bc_program_print(p, inst, 0);
5632*cf5a6c84SAndroid Build Coastguard Worker break;
5633*cf5a6c84SAndroid Build Coastguard Worker }
5634*cf5a6c84SAndroid Build Coastguard Worker
5635*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_STR:
5636*cf5a6c84SAndroid Build Coastguard Worker {
5637*cf5a6c84SAndroid Build Coastguard Worker r.t = BC_RESULT_STR;
5638*cf5a6c84SAndroid Build Coastguard Worker r.d.id.len = bc_program_index(code, &ip->idx);
5639*cf5a6c84SAndroid Build Coastguard Worker bc_vec_push(&p->results, &r);
5640*cf5a6c84SAndroid Build Coastguard Worker break;
5641*cf5a6c84SAndroid Build Coastguard Worker }
5642*cf5a6c84SAndroid Build Coastguard Worker
5643*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_POWER:
5644*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_MULTIPLY:
5645*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_DIVIDE:
5646*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_MODULUS:
5647*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_PLUS:
5648*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_MINUS:
5649*cf5a6c84SAndroid Build Coastguard Worker {
5650*cf5a6c84SAndroid Build Coastguard Worker s = bc_program_op(p, inst);
5651*cf5a6c84SAndroid Build Coastguard Worker break;
5652*cf5a6c84SAndroid Build Coastguard Worker }
5653*cf5a6c84SAndroid Build Coastguard Worker
5654*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_NEG:
5655*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_BOOL_NOT:
5656*cf5a6c84SAndroid Build Coastguard Worker {
5657*cf5a6c84SAndroid Build Coastguard Worker s = bc_program_unary(p, inst);
5658*cf5a6c84SAndroid Build Coastguard Worker break;
5659*cf5a6c84SAndroid Build Coastguard Worker }
5660*cf5a6c84SAndroid Build Coastguard Worker
5661*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_ASSIGN_POWER:
5662*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_ASSIGN_MULTIPLY:
5663*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_ASSIGN_DIVIDE:
5664*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_ASSIGN_MODULUS:
5665*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_ASSIGN_PLUS:
5666*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_ASSIGN_MINUS:
5667*cf5a6c84SAndroid Build Coastguard Worker case BC_INST_ASSIGN:
5668*cf5a6c84SAndroid Build Coastguard Worker {
5669*cf5a6c84SAndroid Build Coastguard Worker s = bc_program_assign(p, inst);
5670*cf5a6c84SAndroid Build Coastguard Worker break;
5671*cf5a6c84SAndroid Build Coastguard Worker }
5672*cf5a6c84SAndroid Build Coastguard Worker }
5673*cf5a6c84SAndroid Build Coastguard Worker
5674*cf5a6c84SAndroid Build Coastguard Worker if ((s && s != BC_STATUS_QUIT) || TT.sig) s = bc_program_reset(p, s);
5675*cf5a6c84SAndroid Build Coastguard Worker
5676*cf5a6c84SAndroid Build Coastguard Worker // If the stack has changed, pointers may be invalid.
5677*cf5a6c84SAndroid Build Coastguard Worker ip = bc_vec_top(&p->stack);
5678*cf5a6c84SAndroid Build Coastguard Worker func = bc_vec_item(&p->fns, ip->func);
5679*cf5a6c84SAndroid Build Coastguard Worker code = func->code.v;
5680*cf5a6c84SAndroid Build Coastguard Worker }
5681*cf5a6c84SAndroid Build Coastguard Worker
5682*cf5a6c84SAndroid Build Coastguard Worker return s;
5683*cf5a6c84SAndroid Build Coastguard Worker }
5684*cf5a6c84SAndroid Build Coastguard Worker
bc_vm_sig(int sig)5685*cf5a6c84SAndroid Build Coastguard Worker static void bc_vm_sig(int sig) {
5686*cf5a6c84SAndroid Build Coastguard Worker int err = errno;
5687*cf5a6c84SAndroid Build Coastguard Worker
5688*cf5a6c84SAndroid Build Coastguard Worker // If you run bc 2>/dev/full ctrl-C is ignored. Why? No idea.
5689*cf5a6c84SAndroid Build Coastguard Worker if (sig == SIGINT) {
5690*cf5a6c84SAndroid Build Coastguard Worker size_t len = strlen(bc_sig_msg);
5691*cf5a6c84SAndroid Build Coastguard Worker if (write(2, bc_sig_msg, len) != len) sig = 0;
5692*cf5a6c84SAndroid Build Coastguard Worker }
5693*cf5a6c84SAndroid Build Coastguard Worker TT.sig = sig;
5694*cf5a6c84SAndroid Build Coastguard Worker errno = err;
5695*cf5a6c84SAndroid Build Coastguard Worker }
5696*cf5a6c84SAndroid Build Coastguard Worker
bc_vm_info(void)5697*cf5a6c84SAndroid Build Coastguard Worker void bc_vm_info(void) {
5698*cf5a6c84SAndroid Build Coastguard Worker printf("%s %s\n", toys.which->name, "1.1.0");
5699*cf5a6c84SAndroid Build Coastguard Worker fputs(bc_copyright, stdout);
5700*cf5a6c84SAndroid Build Coastguard Worker }
5701*cf5a6c84SAndroid Build Coastguard Worker
bc_vm_printError(BcError e,char * fmt,size_t line,va_list args)5702*cf5a6c84SAndroid Build Coastguard Worker static void bc_vm_printError(BcError e, char *fmt,
5703*cf5a6c84SAndroid Build Coastguard Worker size_t line, va_list args)
5704*cf5a6c84SAndroid Build Coastguard Worker {
5705*cf5a6c84SAndroid Build Coastguard Worker // Make sure all of stdout is written first.
5706*cf5a6c84SAndroid Build Coastguard Worker fflush(stdout);
5707*cf5a6c84SAndroid Build Coastguard Worker
5708*cf5a6c84SAndroid Build Coastguard Worker fprintf(stderr, fmt, bc_errs[(size_t) bc_err_ids[e]]);
5709*cf5a6c84SAndroid Build Coastguard Worker vfprintf(stderr, bc_err_msgs[e], args);
5710*cf5a6c84SAndroid Build Coastguard Worker
5711*cf5a6c84SAndroid Build Coastguard Worker // This is the condition for parsing vs runtime.
5712*cf5a6c84SAndroid Build Coastguard Worker // If line is not 0, it is parsing.
5713*cf5a6c84SAndroid Build Coastguard Worker if (line) {
5714*cf5a6c84SAndroid Build Coastguard Worker fprintf(stderr, "\n %s", TT.file);
5715*cf5a6c84SAndroid Build Coastguard Worker fprintf(stderr, bc_err_line, line);
5716*cf5a6c84SAndroid Build Coastguard Worker }
5717*cf5a6c84SAndroid Build Coastguard Worker else {
5718*cf5a6c84SAndroid Build Coastguard Worker BcInstPtr *ip = bc_vec_item_rev(&BC_VM->prog.stack, 0);
5719*cf5a6c84SAndroid Build Coastguard Worker BcFunc *f = bc_vec_item(&BC_VM->prog.fns, ip->func);
5720*cf5a6c84SAndroid Build Coastguard Worker fprintf(stderr, "\n Function: %s", f->name);
5721*cf5a6c84SAndroid Build Coastguard Worker }
5722*cf5a6c84SAndroid Build Coastguard Worker
5723*cf5a6c84SAndroid Build Coastguard Worker fputs("\n\n", stderr);
5724*cf5a6c84SAndroid Build Coastguard Worker fflush(stderr);
5725*cf5a6c84SAndroid Build Coastguard Worker }
5726*cf5a6c84SAndroid Build Coastguard Worker
bc_vm_error(BcError e,size_t line,...)5727*cf5a6c84SAndroid Build Coastguard Worker BcStatus bc_vm_error(BcError e, size_t line, ...) {
5728*cf5a6c84SAndroid Build Coastguard Worker
5729*cf5a6c84SAndroid Build Coastguard Worker va_list args;
5730*cf5a6c84SAndroid Build Coastguard Worker
5731*cf5a6c84SAndroid Build Coastguard Worker va_start(args, line);
5732*cf5a6c84SAndroid Build Coastguard Worker bc_vm_printError(e, bc_err_fmt, line, args);
5733*cf5a6c84SAndroid Build Coastguard Worker va_end(args);
5734*cf5a6c84SAndroid Build Coastguard Worker
5735*cf5a6c84SAndroid Build Coastguard Worker return BC_STATUS_ERROR;
5736*cf5a6c84SAndroid Build Coastguard Worker }
5737*cf5a6c84SAndroid Build Coastguard Worker
bc_vm_posixError(BcError e,size_t line,...)5738*cf5a6c84SAndroid Build Coastguard Worker BcStatus bc_vm_posixError(BcError e, size_t line, ...) {
5739*cf5a6c84SAndroid Build Coastguard Worker
5740*cf5a6c84SAndroid Build Coastguard Worker va_list args;
5741*cf5a6c84SAndroid Build Coastguard Worker
5742*cf5a6c84SAndroid Build Coastguard Worker if (!(FLAG(s) || FLAG(w))) return BC_STATUS_SUCCESS;
5743*cf5a6c84SAndroid Build Coastguard Worker
5744*cf5a6c84SAndroid Build Coastguard Worker va_start(args, line);
5745*cf5a6c84SAndroid Build Coastguard Worker bc_vm_printError(e, FLAG(s) ? bc_err_fmt : bc_warn_fmt, line, args);
5746*cf5a6c84SAndroid Build Coastguard Worker va_end(args);
5747*cf5a6c84SAndroid Build Coastguard Worker
5748*cf5a6c84SAndroid Build Coastguard Worker return FLAG(s) ? BC_STATUS_ERROR : BC_STATUS_SUCCESS;
5749*cf5a6c84SAndroid Build Coastguard Worker }
5750*cf5a6c84SAndroid Build Coastguard Worker
bc_vm_clean()5751*cf5a6c84SAndroid Build Coastguard Worker static void bc_vm_clean()
5752*cf5a6c84SAndroid Build Coastguard Worker {
5753*cf5a6c84SAndroid Build Coastguard Worker BcProgram *prog = &BC_VM->prog;
5754*cf5a6c84SAndroid Build Coastguard Worker BcFunc *f = bc_vec_item(&prog->fns, BC_PROG_MAIN);
5755*cf5a6c84SAndroid Build Coastguard Worker BcInstPtr *ip = bc_vec_item(&prog->stack, 0);
5756*cf5a6c84SAndroid Build Coastguard Worker
5757*cf5a6c84SAndroid Build Coastguard Worker // If this condition is 1, we can get rid of strings,
5758*cf5a6c84SAndroid Build Coastguard Worker // constants, and code. This is an idea from busybox.
5759*cf5a6c84SAndroid Build Coastguard Worker if (!BC_PARSE_NO_EXEC(&BC_VM->prs) && prog->stack.len == 1 &&
5760*cf5a6c84SAndroid Build Coastguard Worker !prog->results.len && ip->idx == f->code.len)
5761*cf5a6c84SAndroid Build Coastguard Worker {
5762*cf5a6c84SAndroid Build Coastguard Worker bc_vec_npop(&f->labels, f->labels.len);
5763*cf5a6c84SAndroid Build Coastguard Worker bc_vec_npop(&f->strs, f->strs.len);
5764*cf5a6c84SAndroid Build Coastguard Worker bc_vec_npop(&f->consts, f->consts.len);
5765*cf5a6c84SAndroid Build Coastguard Worker bc_vec_npop(&f->code, f->code.len);
5766*cf5a6c84SAndroid Build Coastguard Worker ip->idx = 0;
5767*cf5a6c84SAndroid Build Coastguard Worker }
5768*cf5a6c84SAndroid Build Coastguard Worker }
5769*cf5a6c84SAndroid Build Coastguard Worker
bc_vm_process(char * text,int is_stdin)5770*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_vm_process(char *text, int is_stdin) {
5771*cf5a6c84SAndroid Build Coastguard Worker
5772*cf5a6c84SAndroid Build Coastguard Worker BcStatus s;
5773*cf5a6c84SAndroid Build Coastguard Worker uint16_t *flags;
5774*cf5a6c84SAndroid Build Coastguard Worker
5775*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_text(&BC_VM->prs, text);
5776*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
5777*cf5a6c84SAndroid Build Coastguard Worker
5778*cf5a6c84SAndroid Build Coastguard Worker while (BC_VM->prs.l.t != BC_LEX_EOF) {
5779*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_parse(&BC_VM->prs);
5780*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
5781*cf5a6c84SAndroid Build Coastguard Worker }
5782*cf5a6c84SAndroid Build Coastguard Worker
5783*cf5a6c84SAndroid Build Coastguard Worker flags = BC_PARSE_TOP_FLAG_PTR(&BC_VM->prs);
5784*cf5a6c84SAndroid Build Coastguard Worker
5785*cf5a6c84SAndroid Build Coastguard Worker if (!is_stdin && BC_VM->prs.flags.len == 1 && *flags == BC_PARSE_FLAG_IF_END)
5786*cf5a6c84SAndroid Build Coastguard Worker bc_parse_noElse(&BC_VM->prs);
5787*cf5a6c84SAndroid Build Coastguard Worker
5788*cf5a6c84SAndroid Build Coastguard Worker if (BC_PARSE_NO_EXEC(&BC_VM->prs)) goto err;
5789*cf5a6c84SAndroid Build Coastguard Worker
5790*cf5a6c84SAndroid Build Coastguard Worker s = bc_program_exec(&BC_VM->prog);
5791*cf5a6c84SAndroid Build Coastguard Worker if (FLAG(i)) fflush(stdout);
5792*cf5a6c84SAndroid Build Coastguard Worker
5793*cf5a6c84SAndroid Build Coastguard Worker err:
5794*cf5a6c84SAndroid Build Coastguard Worker if (s || TT.sig) s = bc_program_reset(&BC_VM->prog, s);
5795*cf5a6c84SAndroid Build Coastguard Worker bc_vm_clean();
5796*cf5a6c84SAndroid Build Coastguard Worker return s == BC_STATUS_QUIT || !FLAG(i) || !is_stdin ? s : BC_STATUS_SUCCESS;
5797*cf5a6c84SAndroid Build Coastguard Worker }
5798*cf5a6c84SAndroid Build Coastguard Worker
bc_vm_file(char * file)5799*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_vm_file(char *file) {
5800*cf5a6c84SAndroid Build Coastguard Worker
5801*cf5a6c84SAndroid Build Coastguard Worker BcStatus s;
5802*cf5a6c84SAndroid Build Coastguard Worker char *data;
5803*cf5a6c84SAndroid Build Coastguard Worker
5804*cf5a6c84SAndroid Build Coastguard Worker bc_lex_file(&BC_VM->prs.l, file);
5805*cf5a6c84SAndroid Build Coastguard Worker s = bc_read_file(file, &data);
5806*cf5a6c84SAndroid Build Coastguard Worker if (s) return s;
5807*cf5a6c84SAndroid Build Coastguard Worker
5808*cf5a6c84SAndroid Build Coastguard Worker s = bc_vm_process(data, 0);
5809*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
5810*cf5a6c84SAndroid Build Coastguard Worker
5811*cf5a6c84SAndroid Build Coastguard Worker if (BC_PARSE_NO_EXEC(&BC_VM->prs))
5812*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_err(&BC_VM->prs, BC_ERROR_PARSE_BLOCK);
5813*cf5a6c84SAndroid Build Coastguard Worker
5814*cf5a6c84SAndroid Build Coastguard Worker err:
5815*cf5a6c84SAndroid Build Coastguard Worker free(data);
5816*cf5a6c84SAndroid Build Coastguard Worker return s;
5817*cf5a6c84SAndroid Build Coastguard Worker }
5818*cf5a6c84SAndroid Build Coastguard Worker
bc_vm_stdin(void)5819*cf5a6c84SAndroid Build Coastguard Worker static BcStatus bc_vm_stdin(void) {
5820*cf5a6c84SAndroid Build Coastguard Worker
5821*cf5a6c84SAndroid Build Coastguard Worker BcStatus s = BC_STATUS_SUCCESS;
5822*cf5a6c84SAndroid Build Coastguard Worker BcVec buf, buffer;
5823*cf5a6c84SAndroid Build Coastguard Worker size_t string = 0;
5824*cf5a6c84SAndroid Build Coastguard Worker int comment = 0, done = 0;
5825*cf5a6c84SAndroid Build Coastguard Worker
5826*cf5a6c84SAndroid Build Coastguard Worker bc_lex_file(&BC_VM->prs.l, "<stdin>");
5827*cf5a6c84SAndroid Build Coastguard Worker
5828*cf5a6c84SAndroid Build Coastguard Worker bc_vec_init(&buffer, sizeof(char), NULL);
5829*cf5a6c84SAndroid Build Coastguard Worker bc_vec_init(&buf, sizeof(char), NULL);
5830*cf5a6c84SAndroid Build Coastguard Worker bc_vec_pushByte(&buffer, '\0');
5831*cf5a6c84SAndroid Build Coastguard Worker
5832*cf5a6c84SAndroid Build Coastguard Worker // This loop is complex because the vm tries not to send any lines that end
5833*cf5a6c84SAndroid Build Coastguard Worker // with a backslash to the parser, which
5834*cf5a6c84SAndroid Build Coastguard Worker // treats a backslash+newline combo as whitespace per the bc spec. In that
5835*cf5a6c84SAndroid Build Coastguard Worker // case, and for strings and comments, the parser will expect more stuff.
5836*cf5a6c84SAndroid Build Coastguard Worker while (!done && (s = bc_read_line(&buf, ">>> ")) != BC_STATUS_ERROR &&
5837*cf5a6c84SAndroid Build Coastguard Worker buf.len > 1 && !TT.sig && s != BC_STATUS_SIGNAL)
5838*cf5a6c84SAndroid Build Coastguard Worker {
5839*cf5a6c84SAndroid Build Coastguard Worker char c2, *str = buf.v;
5840*cf5a6c84SAndroid Build Coastguard Worker size_t i, len = buf.len - 1;
5841*cf5a6c84SAndroid Build Coastguard Worker
5842*cf5a6c84SAndroid Build Coastguard Worker done = (s == BC_STATUS_EOF);
5843*cf5a6c84SAndroid Build Coastguard Worker
5844*cf5a6c84SAndroid Build Coastguard Worker if (len >= 2 && str[len - 1] == '\n' && str[len - 2] == '\\') {
5845*cf5a6c84SAndroid Build Coastguard Worker bc_vec_concat(&buffer, buf.v);
5846*cf5a6c84SAndroid Build Coastguard Worker continue;
5847*cf5a6c84SAndroid Build Coastguard Worker }
5848*cf5a6c84SAndroid Build Coastguard Worker
5849*cf5a6c84SAndroid Build Coastguard Worker for (i = 0; i < len; ++i) {
5850*cf5a6c84SAndroid Build Coastguard Worker
5851*cf5a6c84SAndroid Build Coastguard Worker int notend = len > i + 1;
5852*cf5a6c84SAndroid Build Coastguard Worker char c = (char) str[i];
5853*cf5a6c84SAndroid Build Coastguard Worker
5854*cf5a6c84SAndroid Build Coastguard Worker if (!comment && (i - 1 > len || str[i - 1] != '\\')) string ^= c == '"';
5855*cf5a6c84SAndroid Build Coastguard Worker
5856*cf5a6c84SAndroid Build Coastguard Worker if (!string && notend) {
5857*cf5a6c84SAndroid Build Coastguard Worker
5858*cf5a6c84SAndroid Build Coastguard Worker c2 = str[i + 1];
5859*cf5a6c84SAndroid Build Coastguard Worker
5860*cf5a6c84SAndroid Build Coastguard Worker if (c == '/' && !comment && c2 == '*') {
5861*cf5a6c84SAndroid Build Coastguard Worker comment = 1;
5862*cf5a6c84SAndroid Build Coastguard Worker ++i;
5863*cf5a6c84SAndroid Build Coastguard Worker }
5864*cf5a6c84SAndroid Build Coastguard Worker else if (c == '*' && comment && c2 == '/') {
5865*cf5a6c84SAndroid Build Coastguard Worker comment = 0;
5866*cf5a6c84SAndroid Build Coastguard Worker ++i;
5867*cf5a6c84SAndroid Build Coastguard Worker }
5868*cf5a6c84SAndroid Build Coastguard Worker }
5869*cf5a6c84SAndroid Build Coastguard Worker }
5870*cf5a6c84SAndroid Build Coastguard Worker
5871*cf5a6c84SAndroid Build Coastguard Worker bc_vec_concat(&buffer, buf.v);
5872*cf5a6c84SAndroid Build Coastguard Worker
5873*cf5a6c84SAndroid Build Coastguard Worker if (string || comment) continue;
5874*cf5a6c84SAndroid Build Coastguard Worker if (len >= 2 && str[len - 2] == '\\' && str[len - 1] == '\n') continue;
5875*cf5a6c84SAndroid Build Coastguard Worker
5876*cf5a6c84SAndroid Build Coastguard Worker s = bc_vm_process(buffer.v, 1);
5877*cf5a6c84SAndroid Build Coastguard Worker if (s) goto err;
5878*cf5a6c84SAndroid Build Coastguard Worker
5879*cf5a6c84SAndroid Build Coastguard Worker bc_vec_empty(&buffer);
5880*cf5a6c84SAndroid Build Coastguard Worker }
5881*cf5a6c84SAndroid Build Coastguard Worker
5882*cf5a6c84SAndroid Build Coastguard Worker if (s && s != BC_STATUS_EOF) goto err;
5883*cf5a6c84SAndroid Build Coastguard Worker else if (TT.sig && !s) s = BC_STATUS_SIGNAL;
5884*cf5a6c84SAndroid Build Coastguard Worker else if (s != BC_STATUS_ERROR) {
5885*cf5a6c84SAndroid Build Coastguard Worker if (comment) s = bc_parse_err(&BC_VM->prs, BC_ERROR_PARSE_COMMENT);
5886*cf5a6c84SAndroid Build Coastguard Worker else if (string) s = bc_parse_err(&BC_VM->prs, BC_ERROR_PARSE_STRING);
5887*cf5a6c84SAndroid Build Coastguard Worker else if (BC_PARSE_NO_EXEC(&BC_VM->prs))
5888*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_err(&BC_VM->prs, BC_ERROR_PARSE_BLOCK);
5889*cf5a6c84SAndroid Build Coastguard Worker }
5890*cf5a6c84SAndroid Build Coastguard Worker
5891*cf5a6c84SAndroid Build Coastguard Worker err:
5892*cf5a6c84SAndroid Build Coastguard Worker bc_vec_free(&buf);
5893*cf5a6c84SAndroid Build Coastguard Worker bc_vec_free(&buffer);
5894*cf5a6c84SAndroid Build Coastguard Worker return s;
5895*cf5a6c84SAndroid Build Coastguard Worker }
5896*cf5a6c84SAndroid Build Coastguard Worker
bc_main(void)5897*cf5a6c84SAndroid Build Coastguard Worker void bc_main(void)
5898*cf5a6c84SAndroid Build Coastguard Worker {
5899*cf5a6c84SAndroid Build Coastguard Worker BcStatus s = 0;
5900*cf5a6c84SAndroid Build Coastguard Worker char *ss;
5901*cf5a6c84SAndroid Build Coastguard Worker
5902*cf5a6c84SAndroid Build Coastguard Worker struct sigaction sa;
5903*cf5a6c84SAndroid Build Coastguard Worker
5904*cf5a6c84SAndroid Build Coastguard Worker sigemptyset(&sa.sa_mask);
5905*cf5a6c84SAndroid Build Coastguard Worker sa.sa_handler = bc_vm_sig;
5906*cf5a6c84SAndroid Build Coastguard Worker sa.sa_flags = 0;
5907*cf5a6c84SAndroid Build Coastguard Worker sigaction(SIGINT, &sa, NULL);
5908*cf5a6c84SAndroid Build Coastguard Worker sigaction(SIGTERM, &sa, NULL);
5909*cf5a6c84SAndroid Build Coastguard Worker sigaction(SIGQUIT, &sa, NULL);
5910*cf5a6c84SAndroid Build Coastguard Worker
5911*cf5a6c84SAndroid Build Coastguard Worker TT.line_len = 69;
5912*cf5a6c84SAndroid Build Coastguard Worker ss = getenv("BC_LINE_LENGTH");
5913*cf5a6c84SAndroid Build Coastguard Worker if (ss) {
5914*cf5a6c84SAndroid Build Coastguard Worker int len = atoi(ss);
5915*cf5a6c84SAndroid Build Coastguard Worker if (len>=2 && len <= UINT16_MAX) TT.line_len = len;
5916*cf5a6c84SAndroid Build Coastguard Worker }
5917*cf5a6c84SAndroid Build Coastguard Worker
5918*cf5a6c84SAndroid Build Coastguard Worker TT.vm = xzalloc(sizeof(BcVm));
5919*cf5a6c84SAndroid Build Coastguard Worker bc_program_init(&BC_VM->prog);
5920*cf5a6c84SAndroid Build Coastguard Worker bc_parse_init(&BC_VM->prs, &BC_VM->prog, BC_PROG_MAIN);
5921*cf5a6c84SAndroid Build Coastguard Worker
5922*cf5a6c84SAndroid Build Coastguard Worker if (getenv("POSIXLY_CORRECT")) toys.optflags |= FLAG_s;
5923*cf5a6c84SAndroid Build Coastguard Worker toys.optflags |= isatty(0) ? BC_FLAG_TTYIN : 0;
5924*cf5a6c84SAndroid Build Coastguard Worker toys.optflags |= BC_TTYIN && isatty(1) ? FLAG_i : 0;
5925*cf5a6c84SAndroid Build Coastguard Worker
5926*cf5a6c84SAndroid Build Coastguard Worker TT.max_ibase = !FLAG(s) && !FLAG(w) ? 16 : 36;
5927*cf5a6c84SAndroid Build Coastguard Worker
5928*cf5a6c84SAndroid Build Coastguard Worker if (FLAG(i) && !(toys.optflags & FLAG_q)) bc_vm_info();
5929*cf5a6c84SAndroid Build Coastguard Worker
5930*cf5a6c84SAndroid Build Coastguard Worker // load -l library (if any)
5931*cf5a6c84SAndroid Build Coastguard Worker if (FLAG(l)) {
5932*cf5a6c84SAndroid Build Coastguard Worker bc_lex_file(&BC_VM->prs.l, bc_lib_name);
5933*cf5a6c84SAndroid Build Coastguard Worker s = bc_parse_text(&BC_VM->prs, bc_lib);
5934*cf5a6c84SAndroid Build Coastguard Worker
5935*cf5a6c84SAndroid Build Coastguard Worker while (!s && BC_VM->prs.l.t != BC_LEX_EOF) s = bc_parse_parse(&BC_VM->prs);
5936*cf5a6c84SAndroid Build Coastguard Worker }
5937*cf5a6c84SAndroid Build Coastguard Worker
5938*cf5a6c84SAndroid Build Coastguard Worker // parse command line argument files, then stdin
5939*cf5a6c84SAndroid Build Coastguard Worker if (!s) {
5940*cf5a6c84SAndroid Build Coastguard Worker int i;
5941*cf5a6c84SAndroid Build Coastguard Worker
5942*cf5a6c84SAndroid Build Coastguard Worker for (i = 0; !s && i < toys.optc; ++i) s = bc_vm_file(toys.optargs[i]);
5943*cf5a6c84SAndroid Build Coastguard Worker if (!s) s = bc_vm_stdin();
5944*cf5a6c84SAndroid Build Coastguard Worker }
5945*cf5a6c84SAndroid Build Coastguard Worker
5946*cf5a6c84SAndroid Build Coastguard Worker if (CFG_TOYBOX_FREE) {
5947*cf5a6c84SAndroid Build Coastguard Worker bc_program_free(&BC_VM->prog);
5948*cf5a6c84SAndroid Build Coastguard Worker bc_parse_free(&BC_VM->prs);
5949*cf5a6c84SAndroid Build Coastguard Worker free(TT.vm);
5950*cf5a6c84SAndroid Build Coastguard Worker }
5951*cf5a6c84SAndroid Build Coastguard Worker
5952*cf5a6c84SAndroid Build Coastguard Worker toys.exitval = s == BC_STATUS_ERROR;
5953*cf5a6c84SAndroid Build Coastguard Worker }
5954