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