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