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