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