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