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