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