From 01055ba89a92470587d9012c7e8707d943ebd875 Mon Sep 17 00:00:00 2001 From: Gavin Howard Date: Sat, 3 Nov 2018 11:00:21 -0600 Subject: bc: new applet, throws warning Signed-off-by: Gavin Howard Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 7449 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ miscutils/dc.c | 84 +- 2 files changed, 7492 insertions(+), 41 deletions(-) create mode 100644 miscutils/bc.c diff --git a/miscutils/bc.c b/miscutils/bc.c new file mode 100644 index 000000000..bf0cbc397 --- /dev/null +++ b/miscutils/bc.c @@ -0,0 +1,7449 @@ +/* vi: set sw=4 ts=4: */ +/* + * Licensed under GPLv2 or later, see file LICENSE in this source tree. + * Copyright (c) 2018 Gavin D. Howard and contributors. + * + * ** Automatically generated from https://github.com/gavinhoward/bc ** + * ** Do not edit unless you know what you are doing. ** + */ +//config:config BC +//config: bool "bc (45 kb; 49 kb when combined with dc)" +//config: default y +//config: help +//config: bc is a command-line, arbitrary-precision calculator with a +//config: Turing-complete language. See the GNU bc manual +//config: (https://www.gnu.org/software/bc/manual/bc.html) and bc spec +//config: (http://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html) +//config: for details. +//config: +//config: This bc has four differences to the GNU bc: +//config: +//config: 1) The period (.) can also be used as a shortcut for "last", as in +//config: the BSD bc. +//config: 2) Arrays are copied before being passed as arguments to +//config: functions. This behavior is required by the bc spec. +//config: 3) Arrays can be passed to the builtin "length" function to get +//config: the number of elements currently in the array. The following +//config: example prints "1": +//config: +//config: a[0] = 0 +//config: length(a[]) +//config: +//config: 4) The precedence of the boolean "not" operator (!) is equal to +//config: that of the unary minus (-), or negation, operator. This still +//config: allows POSIX-compliant scripts to work while somewhat +//config: preserving expected behavior (versus C) and making parsing +//config: easier. +//config: +//config: Options: +//config: +//config: -i --interactive force interactive mode +//config: -l --mathlib use predefined math routines: +//config: +//config: s(expr) = sine of expr in radians +//config: c(expr) = cosine of expr in radians +//config: a(expr) = arctangent of expr, returning +//config: radians +//config: l(expr) = natural log of expr +//config: e(expr) = raises e to the power of expr +//config: j(n, x) = Bessel function of integer order +//config: n of x +//config: +//config: -q --quiet don't print version and copyright. +//config: -s --standard error if any non-POSIX extensions are used. +//config: -w --warn warn if any non-POSIX extensions are used. +//config: -v --version print version and copyright and exit. +//config: +//config: Long options are only available if FEATURE_BC_LONG_OPTIONS is +//config: enabled. +//config: +//config:config DC +//config: bool "dc (38 kb; 49 kb when combined with bc)" +//config: default y +//config: help +//config: dc is a reverse-polish notation command-line calculator which +//config: supports unlimited precision arithmetic. See the FreeBSD man page +//config: (https://www.unix.com/man-page/FreeBSD/1/dc/) and GNU dc manual +//config: (https://www.gnu.org/software/bc/manual/dc-1.05/html_mono/dc.html) +//config: for details. +//config: +//config: This dc has a few differences from the two above: +//config: +//config: 1) When printing a byte stream (command "P"), this bc follows what +//config: the FreeBSD dc does. +//config: 2) This dc implements the GNU extensions for divmod ("~") and +//config: modular exponentiation ("|"). +//config: 3) This dc implements all FreeBSD extensions, except for "J" and +//config: "M". +//config: 4) Like the FreeBSD dc, this dc supports extended registers. +//config: However, they are implemented differently. When it encounters +//config: whitespace where a register should be, it skips the whitespace. +//config: If the character following is not a lowercase letter, an error +//config: is issued. Otherwise, the register name is parsed by the +//config: following regex: +//config: +//config: [a-z][a-z0-9_]* +//config: +//config: This generally means that register names will be surrounded by +//config: whitespace. +//config: +//config: Examples: +//config: +//config: l idx s temp L index S temp2 < do_thing +//config: +//config: Also note that, like the FreeBSD dc, extended registers are not +//config: allowed unless the "-x" option is given. +//config: +//config:config FEATURE_BC_SIGNALS +//config: bool "Enable bc/dc signal handling" +//config: default y +//config: depends on BC || DC +//config: help +//config: Enable signal handling for bc and dc. +//config: +//config:config FEATURE_BC_LONG_OPTIONS +//config: bool "Enable bc/dc long options" +//config: default y +//config: depends on BC || DC +//config: help +//config: Enable long options for bc and dc. + +//applet:IF_BC(APPLET(bc, BB_DIR_USR_BIN, BB_SUID_DROP)) +//applet:IF_DC(APPLET(dc, BB_DIR_USR_BIN, BB_SUID_DROP)) + +//kbuild:lib-$(CONFIG_BC) += bc.o +//kbuild:lib-$(CONFIG_DC) += bc.o + +//usage:#define bc_trivial_usage +//usage: "EXPRESSION...\n" +//usage: "function_definition\n" +//usage: +//usage:#define bc_full_usage "\n\n" +//usage: "See www.gnu.org/software/bc/manual/bc.html\n" +//usage: +//usage:#define bc_example_usage +//usage: "3 + 4.129\n" +//usage: "1903 - 2893\n" +//usage: "-129 * 213.28935\n" +//usage: "12 / -1932\n" +//usage: "12 % 12\n" +//usage: "34 ^ 189\n" +//usage: "scale = 13\n" +//usage: "ibase = 2\n" +//usage: "obase = A\n" +//usage: +//usage:#define dc_trivial_usage +//usage: "EXPRESSION..." +//usage: +//usage:#define dc_full_usage "\n\n" +//usage: "Tiny RPN calculator. Operations:\n" +//usage: "+, add, -, sub, *, mul, /, div, %, mod, ^, exp, ~, divmod, |, " +//usage: "modular exponentiation,\n" +//usage: "p - print top of the stack (without popping),\n" +//usage: "f - print entire stack,\n" +//usage: "k - pop the value and set the precision.\n" +//usage: "i - pop the value and set input radix.\n" +//usage: "o - pop the value and set output radix.\n" +//usage: "Examples: 'dc 2 2 add p' -> 4, 'dc 8 8 mul 2 2 + / p' -> 16" +//usage: +//usage:#define dc_example_usage +//usage: "$ dc 2 2 + p\n" +//usage: "4\n" +//usage: "$ dc 8 8 \\* 2 2 + / p\n" +//usage: "16\n" +//usage: "$ dc 0 1 and p\n" +//usage: "0\n" +//usage: "$ dc 0 1 or p\n" +//usage: "1\n" +//usage: "$ echo 72 9 div 8 mul p | dc\n" +//usage: "64\n" + +#include "libbb.h" + +typedef enum BcStatus { + + BC_STATUS_SUCCESS, + + BC_STATUS_ALLOC_ERR, + BC_STATUS_IO_ERR, + BC_STATUS_BIN_FILE, + BC_STATUS_PATH_IS_DIR, + + BC_STATUS_LEX_BAD_CHAR, + BC_STATUS_LEX_NO_STRING_END, + BC_STATUS_LEX_NO_COMMENT_END, + BC_STATUS_LEX_EOF, +#ifdef ENABLE_DC + BC_STATUS_LEX_EXTENDED_REG, +#endif // ENABLE_DC + + BC_STATUS_PARSE_BAD_TOKEN, + BC_STATUS_PARSE_BAD_EXP, + BC_STATUS_PARSE_EMPTY_EXP, + BC_STATUS_PARSE_BAD_PRINT, + BC_STATUS_PARSE_BAD_FUNC, + BC_STATUS_PARSE_BAD_ASSIGN, + BC_STATUS_PARSE_NO_AUTO, + BC_STATUS_PARSE_DUPLICATE_LOCAL, + BC_STATUS_PARSE_NO_BLOCK_END, + + BC_STATUS_MATH_NEGATIVE, + BC_STATUS_MATH_NON_INTEGER, + BC_STATUS_MATH_OVERFLOW, + BC_STATUS_MATH_DIVIDE_BY_ZERO, + BC_STATUS_MATH_BAD_STRING, + + BC_STATUS_EXEC_FILE_ERR, + BC_STATUS_EXEC_MISMATCHED_PARAMS, + BC_STATUS_EXEC_UNDEFINED_FUNC, + BC_STATUS_EXEC_FILE_NOT_EXECUTABLE, + BC_STATUS_EXEC_NUM_LEN, + BC_STATUS_EXEC_NAME_LEN, + BC_STATUS_EXEC_STRING_LEN, + BC_STATUS_EXEC_ARRAY_LEN, + BC_STATUS_EXEC_BAD_IBASE, + BC_STATUS_EXEC_BAD_SCALE, + BC_STATUS_EXEC_BAD_READ_EXPR, + BC_STATUS_EXEC_REC_READ, + BC_STATUS_EXEC_BAD_TYPE, + BC_STATUS_EXEC_BAD_OBASE, + BC_STATUS_EXEC_SIGNAL, + BC_STATUS_EXEC_STACK, + + BC_STATUS_VEC_OUT_OF_BOUNDS, + BC_STATUS_VEC_ITEM_EXISTS, + +#ifdef ENABLE_BC + BC_STATUS_POSIX_NAME_LEN, + BC_STATUS_POSIX_COMMENT, + BC_STATUS_POSIX_BAD_KW, + BC_STATUS_POSIX_DOT, + BC_STATUS_POSIX_RET, + BC_STATUS_POSIX_BOOL, + BC_STATUS_POSIX_REL_POS, + BC_STATUS_POSIX_MULTIREL, + BC_STATUS_POSIX_FOR1, + BC_STATUS_POSIX_FOR2, + BC_STATUS_POSIX_FOR3, + BC_STATUS_POSIX_BRACE, +#endif // ENABLE_BC + + BC_STATUS_QUIT, + BC_STATUS_LIMITS, + + BC_STATUS_INVALID_OPTION, + +} BcStatus; + +#define BC_ERR_IDX_VM (0) +#define BC_ERR_IDX_LEX (1) +#define BC_ERR_IDX_PARSE (2) +#define BC_ERR_IDX_MATH (3) +#define BC_ERR_IDX_EXEC (4) +#define BC_ERR_IDX_VEC (5) +#ifdef ENABLE_BC +#define BC_ERR_IDX_POSIX (6) +#endif // ENABLE_BC + +#define BC_VEC_INVALID_IDX ((size_t) -1) +#define BC_VEC_START_CAP (1 << 5) + +typedef void (*BcVecFree)(void *); +typedef int (*BcVecCmp)(const void *, const void *); + +typedef struct BcVec { + char *v; + size_t len; + size_t cap; + size_t size; + BcVecFree dtor; +} BcVec; + +#define bc_vec_pop(v) (bc_vec_npop((v), 1)) +#define bc_vec_top(v) (bc_vec_item_rev((v), 0)) + +#define bc_map_init(v) (bc_vec_init((v), sizeof(BcId), bc_id_free)) + +#define BC_READ_BIN_CHAR(c) ((((c) < ' ' && !isspace((c))) || (c) > '~')) + +typedef signed char BcDig; + +typedef struct BcNum { + BcDig *restrict num; + size_t rdx; + size_t len; + size_t cap; + bool neg; +} BcNum; + +#define BC_NUM_MIN_BASE ((unsigned long) 2) +#define BC_NUM_MAX_IBASE ((unsigned long) 16) +#define BC_NUM_DEF_SIZE (16) +#define BC_NUM_PRINT_WIDTH (69) + +#define BC_NUM_KARATSUBA_LEN (32) + +#define BC_NUM_NEG(n, neg) ((((ssize_t)(n)) ^ -((ssize_t)(neg))) + (neg)) +#define BC_NUM_ONE(n) ((n)->len == 1 && (n)->rdx == 0 && (n)->num[0] == 1) +#define BC_NUM_INT(n) ((n)->len - (n)->rdx) +#define BC_NUM_AREQ(a, b) \ + (BC_MAX((a)->rdx, (b)->rdx) + BC_MAX(BC_NUM_INT(a), BC_NUM_INT(b)) + 1) +#define BC_NUM_MREQ(a, b, scale) \ + (BC_NUM_INT(a) + BC_NUM_INT(b) + BC_MAX((scale), (a)->rdx + (b)->rdx) + 1) + +typedef BcStatus (*BcNumBinaryOp)(BcNum *, BcNum *, BcNum *, size_t); +typedef void (*BcNumDigitOp)(size_t, size_t, bool, size_t *, size_t); + +static void bc_num_init(BcNum *n, size_t req); +static void bc_num_expand(BcNum *n, size_t req); +static void bc_num_copy(BcNum *d, BcNum *s); +static void bc_num_free(void *num); + +static BcStatus bc_num_ulong(BcNum *n, unsigned long *result); +static BcStatus bc_num_ulong2num(BcNum *n, unsigned long val); + +static BcStatus bc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale); +static BcStatus bc_num_sub(BcNum *a, BcNum *b, BcNum *c, size_t scale); +static BcStatus bc_num_mul(BcNum *a, BcNum *b, BcNum *c, size_t scale); +static BcStatus bc_num_div(BcNum *a, BcNum *b, BcNum *c, size_t scale); +static BcStatus bc_num_mod(BcNum *a, BcNum *b, BcNum *c, size_t scale); +static BcStatus bc_num_pow(BcNum *a, BcNum *b, BcNum *c, size_t scale); +static BcStatus bc_num_sqrt(BcNum *a, BcNum *b, size_t scale); +static BcStatus bc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d, + size_t scale); + +typedef enum BcInst { + +#ifdef ENABLE_BC + BC_INST_INC_PRE, + BC_INST_DEC_PRE, + BC_INST_INC_POST, + BC_INST_DEC_POST, +#endif // ENABLE_BC + + BC_INST_NEG, + + BC_INST_POWER, + BC_INST_MULTIPLY, + BC_INST_DIVIDE, + BC_INST_MODULUS, + BC_INST_PLUS, + BC_INST_MINUS, + + BC_INST_REL_EQ, + BC_INST_REL_LE, + BC_INST_REL_GE, + BC_INST_REL_NE, + BC_INST_REL_LT, + BC_INST_REL_GT, + + BC_INST_BOOL_NOT, + BC_INST_BOOL_OR, + BC_INST_BOOL_AND, + +#ifdef ENABLE_BC + BC_INST_ASSIGN_POWER, + BC_INST_ASSIGN_MULTIPLY, + BC_INST_ASSIGN_DIVIDE, + BC_INST_ASSIGN_MODULUS, + BC_INST_ASSIGN_PLUS, + BC_INST_ASSIGN_MINUS, +#endif // ENABLE_BC + BC_INST_ASSIGN, + + BC_INST_NUM, + BC_INST_VAR, + BC_INST_ARRAY_ELEM, + BC_INST_ARRAY, + + BC_INST_SCALE_FUNC, + BC_INST_IBASE, + BC_INST_SCALE, + BC_INST_LAST, + BC_INST_LENGTH, + BC_INST_READ, + BC_INST_OBASE, + BC_INST_SQRT, + + BC_INST_PRINT, + BC_INST_PRINT_POP, + BC_INST_STR, + BC_INST_PRINT_STR, + +#ifdef ENABLE_BC + BC_INST_JUMP, + BC_INST_JUMP_ZERO, + + BC_INST_CALL, + + BC_INST_RET, + BC_INST_RET0, + + BC_INST_HALT, +#endif // ENABLE_BC + + BC_INST_POP, + BC_INST_POP_EXEC, + +#ifdef ENABLE_DC + BC_INST_MODEXP, + BC_INST_DIVMOD, + + BC_INST_EXECUTE, + BC_INST_EXEC_COND, + + BC_INST_ASCIIFY, + BC_INST_PRINT_STREAM, + + BC_INST_PRINT_STACK, + BC_INST_CLEAR_STACK, + BC_INST_STACK_LEN, + BC_INST_DUPLICATE, + BC_INST_SWAP, + + BC_INST_LOAD, + BC_INST_PUSH_VAR, + BC_INST_PUSH_TO_VAR, + + BC_INST_QUIT, + BC_INST_NQUIT, + + BC_INST_INVALID = -1, +#endif // ENABLE_DC + +} BcInst; + +typedef struct BcId { + char *name; + size_t idx; +} BcId; + +typedef struct BcFunc { + BcVec code; + BcVec labels; + size_t nparams; + BcVec autos; +} BcFunc; + +typedef enum BcResultType { + + BC_RESULT_TEMP, + + BC_RESULT_VAR, + BC_RESULT_ARRAY_ELEM, + BC_RESULT_ARRAY, + + BC_RESULT_STR, + + BC_RESULT_IBASE, + BC_RESULT_SCALE, + BC_RESULT_LAST, + + // These are between to calculate ibase, obase, and last from instructions. + BC_RESULT_CONSTANT, + BC_RESULT_ONE, + + BC_RESULT_OBASE, + +} BcResultType; + +typedef union BcResultData { + BcNum n; + BcVec v; + BcId id; +} BcResultData; + +typedef struct BcResult { + BcResultType t; + BcResultData d; +} BcResult; + +typedef struct BcInstPtr { + size_t func; + size_t idx; + size_t len; +} BcInstPtr; + +static void bc_array_expand(BcVec *a, size_t len); +static int bc_id_cmp(const void *e1, const void *e2); + +// BC_LEX_NEG is not used in lexing; it is only for parsing. +typedef enum BcLexType { + + BC_LEX_EOF, + BC_LEX_INVALID, + + BC_LEX_OP_INC, + BC_LEX_OP_DEC, + + BC_LEX_NEG, + + BC_LEX_OP_POWER, + BC_LEX_OP_MULTIPLY, + BC_LEX_OP_DIVIDE, + BC_LEX_OP_MODULUS, + BC_LEX_OP_PLUS, + BC_LEX_OP_MINUS, + + BC_LEX_OP_REL_EQ, + BC_LEX_OP_REL_LE, + BC_LEX_OP_REL_GE, + BC_LEX_OP_REL_NE, + BC_LEX_OP_REL_LT, + BC_LEX_OP_REL_GT, + + BC_LEX_OP_BOOL_NOT, + BC_LEX_OP_BOOL_OR, + BC_LEX_OP_BOOL_AND, + + BC_LEX_OP_ASSIGN_POWER, + BC_LEX_OP_ASSIGN_MULTIPLY, + BC_LEX_OP_ASSIGN_DIVIDE, + BC_LEX_OP_ASSIGN_MODULUS, + BC_LEX_OP_ASSIGN_PLUS, + BC_LEX_OP_ASSIGN_MINUS, + BC_LEX_OP_ASSIGN, + + BC_LEX_NLINE, + BC_LEX_WHITESPACE, + + BC_LEX_LPAREN, + BC_LEX_RPAREN, + + BC_LEX_LBRACKET, + BC_LEX_COMMA, + BC_LEX_RBRACKET, + + BC_LEX_LBRACE, + BC_LEX_SCOLON, + BC_LEX_RBRACE, + + BC_LEX_STR, + BC_LEX_NAME, + BC_LEX_NUMBER, + + BC_LEX_KEY_AUTO, + BC_LEX_KEY_BREAK, + BC_LEX_KEY_CONTINUE, + BC_LEX_KEY_DEFINE, + BC_LEX_KEY_ELSE, + BC_LEX_KEY_FOR, + BC_LEX_KEY_HALT, + BC_LEX_KEY_IBASE, + BC_LEX_KEY_IF, + BC_LEX_KEY_LAST, + BC_LEX_KEY_LENGTH, + BC_LEX_KEY_LIMITS, + BC_LEX_KEY_OBASE, + BC_LEX_KEY_PRINT, + BC_LEX_KEY_QUIT, + BC_LEX_KEY_READ, + BC_LEX_KEY_RETURN, + BC_LEX_KEY_SCALE, + BC_LEX_KEY_SQRT, + BC_LEX_KEY_WHILE, + +#ifdef ENABLE_DC + BC_LEX_EQ_NO_REG, + BC_LEX_OP_MODEXP, + BC_LEX_OP_DIVMOD, + + BC_LEX_COLON, + BC_LEX_ELSE, + BC_LEX_EXECUTE, + BC_LEX_PRINT_STACK, + BC_LEX_CLEAR_STACK, + BC_LEX_STACK_LEVEL, + BC_LEX_DUPLICATE, + BC_LEX_SWAP, + BC_LEX_POP, + + BC_LEX_ASCIIFY, + BC_LEX_PRINT_STREAM, + + BC_LEX_STORE_IBASE, + BC_LEX_STORE_SCALE, + BC_LEX_LOAD, + BC_LEX_LOAD_POP, + BC_LEX_STORE_PUSH, + BC_LEX_STORE_OBASE, + BC_LEX_PRINT_POP, + BC_LEX_NQUIT, + BC_LEX_SCALE_FACTOR, +#endif // ENABLE_DC + +} BcLexType; + +struct BcLex; +typedef BcStatus (*BcLexNext)(struct BcLex *); + +typedef struct BcLex { + + const char *buf; + size_t i; + size_t line; + const char *f; + size_t len; + bool newline; + + struct { + BcLexType t; + BcLexType last; + BcVec v; + } t; + + BcLexNext next; + +} BcLex; + +#define BC_PARSE_STREND ((char) UCHAR_MAX) + +#define bc_parse_push(p, i) (bc_vec_pushByte(&(p)->func->code, (char) (i))) +#define bc_parse_updateFunc(p, f) \ + ((p)->func = bc_vec_item(&(p)->prog->fns, ((p)->fidx = (f)))) + +#define BC_PARSE_REL (1 << 0) +#define BC_PARSE_PRINT (1 << 1) +#define BC_PARSE_NOCALL (1 << 2) +#define BC_PARSE_NOREAD (1 << 3) +#define BC_PARSE_ARRAY (1 << 4) + +#define BC_PARSE_TOP_FLAG_PTR(parse) ((uint8_t *) bc_vec_top(&(parse)->flags)) +#define BC_PARSE_TOP_FLAG(parse) (*(BC_PARSE_TOP_FLAG_PTR(parse))) + +#define BC_PARSE_FLAG_FUNC_INNER (1 << 0) +#define BC_PARSE_FUNC_INNER(parse) \ + (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_FUNC_INNER) + +#define BC_PARSE_FLAG_FUNC (1 << 1) +#define BC_PARSE_FUNC(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_FUNC) + +#define BC_PARSE_FLAG_BODY (1 << 2) +#define BC_PARSE_BODY(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_BODY) + +#define BC_PARSE_FLAG_LOOP (1 << 3) +#define BC_PARSE_LOOP(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_LOOP) + +#define BC_PARSE_FLAG_LOOP_INNER (1 << 4) +#define BC_PARSE_LOOP_INNER(parse) \ + (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_LOOP_INNER) + +#define BC_PARSE_FLAG_IF (1 << 5) +#define BC_PARSE_IF(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_IF) + +#define BC_PARSE_FLAG_ELSE (1 << 6) +#define BC_PARSE_ELSE(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_ELSE) + +#define BC_PARSE_FLAG_IF_END (1 << 7) +#define BC_PARSE_IF_END(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_IF_END) + +#define BC_PARSE_CAN_EXEC(parse) \ + (!(BC_PARSE_TOP_FLAG(parse) & \ + (BC_PARSE_FLAG_FUNC_INNER | BC_PARSE_FLAG_FUNC | BC_PARSE_FLAG_BODY | \ + BC_PARSE_FLAG_LOOP | BC_PARSE_FLAG_LOOP_INNER | BC_PARSE_FLAG_IF | \ + BC_PARSE_FLAG_ELSE | BC_PARSE_FLAG_IF_END))) + +typedef struct BcOp { + char prec; + bool left; +} BcOp; + +typedef struct BcParseNext { + uint32_t len; + BcLexType tokens[4]; +} BcParseNext; + +#define BC_PARSE_NEXT_TOKENS(...) .tokens = { __VA_ARGS__ } +#define BC_PARSE_NEXT(a, ...) \ + { \ + .len = (a), BC_PARSE_NEXT_TOKENS(__VA_ARGS__) \ + } + +struct BcParse; + +struct BcProgram; + +typedef void (*BcParseInit)(struct BcParse *, struct BcProgram *, size_t); +typedef BcStatus (*BcParseParse)(struct BcParse *); +typedef BcStatus (*BcParseExpr)(struct BcParse *, uint8_t); + +typedef struct BcParse { + + BcParseParse parse; + + BcLex l; + + BcVec flags; + + BcVec exits; + BcVec conds; + + BcVec ops; + + struct BcProgram *prog; + BcFunc *func; + size_t fidx; + + size_t nbraces; + bool auto_part; + +} BcParse; + +#ifdef ENABLE_BC + +BcStatus bc_main(int argc, char *argv[]); + +typedef struct BcLexKeyword { + const char name[9]; + const char len; + const bool posix; +} BcLexKeyword; + +#define BC_LEX_KW_ENTRY(a, b, c) \ + { \ + .name = a, .len = (b), .posix = (c) \ + } + +static BcStatus bc_lex_token(BcLex *l); + +#define BC_PARSE_TOP_OP(p) (*((BcLexType *) bc_vec_top(&(p)->ops))) +#define BC_PARSE_LEAF(p, rparen) \ + (((p) >= BC_INST_NUM && (p) <= BC_INST_SQRT) || (rparen) || \ + (p) == BC_INST_INC_POST || (p) == BC_INST_DEC_POST) + +// We can calculate the conversion between tokens and exprs by subtracting the +// position of the first operator in the lex enum and adding the position of the +// first in the expr enum. Note: This only works for binary operators. +#define BC_PARSE_TOKEN_INST(t) ((char) ((t) -BC_LEX_NEG + BC_INST_NEG)) + +static BcStatus bc_parse_parse(BcParse *p); +static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next); + +#endif // ENABLE_BC + +#ifdef ENABLE_DC + +#define DC_PARSE_BUF_LEN ((int) (sizeof(uint32_t) * CHAR_BIT)) + +BcStatus dc_main(int argc, char *argv[]); + +static BcStatus dc_lex_token(BcLex *l); + +static void dc_parse_init(BcParse *p, struct BcProgram *prog, size_t func); +static BcStatus dc_parse_expr(BcParse *p, uint8_t flags); + +#endif // ENABLE_DC + +typedef struct BcProgram { + + size_t len; + size_t scale; + + BcNum ib; + size_t ib_t; + BcNum ob; + size_t ob_t; + + BcNum hexb; + +#ifdef ENABLE_DC + BcNum strmb; +#endif // ENABLE_DC + + BcVec results; + BcVec stack; + + BcVec fns; + BcVec fn_map; + + BcVec vars; + BcVec var_map; + + BcVec arrs; + BcVec arr_map; + + BcVec strs; + BcVec consts; + + const char *file; + + BcNum last; + BcNum zero; + BcNum one; + + size_t nchars; + + BcParseInit parse_init; + BcParseExpr parse_expr; + +} BcProgram; + +#define BC_PROG_STACK(s, n) ((s)->len >= ((size_t) n)) + +#define BC_PROG_MAIN (0) +#define BC_PROG_READ (1) + +#ifdef ENABLE_DC +#define BC_PROG_REQ_FUNCS (2) +#endif // ENABLE_DC + +#define BC_PROG_STR(n) (!(n)->num && !(n)->cap) +#define BC_PROG_NUM(r, n) \ + ((r)->t != BC_RESULT_ARRAY && (r)->t != BC_RESULT_STR && !BC_PROG_STR(n)) + +typedef unsigned long (*BcProgramBuiltIn)(BcNum *); + +static void bc_program_addFunc(BcProgram *p, char *name, size_t *idx); +static BcStatus bc_program_reset(BcProgram *p, BcStatus s); +static BcStatus bc_program_exec(BcProgram *p); + +#define BC_FLAG_X (1 << 0) +#define BC_FLAG_W (1 << 1) +#define BC_FLAG_V (1 << 2) +#define BC_FLAG_S (1 << 3) +#define BC_FLAG_Q (1 << 4) +#define BC_FLAG_L (1 << 5) +#define BC_FLAG_I (1 << 6) + +#define BC_MAX(a, b) ((a) > (b) ? (a) : (b)) +#define BC_MIN(a, b) ((a) < (b) ? (a) : (b)) + +#define BC_MAX_OBASE ((unsigned long) 999) +#define BC_MAX_DIM ((unsigned long) INT_MAX) +#define BC_MAX_SCALE ((unsigned long) UINT_MAX) +#define BC_MAX_STRING ((unsigned long) UINT_MAX - 1) +#define BC_MAX_NAME BC_MAX_STRING +#define BC_MAX_NUM BC_MAX_STRING +#define BC_MAX_EXP ((unsigned long) LONG_MAX) +#define BC_MAX_VARS ((unsigned long) SIZE_MAX - 1) + +typedef struct BcVmExe { + BcParseInit init; + BcParseExpr exp; + char sbgn; + char send; +} BcVmExe; + +typedef struct BcVm { + + BcParse prs; + BcProgram prog; + + uint32_t flags; + BcVec files; + + char *env_args; + BcVmExe exe; + +} BcVm; + +typedef struct BcGlobals { + + unsigned long sig; + unsigned long sigc; + unsigned long signe; + + long tty; + long ttyin; + long posix; + long warn; + long exreg; + + const char *name; +#if ENABLE_FEATURE_BC_SIGNALS + const char *sig_msg; +#endif // ENABLE_FEATURE_BC_SIGNALS + const char *help; + bool bc; + +} BcGlobals; + +#ifdef ENABLE_BC +static BcStatus bc_vm_posixError(BcStatus s, const char *file, size_t line, + const char *msg); +#endif // ENABLE_BC + +static void bc_vm_exit(BcStatus s); +static void bc_vm_printf(FILE *restrict f, const char *fmt, ...); +static void bc_vm_puts(const char *str, FILE *restrict f); +static void bc_vm_putchar(int c); +static void bc_vm_fflush(FILE *restrict f); + +static void bc_vm_info(const char *const help); +static BcStatus bc_vm_run(int argc, char *argv[], BcVmExe exe, + const char *env_len); + +static BcGlobals bcg; + +#ifdef ENABLE_BC +static const char bc_name[] = "bc"; +#if ENABLE_FEATURE_BC_SIGNALS +static const char bc_sig_msg[] = "\ninterrupt (type \"quit\" to exit)\n"; +#endif // ENABLE_FEATURE_BC_SIGNALS +#endif // ENABLE_BC + +#ifdef ENABLE_DC +static const char dc_name[] = "dc"; +#if ENABLE_FEATURE_BC_SIGNALS +static const char dc_sig_msg[] = "\ninterrupt (type \"q\" to exit)\n"; +#endif // ENABLE_FEATURE_BC_SIGNALS +#endif // ENABLE_DC + +static const char bc_copyright[] = + "Copyright (c) 2018 Gavin D. Howard and contributors\n" + "Report bugs at: https://github.com/gavinhoward/bc\n\n" + "This is free software with ABSOLUTELY NO WARRANTY.\n"; + +static const char* const bc_args_env_name = "BC_ENV_ARGS"; + +static const char bc_err_fmt[] = "\n%s error: %s\n"; +static const char bc_warn_fmt[] = "\n%s warning: %s\n"; +static const char bc_err_line[] = ":%zu\n\n"; + +static const char *bc_errs[] = { + "VM", + "Lex", + "Parse", + "Math", + "Runtime", + "Vector", +#ifdef ENABLE_BC + "POSIX", +#endif // ENABLE_BC +}; + +static const uint8_t bc_err_ids[] = { + BC_ERR_IDX_VM, BC_ERR_IDX_VM, BC_ERR_IDX_VM, BC_ERR_IDX_VM, BC_ERR_IDX_VM, + BC_ERR_IDX_LEX, BC_ERR_IDX_LEX, BC_ERR_IDX_LEX, BC_ERR_IDX_LEX, +#ifdef ENABLE_DC + BC_ERR_IDX_LEX, +#endif // ENABLE_DC + BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, + BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, + BC_ERR_IDX_MATH, BC_ERR_IDX_MATH, BC_ERR_IDX_MATH, BC_ERR_IDX_MATH, + BC_ERR_IDX_MATH, +#ifdef ENABLE_DC + BC_ERR_IDX_MATH, +#endif // ENABLE_DC + BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, + BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, + BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, + BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, + BC_ERR_IDX_EXEC, + BC_ERR_IDX_VEC, BC_ERR_IDX_VEC, +#ifdef ENABLE_BC + BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX, + BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX, + BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX, +#endif // ENABLE_BC + BC_ERR_IDX_VM, BC_ERR_IDX_VM, BC_ERR_IDX_VM, +}; + +static const char *bc_err_msgs[] = { + + NULL, + "memory allocation error", + "I/O error", + "file is not text:", + "path is a directory:", + + "bad character", + "string end could not be found", + "comment end could not be found", + "end of file", +#ifdef ENABLE_DC + "extended register", +#endif // ENABLE_DC + + "bad token", + "bad expression", + "empty expression", + "bad print statement", + "bad function definition", + "bad assignment: left side must be scale, ibase, " + "obase, last, var, or array element", + "no auto variable found", + "function parameter or auto var has the same name as another", + "block end could not be found", + + "negative number", + "non integer number", + "overflow", + "divide by zero", + "bad number string", + + "could not open file:", + "mismatched parameters", + "undefined function", + "file is not executable:", + "number too long: must be [1, BC_NUM_MAX]", + "name too long: must be [1, BC_NAME_MAX]", + "string too long: must be [1, BC_STRING_MAX]", + "array too long; must be [1, BC_DIM_MAX]", + "bad ibase; must be [2, 16]", + "bad scale; must be [0, BC_SCALE_MAX]", + "bad read() expression", + "read() call inside of a read() call", + "variable is wrong type", + "bad obase; must be [2, BC_BASE_MAX]", + "signal caught and not handled", + "stack has too few elements", + + "index is out of bounds", + "item already exists", + +#ifdef ENABLE_BC + "POSIX only allows one character names; the following is bad:", + "POSIX does not allow '#' script comments", + "POSIX does not allow the following keyword:", + "POSIX does not allow a period ('.') as a shortcut for the last result", + "POSIX requires parentheses around return expressions", + "POSIX does not allow boolean operators; the following is bad:", + "POSIX does not allow comparison operators outside if or loops", + "POSIX requires exactly one comparison operator per condition", + "POSIX does not allow an empty init expression in a for loop", + "POSIX does not allow an empty condition expression in a for loop", + "POSIX does not allow an empty update expression in a for loop", + "POSIX requires the left brace be on the same line as the function header", +#endif // ENABLE_BC + +}; + +static const char bc_func_main[] = "(main)"; +static const char bc_func_read[] = "(read)"; + +#ifdef ENABLE_BC +static const BcLexKeyword bc_lex_kws[20] = { + BC_LEX_KW_ENTRY("auto", 4, true), + BC_LEX_KW_ENTRY("break", 5, true), + BC_LEX_KW_ENTRY("continue", 8, false), + BC_LEX_KW_ENTRY("define", 6, true), + BC_LEX_KW_ENTRY("else", 4, false), + BC_LEX_KW_ENTRY("for", 3, true), + BC_LEX_KW_ENTRY("halt", 4, false), + BC_LEX_KW_ENTRY("ibase", 5, true), + BC_LEX_KW_ENTRY("if", 2, true), + BC_LEX_KW_ENTRY("last", 4, false), + BC_LEX_KW_ENTRY("length", 6, true), + BC_LEX_KW_ENTRY("limits", 6, false), + BC_LEX_KW_ENTRY("obase", 5, true), + BC_LEX_KW_ENTRY("print", 5, false), + BC_LEX_KW_ENTRY("quit", 4, true), + BC_LEX_KW_ENTRY("read", 4, false), + BC_LEX_KW_ENTRY("return", 6, true), + BC_LEX_KW_ENTRY("scale", 5, true), + BC_LEX_KW_ENTRY("sqrt", 4, true), + BC_LEX_KW_ENTRY("while", 5, true), +}; + +// This is an array that corresponds to token types. An entry is +// true if the token is valid in an expression, false otherwise. +static const bool bc_parse_exprs[] = { + false, false, true, true, true, true, true, true, true, true, true, true, + true, true, true, true, true, true, true, true, true, true, true, true, + true, true, true, false, false, true, true, false, false, false, false, + false, false, false, true, true, false, false, false, false, false, false, + false, true, false, true, true, true, true, false, false, true, false, true, + true, false, +}; + +// This is an array of data for operators that correspond to token types. +static const BcOp bc_parse_ops[] = { + { 0, false }, { 0, false }, + { 1, false }, + { 2, false }, + { 3, true }, { 3, true }, { 3, true }, + { 4, true }, { 4, true }, + { 6, true }, { 6, true }, { 6, true }, { 6, true }, { 6, true }, { 6, true }, + { 1, false }, + { 7, true }, { 7, true }, + { 5, false }, { 5, false }, { 5, false }, { 5, false }, { 5, false }, + { 5, false }, { 5, false }, +}; + +// These identify what tokens can come after expressions in certain cases. +static const BcParseNext bc_parse_next_expr = + BC_PARSE_NEXT(4, BC_LEX_NLINE, BC_LEX_SCOLON, BC_LEX_RBRACE, BC_LEX_EOF); +static const BcParseNext bc_parse_next_param = + BC_PARSE_NEXT(2, BC_LEX_RPAREN, BC_LEX_COMMA); +static const BcParseNext bc_parse_next_print = + BC_PARSE_NEXT(4, BC_LEX_COMMA, BC_LEX_NLINE, BC_LEX_SCOLON, BC_LEX_EOF); +static const BcParseNext bc_parse_next_rel = BC_PARSE_NEXT(1, BC_LEX_RPAREN); +static const BcParseNext bc_parse_next_elem = BC_PARSE_NEXT(1, BC_LEX_RBRACKET); +static const BcParseNext bc_parse_next_for = BC_PARSE_NEXT(1, BC_LEX_SCOLON); +static const BcParseNext bc_parse_next_read = + BC_PARSE_NEXT(2, BC_LEX_NLINE, BC_LEX_EOF); +#endif // ENABLE_BC + +#ifdef ENABLE_DC +static const BcLexType dc_lex_regs[] = { + BC_LEX_OP_REL_EQ, BC_LEX_OP_REL_LE, BC_LEX_OP_REL_GE, BC_LEX_OP_REL_NE, + BC_LEX_OP_REL_LT, BC_LEX_OP_REL_GT, BC_LEX_SCOLON, BC_LEX_COLON, + BC_LEX_ELSE, BC_LEX_LOAD, BC_LEX_LOAD_POP, BC_LEX_OP_ASSIGN, + BC_LEX_STORE_PUSH, +}; + +static const size_t dc_lex_regs_len = sizeof(dc_lex_regs) / sizeof(BcLexType); + +static const BcLexType dc_lex_tokens[] = { + BC_LEX_OP_MODULUS, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_LPAREN, + BC_LEX_INVALID, BC_LEX_OP_MULTIPLY, BC_LEX_OP_PLUS, BC_LEX_INVALID, + BC_LEX_OP_MINUS, BC_LEX_INVALID, BC_LEX_OP_DIVIDE, + BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, + BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, + BC_LEX_INVALID, BC_LEX_INVALID, + BC_LEX_COLON, BC_LEX_SCOLON, BC_LEX_OP_REL_GT, BC_LEX_OP_REL_EQ, + BC_LEX_OP_REL_LT, BC_LEX_KEY_READ, BC_LEX_INVALID, + BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, + BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_EQ_NO_REG, BC_LEX_INVALID, + BC_LEX_KEY_IBASE, BC_LEX_INVALID, BC_LEX_KEY_SCALE, BC_LEX_LOAD_POP, + BC_LEX_INVALID, BC_LEX_OP_BOOL_NOT, BC_LEX_KEY_OBASE, BC_LEX_PRINT_STREAM, + BC_LEX_NQUIT, BC_LEX_POP, BC_LEX_STORE_PUSH, BC_LEX_INVALID, BC_LEX_INVALID, + BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_SCALE_FACTOR, BC_LEX_INVALID, + BC_LEX_KEY_LENGTH, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, + BC_LEX_OP_POWER, BC_LEX_NEG, BC_LEX_INVALID, + BC_LEX_ASCIIFY, BC_LEX_INVALID, BC_LEX_CLEAR_STACK, BC_LEX_DUPLICATE, + BC_LEX_ELSE, BC_LEX_PRINT_STACK, BC_LEX_INVALID, BC_LEX_INVALID, + BC_LEX_STORE_IBASE, BC_LEX_INVALID, BC_LEX_STORE_SCALE, BC_LEX_LOAD, + BC_LEX_INVALID, BC_LEX_PRINT_POP, BC_LEX_STORE_OBASE, BC_LEX_KEY_PRINT, + BC_LEX_KEY_QUIT, BC_LEX_SWAP, BC_LEX_OP_ASSIGN, BC_LEX_INVALID, + BC_LEX_INVALID, BC_LEX_KEY_SQRT, BC_LEX_INVALID, BC_LEX_EXECUTE, + BC_LEX_INVALID, BC_LEX_STACK_LEVEL, + BC_LEX_LBRACE, BC_LEX_OP_MODEXP, BC_LEX_INVALID, BC_LEX_OP_DIVMOD, + BC_LEX_INVALID +}; + +static const BcInst dc_parse_insts[] = { + BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_REL_GE, + BC_INST_INVALID, BC_INST_POWER, BC_INST_MULTIPLY, BC_INST_DIVIDE, + BC_INST_MODULUS, BC_INST_PLUS, BC_INST_MINUS, + BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, + BC_INST_INVALID, BC_INST_INVALID, + BC_INST_BOOL_NOT, BC_INST_INVALID, BC_INST_INVALID, + BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, + BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, + BC_INST_INVALID, BC_INST_INVALID, BC_INST_REL_GT, BC_INST_INVALID, + BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_REL_GE, + BC_INST_INVALID, BC_INST_INVALID, + BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, + BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, + BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_IBASE, + BC_INST_INVALID, BC_INST_INVALID, BC_INST_LENGTH, BC_INST_INVALID, + BC_INST_OBASE, BC_INST_PRINT, BC_INST_QUIT, BC_INST_INVALID, + BC_INST_INVALID, BC_INST_SCALE, BC_INST_SQRT, BC_INST_INVALID, + BC_INST_REL_EQ, BC_INST_MODEXP, BC_INST_DIVMOD, BC_INST_INVALID, + BC_INST_INVALID, BC_INST_EXECUTE, BC_INST_PRINT_STACK, BC_INST_CLEAR_STACK, + BC_INST_STACK_LEN, BC_INST_DUPLICATE, BC_INST_SWAP, BC_INST_POP, + BC_INST_ASCIIFY, BC_INST_PRINT_STREAM, BC_INST_INVALID, BC_INST_INVALID, + BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, + BC_INST_PRINT, BC_INST_NQUIT, BC_INST_SCALE_FUNC, +}; +#endif // ENABLE_DC + +static const char bc_num_hex_digits[] = "0123456789ABCDEF"; + +static const BcNumBinaryOp bc_program_ops[] = { + bc_num_pow, bc_num_mul, bc_num_div, bc_num_mod, bc_num_add, bc_num_sub, +}; + +static const char bc_program_stdin_name[] = ""; +static const char bc_program_ready_msg[] = "ready for more input\n"; + +#ifdef ENABLE_BC +static const char *bc_lib_name = "gen/lib.bc"; + +static const char bc_lib[] = { + 115,99,97,108,101,61,50,48,10,100,101,102,105,110,101,32,101,40,120,41,123, + 10,9,97,117,116,111,32,98,44,115,44,110,44,114,44,100,44,105,44,112,44,102, + 44,118,10,9,98,61,105,98,97,115,101,10,9,105,98,97,115,101,61,65,10,9,105,102, + 40,120,60,48,41,123,10,9,9,110,61,49,10,9,9,120,61,45,120,10,9,125,10,9,115, + 61,115,99,97,108,101,10,9,114,61,54,43,115,43,48,46,52,52,42,120,10,9,115,99, + 97,108,101,61,115,99,97,108,101,40,120,41,43,49,10,9,119,104,105,108,101,40, + 120,62,49,41,123,10,9,9,100,43,61,49,10,9,9,120,47,61,50,10,9,9,115,99,97,108, + 101,43,61,49,10,9,125,10,9,115,99,97,108,101,61,114,10,9,114,61,120,43,49,10, + 9,112,61,120,10,9,102,61,118,61,49,10,9,102,111,114,40,105,61,50,59,118,33, + 61,48,59,43,43,105,41,123,10,9,9,112,42,61,120,10,9,9,102,42,61,105,10,9,9, + 118,61,112,47,102,10,9,9,114,43,61,118,10,9,125,10,9,119,104,105,108,101,40, + 40,100,45,45,41,33,61,48,41,114,42,61,114,10,9,115,99,97,108,101,61,115,10, + 9,105,98,97,115,101,61,98,10,9,105,102,40,110,33,61,48,41,114,101,116,117,114, + 110,40,49,47,114,41,10,9,114,101,116,117,114,110,40,114,47,49,41,10,125,10, + 100,101,102,105,110,101,32,108,40,120,41,123,10,9,97,117,116,111,32,98,44,115, + 44,114,44,112,44,97,44,113,44,105,44,118,10,9,98,61,105,98,97,115,101,10,9, + 105,98,97,115,101,61,65,10,9,105,102,40,120,60,61,48,41,123,10,9,9,114,61,40, + 49,45,49,48,94,115,99,97,108,101,41,47,49,10,9,9,105,98,97,115,101,61,98,10, + 9,9,114,101,116,117,114,110,40,114,41,10,9,125,10,9,115,61,115,99,97,108,101, + 10,9,115,99,97,108,101,43,61,54,10,9,112,61,50,10,9,119,104,105,108,101,40, + 120,62,61,50,41,123,10,9,9,112,42,61,50,10,9,9,120,61,115,113,114,116,40,120, + 41,10,9,125,10,9,119,104,105,108,101,40,120,60,61,48,46,53,41,123,10,9,9,112, + 42,61,50,10,9,9,120,61,115,113,114,116,40,120,41,10,9,125,10,9,114,61,97,61, + 40,120,45,49,41,47,40,120,43,49,41,10,9,113,61,97,42,97,10,9,118,61,49,10,9, + 102,111,114,40,105,61,51,59,118,33,61,48,59,105,43,61,50,41,123,10,9,9,97,42, + 61,113,10,9,9,118,61,97,47,105,10,9,9,114,43,61,118,10,9,125,10,9,114,42,61, + 112,10,9,115,99,97,108,101,61,115,10,9,105,98,97,115,101,61,98,10,9,114,101, + 116,117,114,110,40,114,47,49,41,10,125,10,100,101,102,105,110,101,32,115,40, + 120,41,123,10,9,97,117,116,111,32,98,44,115,44,114,44,110,44,97,44,113,44,105, + 10,9,98,61,105,98,97,115,101,10,9,105,98,97,115,101,61,65,10,9,115,61,115,99, + 97,108,101,10,9,115,99,97,108,101,61,49,46,49,42,115,43,50,10,9,97,61,97,40, + 49,41,10,9,105,102,40,120,60,48,41,123,10,9,9,110,61,49,10,9,9,120,61,45,120, + 10,9,125,10,9,115,99,97,108,101,61,48,10,9,113,61,40,120,47,97,43,50,41,47, + 52,10,9,120,61,120,45,52,42,113,42,97,10,9,105,102,40,113,37,50,33,61,48,41, + 120,61,45,120,10,9,115,99,97,108,101,61,115,43,50,10,9,114,61,97,61,120,10, + 9,113,61,45,120,42,120,10,9,102,111,114,40,105,61,51,59,97,33,61,48,59,105, + 43,61,50,41,123,10,9,9,97,42,61,113,47,40,105,42,40,105,45,49,41,41,10,9,9, + 114,43,61,97,10,9,125,10,9,115,99,97,108,101,61,115,10,9,105,98,97,115,101, + 61,98,10,9,105,102,40,110,33,61,48,41,114,101,116,117,114,110,40,45,114,47, + 49,41,10,9,114,101,116,117,114,110,40,114,47,49,41,10,125,10,100,101,102,105, + 110,101,32,99,40,120,41,123,10,9,97,117,116,111,32,98,44,115,10,9,98,61,105, + 98,97,115,101,10,9,105,98,97,115,101,61,65,10,9,115,61,115,99,97,108,101,10, + 9,115,99,97,108,101,42,61,49,46,50,10,9,120,61,115,40,50,42,97,40,49,41,43, + 120,41,10,9,115,99,97,108,101,61,115,10,9,105,98,97,115,101,61,98,10,9,114, + 101,116,117,114,110,40,120,47,49,41,10,125,10,100,101,102,105,110,101,32,97, + 40,120,41,123,10,9,97,117,116,111,32,98,44,115,44,114,44,110,44,97,44,109,44, + 116,44,102,44,105,44,117,10,9,98,61,105,98,97,115,101,10,9,105,98,97,115,101, + 61,65,10,9,110,61,49,10,9,105,102,40,120,60,48,41,123,10,9,9,110,61,45,49,10, + 9,9,120,61,45,120,10,9,125,10,9,105,102,40,120,61,61,49,41,123,10,9,9,105,102, + 40,115,99,97,108,101,60,54,53,41,123,10,9,9,9,114,101,116,117,114,110,40,46, + 55,56,53,51,57,56,49,54,51,51,57,55,52,52,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,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,47,110,41,10,9,9,125,10,9,125,10, + 9,105,102,40,120,61,61,46,50,41,123,10,9,9,105,102,40,115,99,97,108,101,60, + 54,53,41,123,10,9,9,9,114,101,116,117,114,110,40,46,49,57,55,51,57,53,53,53, + 57,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,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,56,57,52,48,50,47,110,41,10,9,9,125,10,9,125,10,9,115,61,115,99,97,108,101, + 10,9,105,102,40,120,62,46,50,41,123,10,9,9,115,99,97,108,101,43,61,53,10,9, + 9,97,61,97,40,46,50,41,10,9,125,10,9,115,99,97,108,101,61,115,43,51,10,9,119, + 104,105,108,101,40,120,62,46,50,41,123,10,9,9,109,43,61,49,10,9,9,120,61,40, + 120,45,46,50,41,47,40,49,43,46,50,42,120,41,10,9,125,10,9,114,61,117,61,120, + 10,9,102,61,45,120,42,120,10,9,116,61,49,10,9,102,111,114,40,105,61,51,59,116, + 33,61,48,59,105,43,61,50,41,123,10,9,9,117,42,61,102,10,9,9,116,61,117,47,105, + 10,9,9,114,43,61,116,10,9,125,10,9,115,99,97,108,101,61,115,10,9,105,98,97, + 115,101,61,98,10,9,114,101,116,117,114,110,40,40,109,42,97,43,114,41,47,110, + 41,10,125,10,100,101,102,105,110,101,32,106,40,110,44,120,41,123,10,9,97,117, + 116,111,32,98,44,115,44,111,44,97,44,105,44,118,44,102,10,9,98,61,105,98,97, + 115,101,10,9,105,98,97,115,101,61,65,10,9,115,61,115,99,97,108,101,10,9,115, + 99,97,108,101,61,48,10,9,110,47,61,49,10,9,105,102,40,110,60,48,41,123,10,9, + 9,110,61,45,110,10,9,9,105,102,40,110,37,50,61,61,49,41,111,61,49,10,9,125, + 10,9,97,61,49,10,9,102,111,114,40,105,61,50,59,105,60,61,110,59,43,43,105,41, + 97,42,61,105,10,9,115,99,97,108,101,61,49,46,53,42,115,10,9,97,61,40,120,94, + 110,41,47,50,94,110,47,97,10,9,114,61,118,61,49,10,9,102,61,45,120,42,120,47, + 52,10,9,115,99,97,108,101,61,115,99,97,108,101,43,108,101,110,103,116,104,40, + 97,41,45,115,99,97,108,101,40,97,41,10,9,102,111,114,40,105,61,49,59,118,33, + 61,48,59,43,43,105,41,123,10,9,9,118,61,118,42,102,47,105,47,40,110,43,105, + 41,10,9,9,114,43,61,118,10,9,125,10,9,115,99,97,108,101,61,115,10,9,105,98, + 97,115,101,61,98,10,9,105,102,40,111,33,61,48,41,97,61,45,97,10,9,114,101,116, + 117,114,110,40,97,42,114,47,49,41,10,125,10,0 +}; +#endif // ENABLE_BC + +static void bc_vec_grow(BcVec *v, size_t n) +{ + size_t cap = v->cap * 2; + while (cap < v->len + n) cap *= 2; + v->v = xrealloc(v->v, v->size * cap); + v->cap = cap; +} + +static void bc_vec_init(BcVec *v, size_t esize, BcVecFree dtor) +{ + v->size = esize; + v->cap = BC_VEC_START_CAP; + v->len = 0; + v->dtor = dtor; + v->v = xmalloc(esize * BC_VEC_START_CAP); +} + +static void bc_vec_expand(BcVec *v, size_t req) +{ + if (v->cap < req) { + v->v = xrealloc(v->v, v->size * req); + v->cap = req; + } +} + +static void bc_vec_npop(BcVec *v, size_t n) +{ + if (!v->dtor) + v->len -= n; + else { + size_t len = v->len - n; + while (v->len > len) v->dtor(v->v + (v->size * --v->len)); + } +} + +static void bc_vec_push(BcVec *v, const void *data) +{ + if (v->len + 1 > v->cap) bc_vec_grow(v, 1); + memmove(v->v + (v->size * v->len), data, v->size); + v->len += 1; +} + +static void bc_vec_pushByte(BcVec *v, char data) +{ + bc_vec_push(v, &data); +} + +static void bc_vec_pushAt(BcVec *v, const void *data, size_t idx) +{ + if (idx == v->len) + bc_vec_push(v, data); + else { + + char *ptr; + + if (v->len == v->cap) bc_vec_grow(v, 1); + + ptr = v->v + v->size * idx; + + memmove(ptr + v->size, ptr, v->size * (v->len++ - idx)); + memmove(ptr, data, v->size); + } +} + +static void bc_vec_string(BcVec *v, size_t len, const char *str) +{ + bc_vec_npop(v, v->len); + bc_vec_expand(v, len + 1); + memcpy(v->v, str, len); + v->len = len; + + bc_vec_pushByte(v, '\0'); +} + +static void bc_vec_concat(BcVec *v, const char *str) +{ + size_t len; + + if (v->len == 0) bc_vec_pushByte(v, '\0'); + + len = v->len + strlen(str); + + if (v->cap < len) bc_vec_grow(v, len - v->len); + strcat(v->v, str); + + v->len = len; +} + +static void *bc_vec_item(const BcVec *v, size_t idx) +{ + return v->v + v->size * idx; +} + +static void *bc_vec_item_rev(const BcVec *v, size_t idx) +{ + return v->v + v->size * (v->len - idx - 1); +} + +static void bc_vec_free(void *vec) +{ + BcVec *v = (BcVec *) vec; + bc_vec_npop(v, v->len); + free(v->v); +} + +static size_t bc_map_find(const BcVec *v, const void *ptr) +{ + size_t low = 0, high = v->len; + + while (low < high) { + + size_t mid = (low + high) / 2; + BcId *id = bc_vec_item(v, mid); + int result = bc_id_cmp(ptr, id); + + if (result == 0) + return mid; + else if (result < 0) + high = mid; + else + low = mid + 1; + } + + return low; +} + +static BcStatus bc_map_insert(BcVec *v, const void *ptr, size_t *i) +{ + BcStatus s = BC_STATUS_SUCCESS; + + *i = bc_map_find(v, ptr); + + if (*i == v->len) + bc_vec_push(v, ptr); + else if (!bc_id_cmp(ptr, bc_vec_item(v, *i))) + s = BC_STATUS_VEC_ITEM_EXISTS; + else + bc_vec_pushAt(v, ptr, *i); + + return s; +} + +static size_t bc_map_index(const BcVec *v, const void *ptr) +{ + size_t i = bc_map_find(v, ptr); + if (i >= v->len) return BC_VEC_INVALID_IDX; + return bc_id_cmp(ptr, bc_vec_item(v, i)) ? BC_VEC_INVALID_IDX : i; +} + +static BcStatus bc_read_line(BcVec *vec, const char *prompt) +{ + int i; + signed char c = 0; + + if (bcg.ttyin && !bcg.posix) { + bc_vm_puts(prompt, stderr); + bc_vm_fflush(stderr); + } + + bc_vec_npop(vec, vec->len); + + while (c != '\n') { + + i = fgetc(stdin); + + if (i == EOF) { + +#if ENABLE_FEATURE_BC_SIGNALS + if (errno == EINTR) { + + bcg.sigc = bcg.sig; + bcg.signe = 0; + + if (bcg.ttyin) { + bc_vm_puts(bc_program_ready_msg, stderr); + if (!bcg.posix) bc_vm_puts(prompt, stderr); + bc_vm_fflush(stderr); + } + + continue; + } +#endif // ENABLE_FEATURE_BC_SIGNALS + + return BC_STATUS_IO_ERR; + } + + c = (signed char) i; + if (i > UCHAR_MAX || BC_READ_BIN_CHAR(c)) return BC_STATUS_BIN_FILE; + bc_vec_push(vec, &c); + } + + bc_vec_pushByte(vec, '\0'); + + return BC_STATUS_SUCCESS; +} + +static BcStatus bc_read_file(const char *path, char **buf) +{ + BcStatus s = BC_STATUS_BIN_FILE; + size_t size = ((size_t) -1), read; + + *buf = xmalloc_open_read_close(path, &size); + + for (read = 0; read < size; ++read) { + if (BC_READ_BIN_CHAR((*buf)[read])) goto read_err; + } + + return BC_STATUS_SUCCESS; + +read_err: + free(*buf); + return s; +} + +#if ENABLE_FEATURE_BC_LONG_OPTIONS +static const char bc_args_lopt[] ALIGN1 = + "extended-register\0"No_argument"x" + "warn\0"No_argument"w" + "version\0"No_argument"v" + "standard\0"No_argument"s" + "quiet\0"No_argument"q" + "mathlib\0"No_argument"l" + "interactive\0"No_argument"i"; +#endif // ENABLE_FEATURE_BC_LONG_OPTIONS + +static const char bc_args_opt[] ALIGN1 = "xwvsqli"; + +static BcStatus bc_args(int argc, char *argv[], uint32_t *flags, BcVec *files) +{ + BcStatus s = BC_STATUS_SUCCESS; + int i; + bool do_exit = false; + + i = optind = 0; + +#if ENABLE_FEATURE_BC_LONG_OPTIONS + *flags = getopt32long(argv, bc_args_opt, bc_args_lopt); +#else // ENABLE_FEATURE_BC_LONG_OPTIONS + *flags = getopt32(argv, bc_args_opt); +#endif // ENABLE_FEATURE_BC_LONG_OPTIONS + + if ((*flags) & BC_FLAG_V) bc_vm_info(NULL); + if (do_exit) exit((int) s); + if (argv[optind] && !strcmp(argv[optind], "--")) ++optind; + + for (i = optind; i < argc; ++i) bc_vec_push(files, argv + i); + + return s; +} + +static void bc_num_setToZero(BcNum *n, size_t scale) +{ + n->len = 0; + n->neg = false; + n->rdx = scale; +} + +static void bc_num_zero(BcNum *n) +{ + bc_num_setToZero(n, 0); +} + +static void bc_num_one(BcNum *n) +{ + bc_num_setToZero(n, 0); + n->len = 1; + n->num[0] = 1; +} + +static void bc_num_ten(BcNum *n) +{ + bc_num_setToZero(n, 0); + n->len = 2; + n->num[0] = 0; + n->num[1] = 1; +} + +static BcStatus bc_num_subArrays(BcDig *restrict a, BcDig *restrict b, + size_t len) +{ + size_t i, j; + for (i = 0; !bcg.signe && i < len; ++i) { + for (a[i] -= b[i], j = 0; !bcg.signe && a[i + j] < 0;) { + a[i + j++] += 10; + a[i + j] -= 1; + } + } + return bcg.signe ? BC_STATUS_EXEC_SIGNAL : BC_STATUS_SUCCESS; +} + +static ssize_t bc_num_compare(BcDig *restrict a, BcDig *restrict b, size_t len) +{ + size_t i; + int c = 0; + for (i = len - 1; !bcg.signe && i < len && !(c = a[i] - b[i]); --i); + return BC_NUM_NEG(i + 1, c < 0); +} + +static ssize_t bc_num_cmp(BcNum *a, BcNum *b) +{ + size_t i, min, a_int, b_int, diff; + BcDig *max_num, *min_num; + bool a_max, neg = false; + ssize_t cmp; + + if (a == b) return 0; + if (a->len == 0) return BC_NUM_NEG(!!b->len, !b->neg); + if (b->len == 0) return BC_NUM_NEG(1, a->neg); + if (a->neg) { + if (b->neg) + neg = true; + else + return -1; + } + else if (b->neg) + return 1; + + a_int = BC_NUM_INT(a); + b_int = BC_NUM_INT(b); + a_int -= b_int; + a_max = (a->rdx > b->rdx); + + if (a_int != 0) return (ssize_t) a_int; + + if (a_max) { + min = b->rdx; + diff = a->rdx - b->rdx; + max_num = a->num + diff; + min_num = b->num; + } + else { + min = a->rdx; + diff = b->rdx - a->rdx; + max_num = b->num + diff; + min_num = a->num; + } + + cmp = bc_num_compare(max_num, min_num, b_int + min); + if (cmp != 0) return BC_NUM_NEG(cmp, (!a_max) != neg); + + for (max_num -= diff, i = diff - 1; !bcg.signe && i < diff; --i) { + if (max_num[i]) return BC_NUM_NEG(1, (!a_max) != neg); + } + + return 0; +} + +static void bc_num_truncate(BcNum *n, size_t places) +{ + if (places == 0) return; + + n->rdx -= places; + + if (n->len != 0) { + n->len -= places; + memmove(n->num, n->num + places, n->len * sizeof(BcDig)); + } +} + +static void bc_num_extend(BcNum *n, size_t places) +{ + size_t len = n->len + places; + + if (places != 0) { + + if (n->cap < len) bc_num_expand(n, len); + + memmove(n->num + places, n->num, sizeof(BcDig) * n->len); + memset(n->num, 0, sizeof(BcDig) * places); + + n->len += places; + n->rdx += places; + } +} + +static void bc_num_clean(BcNum *n) +{ + while (n->len > 0 && n->num[n->len - 1] == 0) --n->len; + if (n->len == 0) + n->neg = false; + else if (n->len < n->rdx) + n->len = n->rdx; +} + +static void bc_num_retireMul(BcNum *n, size_t scale, bool neg1, bool neg2) +{ + if (n->rdx < scale) + bc_num_extend(n, scale - n->rdx); + else + bc_num_truncate(n, n->rdx - scale); + + bc_num_clean(n); + if (n->len != 0) n->neg = !neg1 != !neg2; +} + +static void bc_num_split(BcNum *restrict n, size_t idx, BcNum *restrict a, + BcNum *restrict b) +{ + if (idx < n->len) { + + b->len = n->len - idx; + a->len = idx; + a->rdx = b->rdx = 0; + + memcpy(b->num, n->num + idx, b->len * sizeof(BcDig)); + memcpy(a->num, n->num, idx * sizeof(BcDig)); + } + else { + bc_num_zero(b); + bc_num_copy(a, n); + } + + bc_num_clean(a); + bc_num_clean(b); +} + +static BcStatus bc_num_shift(BcNum *n, size_t places) +{ + if (places == 0 || n->len == 0) return BC_STATUS_SUCCESS; + if (places + n->len > BC_MAX_NUM) return BC_STATUS_EXEC_NUM_LEN; + + if (n->rdx >= places) + n->rdx -= places; + else { + bc_num_extend(n, places - n->rdx); + n->rdx = 0; + } + + bc_num_clean(n); + + return BC_STATUS_SUCCESS; +} + +static BcStatus bc_num_inv(BcNum *a, BcNum *b, size_t scale) +{ + BcNum one; + BcDig num[2]; + + one.cap = 2; + one.num = num; + bc_num_one(&one); + + return bc_num_div(&one, a, b, scale); +} + +static BcStatus bc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) +{ + BcDig *ptr, *ptr_a, *ptr_b, *ptr_c; + size_t i, max, min_rdx, min_int, diff, a_int, b_int; + int carry, in; + + // Because this function doesn't need to use scale (per the bc spec), + // I am hijacking it to say whether it's doing an add or a subtract. + + if (a->len == 0) { + bc_num_copy(c, b); + if (sub && c->len) c->neg = !c->neg; + return BC_STATUS_SUCCESS; + } + else if (b->len == 0) { + bc_num_copy(c, a); + return BC_STATUS_SUCCESS; + } + + c->neg = a->neg; + c->rdx = BC_MAX(a->rdx, b->rdx); + min_rdx = BC_MIN(a->rdx, b->rdx); + c->len = 0; + + if (a->rdx > b->rdx) { + diff = a->rdx - b->rdx; + ptr = a->num; + ptr_a = a->num + diff; + ptr_b = b->num; + } + else { + diff = b->rdx - a->rdx; + ptr = b->num; + ptr_a = a->num; + ptr_b = b->num + diff; + } + + for (ptr_c = c->num, i = 0; i < diff; ++i, ++c->len) ptr_c[i] = ptr[i]; + + ptr_c += diff; + a_int = BC_NUM_INT(a); + b_int = BC_NUM_INT(b); + + if (a_int > b_int) { + min_int = b_int; + max = a_int; + ptr = ptr_a; + } + else { + min_int = a_int; + max = b_int; + ptr = ptr_b; + } + + for (carry = 0, i = 0; !bcg.signe && i < min_rdx + min_int; ++i, ++c->len) { + in = ((int) ptr_a[i]) + ((int) ptr_b[i]) + carry; + carry = in / 10; + ptr_c[i] = (BcDig)(in % 10); + } + + for (; !bcg.signe && i < max + min_rdx; ++i, ++c->len) { + in = ((int) ptr[i]) + carry; + carry = in / 10; + ptr_c[i] = (BcDig)(in % 10); + } + + if (carry != 0) c->num[c->len++] = (BcDig) carry; + + return bcg.signe ? BC_STATUS_EXEC_SIGNAL : BC_STATUS_SUCCESS; +} + +static BcStatus bc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) +{ + BcStatus s; + ssize_t cmp; + BcNum *minuend, *subtrahend; + size_t start; + bool aneg, bneg, neg; + + // Because this function doesn't need to use scale (per the bc spec), + // I am hijacking it to say whether it's doing an add or a subtract. + + if (a->len == 0) { + bc_num_copy(c, b); + if (sub && c->len) c->neg = !c->neg; + return BC_STATUS_SUCCESS; + } + else if (b->len == 0) { + bc_num_copy(c, a); + return BC_STATUS_SUCCESS; + } + + aneg = a->neg; + bneg = b->neg; + a->neg = b->neg = false; + + cmp = bc_num_cmp(a, b); + + a->neg = aneg; + b->neg = bneg; + + if (cmp == 0) { + bc_num_setToZero(c, BC_MAX(a->rdx, b->rdx)); + return BC_STATUS_SUCCESS; + } + else if (cmp > 0) { + neg = a->neg; + minuend = a; + subtrahend = b; + } + else { + neg = b->neg; + if (sub) neg = !neg; + minuend = b; + subtrahend = a; + } + + bc_num_copy(c, minuend); + c->neg = neg; + + if (c->rdx < subtrahend->rdx) { + bc_num_extend(c, subtrahend->rdx - c->rdx); + start = 0; + } + else + start = c->rdx - subtrahend->rdx; + + s = bc_num_subArrays(c->num + start, subtrahend->num, subtrahend->len); + + bc_num_clean(c); + + return s; +} + +static BcStatus bc_num_k(BcNum *restrict a, BcNum *restrict b, + BcNum *restrict c) +{ + BcStatus s; + int carry; + size_t i, j, len, max = BC_MAX(a->len, b->len), max2 = (max + 1) / 2; + BcNum l1, h1, l2, h2, m2, m1, z0, z1, z2, temp; + bool aone = BC_NUM_ONE(a); + + if (bcg.signe) return BC_STATUS_EXEC_SIGNAL; + if (a->len == 0 || b->len == 0) { + bc_num_zero(c); + return BC_STATUS_SUCCESS; + } + else if (aone || BC_NUM_ONE(b)) { + bc_num_copy(c, aone ? b : a); + return BC_STATUS_SUCCESS; + } + + if (a->len + b->len < BC_NUM_KARATSUBA_LEN || + a->len < BC_NUM_KARATSUBA_LEN || b->len < BC_NUM_KARATSUBA_LEN) + { + bc_num_expand(c, a->len + b->len + 1); + + memset(c->num, 0, sizeof(BcDig) * c->cap); + c->len = carry = len = 0; + + for (i = 0; !bcg.signe && i < b->len; ++i) { + + for (j = 0; !bcg.signe && j < a->len; ++j) { + int in = (int) c->num[i + j]; + in += ((int) a->num[j]) * ((int) b->num[i]) + carry; + carry = in / 10; + c->num[i + j] = (BcDig)(in % 10); + } + + c->num[i + j] += (BcDig) carry; + len = BC_MAX(len, i + j + !!carry); + carry = 0; + } + + c->len = len; + + return bcg.signe ? BC_STATUS_EXEC_SIGNAL : BC_STATUS_SUCCESS; + } + + bc_num_init(&l1, max); + bc_num_init(&h1, max); + bc_num_init(&l2, max); + bc_num_init(&h2, max); + bc_num_init(&m1, max); + bc_num_init(&m2, max); + bc_num_init(&z0, max); + bc_num_init(&z1, max); + bc_num_init(&z2, max); + bc_num_init(&temp, max + max); + + bc_num_split(a, max2, &l1, &h1); + bc_num_split(b, max2, &l2, &h2); + + s = bc_num_add(&h1, &l1, &m1, 0); + if (s) goto err; + s = bc_num_add(&h2, &l2, &m2, 0); + if (s) goto err; + + s = bc_num_k(&h1, &h2, &z0); + if (s) goto err; + s = bc_num_k(&m1, &m2, &z1); + if (s) goto err; + s = bc_num_k(&l1, &l2, &z2); + if (s) goto err; + + s = bc_num_sub(&z1, &z0, &temp, 0); + if (s) goto err; + s = bc_num_sub(&temp, &z2, &z1, 0); + if (s) goto err; + + s = bc_num_shift(&z0, max2 * 2); + if (s) goto err; + s = bc_num_shift(&z1, max2); + if (s) goto err; + s = bc_num_add(&z0, &z1, &temp, 0); + if (s) goto err; + s = bc_num_add(&temp, &z2, c, 0); + +err: + bc_num_free(&temp); + bc_num_free(&z2); + bc_num_free(&z1); + bc_num_free(&z0); + bc_num_free(&m2); + bc_num_free(&m1); + bc_num_free(&h2); + bc_num_free(&l2); + bc_num_free(&h1); + bc_num_free(&l1); + return s; +} + +static BcStatus bc_num_m(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) +{ + BcStatus s; + BcNum cpa, cpb; + size_t maxrdx = BC_MAX(a->rdx, b->rdx); + + scale = BC_MAX(scale, a->rdx); + scale = BC_MAX(scale, b->rdx); + scale = BC_MIN(a->rdx + b->rdx, scale); + maxrdx = BC_MAX(maxrdx, scale); + + bc_num_init(&cpa, a->len); + bc_num_init(&cpb, b->len); + + bc_num_copy(&cpa, a); + bc_num_copy(&cpb, b); + cpa.neg = cpb.neg = false; + + s = bc_num_shift(&cpa, maxrdx); + if (s) goto err; + s = bc_num_shift(&cpb, maxrdx); + if (s) goto err; + s = bc_num_k(&cpa, &cpb, c); + if (s) goto err; + + maxrdx += scale; + bc_num_expand(c, c->len + maxrdx); + + if (c->len < maxrdx) { + memset(c->num + c->len, 0, (c->cap - c->len) * sizeof(BcDig)); + c->len += maxrdx; + } + + c->rdx = maxrdx; + bc_num_retireMul(c, scale, a->neg, b->neg); + +err: + bc_num_free(&cpb); + bc_num_free(&cpa); + return s; +} + +static BcStatus bc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) +{ + BcStatus s = BC_STATUS_SUCCESS; + BcDig *n, *p, q; + size_t len, end, i; + BcNum cp; + bool zero = true; + + if (b->len == 0) + return BC_STATUS_MATH_DIVIDE_BY_ZERO; + else if (a->len == 0) { + bc_num_setToZero(c, scale); + return BC_STATUS_SUCCESS; + } + else if (BC_NUM_ONE(b)) { + bc_num_copy(c, a); + bc_num_retireMul(c, scale, a->neg, b->neg); + return BC_STATUS_SUCCESS; + } + + bc_num_init(&cp, BC_NUM_MREQ(a, b, scale)); + bc_num_copy(&cp, a); + len = b->len; + + if (len > cp.len) { + bc_num_expand(&cp, len + 2); + bc_num_extend(&cp, len - cp.len); + } + + if (b->rdx > cp.rdx) bc_num_extend(&cp, b->rdx - cp.rdx); + cp.rdx -= b->rdx; + if (scale > cp.rdx) bc_num_extend(&cp, scale - cp.rdx); + + if (b->rdx == b->len) { + for (i = 0; zero && i < len; ++i) zero = !b->num[len - i - 1]; + len -= i - 1; + } + + if (cp.cap == cp.len) bc_num_expand(&cp, cp.len + 1); + + // We want an extra zero in front to make things simpler. + cp.num[cp.len++] = 0; + end = cp.len - len; + + bc_num_expand(c, cp.len); + + bc_num_zero(c); + memset(c->num + end, 0, (c->cap - end) * sizeof(BcDig)); + c->rdx = cp.rdx; + c->len = cp.len; + p = b->num; + + for (i = end - 1; !bcg.signe && !s && i < end; --i) { + n = cp.num + i; + for (q = 0; (!s && n[len] != 0) || bc_num_compare(n, p, len) >= 0; ++q) + s = bc_num_subArrays(n, p, len); + c->num[i] = q; + } + + if (!s) bc_num_retireMul(c, scale, a->neg, b->neg); + bc_num_free(&cp); + + return s; +} + +static BcStatus bc_num_r(BcNum *a, BcNum *b, BcNum *restrict c, + BcNum *restrict d, size_t scale, size_t ts) +{ + BcStatus s; + BcNum temp; + bool neg; + + if (b->len == 0) return BC_STATUS_MATH_DIVIDE_BY_ZERO; + + if (a->len == 0) { + bc_num_setToZero(d, ts); + return BC_STATUS_SUCCESS; + } + + bc_num_init(&temp, d->cap); + bc_num_d(a, b, c, scale); + + if (scale != 0) scale = ts; + + s = bc_num_m(c, b, &temp, scale); + if (s) goto err; + s = bc_num_sub(a, &temp, d, scale); + if (s) goto err; + + if (ts > d->rdx && d->len) bc_num_extend(d, ts - d->rdx); + + neg = d->neg; + bc_num_retireMul(d, ts, a->neg, b->neg); + d->neg = neg; + +err: + bc_num_free(&temp); + return s; +} + +static BcStatus bc_num_rem(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) +{ + BcStatus s; + BcNum c1; + size_t ts = BC_MAX(scale + b->rdx, a->rdx), len = BC_NUM_MREQ(a, b, ts); + + bc_num_init(&c1, len); + s = bc_num_r(a, b, &c1, c, scale, ts); + bc_num_free(&c1); + + return s; +} + +static BcStatus bc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) +{ + BcStatus s = BC_STATUS_SUCCESS; + BcNum copy; + unsigned long pow; + size_t i, powrdx, resrdx; + bool neg, zero; + + if (b->rdx) return BC_STATUS_MATH_NON_INTEGER; + + if (b->len == 0) { + bc_num_one(c); + return BC_STATUS_SUCCESS; + } + else if (a->len == 0) { + bc_num_setToZero(c, scale); + return BC_STATUS_SUCCESS; + } + else if (BC_NUM_ONE(b)) { + if (!b->neg) + bc_num_copy(c, a); + else + s = bc_num_inv(a, c, scale); + return s; + } + + neg = b->neg; + b->neg = false; + + s = bc_num_ulong(b, &pow); + if (s) return s; + + bc_num_init(©, a->len); + bc_num_copy(©, a); + + if (!neg) scale = BC_MIN(a->rdx * pow, BC_MAX(scale, a->rdx)); + + b->neg = neg; + + for (powrdx = a->rdx; !bcg.signe && !(pow & 1); pow >>= 1) { + powrdx <<= 1; + s = bc_num_mul(©, ©, ©, powrdx); + if (s) goto err; + } + + if (bcg.signe) { + s = BC_STATUS_EXEC_SIGNAL; + goto err; + } + + bc_num_copy(c, ©); + + for (resrdx = powrdx, pow >>= 1; !bcg.signe && pow != 0; pow >>= 1) { + + powrdx <<= 1; + s = bc_num_mul(©, ©, ©, powrdx); + if (s) goto err; + + if (pow & 1) { + resrdx += powrdx; + s = bc_num_mul(c, ©, c, resrdx); + if (s) goto err; + } + } + + if (neg) { + s = bc_num_inv(c, c, scale); + if (s) goto err; + } + + if (bcg.signe) { + s = BC_STATUS_EXEC_SIGNAL; + goto err; + } + + if (c->rdx > scale) bc_num_truncate(c, c->rdx - scale); + + // We can't use bc_num_clean() here. + for (zero = true, i = 0; zero && i < c->len; ++i) zero = !c->num[i]; + if (zero) bc_num_setToZero(c, scale); + +err: + bc_num_free(©); + return s; +} + +static BcStatus bc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale, + BcNumBinaryOp op, size_t req) +{ + BcStatus s; + BcNum num2, *ptr_a, *ptr_b; + bool init = false; + + if (c == a) { + ptr_a = &num2; + memcpy(ptr_a, c, sizeof(BcNum)); + init = true; + } + else + ptr_a = a; + + if (c == b) { + ptr_b = &num2; + if (c != a) { + memcpy(ptr_b, c, sizeof(BcNum)); + init = true; + } + } + else + ptr_b = b; + + if (init) + bc_num_init(c, req); + else + bc_num_expand(c, req); + + s = op(ptr_a, ptr_b, c, scale); + + if (init) bc_num_free(&num2); + + return s; +} + +static bool bc_num_strValid(const char *val, size_t base) +{ + BcDig b; + bool small, radix = false; + size_t i, len = strlen(val); + + if (!len) return true; + + small = base <= 10; + b = (BcDig)(small ? base + '0' : base - 10 + 'A'); + + for (i = 0; i < len; ++i) { + + BcDig c = val[i]; + + if (c == '.') { + + if (radix) return false; + + radix = true; + continue; + } + + if (c < '0' || (small && c >= b) || (c > '9' && (c < 'A' || c >= b))) + return false; + } + + return true; +} + +static void bc_num_parseDecimal(BcNum *n, const char *val) +{ + size_t len, i; + const char *ptr; + bool zero = true; + + for (i = 0; val[i] == '0'; ++i); + + val += i; + len = strlen(val); + bc_num_zero(n); + + if (len != 0) { + for (i = 0; zero && i < len; ++i) zero = val[i] == '0' || val[i] == '.'; + bc_num_expand(n, len); + } + + ptr = strchr(val, '.'); + + // Explicitly test for NULL here to produce either a 0 or 1. + n->rdx = (size_t)((ptr != NULL) * ((val + len) - (ptr + 1))); + + if (!zero) { + for (i = len - 1; i < len; ++n->len, i -= 1 + (i && val[i - 1] == '.')) + n->num[n->len] = val[i] - '0'; + } +} + +static void bc_num_parseBase(BcNum *n, const char *val, BcNum *base) +{ + BcStatus s; + BcNum temp, mult, result; + BcDig c = '\0'; + bool zero = true; + unsigned long v; + size_t i, digits, len = strlen(val); + + bc_num_zero(n); + + for (i = 0; zero && i < len; ++i) zero = (val[i] == '.' || val[i] == '0'); + if (zero) return; + + bc_num_init(&temp, BC_NUM_DEF_SIZE); + bc_num_init(&mult, BC_NUM_DEF_SIZE); + + for (i = 0; i < len; ++i) { + + c = val[i]; + if (c == '.') break; + + v = (unsigned long) (c <= '9' ? c - '0' : c - 'A' + 10); + + s = bc_num_mul(n, base, &mult, 0); + if (s) goto int_err; + s = bc_num_ulong2num(&temp, v); + if (s) goto int_err; + s = bc_num_add(&mult, &temp, n, 0); + if (s) goto int_err; + } + + if (i == len) { + c = val[i]; + if (c == 0) goto int_err; + } + + bc_num_init(&result, base->len); + bc_num_zero(&result); + bc_num_one(&mult); + + for (i += 1, digits = 0; i < len; ++i, ++digits) { + + c = val[i]; + if (c == 0) break; + + v = (unsigned long) (c <= '9' ? c - '0' : c - 'A' + 10); + + s = bc_num_mul(&result, base, &result, 0); + if (s) goto err; + s = bc_num_ulong2num(&temp, v); + if (s) goto err; + s = bc_num_add(&result, &temp, &result, 0); + if (s) goto err; + s = bc_num_mul(&mult, base, &mult, 0); + if (s) goto err; + } + + s = bc_num_div(&result, &mult, &result, digits); + if (s) goto err; + s = bc_num_add(n, &result, n, digits); + if (s) goto err; + + if (n->len != 0) { + if (n->rdx < digits) bc_num_extend(n, digits - n->rdx); + } + else + bc_num_zero(n); + +err: + bc_num_free(&result); +int_err: + bc_num_free(&mult); + bc_num_free(&temp); +} + +static void bc_num_printNewline(size_t *nchars, size_t line_len) +{ + if (*nchars == line_len - 1) { + bc_vm_putchar('\\'); + bc_vm_putchar('\n'); + *nchars = 0; + } +} + +#ifdef ENABLE_DC +static void bc_num_printChar(size_t num, size_t width, bool radix, + size_t *nchars, size_t line_len) +{ + (void) radix, (void) line_len; + bc_vm_putchar((char) num); + *nchars = *nchars + width; +} +#endif // ENABLE_DC + +static void bc_num_printDigits(size_t num, size_t width, bool radix, + size_t *nchars, size_t line_len) +{ + size_t exp, pow, div; + + bc_num_printNewline(nchars, line_len); + bc_vm_putchar(radix ? '.' : ' '); + ++(*nchars); + + bc_num_printNewline(nchars, line_len); + for (exp = 0, pow = 1; exp < width - 1; ++exp, pow *= 10); + + for (exp = 0; exp < width; pow /= 10, ++(*nchars), ++exp) { + bc_num_printNewline(nchars, line_len); + div = num / pow; + num -= div * pow; + bc_vm_putchar(((char) div) + '0'); + } +} + +static void bc_num_printHex(size_t num, size_t width, bool radix, + size_t *nchars, size_t line_len) +{ + if (radix) { + bc_num_printNewline(nchars, line_len); + bc_vm_putchar('.'); + *nchars += 1; + } + + bc_num_printNewline(nchars, line_len); + bc_vm_putchar(bc_num_hex_digits[num]); + *nchars = *nchars + width; +} + +static void bc_num_printDecimal(BcNum *n, size_t *nchars, size_t len) +{ + size_t i, rdx = n->rdx - 1; + + if (n->neg) bc_vm_putchar('-'); + (*nchars) += n->neg; + + for (i = n->len - 1; i < n->len; --i) + bc_num_printHex((size_t) n->num[i], 1, i == rdx, nchars, len); +} + +static BcStatus bc_num_printNum(BcNum *n, BcNum *base, size_t width, + size_t *nchars, size_t len, BcNumDigitOp print) +{ + BcStatus s; + BcVec stack; + BcNum intp, fracp, digit, frac_len; + unsigned long dig, *ptr; + size_t i; + bool radix; + + if (n->len == 0) { + print(0, width, false, nchars, len); + return BC_STATUS_SUCCESS; + } + + bc_vec_init(&stack, sizeof(long), NULL); + bc_num_init(&intp, n->len); + bc_num_init(&fracp, n->rdx); + bc_num_init(&digit, width); + bc_num_init(&frac_len, BC_NUM_INT(n)); + bc_num_copy(&intp, n); + bc_num_one(&frac_len); + + bc_num_truncate(&intp, intp.rdx); + s = bc_num_sub(n, &intp, &fracp, 0); + if (s) goto err; + + while (intp.len != 0) { + s = bc_num_divmod(&intp, base, &intp, &digit, 0); + if (s) goto err; + s = bc_num_ulong(&digit, &dig); + if (s) goto err; + bc_vec_push(&stack, &dig); + } + + for (i = 0; i < stack.len; ++i) { + ptr = bc_vec_item_rev(&stack, i); + print(*ptr, width, false, nchars, len); + } + + if (!n->rdx) goto err; + + for (radix = true; frac_len.len <= n->rdx; radix = false) { + s = bc_num_mul(&fracp, base, &fracp, n->rdx); + if (s) goto err; + s = bc_num_ulong(&fracp, &dig); + if (s) goto err; + s = bc_num_ulong2num(&intp, dig); + if (s) goto err; + s = bc_num_sub(&fracp, &intp, &fracp, 0); + if (s) goto err; + print(dig, width, radix, nchars, len); + s = bc_num_mul(&frac_len, base, &frac_len, 0); + if (s) goto err; + } + +err: + bc_num_free(&frac_len); + bc_num_free(&digit); + bc_num_free(&fracp); + bc_num_free(&intp); + bc_vec_free(&stack); + return s; +} + +static BcStatus bc_num_printBase(BcNum *n, BcNum *base, size_t base_t, + size_t *nchars, size_t line_len) +{ + BcStatus s; + size_t width, i; + BcNumDigitOp print; + bool neg = n->neg; + + if (neg) bc_vm_putchar('-'); + (*nchars) += neg; + + n->neg = false; + + if (base_t <= BC_NUM_MAX_IBASE) { + width = 1; + print = bc_num_printHex; + } + else { + for (i = base_t - 1, width = 0; i != 0; i /= 10, ++width); + print = bc_num_printDigits; + } + + s = bc_num_printNum(n, base, width, nchars, line_len, print); + n->neg = neg; + + return s; +} + +#ifdef ENABLE_DC +static BcStatus bc_num_stream(BcNum *n, BcNum *base, size_t *nchars, size_t len) +{ + return bc_num_printNum(n, base, 1, nchars, len, bc_num_printChar); +} +#endif // ENABLE_DC + +static void bc_num_init(BcNum *n, size_t req) +{ + req = req >= BC_NUM_DEF_SIZE ? req : BC_NUM_DEF_SIZE; + memset(n, 0, sizeof(BcNum)); + n->num = xmalloc(req); + n->cap = req; +} + +static void bc_num_expand(BcNum *n, size_t req) +{ + req = req >= BC_NUM_DEF_SIZE ? req : BC_NUM_DEF_SIZE; + if (req > n->cap) { + n->num = xrealloc(n->num, req); + n->cap = req; + } +} + +static void bc_num_free(void *num) +{ + free(((BcNum *) num)->num); +} + +static void bc_num_copy(BcNum *d, BcNum *s) +{ + if (d != s) { + bc_num_expand(d, s->cap); + d->len = s->len; + d->neg = s->neg; + d->rdx = s->rdx; + memcpy(d->num, s->num, sizeof(BcDig) * d->len); + } +} + +static BcStatus bc_num_parse(BcNum *n, const char *val, BcNum *base, + size_t base_t) +{ + if (!bc_num_strValid(val, base_t)) return BC_STATUS_MATH_BAD_STRING; + + if (base_t == 10) + bc_num_parseDecimal(n, val); + else + bc_num_parseBase(n, val, base); + + return BC_STATUS_SUCCESS; +} + +static BcStatus bc_num_print(BcNum *n, BcNum *base, size_t base_t, bool newline, + size_t *nchars, size_t line_len) +{ + BcStatus s = BC_STATUS_SUCCESS; + + bc_num_printNewline(nchars, line_len); + + if (n->len == 0) { + bc_vm_putchar('0'); + ++(*nchars); + } + else if (base_t == 10) + bc_num_printDecimal(n, nchars, line_len); + else + s = bc_num_printBase(n, base, base_t, nchars, line_len); + + if (newline) { + bc_vm_putchar('\n'); + *nchars = 0; + } + + return s; +} + +static BcStatus bc_num_ulong(BcNum *n, unsigned long *result) +{ + size_t i; + unsigned long pow; + + if (n->neg) return BC_STATUS_MATH_NEGATIVE; + + for (*result = 0, pow = 1, i = n->rdx; i < n->len; ++i) { + + unsigned long prev = *result, powprev = pow; + + *result += ((unsigned long) n->num[i]) * pow; + pow *= 10; + + if (*result < prev || pow < powprev) return BC_STATUS_MATH_OVERFLOW; + } + + return BC_STATUS_SUCCESS; +} + +static BcStatus bc_num_ulong2num(BcNum *n, unsigned long val) +{ + size_t len; + BcDig *ptr; + unsigned long i; + + bc_num_zero(n); + + if (val == 0) return BC_STATUS_SUCCESS; + + for (len = 1, i = ULONG_MAX; i != 0; i /= 10, ++len) bc_num_expand(n, len); + for (ptr = n->num, i = 0; val; ++i, ++n->len, val /= 10) ptr[i] = val % 10; + + return BC_STATUS_SUCCESS; +} + +static BcStatus bc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale) +{ + BcNumBinaryOp op = (!a->neg == !b->neg) ? bc_num_a : bc_num_s; + (void) scale; + return bc_num_binary(a, b, c, false, op, BC_NUM_AREQ(a, b)); +} + +static BcStatus bc_num_sub(BcNum *a, BcNum *b, BcNum *c, size_t scale) +{ + BcNumBinaryOp op = (!a->neg == !b->neg) ? bc_num_s : bc_num_a; + (void) scale; + return bc_num_binary(a, b, c, true, op, BC_NUM_AREQ(a, b)); +} + +static BcStatus bc_num_mul(BcNum *a, BcNum *b, BcNum *c, size_t scale) +{ + size_t req = BC_NUM_MREQ(a, b, scale); + return bc_num_binary(a, b, c, scale, bc_num_m, req); +} + +static BcStatus bc_num_div(BcNum *a, BcNum *b, BcNum *c, size_t scale) +{ + size_t req = BC_NUM_MREQ(a, b, scale); + return bc_num_binary(a, b, c, scale, bc_num_d, req); +} + +static BcStatus bc_num_mod(BcNum *a, BcNum *b, BcNum *c, size_t scale) +{ + size_t req = BC_NUM_MREQ(a, b, scale); + return bc_num_binary(a, b, c, scale, bc_num_rem, req); +} + +static BcStatus bc_num_pow(BcNum *a, BcNum *b, BcNum *c, size_t scale) +{ + return bc_num_binary(a, b, c, scale, bc_num_p, a->len * b->len + 1); +} + +static BcStatus bc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale) +{ + BcStatus s; + BcNum num1, num2, half, f, fprime, *x0, *x1, *temp; + size_t pow, len, digs, digs1, resrdx, req, times = 0; + ssize_t cmp = 1, cmp1 = SSIZE_MAX, cmp2 = SSIZE_MAX; + + req = BC_MAX(scale, a->rdx) + ((BC_NUM_INT(a) + 1) >> 1) + 1; + bc_num_expand(b, req); + + if (a->len == 0) { + bc_num_setToZero(b, scale); + return BC_STATUS_SUCCESS; + } + else if (a->neg) + return BC_STATUS_MATH_NEGATIVE; + else if (BC_NUM_ONE(a)) { + bc_num_one(b); + bc_num_extend(b, scale); + return BC_STATUS_SUCCESS; + } + + scale = BC_MAX(scale, a->rdx) + 1; + len = a->len + scale; + + bc_num_init(&num1, len); + bc_num_init(&num2, len); + bc_num_init(&half, BC_NUM_DEF_SIZE); + + bc_num_one(&half); + half.num[0] = 5; + half.rdx = 1; + + bc_num_init(&f, len); + bc_num_init(&fprime, len); + + x0 = &num1; + x1 = &num2; + + bc_num_one(x0); + pow = BC_NUM_INT(a); + + if (pow) { + + if (pow & 1) + x0->num[0] = 2; + else + x0->num[0] = 6; + + pow -= 2 - (pow & 1); + + bc_num_extend(x0, pow); + + // Make sure to move the radix back. + x0->rdx -= pow; + } + + x0->rdx = digs = digs1 = 0; + resrdx = scale + 2; + len = BC_NUM_INT(x0) + resrdx - 1; + + while (!bcg.signe && (cmp != 0 || digs < len)) { + + s = bc_num_div(a, x0, &f, resrdx); + if (s) goto err; + s = bc_num_add(x0, &f, &fprime, resrdx); + if (s) goto err; + s = bc_num_mul(&fprime, &half, x1, resrdx); + if (s) goto err; + + cmp = bc_num_cmp(x1, x0); + digs = x1->len - (unsigned long long) llabs(cmp); + + if (cmp == cmp2 && digs == digs1) + times += 1; + else + times = 0; + + resrdx += times > 4; + + cmp2 = cmp1; + cmp1 = cmp; + digs1 = digs; + + temp = x0; + x0 = x1; + x1 = temp; + } + + if (bcg.signe) { + s = BC_STATUS_EXEC_SIGNAL; + goto err; + } + + bc_num_copy(b, x0); + scale -= 1; + if (b->rdx > scale) bc_num_truncate(b, b->rdx - scale); + +err: + bc_num_free(&fprime); + bc_num_free(&f); + bc_num_free(&half); + bc_num_free(&num2); + bc_num_free(&num1); + return s; +} + +static BcStatus bc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d, + size_t scale) +{ + BcStatus s; + BcNum num2, *ptr_a; + bool init = false; + size_t ts = BC_MAX(scale + b->rdx, a->rdx), len = BC_NUM_MREQ(a, b, ts); + + if (c == a) { + memcpy(&num2, c, sizeof(BcNum)); + ptr_a = &num2; + bc_num_init(c, len); + init = true; + } + else { + ptr_a = a; + bc_num_expand(c, len); + } + + s = bc_num_r(ptr_a, b, c, d, scale, ts); + + if (init) bc_num_free(&num2); + + return s; +} + +#ifdef ENABLE_DC +static BcStatus bc_num_modexp(BcNum *a, BcNum *b, BcNum *c, BcNum *restrict d) +{ + BcStatus s; + BcNum base, exp, two, temp; + + if (c->len == 0) return BC_STATUS_MATH_DIVIDE_BY_ZERO; + if (a->rdx || b->rdx || c->rdx) return BC_STATUS_MATH_NON_INTEGER; + if (b->neg) return BC_STATUS_MATH_NEGATIVE; + + bc_num_expand(d, c->len); + bc_num_init(&base, c->len); + bc_num_init(&exp, b->len); + bc_num_init(&two, BC_NUM_DEF_SIZE); + bc_num_init(&temp, b->len); + + bc_num_one(&two); + two.num[0] = 2; + bc_num_one(d); + + s = bc_num_rem(a, c, &base, 0); + if (s) goto err; + bc_num_copy(&exp, b); + + while (exp.len != 0) { + + s = bc_num_divmod(&exp, &two, &exp, &temp, 0); + if (s) goto err; + + if (BC_NUM_ONE(&temp)) { + s = bc_num_mul(d, &base, &temp, 0); + if (s) goto err; + s = bc_num_rem(&temp, c, d, 0); + if (s) goto err; + } + + s = bc_num_mul(&base, &base, &temp, 0); + if (s) goto err; + s = bc_num_rem(&temp, c, &base, 0); + if (s) goto err; + } + +err: + bc_num_free(&temp); + bc_num_free(&two); + bc_num_free(&exp); + bc_num_free(&base); + return s; +} +#endif // ENABLE_DC + +static int bc_id_cmp(const void *e1, const void *e2) +{ + return strcmp(((const BcId *) e1)->name, ((const BcId *) e2)->name); +} + +static void bc_id_free(void *id) +{ + free(((BcId *) id)->name); +} + +static BcStatus bc_func_insert(BcFunc *f, char *name, bool var) +{ + BcId a; + size_t i; + + for (i = 0; i < f->autos.len; ++i) { + if (!strcmp(name, ((BcId *) bc_vec_item(&f->autos, i))->name)) + return BC_STATUS_PARSE_DUPLICATE_LOCAL; + } + + a.idx = var; + a.name = name; + + bc_vec_push(&f->autos, &a); + + return BC_STATUS_SUCCESS; +} + +static void bc_func_init(BcFunc *f) +{ + bc_vec_init(&f->code, sizeof(char), NULL); + bc_vec_init(&f->autos, sizeof(BcId), bc_id_free); + bc_vec_init(&f->labels, sizeof(size_t), NULL); + f->nparams = 0; +} + +static void bc_func_free(void *func) +{ + BcFunc *f = (BcFunc *) func; + bc_vec_free(&f->code); + bc_vec_free(&f->autos); + bc_vec_free(&f->labels); +} + +static void bc_array_init(BcVec *a, bool nums) +{ + if (nums) + bc_vec_init(a, sizeof(BcNum), bc_num_free); + else + bc_vec_init(a, sizeof(BcVec), bc_vec_free); + bc_array_expand(a, 1); +} + +static void bc_array_copy(BcVec *d, const BcVec *s) +{ + size_t i; + + bc_vec_npop(d, d->len); + bc_vec_expand(d, s->cap); + d->len = s->len; + + for (i = 0; i < s->len; ++i) { + BcNum *dnum = bc_vec_item(d, i), *snum = bc_vec_item(s, i); + bc_num_init(dnum, snum->len); + bc_num_copy(dnum, snum); + } +} + +static void bc_array_expand(BcVec *a, size_t len) +{ + BcResultData data; + + if (a->size == sizeof(BcNum) && a->dtor == bc_num_free) { + while (len > a->len) { + bc_num_init(&data.n, BC_NUM_DEF_SIZE); + bc_vec_push(a, &data.n); + } + } + else { + while (len > a->len) { + bc_array_init(&data.v, true); + bc_vec_push(a, &data.v); + } + } +} + +static void bc_string_free(void *string) +{ + free(*((char **) string)); +} + +#ifdef ENABLE_DC +static void bc_result_copy(BcResult *d, BcResult *src) +{ + d->t = src->t; + + switch (d->t) { + + case BC_RESULT_TEMP: + case BC_RESULT_IBASE: + case BC_RESULT_SCALE: + case BC_RESULT_OBASE: + { + bc_num_init(&d->d.n, src->d.n.len); + bc_num_copy(&d->d.n, &src->d.n); + break; + } + + case BC_RESULT_VAR: + case BC_RESULT_ARRAY: + case BC_RESULT_ARRAY_ELEM: + { + d->d.id.name = xstrdup(src->d.id.name); + break; + } + + case BC_RESULT_CONSTANT: + case BC_RESULT_LAST: + case BC_RESULT_ONE: + case BC_RESULT_STR: + { + memcpy(&d->d.n, &src->d.n, sizeof(BcNum)); + break; + } + } +} +#endif // ENABLE_DC + +static void bc_result_free(void *result) +{ + BcResult *r = (BcResult *) result; + + switch (r->t) { + + case BC_RESULT_TEMP: + case BC_RESULT_IBASE: + case BC_RESULT_SCALE: + case BC_RESULT_OBASE: + { + bc_num_free(&r->d.n); + break; + } + + case BC_RESULT_VAR: + case BC_RESULT_ARRAY: + case BC_RESULT_ARRAY_ELEM: + { + free(r->d.id.name); + break; + } + + default: + { + // Do nothing. + break; + } + } +} + +static void bc_lex_lineComment(BcLex *l) +{ + l->t.t = BC_LEX_WHITESPACE; + while (l->i < l->len && l->buf[l->i++] != '\n'); + --l->i; +} + +static void bc_lex_whitespace(BcLex *l) +{ + char c; + l->t.t = BC_LEX_WHITESPACE; + for (c = l->buf[l->i]; c != '\n' && isspace(c); c = l->buf[++l->i]); +} + +static BcStatus bc_lex_number(BcLex *l, char start) +{ + const char *buf = l->buf + l->i; + size_t len, hits = 0, bslashes = 0, i = 0, j; + char c = buf[i]; + bool last_pt, pt = start == '.'; + + last_pt = pt; + l->t.t = BC_LEX_NUMBER; + + while (c != 0 && (isdigit(c) || (c >= 'A' && c <= 'F') || + (c == '.' && !pt) || (c == '\\' && buf[i + 1] == '\n'))) + { + if (c != '\\') { + last_pt = c == '.'; + pt = pt || last_pt; + } + else { + ++i; + bslashes += 1; + } + + c = buf[++i]; + } + + len = i + 1 * !last_pt - bslashes * 2; + if (len > BC_MAX_NUM) return BC_STATUS_EXEC_NUM_LEN; + + bc_vec_npop(&l->t.v, l->t.v.len); + bc_vec_expand(&l->t.v, len + 1); + bc_vec_push(&l->t.v, &start); + + for (buf -= 1, j = 1; j < len + hits * 2; ++j) { + + c = buf[j]; + + // If we have hit a backslash, skip it. We don't have + // to check for a newline because it's guaranteed. + if (hits < bslashes && c == '\\') { + ++hits; + ++j; + continue; + } + + bc_vec_push(&l->t.v, &c); + } + + bc_vec_pushByte(&l->t.v, '\0'); + l->i += i; + + return BC_STATUS_SUCCESS; +} + +static BcStatus bc_lex_name(BcLex *l) +{ + size_t i = 0; + const char *buf = l->buf + l->i - 1; + char c = buf[i]; + + l->t.t = BC_LEX_NAME; + + while ((c >= 'a' && c <= 'z') || isdigit(c) || c == '_') c = buf[++i]; + + if (i > BC_MAX_STRING) return BC_STATUS_EXEC_NAME_LEN; + bc_vec_string(&l->t.v, i, buf); + + // Increment the index. We minus 1 because it has already been incremented. + l->i += i - 1; + + return BC_STATUS_SUCCESS; +} + +static void bc_lex_init(BcLex *l, BcLexNext next) +{ + l->next = next; + bc_vec_init(&l->t.v, sizeof(char), NULL); +} + +static void bc_lex_free(BcLex *l) +{ + bc_vec_free(&l->t.v); +} + +static void bc_lex_file(BcLex *l, const char *file) +{ + l->line = 1; + l->newline = false; + l->f = file; +} + +static BcStatus bc_lex_next(BcLex *l) +{ + BcStatus s; + + l->t.last = l->t.t; + if (l->t.last == BC_LEX_EOF) return BC_STATUS_LEX_EOF; + + l->line += l->newline; + l->t.t = BC_LEX_EOF; + + l->newline = (l->i == l->len); + if (l->newline) return BC_STATUS_SUCCESS; + + // Loop until failure or we don't have whitespace. This + // is so the parser doesn't get inundated with whitespace. + do { + s = l->next(l); + } while (!s && l->t.t == BC_LEX_WHITESPACE); + + return s; +} + +static BcStatus bc_lex_text(BcLex *l, const char *text) +{ + l->buf = text; + l->i = 0; + l->len = strlen(text); + l->t.t = l->t.last = BC_LEX_INVALID; + return bc_lex_next(l); +} + +#ifdef ENABLE_BC +static BcStatus bc_lex_identifier(BcLex *l) +{ + BcStatus s; + size_t i; + const char *buf = l->buf + l->i - 1; + + for (i = 0; i < sizeof(bc_lex_kws) / sizeof(bc_lex_kws[0]); ++i) { + + unsigned long len = (unsigned long) bc_lex_kws[i].len; + + if (strncmp(buf, bc_lex_kws[i].name, len) == 0) { + + l->t.t = BC_LEX_KEY_AUTO + (BcLexType) i; + + if (!bc_lex_kws[i].posix) { + s = bc_vm_posixError(BC_STATUS_POSIX_BAD_KW, l->f, l->line, + bc_lex_kws[i].name); + if (s) return s; + } + + // We minus 1 because the index has already been incremented. + l->i += len - 1; + return BC_STATUS_SUCCESS; + } + } + + s = bc_lex_name(l); + if (s) return s; + + if (l->t.v.len - 1 > 1) + s = bc_vm_posixError(BC_STATUS_POSIX_NAME_LEN, l->f, l->line, buf); + + return s; +} + +static BcStatus bc_lex_string(BcLex *l) +{ + size_t len, nls = 0, i = l->i; + char c; + + l->t.t = BC_LEX_STR; + + for (c = l->buf[i]; c != 0 && c != '"'; c = l->buf[++i]) nls += (c == '\n'); + + if (c == '\0') { + l->i = i; + return BC_STATUS_LEX_NO_STRING_END; + } + + len = i - l->i; + if (len > BC_MAX_STRING) return BC_STATUS_EXEC_STRING_LEN; + bc_vec_string(&l->t.v, len, l->buf + l->i); + + l->i = i + 1; + l->line += nls; + + return BC_STATUS_SUCCESS; +} + +static void bc_lex_assign(BcLex *l, BcLexType with, BcLexType without) +{ + if (l->buf[l->i] == '=') { + ++l->i; + l->t.t = with; + } + else + l->t.t = without; +} + +static BcStatus bc_lex_comment(BcLex *l) +{ + size_t i, nls = 0; + const char *buf = l->buf; + bool end = false; + char c; + + l->t.t = BC_LEX_WHITESPACE; + + for (i = ++l->i; !end; i += !end) { + + for (c = buf[i]; c != '*' && c != 0; c = buf[++i]) nls += (c == '\n'); + + if (c == 0 || buf[i + 1] == '\0') { + l->i = i; + return BC_STATUS_LEX_NO_COMMENT_END; + } + + end = buf[i + 1] == '/'; + } + + l->i = i + 2; + l->line += nls; + + return BC_STATUS_SUCCESS; +} + +static BcStatus bc_lex_token(BcLex *l) +{ + BcStatus s = BC_STATUS_SUCCESS; + char c = l->buf[l->i++], c2; + + // This is the workhorse of the lexer. + switch (c) { + + case '\0': + case '\n': + { + l->newline = true; + l->t.t = !c ? BC_LEX_EOF : BC_LEX_NLINE; + break; + } + + case '\t': + case '\v': + case '\f': + case '\r': + case ' ': + { + bc_lex_whitespace(l); + break; + } + + case '!': + { + bc_lex_assign(l, BC_LEX_OP_REL_NE, BC_LEX_OP_BOOL_NOT); + + if (l->t.t == BC_LEX_OP_BOOL_NOT) { + s = bc_vm_posixError(BC_STATUS_POSIX_BOOL, l->f, l->line, "!"); + if (s) return s; + } + + break; + } + + case '"': + { + s = bc_lex_string(l); + break; + } + + case '#': + { + s = bc_vm_posixError(BC_STATUS_POSIX_COMMENT, l->f, l->line, NULL); + if (s) return s; + + bc_lex_lineComment(l); + + break; + } + + case '%': + { + bc_lex_assign(l, BC_LEX_OP_ASSIGN_MODULUS, BC_LEX_OP_MODULUS); + break; + } + + case '&': + { + c2 = l->buf[l->i]; + if (c2 == '&') { + + s = bc_vm_posixError(BC_STATUS_POSIX_BOOL, l->f, l->line, "&&"); + if (s) return s; + + ++l->i; + l->t.t = BC_LEX_OP_BOOL_AND; + } + else { + l->t.t = BC_LEX_INVALID; + s = BC_STATUS_LEX_BAD_CHAR; + } + + break; + } + + case '(': + case ')': + { + l->t.t = (BcLexType)(c - '(' + BC_LEX_LPAREN); + break; + } + + case '*': + { + bc_lex_assign(l, BC_LEX_OP_ASSIGN_MULTIPLY, BC_LEX_OP_MULTIPLY); + break; + } + + case '+': + { + c2 = l->buf[l->i]; + if (c2 == '+') { + ++l->i; + l->t.t = BC_LEX_OP_INC; + } + else + bc_lex_assign(l, BC_LEX_OP_ASSIGN_PLUS, BC_LEX_OP_PLUS); + break; + } + + case ',': + { + l->t.t = BC_LEX_COMMA; + break; + } + + case '-': + { + c2 = l->buf[l->i]; + if (c2 == '-') { + ++l->i; + l->t.t = BC_LEX_OP_DEC; + } + else + bc_lex_assign(l, BC_LEX_OP_ASSIGN_MINUS, BC_LEX_OP_MINUS); + break; + } + + case '.': + { + if (isdigit(l->buf[l->i])) + s = bc_lex_number(l, c); + else { + l->t.t = BC_LEX_KEY_LAST; + s = bc_vm_posixError(BC_STATUS_POSIX_DOT, l->f, l->line, NULL); + } + break; + } + + case '/': + { + c2 = l->buf[l->i]; + if (c2 == '*') + s = bc_lex_comment(l); + else + bc_lex_assign(l, BC_LEX_OP_ASSIGN_DIVIDE, BC_LEX_OP_DIVIDE); + break; + } + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + { + s = bc_lex_number(l, c); + break; + } + + case ';': + { + l->t.t = BC_LEX_SCOLON; + break; + } + + case '<': + { + bc_lex_assign(l, BC_LEX_OP_REL_LE, BC_LEX_OP_REL_LT); + break; + } + + case '=': + { + bc_lex_assign(l, BC_LEX_OP_REL_EQ, BC_LEX_OP_ASSIGN); + break; + } + + case '>': + { + bc_lex_assign(l, BC_LEX_OP_REL_GE, BC_LEX_OP_REL_GT); + break; + } + + case '[': + case ']': + { + l->t.t = (BcLexType)(c - '[' + BC_LEX_LBRACKET); + break; + } + + case '\\': + { + if (l->buf[l->i] == '\n') { + l->t.t = BC_LEX_WHITESPACE; + ++l->i; + } + else + s = BC_STATUS_LEX_BAD_CHAR; + break; + } + + case '^': + { + bc_lex_assign(l, BC_LEX_OP_ASSIGN_POWER, BC_LEX_OP_POWER); + break; + } + + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + case 'h': + case 'i': + case 'j': + case 'k': + case 'l': + case 'm': + case 'n': + case 'o': + case 'p': + case 'q': + case 'r': + case 's': + case 't': + case 'u': + case 'v': + case 'w': + case 'x': + case 'y': + case 'z': + { + s = bc_lex_identifier(l); + break; + } + + case '{': + case '}': + { + l->t.t = (BcLexType)(c - '{' + BC_LEX_LBRACE); + break; + } + + case '|': + { + c2 = l->buf[l->i]; + + if (c2 == '|') { + + s = bc_vm_posixError(BC_STATUS_POSIX_BOOL, l->f, l->line, "||"); + if (s) return s; + + ++l->i; + l->t.t = BC_LEX_OP_BOOL_OR; + } + else { + l->t.t = BC_LEX_INVALID; + s = BC_STATUS_LEX_BAD_CHAR; + } + + break; + } + + default: + { + l->t.t = BC_LEX_INVALID; + s = BC_STATUS_LEX_BAD_CHAR; + break; + } + } + + return s; +} +#endif // ENABLE_BC + +#ifdef ENABLE_DC +static BcStatus dc_lex_register(BcLex *l) +{ + BcStatus s = BC_STATUS_SUCCESS; + + if (isspace(l->buf[l->i - 1])) { + bc_lex_whitespace(l); + ++l->i; + if (!bcg.exreg) + s = BC_STATUS_LEX_EXTENDED_REG; + else + s = bc_lex_name(l); + } + else { + bc_vec_npop(&l->t.v, l->t.v.len); + bc_vec_pushByte(&l->t.v, l->buf[l->i - 1]); + bc_vec_pushByte(&l->t.v, '\0'); + l->t.t = BC_LEX_NAME; + } + + return s; +} + +static BcStatus dc_lex_string(BcLex *l) +{ + size_t depth = 1, nls = 0, i = l->i; + char c; + + l->t.t = BC_LEX_STR; + bc_vec_npop(&l->t.v, l->t.v.len); + + for (c = l->buf[i]; c != 0 && depth; c = l->buf[++i]) { + + depth += (c == '[' && (i == l->i || l->buf[i - 1] != '\\')); + depth -= (c == ']' && (i == l->i || l->buf[i - 1] != '\\')); + nls += (c == '\n'); + + if (depth) bc_vec_push(&l->t.v, &c); + } + + if (c == '\0') { + l->i = i; + return BC_STATUS_LEX_NO_STRING_END; + } + + bc_vec_pushByte(&l->t.v, '\0'); + if (i - l->i > BC_MAX_STRING) return BC_STATUS_EXEC_STRING_LEN; + + l->i = i; + l->line += nls; + + return BC_STATUS_SUCCESS; +} + +static BcStatus dc_lex_token(BcLex *l) +{ + BcStatus s = BC_STATUS_SUCCESS; + char c = l->buf[l->i++], c2; + size_t i; + + for (i = 0; i < dc_lex_regs_len; ++i) { + if (l->t.last == dc_lex_regs[i]) return dc_lex_register(l); + } + + if (c >= '%' && c <= '~' && + (l->t.t = dc_lex_tokens[(c - '%')]) != BC_LEX_INVALID) + { + return s; + } + + // This is the workhorse of the lexer. + switch (c) { + + case '\0': + { + l->t.t = BC_LEX_EOF; + break; + } + + case '\n': + case '\t': + case '\v': + case '\f': + case '\r': + case ' ': + { + l->newline = (c == '\n'); + bc_lex_whitespace(l); + break; + } + + case '!': + { + c2 = l->buf[l->i]; + + if (c2 == '=') + l->t.t = BC_LEX_OP_REL_NE; + else if (c2 == '<') + l->t.t = BC_LEX_OP_REL_LE; + else if (c2 == '>') + l->t.t = BC_LEX_OP_REL_GE; + else + return BC_STATUS_LEX_BAD_CHAR; + + ++l->i; + break; + } + + case '#': + { + bc_lex_lineComment(l); + break; + } + + case '.': + { + if (isdigit(l->buf[l->i])) + s = bc_lex_number(l, c); + else + s = BC_STATUS_LEX_BAD_CHAR; + break; + } + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + { + s = bc_lex_number(l, c); + break; + } + + case '[': + { + s = dc_lex_string(l); + break; + } + + default: + { + l->t.t = BC_LEX_INVALID; + s = BC_STATUS_LEX_BAD_CHAR; + break; + } + } + + return s; +} +#endif // ENABLE_DC + +static void bc_parse_addFunc(BcParse *p, char *name, size_t *idx) +{ + bc_program_addFunc(p->prog, name, idx); + p->func = bc_vec_item(&p->prog->fns, p->fidx); +} + +static void bc_parse_pushName(BcParse *p, char *name) +{ + size_t i = 0, len = strlen(name); + + for (; i < len; ++i) bc_parse_push(p, name[i]); + bc_parse_push(p, BC_PARSE_STREND); + + free(name); +} + +static void bc_parse_pushIndex(BcParse *p, size_t idx) +{ + unsigned char amt, i, nums[sizeof(size_t)]; + + for (amt = 0; idx; ++amt) { + nums[amt] = (char) idx; + idx = (idx & ((unsigned long) ~(UCHAR_MAX))) >> sizeof(char) * CHAR_BIT; + } + + bc_parse_push(p, amt); + for (i = 0; i < amt; ++i) bc_parse_push(p, nums[i]); +} + +static void bc_parse_number(BcParse *p, BcInst *prev, size_t *nexs) +{ + char *num = xstrdup(p->l.t.v.v); + size_t idx = p->prog->consts.len; + + bc_vec_push(&p->prog->consts, &num); + + bc_parse_push(p, BC_INST_NUM); + bc_parse_pushIndex(p, idx); + + ++(*nexs); + (*prev) = BC_INST_NUM; +} + +static BcStatus bc_parse_text(BcParse *p, const char *text) +{ + BcStatus s; + + p->func = bc_vec_item(&p->prog->fns, p->fidx); + + if (!strcmp(text, "") && !BC_PARSE_CAN_EXEC(p)) { + p->l.t.t = BC_LEX_INVALID; + s = p->parse(p); + if (s) return s; + if (!BC_PARSE_CAN_EXEC(p)) return BC_STATUS_EXEC_FILE_NOT_EXECUTABLE; + } + + return bc_lex_text(&p->l, text); +} + +static BcStatus bc_parse_reset(BcParse *p, BcStatus s) +{ + if (p->fidx != BC_PROG_MAIN) { + + p->func->nparams = 0; + bc_vec_npop(&p->func->code, p->func->code.len); + bc_vec_npop(&p->func->autos, p->func->autos.len); + bc_vec_npop(&p->func->labels, p->func->labels.len); + + bc_parse_updateFunc(p, BC_PROG_MAIN); + } + + p->l.i = p->l.len; + p->l.t.t = BC_LEX_EOF; + p->auto_part = (p->nbraces = 0); + + bc_vec_npop(&p->flags, p->flags.len - 1); + bc_vec_npop(&p->exits, p->exits.len); + bc_vec_npop(&p->conds, p->conds.len); + bc_vec_npop(&p->ops, p->ops.len); + + return bc_program_reset(p->prog, s); +} + +static void bc_parse_free(BcParse *p) +{ + bc_vec_free(&p->flags); + bc_vec_free(&p->exits); + bc_vec_free(&p->conds); + bc_vec_free(&p->ops); + bc_lex_free(&p->l); +} + +static void bc_parse_create(BcParse *p, BcProgram *prog, size_t func, + BcParseParse parse, BcLexNext next) +{ + memset(p, 0, sizeof(BcParse)); + + bc_lex_init(&p->l, next); + bc_vec_init(&p->flags, sizeof(uint8_t), NULL); + bc_vec_init(&p->exits, sizeof(BcInstPtr), NULL); + bc_vec_init(&p->conds, sizeof(size_t), NULL); + bc_vec_pushByte(&p->flags, 0); + bc_vec_init(&p->ops, sizeof(BcLexType), NULL); + + p->parse = parse; + p->prog = prog; + p->auto_part = (p->nbraces = 0); + bc_parse_updateFunc(p, func); +} + +#ifdef ENABLE_BC +static BcStatus bc_parse_else(BcParse *p); +static BcStatus bc_parse_stmt(BcParse *p); + +static BcStatus bc_parse_operator(BcParse *p, BcLexType type, size_t start, + size_t *nexprs, bool next) +{ + BcStatus s = BC_STATUS_SUCCESS; + BcLexType t; + char l, r = bc_parse_ops[type - BC_LEX_OP_INC].prec; + bool left = bc_parse_ops[type - BC_LEX_OP_INC].left; + + while (p->ops.len > start) { + + t = BC_PARSE_TOP_OP(p); + if (t == BC_LEX_LPAREN) break; + + l = bc_parse_ops[t - BC_LEX_OP_INC].prec; + if (l >= r && (l != r || !left)) break; + + bc_parse_push(p, BC_PARSE_TOKEN_INST(t)); + bc_vec_pop(&p->ops); + *nexprs -= t != BC_LEX_OP_BOOL_NOT && t != BC_LEX_NEG; + } + + bc_vec_push(&p->ops, &type); + if (next) s = bc_lex_next(&p->l); + + return s; +} + +static BcStatus bc_parse_rightParen(BcParse *p, size_t ops_bgn, size_t *nexs) +{ + BcLexType top; + + if (p->ops.len <= ops_bgn) return BC_STATUS_PARSE_BAD_EXP; + top = BC_PARSE_TOP_OP(p); + + while (top != BC_LEX_LPAREN) { + + bc_parse_push(p, BC_PARSE_TOKEN_INST(top)); + + bc_vec_pop(&p->ops); + *nexs -= top != BC_LEX_OP_BOOL_NOT && top != BC_LEX_NEG; + + if (p->ops.len <= ops_bgn) return BC_STATUS_PARSE_BAD_EXP; + top = BC_PARSE_TOP_OP(p); + } + + bc_vec_pop(&p->ops); + + return bc_lex_next(&p->l); +} + +static BcStatus bc_parse_params(BcParse *p, uint8_t flags) +{ + BcStatus s; + bool comma = false; + size_t nparams; + + s = bc_lex_next(&p->l); + if (s) return s; + + for (nparams = 0; p->l.t.t != BC_LEX_RPAREN; ++nparams) { + + flags = (flags & ~(BC_PARSE_PRINT | BC_PARSE_REL)) | BC_PARSE_ARRAY; + s = bc_parse_expr(p, flags, bc_parse_next_param); + if (s) return s; + + comma = p->l.t.t == BC_LEX_COMMA; + if (comma) { + s = bc_lex_next(&p->l); + if (s) return s; + } + } + + if (comma) return BC_STATUS_PARSE_BAD_TOKEN; + bc_parse_push(p, BC_INST_CALL); + bc_parse_pushIndex(p, nparams); + + return BC_STATUS_SUCCESS; +} + +static BcStatus bc_parse_call(BcParse *p, char *name, uint8_t flags) +{ + BcStatus s; + BcId entry, *entry_ptr; + size_t idx; + + entry.name = name; + + s = bc_parse_params(p, flags); + if (s) goto err; + + if (p->l.t.t != BC_LEX_RPAREN) { + s = BC_STATUS_PARSE_BAD_TOKEN; + goto err; + } + + idx = bc_map_index(&p->prog->fn_map, &entry); + + if (idx == BC_VEC_INVALID_IDX) { + name = xstrdup(entry.name); + bc_parse_addFunc(p, name, &idx); + idx = bc_map_index(&p->prog->fn_map, &entry); + free(entry.name); + } + else + free(name); + + entry_ptr = bc_vec_item(&p->prog->fn_map, idx); + bc_parse_pushIndex(p, entry_ptr->idx); + + return bc_lex_next(&p->l); + +err: + free(name); + return s; +} + +static BcStatus bc_parse_name(BcParse *p, BcInst *type, uint8_t flags) +{ + BcStatus s; + char *name; + + name = xstrdup(p->l.t.v.v); + s = bc_lex_next(&p->l); + if (s) goto err; + + if (p->l.t.t == BC_LEX_LBRACKET) { + + s = bc_lex_next(&p->l); + if (s) goto err; + + if (p->l.t.t == BC_LEX_RBRACKET) { + + if (!(flags & BC_PARSE_ARRAY)) { + s = BC_STATUS_PARSE_BAD_EXP; + goto err; + } + + *type = BC_INST_ARRAY; + } + else { + + *type = BC_INST_ARRAY_ELEM; + + flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL); + s = bc_parse_expr(p, flags, bc_parse_next_elem); + if (s) goto err; + } + + s = bc_lex_next(&p->l); + if (s) goto err; + bc_parse_push(p, *type); + bc_parse_pushName(p, name); + } + else if (p->l.t.t == BC_LEX_LPAREN) { + + if (flags & BC_PARSE_NOCALL) { + s = BC_STATUS_PARSE_BAD_TOKEN; + goto err; + } + + *type = BC_INST_CALL; + s = bc_parse_call(p, name, flags); + } + else { + *type = BC_INST_VAR; + bc_parse_push(p, BC_INST_VAR); + bc_parse_pushName(p, name); + } + + return s; + +err: + free(name); + return s; +} + +static BcStatus bc_parse_read(BcParse *p) +{ + BcStatus s; + + s = bc_lex_next(&p->l); + if (s) return s; + if (p->l.t.t != BC_LEX_LPAREN) return BC_STATUS_PARSE_BAD_TOKEN; + + s = bc_lex_next(&p->l); + if (s) return s; + if (p->l.t.t != BC_LEX_RPAREN) return BC_STATUS_PARSE_BAD_TOKEN; + + bc_parse_push(p, BC_INST_READ); + + return bc_lex_next(&p->l); +} + +static BcStatus bc_parse_builtin(BcParse *p, BcLexType type, uint8_t flags, + BcInst *prev) +{ + BcStatus s; + + s = bc_lex_next(&p->l); + if (s) return s; + if (p->l.t.t != BC_LEX_LPAREN) return BC_STATUS_PARSE_BAD_TOKEN; + + flags = (flags & ~(BC_PARSE_PRINT | BC_PARSE_REL)) | BC_PARSE_ARRAY; + + s = bc_lex_next(&p->l); + if (s) return s; + + s = bc_parse_expr(p, flags, bc_parse_next_rel); + if (s) return s; + + if (p->l.t.t != BC_LEX_RPAREN) return BC_STATUS_PARSE_BAD_TOKEN; + + *prev = (type == BC_LEX_KEY_LENGTH) ? BC_INST_LENGTH : BC_INST_SQRT; + bc_parse_push(p, *prev); + + return bc_lex_next(&p->l); +} + +static BcStatus bc_parse_scale(BcParse *p, BcInst *type, uint8_t flags) +{ + BcStatus s; + + s = bc_lex_next(&p->l); + if (s) return s; + + if (p->l.t.t != BC_LEX_LPAREN) { + *type = BC_INST_SCALE; + bc_parse_push(p, BC_INST_SCALE); + return BC_STATUS_SUCCESS; + } + + *type = BC_INST_SCALE_FUNC; + flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL); + + s = bc_lex_next(&p->l); + if (s) return s; + + s = bc_parse_expr(p, flags, bc_parse_next_rel); + if (s) return s; + if (p->l.t.t != BC_LEX_RPAREN) return BC_STATUS_PARSE_BAD_TOKEN; + bc_parse_push(p, BC_INST_SCALE_FUNC); + + return bc_lex_next(&p->l); +} + +static BcStatus bc_parse_incdec(BcParse *p, BcInst *prev, bool *paren_expr, + size_t *nexprs, uint8_t flags) +{ + BcStatus s; + BcLexType type; + char inst; + BcInst etype = *prev; + + if (etype == BC_INST_VAR || etype == BC_INST_ARRAY_ELEM || + etype == BC_INST_SCALE || etype == BC_INST_LAST || + etype == BC_INST_IBASE || etype == BC_INST_OBASE) + { + *prev = inst = BC_INST_INC_POST + (p->l.t.t != BC_LEX_OP_INC); + bc_parse_push(p, inst); + s = bc_lex_next(&p->l); + } + else { + + *prev = inst = BC_INST_INC_PRE + (p->l.t.t != BC_LEX_OP_INC); + *paren_expr = true; + + s = bc_lex_next(&p->l); + if (s) return s; + type = p->l.t.t; + + // Because we parse the next part of the expression + // right here, we need to increment this. + *nexprs = *nexprs + 1; + + switch (type) { + + case BC_LEX_NAME: + { + s = bc_parse_name(p, prev, flags | BC_PARSE_NOCALL); + break; + } + + case BC_LEX_KEY_IBASE: + case BC_LEX_KEY_LAST: + case BC_LEX_KEY_OBASE: + { + bc_parse_push(p, type - BC_LEX_KEY_IBASE + BC_INST_IBASE); + s = bc_lex_next(&p->l); + break; + } + + case BC_LEX_KEY_SCALE: + { + s = bc_lex_next(&p->l); + if (s) return s; + if (p->l.t.t == BC_LEX_LPAREN) + s = BC_STATUS_PARSE_BAD_TOKEN; + else + bc_parse_push(p, BC_INST_SCALE); + break; + } + + default: + { + s = BC_STATUS_PARSE_BAD_TOKEN; + break; + } + } + + if (!s) bc_parse_push(p, inst); + } + + return s; +} + +static BcStatus bc_parse_minus(BcParse *p, BcInst *prev, size_t ops_bgn, + bool rparen, size_t *nexprs) +{ + BcStatus s; + BcLexType type; + BcInst etype = *prev; + + s = bc_lex_next(&p->l); + if (s) return s; + + type = rparen || etype == BC_INST_INC_POST || etype == BC_INST_DEC_POST || + (etype >= BC_INST_NUM && etype <= BC_INST_SQRT) ? + BC_LEX_OP_MINUS : + BC_LEX_NEG; + *prev = BC_PARSE_TOKEN_INST(type); + + // We can just push onto the op stack because this is the largest + // precedence operator that gets pushed. Inc/dec does not. + if (type != BC_LEX_OP_MINUS) + bc_vec_push(&p->ops, &type); + else + s = bc_parse_operator(p, type, ops_bgn, nexprs, false); + + return s; +} + +static BcStatus bc_parse_string(BcParse *p, char inst) +{ + char *str = xstrdup(p->l.t.v.v); + + bc_parse_push(p, BC_INST_STR); + bc_parse_pushIndex(p, p->prog->strs.len); + bc_vec_push(&p->prog->strs, &str); + bc_parse_push(p, inst); + + return bc_lex_next(&p->l); +} + +static BcStatus bc_parse_print(BcParse *p) +{ + BcStatus s; + BcLexType type; + bool comma = false; + + s = bc_lex_next(&p->l); + if (s) return s; + + type = p->l.t.t; + + if (type == BC_LEX_SCOLON || type == BC_LEX_NLINE) + return BC_STATUS_PARSE_BAD_PRINT; + + while (!s && type != BC_LEX_SCOLON && type != BC_LEX_NLINE) { + + if (type == BC_LEX_STR) + s = bc_parse_string(p, BC_INST_PRINT_POP); + else { + s = bc_parse_expr(p, 0, bc_parse_next_print); + if (s) return s; + bc_parse_push(p, BC_INST_PRINT_POP); + } + + if (s) return s; + + comma = p->l.t.t == BC_LEX_COMMA; + if (comma) s = bc_lex_next(&p->l); + type = p->l.t.t; + } + + if (s) return s; + if (comma) return BC_STATUS_PARSE_BAD_TOKEN; + + return bc_lex_next(&p->l); +} + +static BcStatus bc_parse_return(BcParse *p) +{ + BcStatus s; + BcLexType t; + bool paren; + + if (!BC_PARSE_FUNC(p)) return BC_STATUS_PARSE_BAD_TOKEN; + + s = bc_lex_next(&p->l); + if (s) return s; + + t = p->l.t.t; + paren = t == BC_LEX_LPAREN; + + if (t == BC_LEX_NLINE || t == BC_LEX_SCOLON) + bc_parse_push(p, BC_INST_RET0); + else { + + s = bc_parse_expr(p, 0, bc_parse_next_expr); + if (s && s != BC_STATUS_PARSE_EMPTY_EXP) + return s; + else if (s == BC_STATUS_PARSE_EMPTY_EXP) { + bc_parse_push(p, BC_INST_RET0); + s = bc_lex_next(&p->l); + if (s) return s; + } + + if (!paren || p->l.t.last != BC_LEX_RPAREN) { + s = bc_vm_posixError(BC_STATUS_POSIX_RET, p->l.f, p->l.line, NULL); + if (s) return s; + } + + bc_parse_push(p, BC_INST_RET); + } + + return s; +} + +static BcStatus bc_parse_endBody(BcParse *p, bool brace) +{ + BcStatus s = BC_STATUS_SUCCESS; + + if (p->flags.len <= 1 || (brace && p->nbraces == 0)) + return BC_STATUS_PARSE_BAD_TOKEN; + + if (brace) { + + if (p->l.t.t == BC_LEX_RBRACE) { + if (!p->nbraces) return BC_STATUS_PARSE_BAD_TOKEN; + --p->nbraces; + s = bc_lex_next(&p->l); + if (s) return s; + } + else + return BC_STATUS_PARSE_BAD_TOKEN; + } + + if (BC_PARSE_IF(p)) { + + uint8_t *flag_ptr; + + while (p->l.t.t == BC_LEX_NLINE) { + s = bc_lex_next(&p->l); + if (s) return s; + } + + bc_vec_pop(&p->flags); + + flag_ptr = BC_PARSE_TOP_FLAG_PTR(p); + *flag_ptr = (*flag_ptr | BC_PARSE_FLAG_IF_END); + + if (p->l.t.t == BC_LEX_KEY_ELSE) s = bc_parse_else(p); + } + else if (BC_PARSE_ELSE(p)) { + + BcInstPtr *ip; + size_t *label; + + bc_vec_pop(&p->flags); + + ip = bc_vec_top(&p->exits); + label = bc_vec_item(&p->func->labels, ip->idx); + *label = p->func->code.len; + + bc_vec_pop(&p->exits); + } + else if (BC_PARSE_FUNC_INNER(p)) { + bc_parse_push(p, BC_INST_RET0); + bc_parse_updateFunc(p, BC_PROG_MAIN); + bc_vec_pop(&p->flags); + } + else { + + BcInstPtr *ip = bc_vec_top(&p->exits); + size_t *label = bc_vec_top(&p->conds); + + bc_parse_push(p, BC_INST_JUMP); + bc_parse_pushIndex(p, *label); + + label = bc_vec_item(&p->func->labels, ip->idx); + *label = p->func->code.len; + + bc_vec_pop(&p->flags); + bc_vec_pop(&p->exits); + bc_vec_pop(&p->conds); + } + + return s; +} + +static void bc_parse_startBody(BcParse *p, uint8_t flags) +{ + uint8_t *flag_ptr = BC_PARSE_TOP_FLAG_PTR(p); + flags |= (*flag_ptr & (BC_PARSE_FLAG_FUNC | BC_PARSE_FLAG_LOOP)); + flags |= BC_PARSE_FLAG_BODY; + bc_vec_push(&p->flags, &flags); +} + +static void bc_parse_noElse(BcParse *p) +{ + BcInstPtr *ip; + size_t *label; + uint8_t *flag_ptr = BC_PARSE_TOP_FLAG_PTR(p); + + *flag_ptr = (*flag_ptr & ~(BC_PARSE_FLAG_IF_END)); + + ip = bc_vec_top(&p->exits); + label = bc_vec_item(&p->func->labels, ip->idx); + *label = p->func->code.len; + + bc_vec_pop(&p->exits); +} + +static BcStatus bc_parse_if(BcParse *p) +{ + BcStatus s; + BcInstPtr ip; + + s = bc_lex_next(&p->l); + if (s) return s; + if (p->l.t.t != BC_LEX_LPAREN) return BC_STATUS_PARSE_BAD_TOKEN; + + s = bc_lex_next(&p->l); + if (s) return s; + s = bc_parse_expr(p, BC_PARSE_REL, bc_parse_next_rel); + if (s) return s; + if (p->l.t.t != BC_LEX_RPAREN) return BC_STATUS_PARSE_BAD_TOKEN; + + s = bc_lex_next(&p->l); + if (s) return s; + bc_parse_push(p, BC_INST_JUMP_ZERO); + + ip.idx = p->func->labels.len; + ip.func = ip.len = 0; + + bc_parse_pushIndex(p, ip.idx); + bc_vec_push(&p->exits, &ip); + bc_vec_push(&p->func->labels, &ip.idx); + bc_parse_startBody(p, BC_PARSE_FLAG_IF); + + return BC_STATUS_SUCCESS; +} + +static BcStatus bc_parse_else(BcParse *p) +{ + BcInstPtr ip; + + if (!BC_PARSE_IF_END(p)) return BC_STATUS_PARSE_BAD_TOKEN; + + ip.idx = p->func->labels.len; + ip.func = ip.len = 0; + + bc_parse_push(p, BC_INST_JUMP); + bc_parse_pushIndex(p, ip.idx); + + bc_parse_noElse(p); + + bc_vec_push(&p->exits, &ip); + bc_vec_push(&p->func->labels, &ip.idx); + bc_parse_startBody(p, BC_PARSE_FLAG_ELSE); + + return bc_lex_next(&p->l); +} + +static BcStatus bc_parse_while(BcParse *p) +{ + BcStatus s; + BcInstPtr ip; + + s = bc_lex_next(&p->l); + if (s) return s; + if (p->l.t.t != BC_LEX_LPAREN) return BC_STATUS_PARSE_BAD_TOKEN; + s = bc_lex_next(&p->l); + if (s) return s; + + ip.idx = p->func->labels.len; + + bc_vec_push(&p->func->labels, &p->func->code.len); + bc_vec_push(&p->conds, &ip.idx); + + ip.idx = p->func->labels.len; + ip.func = 1; + ip.len = 0; + + bc_vec_push(&p->exits, &ip); + bc_vec_push(&p->func->labels, &ip.idx); + + s = bc_parse_expr(p, BC_PARSE_REL, bc_parse_next_rel); + if (s) return s; + if (p->l.t.t != BC_LEX_RPAREN) return BC_STATUS_PARSE_BAD_TOKEN; + s = bc_lex_next(&p->l); + if (s) return s; + + bc_parse_push(p, BC_INST_JUMP_ZERO); + bc_parse_pushIndex(p, ip.idx); + bc_parse_startBody(p, BC_PARSE_FLAG_LOOP | BC_PARSE_FLAG_LOOP_INNER); + + return BC_STATUS_SUCCESS; +} + +static BcStatus bc_parse_for(BcParse *p) +{ + BcStatus s; + BcInstPtr ip; + size_t cond_idx, exit_idx, body_idx, update_idx; + + s = bc_lex_next(&p->l); + if (s) return s; + if (p->l.t.t != BC_LEX_LPAREN) return BC_STATUS_PARSE_BAD_TOKEN; + s = bc_lex_next(&p->l); + if (s) return s; + + if (p->l.t.t != BC_LEX_SCOLON) + s = bc_parse_expr(p, 0, bc_parse_next_for); + else + s = bc_vm_posixError(BC_STATUS_POSIX_FOR1, p->l.f, p->l.line, NULL); + + if (s) return s; + if (p->l.t.t != BC_LEX_SCOLON) return BC_STATUS_PARSE_BAD_TOKEN; + s = bc_lex_next(&p->l); + if (s) return s; + + cond_idx = p->func->labels.len; + update_idx = cond_idx + 1; + body_idx = update_idx + 1; + exit_idx = body_idx + 1; + + bc_vec_push(&p->func->labels, &p->func->code.len); + + if (p->l.t.t != BC_LEX_SCOLON) + s = bc_parse_expr(p, BC_PARSE_REL, bc_parse_next_for); + else + s = bc_vm_posixError(BC_STATUS_POSIX_FOR2, p->l.f, p->l.line, NULL); + + if (s) return s; + if (p->l.t.t != BC_LEX_SCOLON) return BC_STATUS_PARSE_BAD_TOKEN; + + s = bc_lex_next(&p->l); + if (s) return s; + + bc_parse_push(p, BC_INST_JUMP_ZERO); + bc_parse_pushIndex(p, exit_idx); + bc_parse_push(p, BC_INST_JUMP); + bc_parse_pushIndex(p, body_idx); + + ip.idx = p->func->labels.len; + + bc_vec_push(&p->conds, &update_idx); + bc_vec_push(&p->func->labels, &p->func->code.len); + + if (p->l.t.t != BC_LEX_RPAREN) + s = bc_parse_expr(p, 0, bc_parse_next_rel); + else + s = bc_vm_posixError(BC_STATUS_POSIX_FOR3, p->l.f, p->l.line, NULL); + + if (s) return s; + + if (p->l.t.t != BC_LEX_RPAREN) return BC_STATUS_PARSE_BAD_TOKEN; + bc_parse_push(p, BC_INST_JUMP); + bc_parse_pushIndex(p, cond_idx); + bc_vec_push(&p->func->labels, &p->func->code.len); + + ip.idx = exit_idx; + ip.func = 1; + ip.len = 0; + + bc_vec_push(&p->exits, &ip); + bc_vec_push(&p->func->labels, &ip.idx); + bc_lex_next(&p->l); + bc_parse_startBody(p, BC_PARSE_FLAG_LOOP | BC_PARSE_FLAG_LOOP_INNER); + + return BC_STATUS_SUCCESS; +} + +static BcStatus bc_parse_loopExit(BcParse *p, BcLexType type) +{ + BcStatus s; + size_t i; + BcInstPtr *ip; + + if (!BC_PARSE_LOOP(p)) return BC_STATUS_PARSE_BAD_TOKEN; + + if (type == BC_LEX_KEY_BREAK) { + + if (p->exits.len == 0) return BC_STATUS_PARSE_BAD_TOKEN; + + i = p->exits.len - 1; + ip = bc_vec_item(&p->exits, i); + + while (!ip->func && i < p->exits.len) ip = bc_vec_item(&p->exits, i--); + if (i >= p->exits.len && !ip->func) return BC_STATUS_PARSE_BAD_TOKEN; + + i = ip->idx; + } + else + i = *((size_t *) bc_vec_top(&p->conds)); + + bc_parse_push(p, BC_INST_JUMP); + bc_parse_pushIndex(p, i); + + s = bc_lex_next(&p->l); + if (s) return s; + + if (p->l.t.t != BC_LEX_SCOLON && p->l.t.t != BC_LEX_NLINE) + return BC_STATUS_PARSE_BAD_TOKEN; + + return bc_lex_next(&p->l); +} + +static BcStatus bc_parse_func(BcParse *p) +{ + BcStatus s; + bool var, comma = false; + uint8_t flags; + char *name; + + s = bc_lex_next(&p->l); + if (s) return s; + if (p->l.t.t != BC_LEX_NAME) return BC_STATUS_PARSE_BAD_FUNC; + + name = xstrdup(p->l.t.v.v); + bc_parse_addFunc(p, name, &p->fidx); + + s = bc_lex_next(&p->l); + if (s) return s; + if (p->l.t.t != BC_LEX_LPAREN) return BC_STATUS_PARSE_BAD_FUNC; + s = bc_lex_next(&p->l); + if (s) return s; + + while (p->l.t.t != BC_LEX_RPAREN) { + + if (p->l.t.t != BC_LEX_NAME) return BC_STATUS_PARSE_BAD_FUNC; + + ++p->func->nparams; + + name = xstrdup(p->l.t.v.v); + s = bc_lex_next(&p->l); + if (s) goto err; + + var = p->l.t.t != BC_LEX_LBRACKET; + + if (!var) { + + s = bc_lex_next(&p->l); + if (s) goto err; + + if (p->l.t.t != BC_LEX_RBRACKET) { + s = BC_STATUS_PARSE_BAD_FUNC; + goto err; + } + + s = bc_lex_next(&p->l); + if (s) goto err; + } + + comma = p->l.t.t == BC_LEX_COMMA; + if (comma) { + s = bc_lex_next(&p->l); + if (s) goto err; + } + + s = bc_func_insert(p->func, name, var); + if (s) goto err; + } + + if (comma) return BC_STATUS_PARSE_BAD_FUNC; + + flags = BC_PARSE_FLAG_FUNC | BC_PARSE_FLAG_FUNC_INNER | BC_PARSE_FLAG_BODY; + bc_parse_startBody(p, flags); + + s = bc_lex_next(&p->l); + if (s) return s; + + if (p->l.t.t != BC_LEX_LBRACE) + s = bc_vm_posixError(BC_STATUS_POSIX_BRACE, p->l.f, p->l.line, NULL); + + return s; + +err: + free(name); + return s; +} + +static BcStatus bc_parse_auto(BcParse *p) +{ + BcStatus s; + bool comma, var, one; + char *name; + + if (!p->auto_part) return BC_STATUS_PARSE_BAD_TOKEN; + s = bc_lex_next(&p->l); + if (s) return s; + + p->auto_part = comma = false; + one = p->l.t.t == BC_LEX_NAME; + + while (p->l.t.t == BC_LEX_NAME) { + + name = xstrdup(p->l.t.v.v); + s = bc_lex_next(&p->l); + if (s) goto err; + + var = p->l.t.t != BC_LEX_LBRACKET; + if (!var) { + + s = bc_lex_next(&p->l); + if (s) goto err; + + if (p->l.t.t != BC_LEX_RBRACKET) { + s = BC_STATUS_PARSE_BAD_FUNC; + goto err; + } + + s = bc_lex_next(&p->l); + if (s) goto err; + } + + comma = p->l.t.t == BC_LEX_COMMA; + if (comma) { + s = bc_lex_next(&p->l); + if (s) goto err; + } + + s = bc_func_insert(p->func, name, var); + if (s) goto err; + } + + if (comma) return BC_STATUS_PARSE_BAD_FUNC; + if (!one) return BC_STATUS_PARSE_NO_AUTO; + + if (p->l.t.t != BC_LEX_NLINE && p->l.t.t != BC_LEX_SCOLON) + return BC_STATUS_PARSE_BAD_TOKEN; + + return bc_lex_next(&p->l); + +err: + free(name); + return s; +} + +static BcStatus bc_parse_body(BcParse *p, bool brace) +{ + BcStatus s = BC_STATUS_SUCCESS; + uint8_t *flag_ptr = bc_vec_top(&p->flags); + + *flag_ptr &= ~(BC_PARSE_FLAG_BODY); + + if (*flag_ptr & BC_PARSE_FLAG_FUNC_INNER) { + + if (!brace) return BC_STATUS_PARSE_BAD_TOKEN; + p->auto_part = p->l.t.t != BC_LEX_KEY_AUTO; + + if (!p->auto_part) { + s = bc_parse_auto(p); + if (s) return s; + } + + if (p->l.t.t == BC_LEX_NLINE) s = bc_lex_next(&p->l); + } + else { + s = bc_parse_stmt(p); + if (!s && !brace) s = bc_parse_endBody(p, false); + } + + return s; +} + +static BcStatus bc_parse_stmt(BcParse *p) +{ + BcStatus s = BC_STATUS_SUCCESS; + + switch (p->l.t.t) { + + case BC_LEX_NLINE: + { + return bc_lex_next(&p->l); + } + + case BC_LEX_KEY_ELSE: + { + p->auto_part = false; + break; + } + + case BC_LEX_LBRACE: + { + if (!BC_PARSE_BODY(p)) return BC_STATUS_PARSE_BAD_TOKEN; + + ++p->nbraces; + s = bc_lex_next(&p->l); + if (s) return s; + + return bc_parse_body(p, true); + } + + case BC_LEX_KEY_AUTO: + { + return bc_parse_auto(p); + } + + default: + { + p->auto_part = false; + + if (BC_PARSE_IF_END(p)) { + bc_parse_noElse(p); + return BC_STATUS_SUCCESS; + } + else if (BC_PARSE_BODY(p)) + return bc_parse_body(p, false); + + break; + } + } + + switch (p->l.t.t) { + + case BC_LEX_OP_INC: + case BC_LEX_OP_DEC: + case BC_LEX_OP_MINUS: + case BC_LEX_OP_BOOL_NOT: + case BC_LEX_LPAREN: + case BC_LEX_NAME: + case BC_LEX_NUMBER: + case BC_LEX_KEY_IBASE: + case BC_LEX_KEY_LAST: + case BC_LEX_KEY_LENGTH: + case BC_LEX_KEY_OBASE: + case BC_LEX_KEY_READ: + case BC_LEX_KEY_SCALE: + case BC_LEX_KEY_SQRT: + { + s = bc_parse_expr(p, BC_PARSE_PRINT, bc_parse_next_expr); + break; + } + + case BC_LEX_KEY_ELSE: + { + s = bc_parse_else(p); + break; + } + + case BC_LEX_SCOLON: + { + while (!s && p->l.t.t == BC_LEX_SCOLON) s = bc_lex_next(&p->l); + break; + } + + case BC_LEX_RBRACE: + { + s = bc_parse_endBody(p, true); + break; + } + + case BC_LEX_STR: + { + s = bc_parse_string(p, BC_INST_PRINT_STR); + break; + } + + case BC_LEX_KEY_BREAK: + case BC_LEX_KEY_CONTINUE: + { + s = bc_parse_loopExit(p, p->l.t.t); + break; + } + + case BC_LEX_KEY_FOR: + { + s = bc_parse_for(p); + break; + } + + case BC_LEX_KEY_HALT: + { + bc_parse_push(p, BC_INST_HALT); + s = bc_lex_next(&p->l); + break; + } + + case BC_LEX_KEY_IF: + { + s = bc_parse_if(p); + break; + } + + case BC_LEX_KEY_LIMITS: + { + s = bc_lex_next(&p->l); + if (s) return s; + s = BC_STATUS_LIMITS; + break; + } + + case BC_LEX_KEY_PRINT: + { + s = bc_parse_print(p); + break; + } + + case BC_LEX_KEY_QUIT: + { + // Quit is a compile-time command. We don't exit directly, + // so the vm can clean up. Limits do the same thing. + s = BC_STATUS_QUIT; + break; + } + + case BC_LEX_KEY_RETURN: + { + s = bc_parse_return(p); + break; + } + + case BC_LEX_KEY_WHILE: + { + s = bc_parse_while(p); + break; + } + + default: + { + s = BC_STATUS_PARSE_BAD_TOKEN; + break; + } + } + + return s; +} + +static BcStatus bc_parse_parse(BcParse *p) +{ + BcStatus s; + + if (p->l.t.t == BC_LEX_EOF) + s = p->flags.len > 0 ? BC_STATUS_PARSE_NO_BLOCK_END : BC_STATUS_LEX_EOF; + else if (p->l.t.t == BC_LEX_KEY_DEFINE) { + if (!BC_PARSE_CAN_EXEC(p)) return BC_STATUS_PARSE_BAD_TOKEN; + s = bc_parse_func(p); + } + else + s = bc_parse_stmt(p); + + if ((s && s != BC_STATUS_QUIT && s != BC_STATUS_LIMITS) || bcg.signe) + s = bc_parse_reset(p, s); + + return s; +} + +static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) +{ + BcStatus s = BC_STATUS_SUCCESS; + BcInst prev = BC_INST_PRINT; + BcLexType top, t = p->l.t.t; + size_t nexprs = 0, ops_bgn = p->ops.len; + uint32_t i, nparens, nrelops; + bool paren_first, paren_expr, rprn, done, get_token, assign, bin_last; + + paren_first = p->l.t.t == BC_LEX_LPAREN; + nparens = nrelops = 0; + paren_expr = rprn = done = get_token = assign = false; + bin_last = true; + + for (; !bcg.signe && !s && !done && bc_parse_exprs[t]; t = p->l.t.t) { + switch (t) { + + case BC_LEX_OP_INC: + case BC_LEX_OP_DEC: + { + s = bc_parse_incdec(p, &prev, &paren_expr, &nexprs, flags); + rprn = get_token = bin_last = false; + break; + } + + case BC_LEX_OP_MINUS: + { + s = bc_parse_minus(p, &prev, ops_bgn, rprn, &nexprs); + rprn = get_token = false; + bin_last = prev == BC_INST_MINUS; + break; + } + + case BC_LEX_OP_ASSIGN_POWER: + case BC_LEX_OP_ASSIGN_MULTIPLY: + case BC_LEX_OP_ASSIGN_DIVIDE: + case BC_LEX_OP_ASSIGN_MODULUS: + case BC_LEX_OP_ASSIGN_PLUS: + case BC_LEX_OP_ASSIGN_MINUS: + case BC_LEX_OP_ASSIGN: + { + if (prev != BC_INST_VAR && prev != BC_INST_ARRAY_ELEM && + prev != BC_INST_SCALE && prev != BC_INST_IBASE && + prev != BC_INST_OBASE && prev != BC_INST_LAST) + { + s = BC_STATUS_PARSE_BAD_ASSIGN; + break; + } + } + // Fallthrough. + case BC_LEX_OP_POWER: + case BC_LEX_OP_MULTIPLY: + case BC_LEX_OP_DIVIDE: + case BC_LEX_OP_MODULUS: + case BC_LEX_OP_PLUS: + case BC_LEX_OP_REL_EQ: + case BC_LEX_OP_REL_LE: + case BC_LEX_OP_REL_GE: + case BC_LEX_OP_REL_NE: + case BC_LEX_OP_REL_LT: + case BC_LEX_OP_REL_GT: + case BC_LEX_OP_BOOL_NOT: + case BC_LEX_OP_BOOL_OR: + case BC_LEX_OP_BOOL_AND: + { + if (((t == BC_LEX_OP_BOOL_NOT) != bin_last) || + (t != BC_LEX_OP_BOOL_NOT && prev == BC_INST_BOOL_NOT)) + { + return BC_STATUS_PARSE_BAD_EXP; + } + + nrelops += t >= BC_LEX_OP_REL_EQ && t <= BC_LEX_OP_REL_GT; + prev = BC_PARSE_TOKEN_INST(t); + s = bc_parse_operator(p, t, ops_bgn, &nexprs, true); + rprn = get_token = false; + bin_last = t != BC_LEX_OP_BOOL_NOT; + + break; + } + + case BC_LEX_LPAREN: + { + if (BC_PARSE_LEAF(prev, rprn)) return BC_STATUS_PARSE_BAD_EXP; + + ++nparens; + paren_expr = rprn = bin_last = false; + get_token = true; + bc_vec_push(&p->ops, &t); + + break; + } + + case BC_LEX_RPAREN: + { + if (bin_last || prev == BC_INST_BOOL_NOT) + return BC_STATUS_PARSE_BAD_EXP; + + if (nparens == 0) { + s = BC_STATUS_SUCCESS; + done = true; + get_token = false; + break; + } + else if (!paren_expr) + return BC_STATUS_PARSE_EMPTY_EXP; + + --nparens; + paren_expr = rprn = true; + get_token = bin_last = false; + + s = bc_parse_rightParen(p, ops_bgn, &nexprs); + + break; + } + + case BC_LEX_NAME: + { + if (BC_PARSE_LEAF(prev, rprn)) return BC_STATUS_PARSE_BAD_EXP; + + paren_expr = true; + rprn = get_token = bin_last = false; + s = bc_parse_name(p, &prev, flags & ~BC_PARSE_NOCALL); + ++nexprs; + + break; + } + + case BC_LEX_NUMBER: + { + if (BC_PARSE_LEAF(prev, rprn)) return BC_STATUS_PARSE_BAD_EXP; + + bc_parse_number(p, &prev, &nexprs); + paren_expr = get_token = true; + rprn = bin_last = false; + + break; + } + + case BC_LEX_KEY_IBASE: + case BC_LEX_KEY_LAST: + case BC_LEX_KEY_OBASE: + { + if (BC_PARSE_LEAF(prev, rprn)) return BC_STATUS_PARSE_BAD_EXP; + + prev = (char) (t - BC_LEX_KEY_IBASE + BC_INST_IBASE); + bc_parse_push(p, (char) prev); + + paren_expr = get_token = true; + rprn = bin_last = false; + ++nexprs; + + break; + } + + case BC_LEX_KEY_LENGTH: + case BC_LEX_KEY_SQRT: + { + if (BC_PARSE_LEAF(prev, rprn)) return BC_STATUS_PARSE_BAD_EXP; + + s = bc_parse_builtin(p, t, flags, &prev); + paren_expr = true; + rprn = get_token = bin_last = false; + ++nexprs; + + break; + } + + case BC_LEX_KEY_READ: + { + if (BC_PARSE_LEAF(prev, rprn)) + return BC_STATUS_PARSE_BAD_EXP; + else if (flags & BC_PARSE_NOREAD) + s = BC_STATUS_EXEC_REC_READ; + else + s = bc_parse_read(p); + + paren_expr = true; + rprn = get_token = bin_last = false; + ++nexprs; + prev = BC_INST_READ; + + break; + } + + case BC_LEX_KEY_SCALE: + { + if (BC_PARSE_LEAF(prev, rprn)) return BC_STATUS_PARSE_BAD_EXP; + + s = bc_parse_scale(p, &prev, flags); + paren_expr = true; + rprn = get_token = bin_last = false; + ++nexprs; + prev = BC_INST_SCALE; + + break; + } + + default: + { + s = BC_STATUS_PARSE_BAD_TOKEN; + break; + } + } + + if (!s && get_token) s = bc_lex_next(&p->l); + } + + if (s) return s; + if (bcg.signe) return BC_STATUS_EXEC_SIGNAL; + + while (p->ops.len > ops_bgn) { + + top = BC_PARSE_TOP_OP(p); + assign = top >= BC_LEX_OP_ASSIGN_POWER && top <= BC_LEX_OP_ASSIGN; + + if (top == BC_LEX_LPAREN || top == BC_LEX_RPAREN) + return BC_STATUS_PARSE_BAD_EXP; + + bc_parse_push(p, BC_PARSE_TOKEN_INST(top)); + + nexprs -= top != BC_LEX_OP_BOOL_NOT && top != BC_LEX_NEG; + bc_vec_pop(&p->ops); + } + + s = BC_STATUS_PARSE_BAD_EXP; + if (prev == BC_INST_BOOL_NOT || nexprs != 1) return s; + + for (i = 0; s && i < next.len; ++i) s *= t != next.tokens[i]; + if (s) return s; + + if (!(flags & BC_PARSE_REL) && nrelops) { + s = bc_vm_posixError(BC_STATUS_POSIX_REL_POS, p->l.f, p->l.line, NULL); + if (s) return s; + } + else if ((flags & BC_PARSE_REL) && nrelops > 1) { + s = bc_vm_posixError(BC_STATUS_POSIX_MULTIREL, p->l.f, p->l.line, NULL); + if (s) return s; + } + + if (flags & BC_PARSE_PRINT) { + if (paren_first || !assign) bc_parse_push(p, BC_INST_PRINT); + bc_parse_push(p, BC_INST_POP); + } + + return s; +} + +static void bc_parse_init(BcParse *p, BcProgram *prog, size_t func) +{ + bc_parse_create(p, prog, func, bc_parse_parse, bc_lex_token); +} + +static BcStatus bc_parse_expression(BcParse *p, uint8_t flags) +{ + return bc_parse_expr(p, flags, bc_parse_next_read); +} +#endif // ENABLE_BC + +#ifdef ENABLE_DC +static BcStatus dc_parse_register(BcParse *p) +{ + BcStatus s; + char *name; + + s = bc_lex_next(&p->l); + if (s) return s; + if (p->l.t.t != BC_LEX_NAME) return BC_STATUS_PARSE_BAD_TOKEN; + + name = xstrdup(p->l.t.v.v); + bc_parse_pushName(p, name); + + return s; +} + +static BcStatus dc_parse_string(BcParse *p) +{ + char *str, *name, b[DC_PARSE_BUF_LEN + 1]; + size_t idx, len = p->prog->strs.len; + + sprintf(b, "%0*zu", DC_PARSE_BUF_LEN, len); + name = xstrdup(b); + + str = xstrdup(p->l.t.v.v); + bc_parse_push(p, BC_INST_STR); + bc_parse_pushIndex(p, len); + bc_vec_push(&p->prog->strs, &str); + bc_parse_addFunc(p, name, &idx); + + return bc_lex_next(&p->l); +} + +static BcStatus dc_parse_mem(BcParse *p, uint8_t inst, bool name, bool store) +{ + BcStatus s; + + bc_parse_push(p, inst); + if (name) { + s = dc_parse_register(p); + if (s) return s; + } + + if (store) { + bc_parse_push(p, BC_INST_SWAP); + bc_parse_push(p, BC_INST_ASSIGN); + bc_parse_push(p, BC_INST_POP); + } + + return bc_lex_next(&p->l); +} + +static BcStatus dc_parse_cond(BcParse *p, uint8_t inst) +{ + BcStatus s; + + bc_parse_push(p, inst); + bc_parse_push(p, BC_INST_EXEC_COND); + + s = dc_parse_register(p); + if (s) return s; + + s = bc_lex_next(&p->l); + if (s) return s; + + if (p->l.t.t == BC_LEX_ELSE) { + s = dc_parse_register(p); + if (s) return s; + s = bc_lex_next(&p->l); + } + else + bc_parse_push(p, BC_PARSE_STREND); + + return s; +} + +static BcStatus dc_parse_token(BcParse *p, BcLexType t, uint8_t flags) +{ + BcStatus s = BC_STATUS_SUCCESS; + BcInst prev; + uint8_t inst; + bool assign, get_token = false; + + switch (t) { + + case BC_LEX_OP_REL_EQ: + case BC_LEX_OP_REL_LE: + case BC_LEX_OP_REL_GE: + case BC_LEX_OP_REL_NE: + case BC_LEX_OP_REL_LT: + case BC_LEX_OP_REL_GT: + { + s = dc_parse_cond(p, t - BC_LEX_OP_REL_EQ + BC_INST_REL_EQ); + break; + } + + case BC_LEX_SCOLON: + case BC_LEX_COLON: + { + s = dc_parse_mem(p, BC_INST_ARRAY_ELEM, true, t == BC_LEX_COLON); + break; + } + + case BC_LEX_STR: + { + s = dc_parse_string(p); + break; + } + + case BC_LEX_NEG: + case BC_LEX_NUMBER: + { + if (t == BC_LEX_NEG) { + s = bc_lex_next(&p->l); + if (s) return s; + if (p->l.t.t != BC_LEX_NUMBER) return BC_STATUS_PARSE_BAD_TOKEN; + } + + bc_parse_number(p, &prev, &p->nbraces); + + if (t == BC_LEX_NEG) bc_parse_push(p, BC_INST_NEG); + get_token = true; + + break; + } + + case BC_LEX_KEY_READ: + { + if (flags & BC_PARSE_NOREAD) + s = BC_STATUS_EXEC_REC_READ; + else + bc_parse_push(p, BC_INST_READ); + get_token = true; + break; + } + + case BC_LEX_OP_ASSIGN: + case BC_LEX_STORE_PUSH: + { + assign = t == BC_LEX_OP_ASSIGN; + inst = assign ? BC_INST_VAR : BC_INST_PUSH_TO_VAR; + s = dc_parse_mem(p, inst, true, assign); + break; + } + + case BC_LEX_LOAD: + case BC_LEX_LOAD_POP: + { + inst = t == BC_LEX_LOAD_POP ? BC_INST_PUSH_VAR : BC_INST_LOAD; + s = dc_parse_mem(p, inst, true, false); + break; + } + + case BC_LEX_STORE_IBASE: + case BC_LEX_STORE_SCALE: + case BC_LEX_STORE_OBASE: + { + inst = t - BC_LEX_STORE_IBASE + BC_INST_IBASE; + s = dc_parse_mem(p, inst, false, true); + break; + } + + default: + { + s = BC_STATUS_PARSE_BAD_TOKEN; + get_token = true; + break; + } + } + + if (!s && get_token) s = bc_lex_next(&p->l); + + return s; +} + +static BcStatus dc_parse_expr(BcParse *p, uint8_t flags) +{ + BcStatus s = BC_STATUS_SUCCESS; + BcInst inst; + BcLexType t; + + if (flags & BC_PARSE_NOCALL) p->nbraces = p->prog->results.len; + + for (t = p->l.t.t; !s && t != BC_LEX_EOF; t = p->l.t.t) { + + inst = dc_parse_insts[t]; + + if (inst != BC_INST_INVALID) { + bc_parse_push(p, inst); + s = bc_lex_next(&p->l); + } + else + s = dc_parse_token(p, t, flags); + } + + if (!s && p->l.t.t == BC_LEX_EOF && (flags & BC_PARSE_NOCALL)) + bc_parse_push(p, BC_INST_POP_EXEC); + + return s; +} + +static BcStatus dc_parse_parse(BcParse *p) +{ + BcStatus s; + + if (p->l.t.t == BC_LEX_EOF) + s = BC_STATUS_LEX_EOF; + else + s = dc_parse_expr(p, 0); + + if (s || bcg.signe) s = bc_parse_reset(p, s); + + return s; +} + +static void dc_parse_init(BcParse *p, BcProgram *prog, size_t func) +{ + bc_parse_create(p, prog, func, dc_parse_parse, dc_lex_token); +} +#endif // ENABLE_DC + +static void bc_program_search(BcProgram *p, char *id, BcVec **ret, bool var) +{ + BcStatus s; + BcId e, *ptr; + BcVec *v, *map; + size_t i; + BcResultData data; + bool new; + + v = var ? &p->vars : &p->arrs; + map = var ? &p->var_map : &p->arr_map; + + e.name = id; + e.idx = v->len; + s = bc_map_insert(map, &e, &i); + new = s != BC_STATUS_VEC_ITEM_EXISTS; + + if (new) { + bc_array_init(&data.v, var); + bc_vec_push(v, &data.v); + } + + ptr = bc_vec_item(map, i); + if (new) ptr->name = xstrdup(e.name); + *ret = bc_vec_item(v, ptr->idx); +} + +static BcStatus bc_program_num(BcProgram *p, BcResult *r, BcNum **num, bool hex) +{ + BcStatus s = BC_STATUS_SUCCESS; + + switch (r->t) { + + case BC_RESULT_STR: + case BC_RESULT_TEMP: + case BC_RESULT_IBASE: + case BC_RESULT_SCALE: + case BC_RESULT_OBASE: + { + *num = &r->d.n; + break; + } + + case BC_RESULT_CONSTANT: + { + char **str = bc_vec_item(&p->consts, r->d.id.idx); + size_t base_t, len = strlen(*str); + BcNum *base; + + bc_num_init(&r->d.n, len); + + hex = hex && len == 1; + base = hex ? &p->hexb : &p->ib; + base_t = hex ? BC_NUM_MAX_IBASE : p->ib_t; + s = bc_num_parse(&r->d.n, *str, base, base_t); + + if (s) { + bc_num_free(&r->d.n); + return s; + } + + *num = &r->d.n; + r->t = BC_RESULT_TEMP; + + break; + } + + case BC_RESULT_VAR: + case BC_RESULT_ARRAY: + case BC_RESULT_ARRAY_ELEM: + { + BcVec *v; + + bc_program_search(p, r->d.id.name, &v, r->t == BC_RESULT_VAR); + + if (r->t == BC_RESULT_ARRAY_ELEM) { + v = bc_vec_top(v); + if (v->len <= r->d.id.idx) bc_array_expand(v, r->d.id.idx + 1); + *num = bc_vec_item(v, r->d.id.idx); + } + else + *num = bc_vec_top(v); + + break; + } + + case BC_RESULT_LAST: + { + *num = &p->last; + break; + } + + case BC_RESULT_ONE: + { + *num = &p->one; + break; + } + } + + return s; +} + +static BcStatus bc_program_binOpPrep(BcProgram *p, BcResult **l, BcNum **ln, + BcResult **r, BcNum **rn, bool assign) +{ + BcStatus s; + bool hex; + BcResultType lt, rt; + + if (!BC_PROG_STACK(&p->results, 2)) return BC_STATUS_EXEC_STACK; + + *r = bc_vec_item_rev(&p->results, 0); + *l = bc_vec_item_rev(&p->results, 1); + + lt = (*l)->t; + rt = (*r)->t; + hex = assign && (lt == BC_RESULT_IBASE || lt == BC_RESULT_OBASE); + + s = bc_program_num(p, *l, ln, false); + if (s) return s; + s = bc_program_num(p, *r, rn, hex); + if (s) return s; + + // We run this again under these conditions in case any vector has been + // reallocated out from under the BcNums or arrays we had. + if (lt == rt && (lt == BC_RESULT_VAR || lt == BC_RESULT_ARRAY_ELEM)) { + s = bc_program_num(p, *l, ln, false); + if (s) return s; + } + + if (!BC_PROG_NUM((*l), (*ln)) && (!assign || (*l)->t != BC_RESULT_VAR)) + return BC_STATUS_EXEC_BAD_TYPE; + if (!assign && !BC_PROG_NUM((*r), (*ln))) return BC_STATUS_EXEC_BAD_TYPE; + +#ifdef ENABLE_DC +#else // ENABLE_DC +#endif // ENABLE_DC + + return s; +} + +static void bc_program_binOpRetire(BcProgram *p, BcResult *r) +{ + r->t = BC_RESULT_TEMP; + bc_vec_pop(&p->results); + bc_vec_pop(&p->results); + bc_vec_push(&p->results, r); +} + +static BcStatus bc_program_prep(BcProgram *p, BcResult **r, BcNum **n) +{ + BcStatus s; + + if (!BC_PROG_STACK(&p->results, 1)) return BC_STATUS_EXEC_STACK; + *r = bc_vec_top(&p->results); + + s = bc_program_num(p, *r, n, false); + if (s) return s; + +#ifdef ENABLE_DC +#endif // ENABLE_DC + + if (!BC_PROG_NUM((*r), (*n))) return BC_STATUS_EXEC_BAD_TYPE; + + return s; +} + +static void bc_program_retire(BcProgram *p, BcResult *r, BcResultType t) +{ + r->t = t; + bc_vec_pop(&p->results); + bc_vec_push(&p->results, r); +} + +static BcStatus bc_program_op(BcProgram *p, char inst) +{ + BcStatus s; + BcResult *opd1, *opd2, res; + BcNum *n1, *n2 = NULL; + + s = bc_program_binOpPrep(p, &opd1, &n1, &opd2, &n2, false); + if (s) return s; + bc_num_init(&res.d.n, BC_NUM_DEF_SIZE); + + s = bc_program_ops[inst - BC_INST_POWER](n1, n2, &res.d.n, p->scale); + if (s) goto err; + bc_program_binOpRetire(p, &res); + + return s; + +err: + bc_num_free(&res.d.n); + return s; +} + +static BcStatus bc_program_read(BcProgram *p) +{ + BcStatus s; + BcParse parse; + BcVec buf; + BcInstPtr ip; + size_t i; + BcFunc *f = bc_vec_item(&p->fns, BC_PROG_READ); + + for (i = 0; i < p->stack.len; ++i) { + BcInstPtr *ip_ptr = bc_vec_item(&p->stack, i); + if (ip_ptr->func == BC_PROG_READ) return BC_STATUS_EXEC_REC_READ; + } + + bc_vec_npop(&f->code, f->code.len); + bc_vec_init(&buf, sizeof(char), NULL); + + s = bc_read_line(&buf, "read> "); + if (s) goto io_err; + + p->parse_init(&parse, p, BC_PROG_READ); + bc_lex_file(&parse.l, bc_program_stdin_name); + + s = bc_parse_text(&parse, buf.v); + if (s) goto exec_err; + s = p->parse_expr(&parse, BC_PARSE_NOREAD); + if (s) goto exec_err; + + if (parse.l.t.t != BC_LEX_NLINE && parse.l.t.t != BC_LEX_EOF) { + s = BC_STATUS_EXEC_BAD_READ_EXPR; + goto exec_err; + } + + ip.func = BC_PROG_READ; + ip.idx = 0; + ip.len = p->results.len; + + // Update this pointer, just in case. + f = bc_vec_item(&p->fns, BC_PROG_READ); + + bc_vec_pushByte(&f->code, BC_INST_POP_EXEC); + bc_vec_push(&p->stack, &ip); + +exec_err: + bc_parse_free(&parse); +io_err: + bc_vec_free(&buf); + return s; +} + +static size_t bc_program_index(char *code, size_t *bgn) +{ + char amt = code[(*bgn)++], i = 0; + size_t res = 0; + + for (; i < amt; ++i, ++(*bgn)) + res |= (((size_t)((int) code[*bgn]) & UCHAR_MAX) << (i * CHAR_BIT)); + + return res; +} + +static char *bc_program_name(char *code, size_t *bgn) +{ + size_t i; + char c, *s, *str = code + *bgn, *ptr = strchr(str, BC_PARSE_STREND); + + s = xmalloc(ptr - str + 1); + c = code[(*bgn)++]; + + for (i = 0; c != 0 && c != BC_PARSE_STREND; c = code[(*bgn)++], ++i) + s[i] = c; + + s[i] = '\0'; + + return s; +} + +static void bc_program_printString(const char *str, size_t *nchars) +{ + size_t i, len = strlen(str); + +#ifdef ENABLE_DC + if (len == 0) { + bc_vm_putchar('\0'); + return; + } +#endif // ENABLE_DC + + for (i = 0; i < len; ++i, ++(*nchars)) { + + int c = str[i]; + + if (c != '\\' || i == len - 1) + bc_vm_putchar(c); + else { + + c = str[++i]; + + switch (c) { + + case 'a': + { + bc_vm_putchar('\a'); + break; + } + + case 'b': + { + bc_vm_putchar('\b'); + break; + } + + case '\\': + case 'e': + { + bc_vm_putchar('\\'); + break; + } + + case 'f': + { + bc_vm_putchar('\f'); + break; + } + + case 'n': + { + bc_vm_putchar('\n'); + *nchars = SIZE_MAX; + break; + } + + case 'r': + { + bc_vm_putchar('\r'); + break; + } + + case 'q': + { + bc_vm_putchar('"'); + break; + } + + case 't': + { + bc_vm_putchar('\t'); + break; + } + + default: + { + // Just print the backslash and following character. + bc_vm_putchar('\\'); + ++(*nchars); + bc_vm_putchar(c); + break; + } + } + } + } +} + +static BcStatus bc_program_print(BcProgram *p, char inst, size_t idx) +{ + BcStatus s = BC_STATUS_SUCCESS; + BcResult *r; + size_t len, i; + char *str; + BcNum *num = NULL; + bool pop = inst != BC_INST_PRINT; + + if (!BC_PROG_STACK(&p->results, idx + 1)) return BC_STATUS_EXEC_STACK; + + r = bc_vec_item_rev(&p->results, idx); + s = bc_program_num(p, r, &num, false); + if (s) return s; + + if (BC_PROG_NUM(r, num)) { + s = bc_num_print(num, &p->ob, p->ob_t, !pop, &p->nchars, p->len); + if (!s) bc_num_copy(&p->last, num); + } + else { + + idx = (r->t == BC_RESULT_STR) ? r->d.id.idx : num->rdx; + str = *((char **) bc_vec_item(&p->strs, idx)); + + if (inst == BC_INST_PRINT_STR) { + for (i = 0, len = strlen(str); i < len; ++i) { + char c = str[i]; + bc_vm_putchar(c); + if (c == '\n') p->nchars = SIZE_MAX; + ++p->nchars; + } + } + else { + bc_program_printString(str, &p->nchars); + if (inst == BC_INST_PRINT) bc_vm_putchar('\n'); + } + } + + if (!s && pop) bc_vec_pop(&p->results); + + return s; +} + +static BcStatus bc_program_negate(BcProgram *p) +{ + BcStatus s; + BcResult res, *ptr; + BcNum *num = NULL; + + s = bc_program_prep(p, &ptr, &num); + if (s) return s; + + bc_num_init(&res.d.n, num->len); + bc_num_copy(&res.d.n, num); + if (res.d.n.len) res.d.n.neg = !res.d.n.neg; + + bc_program_retire(p, &res, BC_RESULT_TEMP); + + return s; +} + +static BcStatus bc_program_logical(BcProgram *p, char inst) +{ + BcStatus s; + BcResult *opd1, *opd2, res; + BcNum *n1, *n2; + bool cond = 0; + ssize_t cmp; + + s = bc_program_binOpPrep(p, &opd1, &n1, &opd2, &n2, false); + if (s) return s; + bc_num_init(&res.d.n, BC_NUM_DEF_SIZE); + + if (inst == BC_INST_BOOL_AND) + cond = bc_num_cmp(n1, &p->zero) && bc_num_cmp(n2, &p->zero); + else if (inst == BC_INST_BOOL_OR) + cond = bc_num_cmp(n1, &p->zero) || bc_num_cmp(n2, &p->zero); + else { + + cmp = bc_num_cmp(n1, n2); + + switch (inst) { + + case BC_INST_REL_EQ: + { + cond = cmp == 0; + break; + } + + case BC_INST_REL_LE: + { + cond = cmp <= 0; + break; + } + + case BC_INST_REL_GE: + { + cond = cmp >= 0; + break; + } + + case BC_INST_REL_NE: + { + cond = cmp != 0; + break; + } + + case BC_INST_REL_LT: + { + cond = cmp < 0; + break; + } + + case BC_INST_REL_GT: + { + cond = cmp > 0; + break; + } + } + } + + (cond ? bc_num_one : bc_num_zero)(&res.d.n); + + bc_program_binOpRetire(p, &res); + + return s; +} + +#ifdef ENABLE_DC +static BcStatus bc_program_assignStr(BcProgram *p, BcResult *r, BcVec *v, + bool push) +{ + BcNum n2; + BcResult res; + + memset(&n2, 0, sizeof(BcNum)); + n2.rdx = res.d.id.idx = r->d.id.idx; + res.t = BC_RESULT_STR; + + if (!push) { + if (!BC_PROG_STACK(&p->results, 2)) return BC_STATUS_EXEC_STACK; + bc_vec_pop(v); + bc_vec_pop(&p->results); + } + + bc_vec_pop(&p->results); + + bc_vec_push(&p->results, &res); + bc_vec_push(v, &n2); + + return BC_STATUS_SUCCESS; +} +#endif // ENABLE_DC + +static BcStatus bc_program_copyToVar(BcProgram *p, char *name, bool var) +{ + BcStatus s; + BcResult *ptr, r; + BcVec *v; + BcNum *n; + + if (!BC_PROG_STACK(&p->results, 1)) return BC_STATUS_EXEC_STACK; + + ptr = bc_vec_top(&p->results); + if ((ptr->t == BC_RESULT_ARRAY) != !var) return BC_STATUS_EXEC_BAD_TYPE; + bc_program_search(p, name, &v, var); + +#ifdef ENABLE_DC + if (ptr->t == BC_RESULT_STR && !var) return BC_STATUS_EXEC_BAD_TYPE; + if (ptr->t == BC_RESULT_STR) return bc_program_assignStr(p, ptr, v, true); +#endif // ENABLE_DC + + s = bc_program_num(p, ptr, &n, false); + if (s) return s; + + // Do this once more to make sure that pointers were not invalidated. + bc_program_search(p, name, &v, var); + + if (var) { + bc_num_init(&r.d.n, BC_NUM_DEF_SIZE); + bc_num_copy(&r.d.n, n); + } + else { + bc_array_init(&r.d.v, true); + bc_array_copy(&r.d.v, (BcVec *) n); + } + + bc_vec_push(v, &r.d); + bc_vec_pop(&p->results); + + return s; +} + +static BcStatus bc_program_assign(BcProgram *p, char inst) +{ + BcStatus s; + BcResult *left, *right, res; + BcNum *l = NULL, *r = NULL; + unsigned long val, max; + bool assign = inst == BC_INST_ASSIGN, ib, sc; + + s = bc_program_binOpPrep(p, &left, &l, &right, &r, assign); + if (s) return s; + + ib = left->t == BC_RESULT_IBASE; + sc = left->t == BC_RESULT_SCALE; + +#ifdef ENABLE_DC + + if (right->t == BC_RESULT_STR) { + + BcVec *v; + + if (left->t != BC_RESULT_VAR) return BC_STATUS_EXEC_BAD_TYPE; + bc_program_search(p, left->d.id.name, &v, true); + + return bc_program_assignStr(p, right, v, false); + } +#endif // ENABLE_DC + + if (left->t == BC_RESULT_CONSTANT || left->t == BC_RESULT_TEMP) + return BC_STATUS_PARSE_BAD_ASSIGN; + +#ifdef ENABLE_BC + if (inst == BC_INST_ASSIGN_DIVIDE && !bc_num_cmp(r, &p->zero)) + return BC_STATUS_MATH_DIVIDE_BY_ZERO; + + if (assign) + bc_num_copy(l, r); + else + s = bc_program_ops[inst - BC_INST_ASSIGN_POWER](l, r, l, p->scale); + + if (s) return s; +#else // ENABLE_BC + bc_num_copy(l, r); +#endif // ENABLE_BC + + if (ib || sc || left->t == BC_RESULT_OBASE) { + + size_t *ptr; + + s = bc_num_ulong(l, &val); + if (s) return s; + s = left->t - BC_RESULT_IBASE + BC_STATUS_EXEC_BAD_IBASE; + + if (sc) { + max = BC_MAX_SCALE; + ptr = &p->scale; + } + else { + if (val < BC_NUM_MIN_BASE) return s; + max = ib ? BC_NUM_MAX_IBASE : BC_MAX_OBASE; + ptr = ib ? &p->ib_t : &p->ob_t; + } + + if (val > max) return s; + if (!sc) bc_num_copy(ib ? &p->ib : &p->ob, l); + + *ptr = (size_t) val; + s = BC_STATUS_SUCCESS; + } + + bc_num_init(&res.d.n, l->len); + bc_num_copy(&res.d.n, l); + bc_program_binOpRetire(p, &res); + + return s; +} + +static BcStatus bc_program_pushVar(BcProgram *p, char *code, size_t *bgn, + bool pop, bool copy) +{ + BcStatus s = BC_STATUS_SUCCESS; + BcResult r; + char *name = bc_program_name(code, bgn); +#ifdef ENABLE_DC // Exclude + BcNum *num; + BcVec *v; +#else // ENABLE_DC + (void) pop, (void) copy; +#endif // ENABLE_DC Exclude + + r.t = BC_RESULT_VAR; + r.d.id.name = name; + +#ifdef ENABLE_DC + bc_program_search(p, name, &v, true); + num = bc_vec_top(v); + + if (pop || copy) { + + if (!BC_PROG_STACK(v, 2 - copy)) { + free(name); + return BC_STATUS_EXEC_STACK; + } + + free(name); + name = NULL; + + if (!BC_PROG_STR(num)) { + + r.t = BC_RESULT_TEMP; + + bc_num_init(&r.d.n, BC_NUM_DEF_SIZE); + bc_num_copy(&r.d.n, num); + } + else { + r.t = BC_RESULT_STR; + r.d.id.idx = num->rdx; + } + + if (!copy) bc_vec_pop(v); + } +#endif // ENABLE_DC + + bc_vec_push(&p->results, &r); + + return s; +} + +static BcStatus bc_program_pushArray(BcProgram *p, char *code, size_t *bgn, + char inst) +{ + BcStatus s = BC_STATUS_SUCCESS; + BcResult r; + BcNum *num; + + r.d.id.name = bc_program_name(code, bgn); + + if (inst == BC_INST_ARRAY) { + r.t = BC_RESULT_ARRAY; + bc_vec_push(&p->results, &r); + } + else { + + BcResult *operand; + unsigned long temp; + + s = bc_program_prep(p, &operand, &num); + if (s) goto err; + s = bc_num_ulong(num, &temp); + if (s) goto err; + + if (temp > BC_MAX_DIM) { + s = BC_STATUS_EXEC_ARRAY_LEN; + goto err; + } + + r.d.id.idx = (size_t) temp; + bc_program_retire(p, &r, BC_RESULT_ARRAY_ELEM); + } + +err: + if (s) free(r.d.id.name); + return s; +} + +#ifdef ENABLE_BC +static BcStatus bc_program_incdec(BcProgram *p, char inst) +{ + BcStatus s; + BcResult *ptr, res, copy; + BcNum *num = NULL; + char inst2 = inst; + + s = bc_program_prep(p, &ptr, &num); + if (s) return s; + + if (inst == BC_INST_INC_POST || inst == BC_INST_DEC_POST) { + copy.t = BC_RESULT_TEMP; + bc_num_init(©.d.n, num->len); + bc_num_copy(©.d.n, num); + } + + res.t = BC_RESULT_ONE; + inst = inst == BC_INST_INC_PRE || inst == BC_INST_INC_POST ? + BC_INST_ASSIGN_PLUS : + BC_INST_ASSIGN_MINUS; + + bc_vec_push(&p->results, &res); + bc_program_assign(p, inst); + + if (inst2 == BC_INST_INC_POST || inst2 == BC_INST_DEC_POST) { + bc_vec_pop(&p->results); + bc_vec_push(&p->results, ©); + } + + return s; +} + +static BcStatus bc_program_call(BcProgram *p, char *code, size_t *idx) +{ + BcStatus s = BC_STATUS_SUCCESS; + BcInstPtr ip; + size_t i, nparams = bc_program_index(code, idx); + BcFunc *func; + BcVec *v; + BcId *a; + BcResultData param; + BcResult *arg; + + ip.idx = 0; + ip.func = bc_program_index(code, idx); + func = bc_vec_item(&p->fns, ip.func); + + if (func->code.len == 0) return BC_STATUS_EXEC_UNDEFINED_FUNC; + if (nparams != func->nparams) return BC_STATUS_EXEC_MISMATCHED_PARAMS; + ip.len = p->results.len - nparams; + + for (i = 0; i < nparams; ++i) { + + a = bc_vec_item(&func->autos, nparams - 1 - i); + arg = bc_vec_top(&p->results); + + if ((!a->idx) != (arg->t == BC_RESULT_ARRAY) || arg->t == BC_RESULT_STR) + return BC_STATUS_EXEC_BAD_TYPE; + + s = bc_program_copyToVar(p, a->name, a->idx); + if (s) return s; + } + + for (; i < func->autos.len; ++i) { + + a = bc_vec_item(&func->autos, i); + bc_program_search(p, a->name, &v, a->idx); + + if (a->idx) { + bc_num_init(¶m.n, BC_NUM_DEF_SIZE); + bc_vec_push(v, ¶m.n); + } + else { + bc_array_init(¶m.v, true); + bc_vec_push(v, ¶m.v); + } + } + + bc_vec_push(&p->stack, &ip); + + return BC_STATUS_SUCCESS; +} + +static BcStatus bc_program_return(BcProgram *p, char inst) +{ + BcStatus s; + BcResult res; + BcFunc *f; + size_t i; + BcInstPtr *ip = bc_vec_top(&p->stack); + + if (!BC_PROG_STACK(&p->results, ip->len + inst == BC_INST_RET)) + return BC_STATUS_EXEC_STACK; + + f = bc_vec_item(&p->fns, ip->func); + res.t = BC_RESULT_TEMP; + + if (inst == BC_INST_RET) { + + BcNum *num; + BcResult *operand = bc_vec_top(&p->results); + + s = bc_program_num(p, operand, &num, false); + if (s) return s; + bc_num_init(&res.d.n, num->len); + bc_num_copy(&res.d.n, num); + } + else { + bc_num_init(&res.d.n, BC_NUM_DEF_SIZE); + bc_num_zero(&res.d.n); + } + + // We need to pop arguments as well, so this takes that into account. + for (i = 0; i < f->autos.len; ++i) { + + BcVec *v; + BcId *a = bc_vec_item(&f->autos, i); + + bc_program_search(p, a->name, &v, a->idx); + bc_vec_pop(v); + } + + bc_vec_npop(&p->results, p->results.len - ip->len); + bc_vec_push(&p->results, &res); + bc_vec_pop(&p->stack); + + return BC_STATUS_SUCCESS; +} +#endif // ENABLE_BC + +static unsigned long bc_program_scale(BcNum *n) +{ + return (unsigned long) n->rdx; +} + +static unsigned long bc_program_len(BcNum *n) +{ + unsigned long len = n->len; + size_t i; + + if (n->rdx != n->len) return len; + for (i = n->len - 1; i < n->len && n->num[i] == 0; --len, --i); + + return len; +} + +static BcStatus bc_program_builtin(BcProgram *p, char inst) +{ + BcStatus s; + BcResult *opnd; + BcNum *num = NULL; + BcResult res; + bool len = inst == BC_INST_LENGTH; + + if (!BC_PROG_STACK(&p->results, 1)) return BC_STATUS_EXEC_STACK; + opnd = bc_vec_top(&p->results); + + s = bc_program_num(p, opnd, &num, false); + if (s) return s; + +#ifdef ENABLE_DC + if (!BC_PROG_NUM(opnd, num) && !len) return BC_STATUS_EXEC_BAD_TYPE; +#endif // ENABLE_DC + + bc_num_init(&res.d.n, BC_NUM_DEF_SIZE); + + if (inst == BC_INST_SQRT) s = bc_num_sqrt(num, &res.d.n, p->scale); +#ifdef ENABLE_BC + else if (len != 0 && opnd->t == BC_RESULT_ARRAY) { + s = bc_num_ulong2num(&res.d.n, (unsigned long) ((BcVec *) num)->len); + } +#endif // ENABLE_BC +#ifdef ENABLE_DC + else if (len != 0 && !BC_PROG_NUM(opnd, num)) { + + char **str; + size_t idx = opnd->t == BC_RESULT_STR ? opnd->d.id.idx : num->rdx; + + str = bc_vec_item(&p->strs, idx); + s = bc_num_ulong2num(&res.d.n, strlen(*str)); + if (s) goto err; + } +#endif // ENABLE_DC + else { + BcProgramBuiltIn f = len ? bc_program_len : bc_program_scale; + s = bc_num_ulong2num(&res.d.n, f(num)); + if (s) goto err; + } + + bc_program_retire(p, &res, BC_RESULT_TEMP); + + return s; + +err: + bc_num_free(&res.d.n); + return s; +} + +#ifdef ENABLE_DC +static BcStatus bc_program_divmod(BcProgram *p) +{ + BcStatus s; + BcResult *opd1, *opd2, res, res2; + BcNum *n1, *n2 = NULL; + + s = bc_program_binOpPrep(p, &opd1, &n1, &opd2, &n2, false); + if (s) return s; + + bc_num_init(&res.d.n, BC_NUM_DEF_SIZE); + bc_num_init(&res2.d.n, n2->len); + + s = bc_num_divmod(n1, n2, &res2.d.n, &res.d.n, p->scale); + if (s) goto err; + + bc_program_binOpRetire(p, &res2); + res.t = BC_RESULT_TEMP; + bc_vec_push(&p->results, &res); + + return s; + +err: + bc_num_free(&res2.d.n); + bc_num_free(&res.d.n); + return s; +} + +static BcStatus bc_program_modexp(BcProgram *p) +{ + BcStatus s; + BcResult *r1, *r2, *r3, res; + BcNum *n1, *n2, *n3; + + if (!BC_PROG_STACK(&p->results, 3)) return BC_STATUS_EXEC_STACK; + s = bc_program_binOpPrep(p, &r2, &n2, &r3, &n3, false); + if (s) return s; + + r1 = bc_vec_item_rev(&p->results, 2); + s = bc_program_num(p, r1, &n1, false); + if (s) return s; + if (!BC_PROG_NUM(r1, n1)) return BC_STATUS_EXEC_BAD_TYPE; + + // Make sure that the values have their pointers updated, if necessary. + if (r1->t == BC_RESULT_VAR || r1->t == BC_RESULT_ARRAY_ELEM) { + + if (r1->t == r2->t) { + s = bc_program_num(p, r2, &n2, false); + if (s) return s; + } + + if (r1->t == r3->t) { + s = bc_program_num(p, r3, &n3, false); + if (s) return s; + } + } + + bc_num_init(&res.d.n, n3->len); + s = bc_num_modexp(n1, n2, n3, &res.d.n); + if (s) goto err; + + bc_vec_pop(&p->results); + bc_program_binOpRetire(p, &res); + + return s; + +err: + bc_num_free(&res.d.n); + return s; +} + +static BcStatus bc_program_stackLen(BcProgram *p) +{ + BcStatus s; + BcResult res; + size_t len = p->results.len; + + res.t = BC_RESULT_TEMP; + + bc_num_init(&res.d.n, BC_NUM_DEF_SIZE); + s = bc_num_ulong2num(&res.d.n, len); + if (s) goto err; + bc_vec_push(&p->results, &res); + + return s; + +err: + bc_num_free(&res.d.n); + return s; +} + +static BcStatus bc_program_asciify(BcProgram *p) +{ + BcStatus s; + BcResult *r, res; + BcNum *num = NULL, n; + char *str, *str2, c; + size_t len = p->strs.len, idx; + unsigned long val; + + if (!BC_PROG_STACK(&p->results, 1)) return BC_STATUS_EXEC_STACK; + r = bc_vec_top(&p->results); + + s = bc_program_num(p, r, &num, false); + if (s) return s; + + if (BC_PROG_NUM(r, num)) { + + bc_num_init(&n, BC_NUM_DEF_SIZE); + bc_num_copy(&n, num); + bc_num_truncate(&n, n.rdx); + + s = bc_num_mod(&n, &p->strmb, &n, 0); + if (s) goto num_err; + s = bc_num_ulong(&n, &val); + if (s) goto num_err; + + c = (char) val; + + bc_num_free(&n); + } + else { + idx = (r->t == BC_RESULT_STR) ? r->d.id.idx : num->rdx; + str2 = *((char **) bc_vec_item(&p->strs, idx)); + c = str2[0]; + } + + str = xmalloc(2); + str[0] = c; + str[1] = '\0'; + + str2 = xstrdup(str); + bc_program_addFunc(p, str2, &idx); + + if (idx != len + BC_PROG_REQ_FUNCS) { + + for (idx = 0; idx < p->strs.len; ++idx) { + if (!strcmp(*((char **) bc_vec_item(&p->strs, idx)), str)) { + len = idx; + break; + } + } + + free(str); + } + else + bc_vec_push(&p->strs, &str); + + res.t = BC_RESULT_STR; + res.d.id.idx = len; + bc_vec_pop(&p->results); + bc_vec_push(&p->results, &res); + + return BC_STATUS_SUCCESS; + +num_err: + bc_num_free(&n); + return s; +} + +static BcStatus bc_program_printStream(BcProgram *p) +{ + BcStatus s; + BcResult *r; + BcNum *n = NULL; + size_t idx; + char *str; + + if (!BC_PROG_STACK(&p->results, 1)) return BC_STATUS_EXEC_STACK; + r = bc_vec_top(&p->results); + + s = bc_program_num(p, r, &n, false); + if (s) return s; + + if (BC_PROG_NUM(r, n)) + s = bc_num_stream(n, &p->strmb, &p->nchars, p->len); + else { + idx = (r->t == BC_RESULT_STR) ? r->d.id.idx : n->rdx; + str = *((char **) bc_vec_item(&p->strs, idx)); + bc_vm_printf(stdout, "%s", str); + } + + return s; +} + +static BcStatus bc_program_nquit(BcProgram *p) +{ + BcStatus s; + BcResult *opnd; + BcNum *num = NULL; + unsigned long val; + + s = bc_program_prep(p, &opnd, &num); + if (s) return s; + s = bc_num_ulong(num, &val); + if (s) return s; + + bc_vec_pop(&p->results); + + if (p->stack.len < val) + return BC_STATUS_EXEC_STACK; + else if (p->stack.len == val) + return BC_STATUS_QUIT; + + bc_vec_npop(&p->stack, val); + + return s; +} + +static BcStatus bc_program_execStr(BcProgram *p, char *code, size_t *bgn, + bool cond) +{ + BcStatus s = BC_STATUS_SUCCESS; + BcResult *r; + char **str; + BcFunc *f; + BcParse prs; + BcInstPtr ip; + size_t fidx, sidx; + BcNum *n; + bool exec; + + if (!BC_PROG_STACK(&p->results, 1)) return BC_STATUS_EXEC_STACK; + + r = bc_vec_top(&p->results); + + if (cond) { + + BcVec *v; + char *name, *then_name = bc_program_name(code, bgn), *else_name = NULL; + + if (code[*bgn] == BC_PARSE_STREND) + (*bgn) += 1; + else + else_name = bc_program_name(code, bgn); + + exec = r->d.n.len != 0; + + if (exec) + name = then_name; + else if (else_name != NULL) { + exec = true; + name = else_name; + } + + if (exec) { + bc_program_search(p, name, &v, true); + n = bc_vec_top(v); + } + + free(then_name); + free(else_name); + + if (!exec) goto exit; + if (!BC_PROG_STR(n)) { + s = BC_STATUS_EXEC_BAD_TYPE; + goto exit; + } + + sidx = n->rdx; + } + else { + + if (r->t == BC_RESULT_STR) + sidx = r->d.id.idx; + else if (r->t == BC_RESULT_VAR) { + s = bc_program_num(p, r, &n, false); + if (s || !BC_PROG_STR(n)) goto exit; + sidx = n->rdx; + } + else + goto exit; + } + + fidx = sidx + BC_PROG_REQ_FUNCS; + + str = bc_vec_item(&p->strs, sidx); + f = bc_vec_item(&p->fns, fidx); + + if (f->code.len == 0) { + + p->parse_init(&prs, p, fidx); + s = bc_parse_text(&prs, *str); + if (s) goto err; + s = p->parse_expr(&prs, BC_PARSE_NOCALL); + if (s) goto err; + + if (prs.l.t.t != BC_LEX_EOF) { + s = BC_STATUS_PARSE_BAD_EXP; + goto err; + } + + bc_parse_free(&prs); + } + + ip.idx = 0; + ip.len = p->results.len; + ip.func = fidx; + + bc_vec_pop(&p->results); + bc_vec_push(&p->stack, &ip); + + return BC_STATUS_SUCCESS; + +err: + bc_parse_free(&prs); + f = bc_vec_item(&p->fns, fidx); + bc_vec_npop(&f->code, f->code.len); +exit: + bc_vec_pop(&p->results); + return s; +} +#endif // ENABLE_DC + +static BcStatus bc_program_pushGlobal(BcProgram *p, char inst) +{ + BcStatus s; + BcResult res; + unsigned long val; + + res.t = inst - BC_INST_IBASE + BC_RESULT_IBASE; + if (inst == BC_INST_IBASE) + val = (unsigned long) p->ib_t; + else if (inst == BC_INST_SCALE) + val = (unsigned long) p->scale; + else + val = (unsigned long) p->ob_t; + + bc_num_init(&res.d.n, BC_NUM_DEF_SIZE); + s = bc_num_ulong2num(&res.d.n, val); + if (s) goto err; + bc_vec_push(&p->results, &res); + + return s; + +err: + bc_num_free(&res.d.n); + return s; +} + +static void bc_program_free(BcProgram *p) +{ + bc_num_free(&p->ib); + bc_num_free(&p->ob); + bc_num_free(&p->hexb); +#ifdef ENABLE_DC + bc_num_free(&p->strmb); +#endif // ENABLE_DC + bc_vec_free(&p->fns); + bc_vec_free(&p->fn_map); + bc_vec_free(&p->vars); + bc_vec_free(&p->var_map); + bc_vec_free(&p->arrs); + bc_vec_free(&p->arr_map); + bc_vec_free(&p->strs); + bc_vec_free(&p->consts); + bc_vec_free(&p->results); + bc_vec_free(&p->stack); + bc_num_free(&p->last); + bc_num_free(&p->zero); + bc_num_free(&p->one); +} + +static void bc_program_init(BcProgram *p, size_t line_len, BcParseInit init, + BcParseExpr expr) +{ + size_t idx; + BcInstPtr ip; + + memset(p, 0, sizeof(BcProgram)); + memset(&ip, 0, sizeof(BcInstPtr)); + + p->nchars = p->scale = 0; + p->len = line_len; + p->parse_init = init; + p->parse_expr = expr; + + bc_num_init(&p->ib, BC_NUM_DEF_SIZE); + bc_num_ten(&p->ib); + p->ib_t = 10; + + bc_num_init(&p->ob, BC_NUM_DEF_SIZE); + bc_num_ten(&p->ob); + p->ob_t = 10; + + bc_num_init(&p->hexb, BC_NUM_DEF_SIZE); + bc_num_ten(&p->hexb); + p->hexb.num[0] = 6; + +#ifdef ENABLE_DC + bc_num_init(&p->strmb, BC_NUM_DEF_SIZE); + bc_num_ulong2num(&p->strmb, UCHAR_MAX + 1); +#endif // ENABLE_DC + + bc_num_init(&p->last, BC_NUM_DEF_SIZE); + bc_num_zero(&p->last); + + bc_num_init(&p->zero, BC_NUM_DEF_SIZE); + bc_num_zero(&p->zero); + + bc_num_init(&p->one, BC_NUM_DEF_SIZE); + bc_num_one(&p->one); + + bc_vec_init(&p->fns, sizeof(BcFunc), bc_func_free); + bc_map_init(&p->fn_map); + + bc_program_addFunc(p, xstrdup(bc_func_main), &idx); + bc_program_addFunc(p, xstrdup(bc_func_read), &idx); + + bc_vec_init(&p->vars, sizeof(BcVec), bc_vec_free); + bc_map_init(&p->var_map); + + bc_vec_init(&p->arrs, sizeof(BcVec), bc_vec_free); + bc_map_init(&p->arr_map); + + bc_vec_init(&p->strs, sizeof(char *), bc_string_free); + bc_vec_init(&p->consts, sizeof(char *), bc_string_free); + bc_vec_init(&p->results, sizeof(BcResult), bc_result_free); + bc_vec_init(&p->stack, sizeof(BcInstPtr), NULL); + bc_vec_push(&p->stack, &ip); +} + +static void bc_program_addFunc(BcProgram *p, char *name, size_t *idx) +{ + BcStatus s; + BcId entry, *entry_ptr; + BcFunc f; + + entry.name = name; + entry.idx = p->fns.len; + + s = bc_map_insert(&p->fn_map, &entry, idx); + if (s) free(name); + + entry_ptr = bc_vec_item(&p->fn_map, *idx); + *idx = entry_ptr->idx; + + if (s == BC_STATUS_VEC_ITEM_EXISTS) { + + BcFunc *func = bc_vec_item(&p->fns, entry_ptr->idx); + + // We need to reset these, so the function can be repopulated. + func->nparams = 0; + bc_vec_npop(&func->autos, func->autos.len); + bc_vec_npop(&func->code, func->code.len); + bc_vec_npop(&func->labels, func->labels.len); + } + else { + bc_func_init(&f); + bc_vec_push(&p->fns, &f); + } +} + +static BcStatus bc_program_reset(BcProgram *p, BcStatus s) +{ + BcFunc *f; + BcInstPtr *ip; + + bc_vec_npop(&p->stack, p->stack.len - 1); + bc_vec_npop(&p->results, p->results.len); + + f = bc_vec_item(&p->fns, 0); + ip = bc_vec_top(&p->stack); + ip->idx = f->code.len; + + if (!s && bcg.signe && !bcg.tty) return BC_STATUS_QUIT; + + bcg.sigc += bcg.signe; + bcg.signe = bcg.sig != bcg.sigc; + + if (!s || s == BC_STATUS_EXEC_SIGNAL) { + if (bcg.ttyin) { + bc_vm_puts(bc_program_ready_msg, stderr); + bc_vm_fflush(stderr); + s = BC_STATUS_SUCCESS; + } + else + s = BC_STATUS_QUIT; + } + + return s; +} + +static BcStatus bc_program_exec(BcProgram *p) +{ + BcStatus s = BC_STATUS_SUCCESS; + size_t idx; + BcResult r, *ptr; + BcNum *num; + BcInstPtr *ip = bc_vec_top(&p->stack); + BcFunc *func = bc_vec_item(&p->fns, ip->func); + char *code = func->code.v; + bool cond = false; + + while (!s && ip->idx < func->code.len) { + + char inst = code[(ip->idx)++]; + + switch (inst) { + +#ifdef ENABLE_BC + case BC_INST_JUMP_ZERO: + { + s = bc_program_prep(p, &ptr, &num); + if (s) return s; + cond = !bc_num_cmp(num, &p->zero); + bc_vec_pop(&p->results); + } + // Fallthrough. + case BC_INST_JUMP: + { + size_t *addr; + idx = bc_program_index(code, &ip->idx); + addr = bc_vec_item(&func->labels, idx); + if (inst == BC_INST_JUMP || cond) ip->idx = *addr; + break; + } + + case BC_INST_CALL: + { + s = bc_program_call(p, code, &ip->idx); + break; + } + + case BC_INST_INC_PRE: + case BC_INST_DEC_PRE: + case BC_INST_INC_POST: + case BC_INST_DEC_POST: + { + s = bc_program_incdec(p, inst); + break; + } + + case BC_INST_HALT: + { + s = BC_STATUS_QUIT; + break; + } + + case BC_INST_RET: + case BC_INST_RET0: + { + s = bc_program_return(p, inst); + break; + } + + case BC_INST_BOOL_OR: + case BC_INST_BOOL_AND: +#endif // ENABLE_BC + case BC_INST_REL_EQ: + case BC_INST_REL_LE: + case BC_INST_REL_GE: + case BC_INST_REL_NE: + case BC_INST_REL_LT: + case BC_INST_REL_GT: + { + s = bc_program_logical(p, inst); + break; + } + + case BC_INST_READ: + { + s = bc_program_read(p); + break; + } + + case BC_INST_VAR: + { + s = bc_program_pushVar(p, code, &ip->idx, false, false); + break; + } + + case BC_INST_ARRAY_ELEM: + case BC_INST_ARRAY: + { + s = bc_program_pushArray(p, code, &ip->idx, inst); + break; + } + + case BC_INST_LAST: + { + r.t = BC_RESULT_LAST; + bc_vec_push(&p->results, &r); + break; + } + + case BC_INST_IBASE: + case BC_INST_SCALE: + case BC_INST_OBASE: + { + s = bc_program_pushGlobal(p, inst); + break; + } + + case BC_INST_SCALE_FUNC: + case BC_INST_LENGTH: + case BC_INST_SQRT: + { + s = bc_program_builtin(p, inst); + break; + } + + case BC_INST_NUM: + { + r.t = BC_RESULT_CONSTANT; + r.d.id.idx = bc_program_index(code, &ip->idx); + bc_vec_push(&p->results, &r); + break; + } + + case BC_INST_POP: + { + if (!BC_PROG_STACK(&p->results, 1)) + s = BC_STATUS_EXEC_STACK; + else + bc_vec_pop(&p->results); + break; + } + + case BC_INST_POP_EXEC: + { + bc_vec_pop(&p->stack); + break; + } + + case BC_INST_PRINT: + case BC_INST_PRINT_POP: + case BC_INST_PRINT_STR: + { + s = bc_program_print(p, inst, 0); + break; + } + + case BC_INST_STR: + { + r.t = BC_RESULT_STR; + r.d.id.idx = bc_program_index(code, &ip->idx); + bc_vec_push(&p->results, &r); + break; + } + + case BC_INST_POWER: + case BC_INST_MULTIPLY: + case BC_INST_DIVIDE: + case BC_INST_MODULUS: + case BC_INST_PLUS: + case BC_INST_MINUS: + { + s = bc_program_op(p, inst); + break; + } + + case BC_INST_BOOL_NOT: + { + s = bc_program_prep(p, &ptr, &num); + if (s) return s; + + bc_num_init(&r.d.n, BC_NUM_DEF_SIZE); + (!bc_num_cmp(num, &p->zero) ? bc_num_one : bc_num_zero)(&r.d.n); + bc_program_retire(p, &r, BC_RESULT_TEMP); + + break; + } + + case BC_INST_NEG: + { + s = bc_program_negate(p); + break; + } + +#ifdef ENABLE_BC + case BC_INST_ASSIGN_POWER: + case BC_INST_ASSIGN_MULTIPLY: + case BC_INST_ASSIGN_DIVIDE: + case BC_INST_ASSIGN_MODULUS: + case BC_INST_ASSIGN_PLUS: + case BC_INST_ASSIGN_MINUS: +#endif // ENABLE_BC + case BC_INST_ASSIGN: + { + s = bc_program_assign(p, inst); + break; + } +#ifdef ENABLE_DC + case BC_INST_MODEXP: + { + s = bc_program_modexp(p); + break; + } + + case BC_INST_DIVMOD: + { + s = bc_program_divmod(p); + break; + } + + case BC_INST_EXECUTE: + case BC_INST_EXEC_COND: + { + cond = inst == BC_INST_EXEC_COND; + s = bc_program_execStr(p, code, &ip->idx, cond); + break; + } + + case BC_INST_PRINT_STACK: + { + for (idx = 0; !s && idx < p->results.len; ++idx) + s = bc_program_print(p, BC_INST_PRINT, idx); + break; + } + + case BC_INST_CLEAR_STACK: + { + bc_vec_npop(&p->results, p->results.len); + break; + } + + case BC_INST_STACK_LEN: + { + s = bc_program_stackLen(p); + break; + } + + case BC_INST_DUPLICATE: + { + if (!BC_PROG_STACK(&p->results, 1)) return BC_STATUS_EXEC_STACK; + ptr = bc_vec_top(&p->results); + bc_result_copy(&r, ptr); + bc_vec_push(&p->results, &r); + break; + } + + case BC_INST_SWAP: + { + BcResult *ptr2; + + if (!BC_PROG_STACK(&p->results, 2)) return BC_STATUS_EXEC_STACK; + + ptr = bc_vec_item_rev(&p->results, 0); + ptr2 = bc_vec_item_rev(&p->results, 1); + memcpy(&r, ptr, sizeof(BcResult)); + memcpy(ptr, ptr2, sizeof(BcResult)); + memcpy(ptr2, &r, sizeof(BcResult)); + + break; + } + + case BC_INST_ASCIIFY: + { + s = bc_program_asciify(p); + break; + } + + case BC_INST_PRINT_STREAM: + { + s = bc_program_printStream(p); + break; + } + + case BC_INST_LOAD: + case BC_INST_PUSH_VAR: + { + bool copy = inst == BC_INST_LOAD; + s = bc_program_pushVar(p, code, &ip->idx, true, copy); + break; + } + + case BC_INST_PUSH_TO_VAR: + { + char *name = bc_program_name(code, &ip->idx); + s = bc_program_copyToVar(p, name, true); + free(name); + break; + } + + case BC_INST_QUIT: + { + if (p->stack.len <= 2) + s = BC_STATUS_QUIT; + else + bc_vec_npop(&p->stack, 2); + break; + } + + case BC_INST_NQUIT: + { + s = bc_program_nquit(p); + break; + } +#endif // ENABLE_DC + } + + if ((s && s != BC_STATUS_QUIT) || bcg.signe) s = bc_program_reset(p, s); + + // If the stack has changed, pointers may be invalid. + ip = bc_vec_top(&p->stack); + func = bc_vec_item(&p->fns, ip->func); + code = func->code.v; + } + + return s; +} + +#if ENABLE_FEATURE_BC_SIGNALS +static void bc_vm_sig(int sig) +{ + int err = errno; + size_t len = strlen(bcg.sig_msg); + if (sig == SIGINT && write(2, bcg.sig_msg, len) == (ssize_t) len) { + bcg.signe = bcg.sig == bcg.sigc; + bcg.sig += bcg.signe; + } + errno = err; +} +#endif // ENABLE_FEATURE_BC_SIGNALS + +static void bc_vm_info(const char *const help) +{ + bc_vm_printf(stdout, "%s %s\n", bcg.name, "1.1"); + bc_vm_puts(bc_copyright, stdout); + if (help) bc_vm_printf(stdout, help, bcg.name); +} + +static BcStatus bc_vm_error(BcStatus s, const char *file, size_t line) +{ + if (!s || s > BC_STATUS_VEC_ITEM_EXISTS) return s; + + bc_vm_printf(stderr, bc_err_fmt, bc_errs[bc_err_ids[s]], bc_err_msgs[s]); + bc_vm_printf(stderr, " %s", file); + bc_vm_printf(stderr, bc_err_line + 4 * !line, line); + + return s * (!bcg.ttyin || !!strcmp(file, bc_program_stdin_name)); +} + +#ifdef ENABLE_BC +static BcStatus bc_vm_posixError(BcStatus s, const char *file, size_t line, + const char *msg) +{ + int p = (int) bcg.posix, w = (int) bcg.warn; + const char *const fmt = p ? bc_err_fmt : bc_warn_fmt; + + if (!(p || w) || s < BC_STATUS_POSIX_NAME_LEN) return BC_STATUS_SUCCESS; + + bc_vm_printf(stderr, fmt, bc_errs[bc_err_ids[s]], bc_err_msgs[s]); + if (msg) bc_vm_printf(stderr, " %s\n", msg); + bc_vm_printf(stderr, " %s", file); + bc_vm_printf(stderr, bc_err_line + 4 * !line, line); + + return s * (!bcg.ttyin && !!p); +} + +static BcStatus bc_vm_envArgs(BcVm *vm) +{ + BcStatus s = BC_STATUS_SUCCESS; + BcVec v; + char *env_args = getenv(bc_args_env_name), *buf; + + if (!env_args) return s; + + vm->env_args = xstrdup(env_args); + buf = vm->env_args; + + bc_vec_init(&v, sizeof(char *), NULL); + bc_vec_push(&v, &bc_args_env_name); + + while (*buf != 0) { + if (!isspace(*buf)) { + bc_vec_push(&v, &buf); + while (*buf != 0 && !isspace(*buf)) ++buf; + if (*buf != 0) (*(buf++)) = '\0'; + } + else + ++buf; + } + + s = bc_args((int) v.len, (char **) v.v, &vm->flags, &vm->files); + + bc_vec_free(&v); + + return s; +} +#endif // ENABLE_BC + +static size_t bc_vm_envLen(const char *var) +{ + char *lenv = getenv(var); + size_t i, len = BC_NUM_PRINT_WIDTH; + int num; + + if (!lenv) return len; + + len = strlen(lenv); + + for (num = 1, i = 0; num && i < len; ++i) num = isdigit(lenv[i]); + if (num) { + len = (size_t) atoi(lenv) - 1; + if (len < 2 || len >= INT32_MAX) len = BC_NUM_PRINT_WIDTH; + } + else + len = BC_NUM_PRINT_WIDTH; + + return len; +} + +static void bc_vm_exit(BcStatus s) +{ + bc_vm_printf(stderr, bc_err_fmt, bc_errs[bc_err_ids[s]], bc_err_msgs[s]); + exit((int) s); +} + +static void bc_vm_printf(FILE *restrict f, const char *fmt, ...) +{ + va_list args; + bool bad; + + va_start(args, fmt); + bad = vfprintf(f, fmt, args) < 0; + va_end(args); + + if (bad) bc_vm_exit(BC_STATUS_IO_ERR); +} + +static void bc_vm_puts(const char *str, FILE *restrict f) +{ + if (fputs(str, f) == EOF) bc_vm_exit(BC_STATUS_IO_ERR); +} + +static void bc_vm_putchar(int c) +{ + if (putchar(c) == EOF) bc_vm_exit(BC_STATUS_IO_ERR); +} + +static void bc_vm_fflush(FILE *restrict f) +{ + if (fflush(f) == EOF) bc_vm_exit(BC_STATUS_IO_ERR); +} + +static BcStatus bc_vm_process(BcVm *vm, const char *text) +{ + BcStatus s = bc_parse_text(&vm->prs, text); + + s = bc_vm_error(s, vm->prs.l.f, vm->prs.l.line); + if (s) return s; + + while (vm->prs.l.t.t != BC_LEX_EOF) { + + s = vm->prs.parse(&vm->prs); + + if (s == BC_STATUS_LIMITS) { + + bc_vm_putchar('\n'); + bc_vm_printf(stdout, "BC_BASE_MAX = %lu\n", BC_MAX_OBASE); + bc_vm_printf(stdout, "BC_DIM_MAX = %lu\n", BC_MAX_DIM); + bc_vm_printf(stdout, "BC_SCALE_MAX = %lu\n", BC_MAX_SCALE); + bc_vm_printf(stdout, "BC_STRING_MAX = %lu\n", BC_MAX_STRING); + bc_vm_printf(stdout, "BC_NAME_MAX = %lu\n", BC_MAX_NAME); + bc_vm_printf(stdout, "BC_NUM_MAX = %lu\n", BC_MAX_NUM); + bc_vm_printf(stdout, "Max Exponent = %lu\n", BC_MAX_EXP); + bc_vm_printf(stdout, "Number of Vars = %lu\n", BC_MAX_VARS); + bc_vm_putchar('\n'); + + s = BC_STATUS_SUCCESS; + } + else { + if (s == BC_STATUS_QUIT) return s; + s = bc_vm_error(s, vm->prs.l.f, vm->prs.l.line); + if (s) return s; + } + } + + if (BC_PARSE_CAN_EXEC(&vm->prs)) { + s = bc_program_exec(&vm->prog); + if (!s && bcg.tty) bc_vm_fflush(stdout); + if (s && s != BC_STATUS_QUIT) + s = bc_vm_error(bc_program_reset(&vm->prog, s), vm->prs.l.f, 0); + } + + return s; +} + +static BcStatus bc_vm_file(BcVm *vm, const char *file) +{ + BcStatus s; + char *data; + BcFunc *main_func; + BcInstPtr *ip; + + vm->prog.file = file; + s = bc_read_file(file, &data); + if (s) return bc_vm_error(s, file, 0); + + bc_lex_file(&vm->prs.l, file); + s = bc_vm_process(vm, data); + if (s) goto err; + + main_func = bc_vec_item(&vm->prog.fns, BC_PROG_MAIN); + ip = bc_vec_item(&vm->prog.stack, 0); + + if (main_func->code.len < ip->idx) s = BC_STATUS_EXEC_FILE_NOT_EXECUTABLE; + +err: + free(data); + return s; +} + +static BcStatus bc_vm_stdin(BcVm *vm) +{ + BcStatus s = BC_STATUS_SUCCESS; + BcVec buf, buffer; + char c; + size_t len, i, str = 0; + bool comment = false, notend; + + vm->prog.file = bc_program_stdin_name; + bc_lex_file(&vm->prs.l, bc_program_stdin_name); + + bc_vec_init(&buffer, sizeof(char), NULL); + bc_vec_init(&buf, sizeof(char), NULL); + bc_vec_pushByte(&buffer, '\0'); + + // This loop is complex because the vm tries not to send any lines that end + // with a backslash to the parser. The reason for that is because the parser + // treats a backslash+newline combo as whitespace, per the bc spec. In that + // case, and for strings and comments, the parser will expect more stuff. + for (s = bc_read_line(&buf, ">>> "); !s; s = bc_read_line(&buf, ">>> ")) { + + char *string = buf.v; + + len = buf.len - 1; + + if (len == 1) { + if (str && buf.v[0] == vm->exe.send) + str -= 1; + else if (buf.v[0] == vm->exe.sbgn) + str += 1; + } + else if (len > 1 || comment) { + + for (i = 0; i < len; ++i) { + + notend = len > i + 1; + c = string[i]; + + if (i - 1 > len || string[i - 1] != '\\') { + if (vm->exe.sbgn == vm->exe.send) + str ^= c == vm->exe.sbgn; + else if (c == vm->exe.send) + str -= 1; + else if (c == vm->exe.sbgn) + str += 1; + } + + if (c == '/' && notend && !comment && string[i + 1] == '*') { + comment = true; + break; + } + else if (c == '*' && notend && comment && string[i + 1] == '/') + comment = false; + } + + if (str || comment || string[len - 2] == '\\') { + bc_vec_concat(&buffer, buf.v); + continue; + } + } + + bc_vec_concat(&buffer, buf.v); + s = bc_vm_process(vm, buffer.v); + if (s) goto err; + + bc_vec_npop(&buffer, buffer.len); + } + + if (s == BC_STATUS_BIN_FILE) s = bc_vm_error(s, vm->prs.l.f, 0); + + // I/O error will always happen when stdin is + // closed. It's not a problem in that case. + s = s == BC_STATUS_IO_ERR || s == BC_STATUS_QUIT ? BC_STATUS_SUCCESS : s; + + if (str) + s = bc_vm_error(BC_STATUS_LEX_NO_STRING_END, vm->prs.l.f, + vm->prs.l.line); + else if (comment) + s = bc_vm_error(BC_STATUS_LEX_NO_COMMENT_END, vm->prs.l.f, + vm->prs.l.line); + +err: + bc_vec_free(&buf); + bc_vec_free(&buffer); + return s; +} + +static BcStatus bc_vm_exec(BcVm *vm) +{ + BcStatus s = BC_STATUS_SUCCESS; + size_t i; + +#ifdef ENABLE_BC + if (vm->flags & BC_FLAG_L) { + + bc_lex_file(&vm->prs.l, bc_lib_name); + s = bc_parse_text(&vm->prs, bc_lib); + + while (!s && vm->prs.l.t.t != BC_LEX_EOF) s = vm->prs.parse(&vm->prs); + + if (s) return s; + s = bc_program_exec(&vm->prog); + if (s) return s; + } +#endif // ENABLE_BC + + for (i = 0; !s && i < vm->files.len; ++i) + s = bc_vm_file(vm, *((char **) bc_vec_item(&vm->files, i))); + if (s && s != BC_STATUS_QUIT) return s; + + if (bcg.bc || !vm->files.len) s = bc_vm_stdin(vm); + if (!s && !BC_PARSE_CAN_EXEC(&vm->prs)) s = bc_vm_process(vm, ""); + + return s == BC_STATUS_QUIT ? BC_STATUS_SUCCESS : s; +} + +static void bc_vm_free(BcVm *vm) +{ + bc_vec_free(&vm->files); + bc_program_free(&vm->prog); + bc_parse_free(&vm->prs); + free(vm->env_args); +} + +static BcStatus bc_vm_init(BcVm *vm, BcVmExe exe, const char *env_len) +{ + BcStatus s = BC_STATUS_SUCCESS; + size_t len = bc_vm_envLen(env_len); +#if ENABLE_FEATURE_BC_SIGNALS + struct sigaction sa; + + sigemptyset(&sa.sa_mask); + sa.sa_handler = bc_vm_sig; + sa.sa_flags = 0; + sigaction(SIGINT, &sa, NULL); +#endif // ENABLE_FEATURE_BC_SIGNALS + + memset(vm, 0, sizeof(BcVm)); + + vm->exe = exe; + vm->flags = 0; + vm->env_args = NULL; + + bc_vec_init(&vm->files, sizeof(char *), NULL); + +#ifdef ENABLE_BC + vm->flags |= BC_FLAG_S * bcg.bc * (getenv("POSIXLY_CORRECT") != NULL); + if (bcg.bc) s = bc_vm_envArgs(vm); +#endif // ENABLE_BC + + bc_program_init(&vm->prog, len, exe.init, exe.exp); + exe.init(&vm->prs, &vm->prog, BC_PROG_MAIN); + + return s; +} + +static BcStatus bc_vm_run(int argc, char *argv[], BcVmExe exe, + const char *env_len) +{ + BcStatus st; + BcVm vm; + + st = bc_vm_init(&vm, exe, env_len); + if (st) goto exit; + st = bc_args(argc, argv, &vm.flags, &vm.files); + if (st) goto exit; + + bcg.ttyin = isatty(0); + bcg.tty = bcg.ttyin || (vm.flags & BC_FLAG_I) || isatty(1); + +#ifdef ENABLE_BC + bcg.posix = vm.flags & BC_FLAG_S; + bcg.warn = vm.flags & BC_FLAG_W; +#endif // ENABLE_BC +#ifdef ENABLE_DC + bcg.exreg = vm.flags & BC_FLAG_X; +#endif // ENABLE_DC + + if (bcg.ttyin && !(vm.flags & BC_FLAG_Q)) bc_vm_info(NULL); + st = bc_vm_exec(&vm); + +exit: + bc_vm_free(&vm); + return st; +} + +#ifdef ENABLE_BC +BcStatus bc_main(int argc, char *argv[]) +{ + BcVmExe exec; + + bcg.bc = true; + bcg.name = bc_name; +#if ENABLE_FEATURE_BC_SIGNALS + bcg.sig_msg = bc_sig_msg; +#endif // ENABLE_FEATURE_BC_SIGNALS + + exec.init = bc_parse_init; + exec.exp = bc_parse_expression; + exec.sbgn = exec.send = '"'; + + return bc_vm_run(argc, argv, exec, "BC_LINE_LENGTH"); +} +#endif // ENABLE_BC + +#ifdef ENABLE_DC +BcStatus dc_main(int argc, char *argv[]) +{ + BcVmExe exec; + + bcg.bc = false; + bcg.name = dc_name; +#if ENABLE_FEATURE_BC_SIGNALS + bcg.sig_msg = dc_sig_msg; +#endif // ENABLE_FEATURE_BC_SIGNALS + + exec.init = dc_parse_init; + exec.exp = dc_parse_expr; + exec.sbgn = '['; + exec.send = ']'; + + return bc_vm_run(argc, argv, exec, "DC_LINE_LENGTH"); +} +#endif // ENABLE_DC diff --git a/miscutils/dc.c b/miscutils/dc.c index b922a7184..d58f97e91 100644 --- a/miscutils/dc.c +++ b/miscutils/dc.c @@ -1,48 +1,49 @@ +#if 0 //TODO: use if bc is not selected /* vi: set sw=4 ts=4: */ /* * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ -//config:config DC -//config: bool "dc (4.2 kb)" -//config: default y -//config: help -//config: Dc is a reverse-polish desk calculator which supports unlimited -//config: precision arithmetic. -//config: -//config:config FEATURE_DC_LIBM -//config: bool "Enable power and exp functions (requires libm)" -//config: default y -//config: depends on DC -//config: help -//config: Enable power and exp functions. -//config: NOTE: This will require libm to be present for linking. - -//applet:IF_DC(APPLET(dc, BB_DIR_USR_BIN, BB_SUID_DROP)) - -//kbuild:lib-$(CONFIG_DC) += dc.o - -//usage:#define dc_trivial_usage -//usage: "EXPRESSION..." -//usage: -//usage:#define dc_full_usage "\n\n" -//usage: "Tiny RPN calculator. Operations:\n" -//usage: "+, add, -, sub, *, mul, /, div, %, mod, "IF_FEATURE_DC_LIBM("**, exp, ")"and, or, not, xor,\n" -//usage: "p - print top of the stack (without popping),\n" -//usage: "f - print entire stack,\n" -//usage: "o - pop the value and set output radix (must be 10, 16, 8 or 2).\n" -//usage: "Examples: 'dc 2 2 add p' -> 4, 'dc 8 8 mul 2 2 + / p' -> 16" -//usage: -//usage:#define dc_example_usage -//usage: "$ dc 2 2 + p\n" -//usage: "4\n" -//usage: "$ dc 8 8 \\* 2 2 + / p\n" -//usage: "16\n" -//usage: "$ dc 0 1 and p\n" -//usage: "0\n" -//usage: "$ dc 0 1 or p\n" -//usage: "1\n" -//usage: "$ echo 72 9 div 8 mul p | dc\n" -//usage: "64\n" + //config:config DC + //config: bool "dc (4.2 kb)" + //config: default y + //config: help + //config: Dc is a reverse-polish desk calculator which supports unlimited + //config: precision arithmetic. + //config: + //config:config FEATURE_DC_LIBM + //config: bool "Enable power and exp functions (requires libm)" + //config: default y + //config: depends on DC + //config: help + //config: Enable power and exp functions. + //config: NOTE: This will require libm to be present for linking. + + //applet:IF_DC(APPLET(dc, BB_DIR_USR_BIN, BB_SUID_DROP)) + + //kbuild:lib-$(CONFIG_DC) += dc.o + + //usage:#define dc_trivial_usage + //usage: "EXPRESSION..." + //usage: + //usage:#define dc_full_usage "\n\n" + //usage: "Tiny RPN calculator. Operations:\n" + //usage: "+, add, -, sub, *, mul, /, div, %, mod, "IF_FEATURE_DC_LIBM("**, exp, ")"and, or, not, xor,\n" + //usage: "p - print top of the stack (without popping),\n" + //usage: "f - print entire stack,\n" + //usage: "o - pop the value and set output radix (must be 10, 16, 8 or 2).\n" + //usage: "Examples: 'dc 2 2 add p' -> 4, 'dc 8 8 mul 2 2 + / p' -> 16" + //usage: + //usage:#define dc_example_usage + //usage: "$ dc 2 2 + p\n" + //usage: "4\n" + //usage: "$ dc 8 8 \\* 2 2 + / p\n" + //usage: "16\n" + //usage: "$ dc 0 1 and p\n" + //usage: "0\n" + //usage: "$ dc 0 1 or p\n" + //usage: "1\n" + //usage: "$ echo 72 9 div 8 mul p | dc\n" + //usage: "64\n" #include "libbb.h" #include "common_bufsiz.h" @@ -302,3 +303,4 @@ int dc_main(int argc UNUSED_PARAM, char **argv) } return EXIT_SUCCESS; } +#endif -- cgit v1.2.3-55-g6feb From ef869ec7283180e3733948ae31d1016ad9da4c0d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 2 Dec 2018 18:49:16 +0100 Subject: bc: fix warnings, initial cleanups function old new delta bc_program_exec - 4401 +4401 bc_vm_run - 2601 +2601 bc_parse_expr - 2215 +2215 bc_parse_stmt - 2197 +2197 bc_lib - 1878 +1878 bc_lex_token - 1333 +1333 bc_program_num - 1134 +1134 bc_num_k - 1010 +1010 bc_program_modexp - 793 +793 bc_program_print - 762 +762 dc_parse_expr - 723 +723 dc_lex_token - 670 +670 bc_num_d - 614 +614 bc_parse_name - 590 +590 bc_program_execStr - 579 +579 bc_num_printNum - 572 +572 bc_num_p - 518 +518 bc_num_a - 480 +480 bc_parse_parse - 471 +471 bc_program_assign - 450 +450 bc_parse_endBody - 423 +423 bc_program_call - 371 +371 dc_lex_tokens - 364 +364 bc_vm_process - 361 +361 bc_program_copyToVar - 355 +355 dc_parse_insts - 332 +332 bc_program_read - 323 +323 bc_program_binOpPrep - 301 +301 bc_lex_number - 301 +301 bc_read_line - 297 +297 bc_num_cmp - 294 +294 bc_num_m - 287 +287 bc_parse_auto - 275 +275 bc_num_s - 258 +258 bc_program_pushVar - 236 +236 bc_num_r - 231 +231 bc_program_addFunc - 220 +220 bc_lex_kws - 220 +220 bc_err_msgs - 216 +216 bc_parse_create - 198 +198 bc_vm_posixError - 194 +194 bc_parse_reset - 194 +194 bc_parse_operator - 181 +181 bc_program_reset - 178 +178 bc_program_printStream - 176 +176 bc_num_divmod - 168 +168 bc_copyright - 155 +155 bc_program_search - 154 +154 bc_num_binary - 150 +150 bc_vm_error - 148 +148 bc_program_pushArray - 143 +143 bc_parse_text - 142 +142 bc_num_printDigits - 142 +142 bc_map_insert - 142 +142 bc_parse_else - 139 +139 bc_program_assignStr - 131 +131 bc_args - 125 +125 dc_parse_mem - 116 +116 bc_parse_body - 116 +116 bc_num_split - 113 +113 bc_num_sub - 112 +112 bc_num_add - 112 +112 packed_usage 32958 33066 +108 bc_num_rem - 104 +104 bc_parse_string - 103 +103 bc_main - 97 +97 bc_num_ulong - 95 +95 bc_func_insert - 89 +89 bc_vm_sig - 88 +88 bc_program_prep - 88 +88 bc_parse_number - 88 +88 bc_array_expand - 88 +88 bc_num_subArrays - 84 +84 bc_num_compare - 84 +84 bc_lex_name - 83 +83 bc_args_lopt - 81 +81 bc_parse_pushIndex - 80 +80 bc_num_mul - 80 +80 bc_num_mod - 80 +80 bc_num_div - 80 +80 bc_vm_info - 76 +76 bc_program_name - 75 +75 bc_map_find - 71 +71 bc_lex_next - 71 +71 bc_num_printHex - 70 +70 bc_vec_concat - 68 +68 bc_num_shift - 68 +68 bc_num_extend - 68 +68 bc_program_index - 66 +66 bc_num_ulong2num - 66 +66 bc_num_retireMul - 66 +66 bc_parse_noElse - 65 +65 bc_vec_string - 64 +64 bc_parse_pushName - 63 +63 bc_parse_exprs - 60 +60 bc_err_ids - 58 +58 bc_result_free - 57 +57 bc_vec_npop - 55 +55 dc_parse_parse - 53 +53 bc_vec_push - 53 +53 bc_parse_free - 53 +53 bc_num_inv - 53 +53 dc_parse_register - 52 +52 dc_lex_regs - 52 +52 bc_lex_whitespace - 52 +52 bc_num_copy - 51 +51 bc_program_binOpRetire - 50 +50 bc_parse_ops - 50 +50 bc_map_index - 50 +50 bcg - 48 +48 bc_num_init - 48 +48 bc_parse_startBody - 47 +47 bc_num_pow - 47 +47 bc_vm_putchar - 46 +46 bc_vm_exit - 46 +46 bc_num_clean - 45 +45 bc_parse_addFunc - 44 +44 bc_vec_grow - 42 +42 bc_program_len - 42 +42 bc_num_truncate - 42 +42 bc_array_init - 42 +42 bc_parse_expression - 39 +39 bc_lex_lineComment - 39 +39 bc_num_expand - 38 +38 bc_vec_init - 37 +37 bc_vm_printf - 36 +36 bc_num_printNewline - 36 +36 bc_func_free - 35 +35 bc_sig_msg - 34 +34 bc_program_retire - 34 +34 bc_lex_assign - 34 +34 dc_parse_init - 33 +33 bc_parse_init - 33 +33 dc_sig_msg - 31 +31 bc_vec_expand - 30 +30 bc_num_ten - 30 +30 bc_num_one - 28 +28 bc_errs - 28 +28 bc_vec_free - 27 +27 bc_program_ops - 24 +24 bc_vm_puts - 23 +23 bc_num_printChar - 23 +23 bc_program_ready_msg - 22 +22 bc_vm_fflush - 21 +21 dc_main 77 97 +20 bc_parse_next_rel - 20 +20 bc_parse_next_read - 20 +20 bc_parse_next_print - 20 +20 bc_parse_next_param - 20 +20 bc_parse_next_for - 20 +20 bc_parse_next_expr - 20 +20 bc_parse_next_elem - 20 +20 bc_warn_fmt - 17 +17 bc_vec_pushByte - 15 +15 bc_string_free - 15 +15 bc_num_setToZero - 15 +15 bc_num_free - 15 +15 bc_lex_file - 15 +15 bc_id_free - 15 +15 bc_err_fmt - 15 +15 bc_vec_item_rev - 14 +14 bc_id_cmp - 12 +12 bc_num_zero - 11 +11 bc_vec_item - 9 +9 bc_program_stdin_name - 8 +8 bc_program_scale - 8 +8 bc_args_opt - 8 +8 bc_func_read - 7 +7 bc_func_main - 7 +7 bc_err_line - 7 +7 bc_lib_name - 4 +4 bc_args_env_name - 4 +4 applet_main 1604 1608 +4 dc_name - 3 +3 bc_name - 3 +3 applet_names 2781 2784 +3 static.bases 5 - -5 check_under 20 - -20 pop 24 - -24 print_no_pop 32 - -32 sub 34 - -34 divide 34 - -34 mul 37 - -37 add 37 - -37 push 38 - -38 print_stack_no_pop 40 - -40 not 72 - -72 set_output_base 95 - -95 or 103 - -103 eor 103 - -103 and 103 - -103 mod 105 - -105 stack_machine 116 - -116 operators 144 - -144 print_base 230 - -230 ------------------------------------------------------------------------------ (add/remove: 173/20 grow/shrink: 4/0 up/down: 38089/-1372) Total: 36717 bytes text data bss dec hex filename 950181 485 7296 957962 e9e0a busybox_old 989722 485 7344 997551 f38af busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 253 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 124 insertions(+), 129 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index bf0cbc397..4cbef4da6 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -173,9 +173,9 @@ typedef enum BcStatus { BC_STATUS_LEX_NO_STRING_END, BC_STATUS_LEX_NO_COMMENT_END, BC_STATUS_LEX_EOF, -#ifdef ENABLE_DC +#if ENABLE_DC BC_STATUS_LEX_EXTENDED_REG, -#endif // ENABLE_DC +#endif BC_STATUS_PARSE_BAD_TOKEN, BC_STATUS_PARSE_BAD_EXP, @@ -213,7 +213,7 @@ typedef enum BcStatus { BC_STATUS_VEC_OUT_OF_BOUNDS, BC_STATUS_VEC_ITEM_EXISTS, -#ifdef ENABLE_BC +#if ENABLE_BC BC_STATUS_POSIX_NAME_LEN, BC_STATUS_POSIX_COMMENT, BC_STATUS_POSIX_BAD_KW, @@ -226,7 +226,7 @@ typedef enum BcStatus { BC_STATUS_POSIX_FOR2, BC_STATUS_POSIX_FOR3, BC_STATUS_POSIX_BRACE, -#endif // ENABLE_BC +#endif BC_STATUS_QUIT, BC_STATUS_LIMITS, @@ -241,9 +241,9 @@ typedef enum BcStatus { #define BC_ERR_IDX_MATH (3) #define BC_ERR_IDX_EXEC (4) #define BC_ERR_IDX_VEC (5) -#ifdef ENABLE_BC +#if ENABLE_BC #define BC_ERR_IDX_POSIX (6) -#endif // ENABLE_BC +#endif #define BC_VEC_INVALID_IDX ((size_t) -1) #define BC_VEC_START_CAP (1 << 5) @@ -314,12 +314,12 @@ static BcStatus bc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d, typedef enum BcInst { -#ifdef ENABLE_BC +#if ENABLE_BC BC_INST_INC_PRE, BC_INST_DEC_PRE, BC_INST_INC_POST, BC_INST_DEC_POST, -#endif // ENABLE_BC +#endif BC_INST_NEG, @@ -341,14 +341,14 @@ typedef enum BcInst { BC_INST_BOOL_OR, BC_INST_BOOL_AND, -#ifdef ENABLE_BC +#if ENABLE_BC BC_INST_ASSIGN_POWER, BC_INST_ASSIGN_MULTIPLY, BC_INST_ASSIGN_DIVIDE, BC_INST_ASSIGN_MODULUS, BC_INST_ASSIGN_PLUS, BC_INST_ASSIGN_MINUS, -#endif // ENABLE_BC +#endif BC_INST_ASSIGN, BC_INST_NUM, @@ -370,7 +370,7 @@ typedef enum BcInst { BC_INST_STR, BC_INST_PRINT_STR, -#ifdef ENABLE_BC +#if ENABLE_BC BC_INST_JUMP, BC_INST_JUMP_ZERO, @@ -380,12 +380,12 @@ typedef enum BcInst { BC_INST_RET0, BC_INST_HALT, -#endif // ENABLE_BC +#endif BC_INST_POP, BC_INST_POP_EXEC, -#ifdef ENABLE_DC +#if ENABLE_DC BC_INST_MODEXP, BC_INST_DIVMOD, @@ -409,7 +409,7 @@ typedef enum BcInst { BC_INST_NQUIT, BC_INST_INVALID = -1, -#endif // ENABLE_DC +#endif } BcInst; @@ -543,7 +543,7 @@ typedef enum BcLexType { BC_LEX_KEY_SQRT, BC_LEX_KEY_WHILE, -#ifdef ENABLE_DC +#if ENABLE_DC BC_LEX_EQ_NO_REG, BC_LEX_OP_MODEXP, BC_LEX_OP_DIVMOD, @@ -570,7 +570,7 @@ typedef enum BcLexType { BC_LEX_PRINT_POP, BC_LEX_NQUIT, BC_LEX_SCALE_FACTOR, -#endif // ENABLE_DC +#endif } BcLexType; @@ -689,7 +689,7 @@ typedef struct BcParse { } BcParse; -#ifdef ENABLE_BC +#if ENABLE_BC BcStatus bc_main(int argc, char *argv[]); @@ -719,7 +719,7 @@ static BcStatus bc_lex_token(BcLex *l); static BcStatus bc_parse_parse(BcParse *p); static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next); -#endif // ENABLE_BC +#endif #ifdef ENABLE_DC @@ -746,9 +746,9 @@ typedef struct BcProgram { BcNum hexb; -#ifdef ENABLE_DC +#if ENABLE_DC BcNum strmb; -#endif // ENABLE_DC +#endif BcVec results; BcVec stack; @@ -783,9 +783,9 @@ typedef struct BcProgram { #define BC_PROG_MAIN (0) #define BC_PROG_READ (1) -#ifdef ENABLE_DC +#if ENABLE_DC #define BC_PROG_REQ_FUNCS (2) -#endif // ENABLE_DC +#endif #define BC_PROG_STR(n) (!(n)->num && !(n)->cap) #define BC_PROG_NUM(r, n) \ @@ -852,16 +852,16 @@ typedef struct BcGlobals { const char *name; #if ENABLE_FEATURE_BC_SIGNALS const char *sig_msg; -#endif // ENABLE_FEATURE_BC_SIGNALS +#endif const char *help; bool bc; } BcGlobals; -#ifdef ENABLE_BC +#if ENABLE_BC static BcStatus bc_vm_posixError(BcStatus s, const char *file, size_t line, const char *msg); -#endif // ENABLE_BC +#endif static void bc_vm_exit(BcStatus s); static void bc_vm_printf(FILE *restrict f, const char *fmt, ...); @@ -875,19 +875,19 @@ static BcStatus bc_vm_run(int argc, char *argv[], BcVmExe exe, static BcGlobals bcg; -#ifdef ENABLE_BC +#if ENABLE_BC static const char bc_name[] = "bc"; -#if ENABLE_FEATURE_BC_SIGNALS +# if ENABLE_FEATURE_BC_SIGNALS static const char bc_sig_msg[] = "\ninterrupt (type \"quit\" to exit)\n"; -#endif // ENABLE_FEATURE_BC_SIGNALS -#endif // ENABLE_BC +# endif +#endif -#ifdef ENABLE_DC +#if ENABLE_DC static const char dc_name[] = "dc"; -#if ENABLE_FEATURE_BC_SIGNALS +# if ENABLE_FEATURE_BC_SIGNALS static const char dc_sig_msg[] = "\ninterrupt (type \"q\" to exit)\n"; -#endif // ENABLE_FEATURE_BC_SIGNALS -#endif // ENABLE_DC +# endif +#endif static const char bc_copyright[] = "Copyright (c) 2018 Gavin D. Howard and contributors\n" @@ -907,35 +907,35 @@ static const char *bc_errs[] = { "Math", "Runtime", "Vector", -#ifdef ENABLE_BC +#if ENABLE_BC "POSIX", -#endif // ENABLE_BC +#endif }; static const uint8_t bc_err_ids[] = { BC_ERR_IDX_VM, BC_ERR_IDX_VM, BC_ERR_IDX_VM, BC_ERR_IDX_VM, BC_ERR_IDX_VM, BC_ERR_IDX_LEX, BC_ERR_IDX_LEX, BC_ERR_IDX_LEX, BC_ERR_IDX_LEX, -#ifdef ENABLE_DC +#if ENABLE_DC BC_ERR_IDX_LEX, -#endif // ENABLE_DC +#endif BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_MATH, BC_ERR_IDX_MATH, BC_ERR_IDX_MATH, BC_ERR_IDX_MATH, BC_ERR_IDX_MATH, -#ifdef ENABLE_DC +#if ENABLE_DC BC_ERR_IDX_MATH, -#endif // ENABLE_DC +#endif BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_VEC, BC_ERR_IDX_VEC, -#ifdef ENABLE_BC +#if ENABLE_BC BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX, -#endif // ENABLE_BC +#endif BC_ERR_IDX_VM, BC_ERR_IDX_VM, BC_ERR_IDX_VM, }; @@ -951,9 +951,9 @@ static const char *bc_err_msgs[] = { "string end could not be found", "comment end could not be found", "end of file", -#ifdef ENABLE_DC +#if ENABLE_DC "extended register", -#endif // ENABLE_DC +#endif "bad token", "bad expression", @@ -992,7 +992,7 @@ static const char *bc_err_msgs[] = { "index is out of bounds", "item already exists", -#ifdef ENABLE_BC +#if ENABLE_BC "POSIX only allows one character names; the following is bad:", "POSIX does not allow '#' script comments", "POSIX does not allow the following keyword:", @@ -1005,14 +1005,14 @@ static const char *bc_err_msgs[] = { "POSIX does not allow an empty condition expression in a for loop", "POSIX does not allow an empty update expression in a for loop", "POSIX requires the left brace be on the same line as the function header", -#endif // ENABLE_BC +#endif }; static const char bc_func_main[] = "(main)"; static const char bc_func_read[] = "(read)"; -#ifdef ENABLE_BC +#if ENABLE_BC static const BcLexKeyword bc_lex_kws[20] = { BC_LEX_KW_ENTRY("auto", 4, true), BC_LEX_KW_ENTRY("break", 5, true), @@ -1075,7 +1075,7 @@ static const BcParseNext bc_parse_next_read = BC_PARSE_NEXT(2, BC_LEX_NLINE, BC_LEX_EOF); #endif // ENABLE_BC -#ifdef ENABLE_DC +#if ENABLE_DC static const BcLexType dc_lex_regs[] = { BC_LEX_OP_REL_EQ, BC_LEX_OP_REL_LE, BC_LEX_OP_REL_GE, BC_LEX_OP_REL_NE, BC_LEX_OP_REL_LT, BC_LEX_OP_REL_GT, BC_LEX_SCOLON, BC_LEX_COLON, @@ -1140,8 +1140,6 @@ static const BcInst dc_parse_insts[] = { }; #endif // ENABLE_DC -static const char bc_num_hex_digits[] = "0123456789ABCDEF"; - static const BcNumBinaryOp bc_program_ops[] = { bc_num_pow, bc_num_mul, bc_num_div, bc_num_mod, bc_num_add, bc_num_sub, }; @@ -1149,7 +1147,7 @@ static const BcNumBinaryOp bc_program_ops[] = { static const char bc_program_stdin_name[] = ""; static const char bc_program_ready_msg[] = "ready for more input\n"; -#ifdef ENABLE_BC +#if ENABLE_BC static const char *bc_lib_name = "gen/lib.bc"; static const char bc_lib[] = { @@ -1417,7 +1415,7 @@ static BcStatus bc_read_line(BcVec *vec, const char *prompt) continue; } -#endif // ENABLE_FEATURE_BC_SIGNALS +#endif return BC_STATUS_IO_ERR; } @@ -1435,12 +1433,14 @@ static BcStatus bc_read_line(BcVec *vec, const char *prompt) static BcStatus bc_read_file(const char *path, char **buf) { BcStatus s = BC_STATUS_BIN_FILE; - size_t size = ((size_t) -1), read; + size_t size = ((size_t) -1); + size_t i; *buf = xmalloc_open_read_close(path, &size); - for (read = 0; read < size; ++read) { - if (BC_READ_BIN_CHAR((*buf)[read])) goto read_err; + for (i = 0; i < size; ++i) { + if (BC_READ_BIN_CHAR((*buf)[i])) + goto read_err; } return BC_STATUS_SUCCESS; @@ -1459,7 +1459,7 @@ static const char bc_args_lopt[] ALIGN1 = "quiet\0"No_argument"q" "mathlib\0"No_argument"l" "interactive\0"No_argument"i"; -#endif // ENABLE_FEATURE_BC_LONG_OPTIONS +#endif static const char bc_args_opt[] ALIGN1 = "xwvsqli"; @@ -1473,9 +1473,9 @@ static BcStatus bc_args(int argc, char *argv[], uint32_t *flags, BcVec *files) #if ENABLE_FEATURE_BC_LONG_OPTIONS *flags = getopt32long(argv, bc_args_opt, bc_args_lopt); -#else // ENABLE_FEATURE_BC_LONG_OPTIONS +#else *flags = getopt32(argv, bc_args_opt); -#endif // ENABLE_FEATURE_BC_LONG_OPTIONS +#endif if ((*flags) & BC_FLAG_V) bc_vm_info(NULL); if (do_exit) exit((int) s); @@ -2335,7 +2335,7 @@ static void bc_num_printNewline(size_t *nchars, size_t line_len) } } -#ifdef ENABLE_DC +#if ENABLE_DC static void bc_num_printChar(size_t num, size_t width, bool radix, size_t *nchars, size_t line_len) { @@ -2343,25 +2343,27 @@ static void bc_num_printChar(size_t num, size_t width, bool radix, bc_vm_putchar((char) num); *nchars = *nchars + width; } -#endif // ENABLE_DC +#endif static void bc_num_printDigits(size_t num, size_t width, bool radix, size_t *nchars, size_t line_len) { - size_t exp, pow, div; + size_t exp, pow; bc_num_printNewline(nchars, line_len); bc_vm_putchar(radix ? '.' : ' '); ++(*nchars); bc_num_printNewline(nchars, line_len); - for (exp = 0, pow = 1; exp < width - 1; ++exp, pow *= 10); + for (exp = 0, pow = 1; exp < width - 1; ++exp, pow *= 10) + continue; for (exp = 0; exp < width; pow /= 10, ++(*nchars), ++exp) { + size_t dig; bc_num_printNewline(nchars, line_len); - div = num / pow; - num -= div * pow; - bc_vm_putchar(((char) div) + '0'); + dig = num / pow; + num -= dig * pow; + bc_vm_putchar(((char) dig) + '0'); } } @@ -2375,7 +2377,7 @@ static void bc_num_printHex(size_t num, size_t width, bool radix, } bc_num_printNewline(nchars, line_len); - bc_vm_putchar(bc_num_hex_digits[num]); + bc_vm_putchar(bb_hexdigits_upcase[num]); *nchars = *nchars + width; } @@ -2483,12 +2485,12 @@ static BcStatus bc_num_printBase(BcNum *n, BcNum *base, size_t base_t, return s; } -#ifdef ENABLE_DC +#if ENABLE_DC static BcStatus bc_num_stream(BcNum *n, BcNum *base, size_t *nchars, size_t len) { return bc_num_printNum(n, base, 1, nchars, len, bc_num_printChar); } -#endif // ENABLE_DC +#endif static void bc_num_init(BcNum *n, size_t req) { @@ -2766,7 +2768,7 @@ static BcStatus bc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d, return s; } -#ifdef ENABLE_DC +#if ENABLE_DC static BcStatus bc_num_modexp(BcNum *a, BcNum *b, BcNum *c, BcNum *restrict d) { BcStatus s; @@ -2908,7 +2910,7 @@ static void bc_string_free(void *string) free(*((char **) string)); } -#ifdef ENABLE_DC +#if ENABLE_DC static void bc_result_copy(BcResult *d, BcResult *src) { d->t = src->t; @@ -3111,7 +3113,7 @@ static BcStatus bc_lex_text(BcLex *l, const char *text) return bc_lex_next(l); } -#ifdef ENABLE_BC +#if ENABLE_BC static BcStatus bc_lex_identifier(BcLex *l) { BcStatus s; @@ -3490,7 +3492,7 @@ static BcStatus bc_lex_token(BcLex *l) } #endif // ENABLE_BC -#ifdef ENABLE_DC +#if ENABLE_DC static BcStatus dc_lex_register(BcLex *l) { BcStatus s = BC_STATUS_SUCCESS; @@ -3762,7 +3764,7 @@ static void bc_parse_create(BcParse *p, BcProgram *prog, size_t func, bc_parse_updateFunc(p, func); } -#ifdef ENABLE_BC +#if ENABLE_BC static BcStatus bc_parse_else(BcParse *p); static BcStatus bc_parse_stmt(BcParse *p); @@ -5083,7 +5085,7 @@ static BcStatus bc_parse_expression(BcParse *p, uint8_t flags) } #endif // ENABLE_BC -#ifdef ENABLE_DC +#if ENABLE_DC static BcStatus dc_parse_register(BcParse *p) { BcStatus s; @@ -5438,10 +5440,6 @@ static BcStatus bc_program_binOpPrep(BcProgram *p, BcResult **l, BcNum **ln, return BC_STATUS_EXEC_BAD_TYPE; if (!assign && !BC_PROG_NUM((*r), (*ln))) return BC_STATUS_EXEC_BAD_TYPE; -#ifdef ENABLE_DC -#else // ENABLE_DC -#endif // ENABLE_DC - return s; } @@ -5463,9 +5461,6 @@ static BcStatus bc_program_prep(BcProgram *p, BcResult **r, BcNum **n) s = bc_program_num(p, *r, n, false); if (s) return s; -#ifdef ENABLE_DC -#endif // ENABLE_DC - if (!BC_PROG_NUM((*r), (*n))) return BC_STATUS_EXEC_BAD_TYPE; return s; @@ -5580,12 +5575,12 @@ static void bc_program_printString(const char *str, size_t *nchars) { size_t i, len = strlen(str); -#ifdef ENABLE_DC +#if ENABLE_DC if (len == 0) { bc_vm_putchar('\0'); return; } -#endif // ENABLE_DC +#endif for (i = 0; i < len; ++i, ++(*nchars)) { @@ -5790,7 +5785,7 @@ static BcStatus bc_program_logical(BcProgram *p, char inst) return s; } -#ifdef ENABLE_DC +#if ENABLE_DC static BcStatus bc_program_assignStr(BcProgram *p, BcResult *r, BcVec *v, bool push) { @@ -5829,10 +5824,10 @@ static BcStatus bc_program_copyToVar(BcProgram *p, char *name, bool var) if ((ptr->t == BC_RESULT_ARRAY) != !var) return BC_STATUS_EXEC_BAD_TYPE; bc_program_search(p, name, &v, var); -#ifdef ENABLE_DC +#if ENABLE_DC if (ptr->t == BC_RESULT_STR && !var) return BC_STATUS_EXEC_BAD_TYPE; if (ptr->t == BC_RESULT_STR) return bc_program_assignStr(p, ptr, v, true); -#endif // ENABLE_DC +#endif s = bc_program_num(p, ptr, &n, false); if (s) return s; @@ -5869,7 +5864,7 @@ static BcStatus bc_program_assign(BcProgram *p, char inst) ib = left->t == BC_RESULT_IBASE; sc = left->t == BC_RESULT_SCALE; -#ifdef ENABLE_DC +#if ENABLE_DC if (right->t == BC_RESULT_STR) { @@ -5880,12 +5875,12 @@ static BcStatus bc_program_assign(BcProgram *p, char inst) return bc_program_assignStr(p, right, v, false); } -#endif // ENABLE_DC +#endif if (left->t == BC_RESULT_CONSTANT || left->t == BC_RESULT_TEMP) return BC_STATUS_PARSE_BAD_ASSIGN; -#ifdef ENABLE_BC +#if ENABLE_BC if (inst == BC_INST_ASSIGN_DIVIDE && !bc_num_cmp(r, &p->zero)) return BC_STATUS_MATH_DIVIDE_BY_ZERO; @@ -5895,9 +5890,9 @@ static BcStatus bc_program_assign(BcProgram *p, char inst) s = bc_program_ops[inst - BC_INST_ASSIGN_POWER](l, r, l, p->scale); if (s) return s; -#else // ENABLE_BC +#else bc_num_copy(l, r); -#endif // ENABLE_BC +#endif if (ib || sc || left->t == BC_RESULT_OBASE) { @@ -5937,17 +5932,17 @@ static BcStatus bc_program_pushVar(BcProgram *p, char *code, size_t *bgn, BcStatus s = BC_STATUS_SUCCESS; BcResult r; char *name = bc_program_name(code, bgn); -#ifdef ENABLE_DC // Exclude +#if ENABLE_DC // Exclude BcNum *num; BcVec *v; -#else // ENABLE_DC +#else (void) pop, (void) copy; -#endif // ENABLE_DC Exclude +#endif r.t = BC_RESULT_VAR; r.d.id.name = name; -#ifdef ENABLE_DC +#if ENABLE_DC bc_program_search(p, name, &v, true); num = bc_vec_top(v); @@ -6019,7 +6014,7 @@ err: return s; } -#ifdef ENABLE_BC +#if ENABLE_BC static BcStatus bc_program_incdec(BcProgram *p, char inst) { BcStatus s; @@ -6180,19 +6175,19 @@ static BcStatus bc_program_builtin(BcProgram *p, char inst) s = bc_program_num(p, opnd, &num, false); if (s) return s; -#ifdef ENABLE_DC +#if ENABLE_DC if (!BC_PROG_NUM(opnd, num) && !len) return BC_STATUS_EXEC_BAD_TYPE; -#endif // ENABLE_DC +#endif bc_num_init(&res.d.n, BC_NUM_DEF_SIZE); if (inst == BC_INST_SQRT) s = bc_num_sqrt(num, &res.d.n, p->scale); -#ifdef ENABLE_BC +#if ENABLE_BC else if (len != 0 && opnd->t == BC_RESULT_ARRAY) { s = bc_num_ulong2num(&res.d.n, (unsigned long) ((BcVec *) num)->len); } -#endif // ENABLE_BC -#ifdef ENABLE_DC +#endif +#if ENABLE_DC else if (len != 0 && !BC_PROG_NUM(opnd, num)) { char **str; @@ -6202,7 +6197,7 @@ static BcStatus bc_program_builtin(BcProgram *p, char inst) s = bc_num_ulong2num(&res.d.n, strlen(*str)); if (s) goto err; } -#endif // ENABLE_DC +#endif else { BcProgramBuiltIn f = len ? bc_program_len : bc_program_scale; s = bc_num_ulong2num(&res.d.n, f(num)); @@ -6218,7 +6213,7 @@ err: return s; } -#ifdef ENABLE_DC +#if ENABLE_DC static BcStatus bc_program_divmod(BcProgram *p) { BcStatus s; @@ -6563,9 +6558,9 @@ static void bc_program_free(BcProgram *p) bc_num_free(&p->ib); bc_num_free(&p->ob); bc_num_free(&p->hexb); -#ifdef ENABLE_DC +#if ENABLE_DC bc_num_free(&p->strmb); -#endif // ENABLE_DC +#endif bc_vec_free(&p->fns); bc_vec_free(&p->fn_map); bc_vec_free(&p->vars); @@ -6607,10 +6602,10 @@ static void bc_program_init(BcProgram *p, size_t line_len, BcParseInit init, bc_num_ten(&p->hexb); p->hexb.num[0] = 6; -#ifdef ENABLE_DC +#if ENABLE_DC bc_num_init(&p->strmb, BC_NUM_DEF_SIZE); bc_num_ulong2num(&p->strmb, UCHAR_MAX + 1); -#endif // ENABLE_DC +#endif bc_num_init(&p->last, BC_NUM_DEF_SIZE); bc_num_zero(&p->last); @@ -6718,7 +6713,7 @@ static BcStatus bc_program_exec(BcProgram *p) switch (inst) { -#ifdef ENABLE_BC +#if ENABLE_BC case BC_INST_JUMP_ZERO: { s = bc_program_prep(p, &ptr, &num); @@ -6888,20 +6883,20 @@ static BcStatus bc_program_exec(BcProgram *p) break; } -#ifdef ENABLE_BC +#if ENABLE_BC case BC_INST_ASSIGN_POWER: case BC_INST_ASSIGN_MULTIPLY: case BC_INST_ASSIGN_DIVIDE: case BC_INST_ASSIGN_MODULUS: case BC_INST_ASSIGN_PLUS: case BC_INST_ASSIGN_MINUS: -#endif // ENABLE_BC +#endif case BC_INST_ASSIGN: { s = bc_program_assign(p, inst); break; } -#ifdef ENABLE_DC +#if ENABLE_DC case BC_INST_MODEXP: { s = bc_program_modexp(p); @@ -7032,7 +7027,7 @@ static void bc_vm_sig(int sig) } errno = err; } -#endif // ENABLE_FEATURE_BC_SIGNALS +#endif static void bc_vm_info(const char *const help) { @@ -7052,7 +7047,7 @@ static BcStatus bc_vm_error(BcStatus s, const char *file, size_t line) return s * (!bcg.ttyin || !!strcmp(file, bc_program_stdin_name)); } -#ifdef ENABLE_BC +#if ENABLE_BC static BcStatus bc_vm_posixError(BcStatus s, const char *file, size_t line, const char *msg) { @@ -7315,7 +7310,7 @@ static BcStatus bc_vm_exec(BcVm *vm) BcStatus s = BC_STATUS_SUCCESS; size_t i; -#ifdef ENABLE_BC +#if ENABLE_BC if (vm->flags & BC_FLAG_L) { bc_lex_file(&vm->prs.l, bc_lib_name); @@ -7327,7 +7322,7 @@ static BcStatus bc_vm_exec(BcVm *vm) s = bc_program_exec(&vm->prog); if (s) return s; } -#endif // ENABLE_BC +#endif for (i = 0; !s && i < vm->files.len; ++i) s = bc_vm_file(vm, *((char **) bc_vec_item(&vm->files, i))); @@ -7358,7 +7353,7 @@ static BcStatus bc_vm_init(BcVm *vm, BcVmExe exe, const char *env_len) sa.sa_handler = bc_vm_sig; sa.sa_flags = 0; sigaction(SIGINT, &sa, NULL); -#endif // ENABLE_FEATURE_BC_SIGNALS +#endif memset(vm, 0, sizeof(BcVm)); @@ -7368,10 +7363,10 @@ static BcStatus bc_vm_init(BcVm *vm, BcVmExe exe, const char *env_len) bc_vec_init(&vm->files, sizeof(char *), NULL); -#ifdef ENABLE_BC +#if ENABLE_BC vm->flags |= BC_FLAG_S * bcg.bc * (getenv("POSIXLY_CORRECT") != NULL); if (bcg.bc) s = bc_vm_envArgs(vm); -#endif // ENABLE_BC +#endif bc_program_init(&vm->prog, len, exe.init, exe.exp); exe.init(&vm->prs, &vm->prog, BC_PROG_MAIN); @@ -7393,13 +7388,13 @@ static BcStatus bc_vm_run(int argc, char *argv[], BcVmExe exe, bcg.ttyin = isatty(0); bcg.tty = bcg.ttyin || (vm.flags & BC_FLAG_I) || isatty(1); -#ifdef ENABLE_BC +#if ENABLE_BC bcg.posix = vm.flags & BC_FLAG_S; bcg.warn = vm.flags & BC_FLAG_W; -#endif // ENABLE_BC -#ifdef ENABLE_DC +#endif +#if ENABLE_DC bcg.exreg = vm.flags & BC_FLAG_X; -#endif // ENABLE_DC +#endif if (bcg.ttyin && !(vm.flags & BC_FLAG_Q)) bc_vm_info(NULL); st = bc_vm_exec(&vm); @@ -7409,16 +7404,16 @@ exit: return st; } -#ifdef ENABLE_BC +#if ENABLE_BC BcStatus bc_main(int argc, char *argv[]) { BcVmExe exec; bcg.bc = true; bcg.name = bc_name; -#if ENABLE_FEATURE_BC_SIGNALS +# if ENABLE_FEATURE_BC_SIGNALS bcg.sig_msg = bc_sig_msg; -#endif // ENABLE_FEATURE_BC_SIGNALS +# endif exec.init = bc_parse_init; exec.exp = bc_parse_expression; @@ -7426,18 +7421,18 @@ BcStatus bc_main(int argc, char *argv[]) return bc_vm_run(argc, argv, exec, "BC_LINE_LENGTH"); } -#endif // ENABLE_BC +#endif -#ifdef ENABLE_DC +#if ENABLE_DC BcStatus dc_main(int argc, char *argv[]) { BcVmExe exec; bcg.bc = false; bcg.name = dc_name; -#if ENABLE_FEATURE_BC_SIGNALS +# if ENABLE_FEATURE_BC_SIGNALS bcg.sig_msg = dc_sig_msg; -#endif // ENABLE_FEATURE_BC_SIGNALS +# endif exec.init = dc_parse_init; exec.exp = dc_parse_expr; @@ -7446,4 +7441,4 @@ BcStatus dc_main(int argc, char *argv[]) return bc_vm_run(argc, argv, exec, "DC_LINE_LENGTH"); } -#endif // ENABLE_DC +#endif -- cgit v1.2.3-55-g6feb From 00d7779a356f9827c0776ebbbe91c35f278b9a4c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 30 Nov 2018 23:13:42 +0100 Subject: bc: simplify, stop testing for IO errors on every output function old new delta bc_read_line 297 342 +45 bc_vm_run 2601 2608 +7 bc_program_reset 178 182 +4 bc_args 125 123 -2 dc_name 3 - -3 bc_name 3 - -3 bc_program_printStream 176 172 -4 bcg 48 40 -8 dc_main 97 80 -17 bc_main 97 80 -17 bc_vm_fflush 21 - -21 bc_vm_puts 23 - -23 bc_vm_printf 36 - -36 bc_vm_putchar 46 - -46 bc_vm_exit 46 - -46 bc_vm_process 361 312 -49 bc_vm_info 76 19 -57 bc_copyright 155 - -155 ------------------------------------------------------------------------------ (add/remove: 0/8 grow/shrink: 3/7 up/down: 56/-487) Total: -431 bytes text data bss dec hex filename 989722 485 7344 997551 f38af busybox_old 989491 485 7336 997312 f37c0 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 203 +++++++++++++++++++++++---------------------------------- 1 file changed, 81 insertions(+), 122 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 4cbef4da6..f36534c36 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -165,7 +165,7 @@ typedef enum BcStatus { BC_STATUS_SUCCESS, BC_STATUS_ALLOC_ERR, - BC_STATUS_IO_ERR, + BC_STATUS_INPUT_EOF, BC_STATUS_BIN_FILE, BC_STATUS_PATH_IS_DIR, @@ -719,9 +719,9 @@ static BcStatus bc_lex_token(BcLex *l); static BcStatus bc_parse_parse(BcParse *p); static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next); -#endif +#endif // ENABLE_BC -#ifdef ENABLE_DC +#if ENABLE_DC #define DC_PARSE_BUF_LEN ((int) (sizeof(uint32_t) * CHAR_BIT)) @@ -849,51 +849,38 @@ typedef struct BcGlobals { long warn; long exreg; - const char *name; #if ENABLE_FEATURE_BC_SIGNALS const char *sig_msg; #endif const char *help; - bool bc; } BcGlobals; +#define IS_BC (ENABLE_BC && (!ENABLE_DC || applet_name[0] == 'b')) + #if ENABLE_BC static BcStatus bc_vm_posixError(BcStatus s, const char *file, size_t line, const char *msg); #endif -static void bc_vm_exit(BcStatus s); -static void bc_vm_printf(FILE *restrict f, const char *fmt, ...); -static void bc_vm_puts(const char *str, FILE *restrict f); -static void bc_vm_putchar(int c); -static void bc_vm_fflush(FILE *restrict f); - -static void bc_vm_info(const char *const help); +static void bc_vm_info(void); static BcStatus bc_vm_run(int argc, char *argv[], BcVmExe exe, const char *env_len); static BcGlobals bcg; #if ENABLE_BC -static const char bc_name[] = "bc"; # if ENABLE_FEATURE_BC_SIGNALS static const char bc_sig_msg[] = "\ninterrupt (type \"quit\" to exit)\n"; # endif #endif #if ENABLE_DC -static const char dc_name[] = "dc"; # if ENABLE_FEATURE_BC_SIGNALS static const char dc_sig_msg[] = "\ninterrupt (type \"q\" to exit)\n"; # endif #endif -static const char bc_copyright[] = - "Copyright (c) 2018 Gavin D. Howard and contributors\n" - "Report bugs at: https://github.com/gavinhoward/bc\n\n" - "This is free software with ABSOLUTELY NO WARRANTY.\n"; - static const char* const bc_args_env_name = "BC_ENV_ARGS"; static const char bc_err_fmt[] = "\n%s error: %s\n"; @@ -1386,18 +1373,22 @@ static size_t bc_map_index(const BcVec *v, const void *ptr) static BcStatus bc_read_line(BcVec *vec, const char *prompt) { int i; - signed char c = 0; + signed char c; if (bcg.ttyin && !bcg.posix) { - bc_vm_puts(prompt, stderr); - bc_vm_fflush(stderr); + fputs(prompt, stderr); + fflush(stderr); } bc_vec_npop(vec, vec->len); - while (c != '\n') { + do { + if (ferror(stdout) || ferror(stderr)) + bb_perror_msg_and_die("output error"); i = fgetc(stdin); + if (ferror(stdin)) + bb_perror_msg_and_die("input error"); if (i == EOF) { @@ -1408,22 +1399,22 @@ static BcStatus bc_read_line(BcVec *vec, const char *prompt) bcg.signe = 0; if (bcg.ttyin) { - bc_vm_puts(bc_program_ready_msg, stderr); - if (!bcg.posix) bc_vm_puts(prompt, stderr); - bc_vm_fflush(stderr); + fputs(bc_program_ready_msg, stderr); + if (!bcg.posix) fputs(prompt, stderr); + fflush(stderr); } continue; } #endif - return BC_STATUS_IO_ERR; + return BC_STATUS_INPUT_EOF; } c = (signed char) i; if (i > UCHAR_MAX || BC_READ_BIN_CHAR(c)) return BC_STATUS_BIN_FILE; bc_vec_push(vec, &c); - } + } while (c != '\n'); bc_vec_pushByte(vec, '\0'); @@ -1477,7 +1468,7 @@ static BcStatus bc_args(int argc, char *argv[], uint32_t *flags, BcVec *files) *flags = getopt32(argv, bc_args_opt); #endif - if ((*flags) & BC_FLAG_V) bc_vm_info(NULL); + if ((*flags) & BC_FLAG_V) bc_vm_info(); if (do_exit) exit((int) s); if (argv[optind] && !strcmp(argv[optind], "--")) ++optind; @@ -2329,8 +2320,8 @@ int_err: static void bc_num_printNewline(size_t *nchars, size_t line_len) { if (*nchars == line_len - 1) { - bc_vm_putchar('\\'); - bc_vm_putchar('\n'); + bb_putchar('\\'); + bb_putchar('\n'); *nchars = 0; } } @@ -2340,7 +2331,7 @@ static void bc_num_printChar(size_t num, size_t width, bool radix, size_t *nchars, size_t line_len) { (void) radix, (void) line_len; - bc_vm_putchar((char) num); + bb_putchar((char) num); *nchars = *nchars + width; } #endif @@ -2351,7 +2342,7 @@ static void bc_num_printDigits(size_t num, size_t width, bool radix, size_t exp, pow; bc_num_printNewline(nchars, line_len); - bc_vm_putchar(radix ? '.' : ' '); + bb_putchar(radix ? '.' : ' '); ++(*nchars); bc_num_printNewline(nchars, line_len); @@ -2363,7 +2354,7 @@ static void bc_num_printDigits(size_t num, size_t width, bool radix, bc_num_printNewline(nchars, line_len); dig = num / pow; num -= dig * pow; - bc_vm_putchar(((char) dig) + '0'); + bb_putchar(((char) dig) + '0'); } } @@ -2372,12 +2363,12 @@ static void bc_num_printHex(size_t num, size_t width, bool radix, { if (radix) { bc_num_printNewline(nchars, line_len); - bc_vm_putchar('.'); + bb_putchar('.'); *nchars += 1; } bc_num_printNewline(nchars, line_len); - bc_vm_putchar(bb_hexdigits_upcase[num]); + bb_putchar(bb_hexdigits_upcase[num]); *nchars = *nchars + width; } @@ -2385,7 +2376,7 @@ static void bc_num_printDecimal(BcNum *n, size_t *nchars, size_t len) { size_t i, rdx = n->rdx - 1; - if (n->neg) bc_vm_putchar('-'); + if (n->neg) bb_putchar('-'); (*nchars) += n->neg; for (i = n->len - 1; i < n->len; --i) @@ -2465,7 +2456,7 @@ static BcStatus bc_num_printBase(BcNum *n, BcNum *base, size_t base_t, BcNumDigitOp print; bool neg = n->neg; - if (neg) bc_vm_putchar('-'); + if (neg) bb_putchar('-'); (*nchars) += neg; n->neg = false; @@ -2546,7 +2537,7 @@ static BcStatus bc_num_print(BcNum *n, BcNum *base, size_t base_t, bool newline, bc_num_printNewline(nchars, line_len); if (n->len == 0) { - bc_vm_putchar('0'); + bb_putchar('0'); ++(*nchars); } else if (base_t == 10) @@ -2555,7 +2546,7 @@ static BcStatus bc_num_print(BcNum *n, BcNum *base, size_t base_t, bool newline, s = bc_num_printBase(n, base, base_t, nchars, line_len); if (newline) { - bc_vm_putchar('\n'); + bb_putchar('\n'); *nchars = 0; } @@ -5577,7 +5568,7 @@ static void bc_program_printString(const char *str, size_t *nchars) #if ENABLE_DC if (len == 0) { - bc_vm_putchar('\0'); + bb_putchar('\0'); return; } #endif @@ -5587,7 +5578,7 @@ static void bc_program_printString(const char *str, size_t *nchars) int c = str[i]; if (c != '\\' || i == len - 1) - bc_vm_putchar(c); + bb_putchar(c); else { c = str[++i]; @@ -5596,60 +5587,60 @@ static void bc_program_printString(const char *str, size_t *nchars) case 'a': { - bc_vm_putchar('\a'); + bb_putchar('\a'); break; } case 'b': { - bc_vm_putchar('\b'); + bb_putchar('\b'); break; } case '\\': case 'e': { - bc_vm_putchar('\\'); + bb_putchar('\\'); break; } case 'f': { - bc_vm_putchar('\f'); + bb_putchar('\f'); break; } case 'n': { - bc_vm_putchar('\n'); + bb_putchar('\n'); *nchars = SIZE_MAX; break; } case 'r': { - bc_vm_putchar('\r'); + bb_putchar('\r'); break; } case 'q': { - bc_vm_putchar('"'); + bb_putchar('"'); break; } case 't': { - bc_vm_putchar('\t'); + bb_putchar('\t'); break; } default: { // Just print the backslash and following character. - bc_vm_putchar('\\'); + bb_putchar('\\'); ++(*nchars); - bc_vm_putchar(c); + bb_putchar(c); break; } } @@ -5684,14 +5675,14 @@ static BcStatus bc_program_print(BcProgram *p, char inst, size_t idx) if (inst == BC_INST_PRINT_STR) { for (i = 0, len = strlen(str); i < len; ++i) { char c = str[i]; - bc_vm_putchar(c); + bb_putchar(c); if (c == '\n') p->nchars = SIZE_MAX; ++p->nchars; } } else { bc_program_printString(str, &p->nchars); - if (inst == BC_INST_PRINT) bc_vm_putchar('\n'); + if (inst == BC_INST_PRINT) bb_putchar('\n'); } } @@ -6392,7 +6383,7 @@ static BcStatus bc_program_printStream(BcProgram *p) else { idx = (r->t == BC_RESULT_STR) ? r->d.id.idx : n->rdx; str = *((char **) bc_vec_item(&p->strs, idx)); - bc_vm_printf(stdout, "%s", str); + printf("%s", str); } return s; @@ -6685,8 +6676,8 @@ static BcStatus bc_program_reset(BcProgram *p, BcStatus s) if (!s || s == BC_STATUS_EXEC_SIGNAL) { if (bcg.ttyin) { - bc_vm_puts(bc_program_ready_msg, stderr); - bc_vm_fflush(stderr); + fputs(bc_program_ready_msg, stderr); + fflush(stderr); s = BC_STATUS_SUCCESS; } else @@ -7029,20 +7020,22 @@ static void bc_vm_sig(int sig) } #endif -static void bc_vm_info(const char *const help) +static void bc_vm_info(void) { - bc_vm_printf(stdout, "%s %s\n", bcg.name, "1.1"); - bc_vm_puts(bc_copyright, stdout); - if (help) bc_vm_printf(stdout, help, bcg.name); + printf("%s "BB_VER"\n" + "Copyright (c) 2018 Gavin D. Howard and contributors\n" + "Report bugs at: https://github.com/gavinhoward/bc\n\n" + "This is free software with ABSOLUTELY NO WARRANTY\n" + , applet_name); } static BcStatus bc_vm_error(BcStatus s, const char *file, size_t line) { if (!s || s > BC_STATUS_VEC_ITEM_EXISTS) return s; - bc_vm_printf(stderr, bc_err_fmt, bc_errs[bc_err_ids[s]], bc_err_msgs[s]); - bc_vm_printf(stderr, " %s", file); - bc_vm_printf(stderr, bc_err_line + 4 * !line, line); + fprintf(stderr, bc_err_fmt, bc_errs[bc_err_ids[s]], bc_err_msgs[s]); + fprintf(stderr, " %s", file); + fprintf(stderr, bc_err_line + 4 * !line, line); return s * (!bcg.ttyin || !!strcmp(file, bc_program_stdin_name)); } @@ -7056,10 +7049,10 @@ static BcStatus bc_vm_posixError(BcStatus s, const char *file, size_t line, if (!(p || w) || s < BC_STATUS_POSIX_NAME_LEN) return BC_STATUS_SUCCESS; - bc_vm_printf(stderr, fmt, bc_errs[bc_err_ids[s]], bc_err_msgs[s]); - if (msg) bc_vm_printf(stderr, " %s\n", msg); - bc_vm_printf(stderr, " %s", file); - bc_vm_printf(stderr, bc_err_line + 4 * !line, line); + fprintf(stderr, fmt, bc_errs[bc_err_ids[s]], bc_err_msgs[s]); + if (msg) fprintf(stderr, " %s\n", msg); + fprintf(stderr, " %s", file); + fprintf(stderr, bc_err_line + 4 * !line, line); return s * (!bcg.ttyin && !!p); } @@ -7117,39 +7110,6 @@ static size_t bc_vm_envLen(const char *var) return len; } -static void bc_vm_exit(BcStatus s) -{ - bc_vm_printf(stderr, bc_err_fmt, bc_errs[bc_err_ids[s]], bc_err_msgs[s]); - exit((int) s); -} - -static void bc_vm_printf(FILE *restrict f, const char *fmt, ...) -{ - va_list args; - bool bad; - - va_start(args, fmt); - bad = vfprintf(f, fmt, args) < 0; - va_end(args); - - if (bad) bc_vm_exit(BC_STATUS_IO_ERR); -} - -static void bc_vm_puts(const char *str, FILE *restrict f) -{ - if (fputs(str, f) == EOF) bc_vm_exit(BC_STATUS_IO_ERR); -} - -static void bc_vm_putchar(int c) -{ - if (putchar(c) == EOF) bc_vm_exit(BC_STATUS_IO_ERR); -} - -static void bc_vm_fflush(FILE *restrict f) -{ - if (fflush(f) == EOF) bc_vm_exit(BC_STATUS_IO_ERR); -} - static BcStatus bc_vm_process(BcVm *vm, const char *text) { BcStatus s = bc_parse_text(&vm->prs, text); @@ -7163,16 +7123,16 @@ static BcStatus bc_vm_process(BcVm *vm, const char *text) if (s == BC_STATUS_LIMITS) { - bc_vm_putchar('\n'); - bc_vm_printf(stdout, "BC_BASE_MAX = %lu\n", BC_MAX_OBASE); - bc_vm_printf(stdout, "BC_DIM_MAX = %lu\n", BC_MAX_DIM); - bc_vm_printf(stdout, "BC_SCALE_MAX = %lu\n", BC_MAX_SCALE); - bc_vm_printf(stdout, "BC_STRING_MAX = %lu\n", BC_MAX_STRING); - bc_vm_printf(stdout, "BC_NAME_MAX = %lu\n", BC_MAX_NAME); - bc_vm_printf(stdout, "BC_NUM_MAX = %lu\n", BC_MAX_NUM); - bc_vm_printf(stdout, "Max Exponent = %lu\n", BC_MAX_EXP); - bc_vm_printf(stdout, "Number of Vars = %lu\n", BC_MAX_VARS); - bc_vm_putchar('\n'); + bb_putchar('\n'); + printf("BC_BASE_MAX = %lu\n", BC_MAX_OBASE); + printf("BC_DIM_MAX = %lu\n", BC_MAX_DIM); + printf("BC_SCALE_MAX = %lu\n", BC_MAX_SCALE); + printf("BC_STRING_MAX = %lu\n", BC_MAX_STRING); + printf("BC_NAME_MAX = %lu\n", BC_MAX_NAME); + printf("BC_NUM_MAX = %lu\n", BC_MAX_NUM); + printf("Max Exponent = %lu\n", BC_MAX_EXP); + printf("Number of Vars = %lu\n", BC_MAX_VARS); + bb_putchar('\n'); s = BC_STATUS_SUCCESS; } @@ -7185,7 +7145,7 @@ static BcStatus bc_vm_process(BcVm *vm, const char *text) if (BC_PARSE_CAN_EXEC(&vm->prs)) { s = bc_program_exec(&vm->prog); - if (!s && bcg.tty) bc_vm_fflush(stdout); + if (!s && bcg.tty) fflush(stdout); if (s && s != BC_STATUS_QUIT) s = bc_vm_error(bc_program_reset(&vm->prog, s), vm->prs.l.f, 0); } @@ -7290,7 +7250,8 @@ static BcStatus bc_vm_stdin(BcVm *vm) // I/O error will always happen when stdin is // closed. It's not a problem in that case. - s = s == BC_STATUS_IO_ERR || s == BC_STATUS_QUIT ? BC_STATUS_SUCCESS : s; + if (s == BC_STATUS_INPUT_EOF || s == BC_STATUS_QUIT) + s = BC_STATUS_SUCCESS; if (str) s = bc_vm_error(BC_STATUS_LEX_NO_STRING_END, vm->prs.l.f, @@ -7328,10 +7289,12 @@ static BcStatus bc_vm_exec(BcVm *vm) s = bc_vm_file(vm, *((char **) bc_vec_item(&vm->files, i))); if (s && s != BC_STATUS_QUIT) return s; - if (bcg.bc || !vm->files.len) s = bc_vm_stdin(vm); + if (IS_BC || !vm->files.len) s = bc_vm_stdin(vm); if (!s && !BC_PARSE_CAN_EXEC(&vm->prs)) s = bc_vm_process(vm, ""); - return s == BC_STATUS_QUIT ? BC_STATUS_SUCCESS : s; + if (s == BC_STATUS_QUIT) + s = BC_STATUS_SUCCESS; + return s; } static void bc_vm_free(BcVm *vm) @@ -7364,8 +7327,8 @@ static BcStatus bc_vm_init(BcVm *vm, BcVmExe exe, const char *env_len) bc_vec_init(&vm->files, sizeof(char *), NULL); #if ENABLE_BC - vm->flags |= BC_FLAG_S * bcg.bc * (getenv("POSIXLY_CORRECT") != NULL); - if (bcg.bc) s = bc_vm_envArgs(vm); + vm->flags |= BC_FLAG_S * IS_BC * (getenv("POSIXLY_CORRECT") != NULL); + if (IS_BC) s = bc_vm_envArgs(vm); #endif bc_program_init(&vm->prog, len, exe.init, exe.exp); @@ -7396,7 +7359,7 @@ static BcStatus bc_vm_run(int argc, char *argv[], BcVmExe exe, bcg.exreg = vm.flags & BC_FLAG_X; #endif - if (bcg.ttyin && !(vm.flags & BC_FLAG_Q)) bc_vm_info(NULL); + if (bcg.ttyin && !(vm.flags & BC_FLAG_Q)) bc_vm_info(); st = bc_vm_exec(&vm); exit: @@ -7409,8 +7372,6 @@ BcStatus bc_main(int argc, char *argv[]) { BcVmExe exec; - bcg.bc = true; - bcg.name = bc_name; # if ENABLE_FEATURE_BC_SIGNALS bcg.sig_msg = bc_sig_msg; # endif @@ -7428,8 +7389,6 @@ BcStatus dc_main(int argc, char *argv[]) { BcVmExe exec; - bcg.bc = false; - bcg.name = dc_name; # if ENABLE_FEATURE_BC_SIGNALS bcg.sig_msg = dc_sig_msg; # endif -- cgit v1.2.3-55-g6feb From 5a9fef5b599b0e9c31d4e1dffbb3e3f9d19a9603 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 2 Dec 2018 14:35:32 +0100 Subject: bc: simplify, and restore ^C, fix ^D handling ^D used to enter infinite loop function old new delta bc_read_line 342 359 +17 bc_args_opt 8 - -8 dc_sig_msg 31 - -31 bc_sig_msg 34 - -34 bc_vm_run 2608 2569 -39 bc_args 123 83 -40 bc_args_lopt 81 - -81 ------------------------------------------------------------------------------ (add/remove: 0/4 grow/shrink: 1/2 up/down: 17/-233) Total: -216 bytes text data bss dec hex filename 989491 485 7336 997312 f37c0 busybox_old 989425 485 7336 997246 f377e busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 105 +++++++++++++++++++-------------------------------------- 1 file changed, 34 insertions(+), 71 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index f36534c36..d5f577598 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -249,7 +249,6 @@ typedef enum BcStatus { #define BC_VEC_START_CAP (1 << 5) typedef void (*BcVecFree)(void *); -typedef int (*BcVecCmp)(const void *, const void *); typedef struct BcVec { char *v; @@ -691,8 +690,6 @@ typedef struct BcParse { #if ENABLE_BC -BcStatus bc_main(int argc, char *argv[]); - typedef struct BcLexKeyword { const char name[9]; const char len; @@ -725,8 +722,6 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next); #define DC_PARSE_BUF_LEN ((int) (sizeof(uint32_t) * CHAR_BIT)) -BcStatus dc_main(int argc, char *argv[]); - static BcStatus dc_lex_token(BcLex *l); static void dc_parse_init(BcParse *p, struct BcProgram *prog, size_t func); @@ -864,23 +859,9 @@ static BcStatus bc_vm_posixError(BcStatus s, const char *file, size_t line, #endif static void bc_vm_info(void); -static BcStatus bc_vm_run(int argc, char *argv[], BcVmExe exe, - const char *env_len); static BcGlobals bcg; -#if ENABLE_BC -# if ENABLE_FEATURE_BC_SIGNALS -static const char bc_sig_msg[] = "\ninterrupt (type \"quit\" to exit)\n"; -# endif -#endif - -#if ENABLE_DC -# if ENABLE_FEATURE_BC_SIGNALS -static const char dc_sig_msg[] = "\ninterrupt (type \"q\" to exit)\n"; -# endif -#endif - static const char* const bc_args_env_name = "BC_ENV_ARGS"; static const char bc_err_fmt[] = "\n%s error: %s\n"; @@ -1386,28 +1367,25 @@ static BcStatus bc_read_line(BcVec *vec, const char *prompt) if (ferror(stdout) || ferror(stderr)) bb_perror_msg_and_die("output error"); + errno = 0; i = fgetc(stdin); - if (ferror(stdin)) - bb_perror_msg_and_die("input error"); if (i == EOF) { - #if ENABLE_FEATURE_BC_SIGNALS if (errno == EINTR) { - bcg.sigc = bcg.sig; bcg.signe = 0; - if (bcg.ttyin) { fputs(bc_program_ready_msg, stderr); if (!bcg.posix) fputs(prompt, stderr); fflush(stderr); } - + clearerr(stdin); continue; } + if (ferror(stdin)) + bb_perror_msg_and_die("input error"); #endif - return BC_STATUS_INPUT_EOF; } @@ -1441,40 +1419,32 @@ read_err: return s; } -#if ENABLE_FEATURE_BC_LONG_OPTIONS -static const char bc_args_lopt[] ALIGN1 = - "extended-register\0"No_argument"x" - "warn\0"No_argument"w" - "version\0"No_argument"v" - "standard\0"No_argument"s" - "quiet\0"No_argument"q" - "mathlib\0"No_argument"l" - "interactive\0"No_argument"i"; -#endif - -static const char bc_args_opt[] ALIGN1 = "xwvsqli"; - -static BcStatus bc_args(int argc, char *argv[], uint32_t *flags, BcVec *files) +static void bc_args(int argc, char *argv[], uint32_t *flags, BcVec *files) { - BcStatus s = BC_STATUS_SUCCESS; int i; bool do_exit = false; - i = optind = 0; - + GETOPT_RESET(); #if ENABLE_FEATURE_BC_LONG_OPTIONS - *flags = getopt32long(argv, bc_args_opt, bc_args_lopt); + *flags = getopt32long(argv, "xwvsqli", + "extended-register\0" No_argument "x" + "warn\0" No_argument "w" + "version\0" No_argument "v" + "standard\0" No_argument "s" + "quiet\0" No_argument "q" + "mathlib\0" No_argument "l" + "interactive\0" No_argument "i" + ); #else - *flags = getopt32(argv, bc_args_opt); + *flags = getopt32(argv, "xwvsqli"); #endif if ((*flags) & BC_FLAG_V) bc_vm_info(); - if (do_exit) exit((int) s); - if (argv[optind] && !strcmp(argv[optind], "--")) ++optind; + if (do_exit) exit(0); + // should not be necessary, getopt32() handles this?? + //if (argv[optind] && !strcmp(argv[optind], "--")) ++optind; for (i = optind; i < argc; ++i) bc_vec_push(files, argv + i); - - return s; } static void bc_num_setToZero(BcNum *n, size_t scale) @@ -7024,7 +6994,7 @@ static void bc_vm_info(void) { printf("%s "BB_VER"\n" "Copyright (c) 2018 Gavin D. Howard and contributors\n" - "Report bugs at: https://github.com/gavinhoward/bc\n\n" + "Report bugs at: https://github.com/gavinhoward/bc\n" "This is free software with ABSOLUTELY NO WARRANTY\n" , applet_name); } @@ -7057,13 +7027,12 @@ static BcStatus bc_vm_posixError(BcStatus s, const char *file, size_t line, return s * (!bcg.ttyin && !!p); } -static BcStatus bc_vm_envArgs(BcVm *vm) +static void bc_vm_envArgs(BcVm *vm) { - BcStatus s = BC_STATUS_SUCCESS; BcVec v; char *env_args = getenv(bc_args_env_name), *buf; - if (!env_args) return s; + if (!env_args) return; vm->env_args = xstrdup(env_args); buf = vm->env_args; @@ -7081,11 +7050,9 @@ static BcStatus bc_vm_envArgs(BcVm *vm) ++buf; } - s = bc_args((int) v.len, (char **) v.v, &vm->flags, &vm->files); + bc_args((int) v.len, (char **) v.v, &vm->flags, &vm->files); bc_vec_free(&v); - - return s; } #endif // ENABLE_BC @@ -7248,7 +7215,7 @@ static BcStatus bc_vm_stdin(BcVm *vm) if (s == BC_STATUS_BIN_FILE) s = bc_vm_error(s, vm->prs.l.f, 0); - // I/O error will always happen when stdin is + // INPUT_EOF will always happen when stdin is // closed. It's not a problem in that case. if (s == BC_STATUS_INPUT_EOF || s == BC_STATUS_QUIT) s = BC_STATUS_SUCCESS; @@ -7305,9 +7272,8 @@ static void bc_vm_free(BcVm *vm) free(vm->env_args); } -static BcStatus bc_vm_init(BcVm *vm, BcVmExe exe, const char *env_len) +static void bc_vm_init(BcVm *vm, BcVmExe exe, const char *env_len) { - BcStatus s = BC_STATUS_SUCCESS; size_t len = bc_vm_envLen(env_len); #if ENABLE_FEATURE_BC_SIGNALS struct sigaction sa; @@ -7328,13 +7294,11 @@ static BcStatus bc_vm_init(BcVm *vm, BcVmExe exe, const char *env_len) #if ENABLE_BC vm->flags |= BC_FLAG_S * IS_BC * (getenv("POSIXLY_CORRECT") != NULL); - if (IS_BC) s = bc_vm_envArgs(vm); + if (IS_BC) bc_vm_envArgs(vm); #endif bc_program_init(&vm->prog, len, exe.init, exe.exp); exe.init(&vm->prs, &vm->prog, BC_PROG_MAIN); - - return s; } static BcStatus bc_vm_run(int argc, char *argv[], BcVmExe exe, @@ -7343,10 +7307,8 @@ static BcStatus bc_vm_run(int argc, char *argv[], BcVmExe exe, BcStatus st; BcVm vm; - st = bc_vm_init(&vm, exe, env_len); - if (st) goto exit; - st = bc_args(argc, argv, &vm.flags, &vm.files); - if (st) goto exit; + bc_vm_init(&vm, exe, env_len); + bc_args(argc, argv, &vm.flags, &vm.files); bcg.ttyin = isatty(0); bcg.tty = bcg.ttyin || (vm.flags & BC_FLAG_I) || isatty(1); @@ -7362,18 +7324,18 @@ static BcStatus bc_vm_run(int argc, char *argv[], BcVmExe exe, if (bcg.ttyin && !(vm.flags & BC_FLAG_Q)) bc_vm_info(); st = bc_vm_exec(&vm); -exit: bc_vm_free(&vm); return st; } #if ENABLE_BC -BcStatus bc_main(int argc, char *argv[]) +int bc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int bc_main(int argc, char **argv) { BcVmExe exec; # if ENABLE_FEATURE_BC_SIGNALS - bcg.sig_msg = bc_sig_msg; + bcg.sig_msg = "\ninterrupt (type \"quit\" to exit)\n"; # endif exec.init = bc_parse_init; @@ -7385,12 +7347,13 @@ BcStatus bc_main(int argc, char *argv[]) #endif #if ENABLE_DC -BcStatus dc_main(int argc, char *argv[]) +int dc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int dc_main(int argc, char **argv) { BcVmExe exec; # if ENABLE_FEATURE_BC_SIGNALS - bcg.sig_msg = dc_sig_msg; + bcg.sig_msg = "\ninterrupt (type \"q\" to exit)\n"; # endif exec.init = dc_parse_init; -- cgit v1.2.3-55-g6feb From 6d9146ab56018b232a178b8fa463338cf731a832 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 2 Dec 2018 15:48:37 +0100 Subject: bc: convert to "G trick" - this returns bc to zero bss increase function old new delta bc_num_p 518 540 +22 bc_num_k 1010 1031 +21 bc_vm_process 312 327 +15 bc_program_exec 4401 4413 +12 bc_vm_posixError 194 205 +11 bc_num_a 480 491 +11 bc_program_reset 182 192 +10 bc_vm_sig 88 97 +9 bc_vm_error 148 156 +8 bc_parse_expr 2215 2222 +7 bc_num_compare 84 90 +6 dc_parse_parse 53 58 +5 dc_lex_token 670 675 +5 bc_read_line 359 364 +5 bc_parse_parse 471 476 +5 bc_num_cmp 294 299 +5 bc_num_subArrays 84 82 -2 bc_num_d 614 609 -5 dc_main 80 72 -8 bc_main 80 72 -8 bcg 40 - -40 bc_vm_run 2569 2382 -187 ------------------------------------------------------------------------------ (add/remove: 0/1 grow/shrink: 16/5 up/down: 157/-250) Total: -93 bytes text data bss dec hex filename 989425 485 7336 997246 f377e busybox_old 989372 485 7296 997153 f3721 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 292 ++++++++++++++++++++++++++------------------------------- 1 file changed, 133 insertions(+), 159 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index d5f577598..e13b2283c 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -812,44 +812,39 @@ static BcStatus bc_program_exec(BcProgram *p); #define BC_MAX_EXP ((unsigned long) LONG_MAX) #define BC_MAX_VARS ((unsigned long) SIZE_MAX - 1) -typedef struct BcVmExe { +struct globals { BcParseInit init; BcParseExpr exp; char sbgn; char send; -} BcVmExe; - -typedef struct BcVm { BcParse prs; BcProgram prog; - uint32_t flags; + unsigned flags; BcVec files; char *env_args; - BcVmExe exe; - -} BcVm; -typedef struct BcGlobals { + unsigned sig; //counter? + unsigned sigc; //counter? + smallint signe; //flag - unsigned long sig; - unsigned long sigc; - unsigned long signe; - - long tty; - long ttyin; - long posix; - long warn; - long exreg; + smallint tty; + smallint ttyin; #if ENABLE_FEATURE_BC_SIGNALS const char *sig_msg; #endif - const char *help; +} FIX_ALIASING; +#define G (*ptr_to_globals) +#define INIT_G() do { \ + SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ +} while (0) +#define G_posix (ENABLE_BC && (G.flags & BC_FLAG_S)) +#define G_warn (ENABLE_BC && (G.flags & BC_FLAG_W)) +#define G_exreg (ENABLE_DC && (G.flags & BC_FLAG_X)) -} BcGlobals; #define IS_BC (ENABLE_BC && (!ENABLE_DC || applet_name[0] == 'b')) @@ -860,8 +855,6 @@ static BcStatus bc_vm_posixError(BcStatus s, const char *file, size_t line, static void bc_vm_info(void); -static BcGlobals bcg; - static const char* const bc_args_env_name = "BC_ENV_ARGS"; static const char bc_err_fmt[] = "\n%s error: %s\n"; @@ -1356,7 +1349,7 @@ static BcStatus bc_read_line(BcVec *vec, const char *prompt) int i; signed char c; - if (bcg.ttyin && !bcg.posix) { + if (G.ttyin && !G_posix) { fputs(prompt, stderr); fflush(stderr); } @@ -1373,11 +1366,11 @@ static BcStatus bc_read_line(BcVec *vec, const char *prompt) if (i == EOF) { #if ENABLE_FEATURE_BC_SIGNALS if (errno == EINTR) { - bcg.sigc = bcg.sig; - bcg.signe = 0; - if (bcg.ttyin) { + G.sigc = G.sig; + G.signe = 0; + if (G.ttyin) { fputs(bc_program_ready_msg, stderr); - if (!bcg.posix) fputs(prompt, stderr); + if (!G_posix) fputs(prompt, stderr); fflush(stderr); } clearerr(stdin); @@ -1478,20 +1471,20 @@ static BcStatus bc_num_subArrays(BcDig *restrict a, BcDig *restrict b, size_t len) { size_t i, j; - for (i = 0; !bcg.signe && i < len; ++i) { - for (a[i] -= b[i], j = 0; !bcg.signe && a[i + j] < 0;) { + for (i = 0; !G.signe && i < len; ++i) { + for (a[i] -= b[i], j = 0; !G.signe && a[i + j] < 0;) { a[i + j++] += 10; a[i + j] -= 1; } } - return bcg.signe ? BC_STATUS_EXEC_SIGNAL : BC_STATUS_SUCCESS; + return G.signe ? BC_STATUS_EXEC_SIGNAL : BC_STATUS_SUCCESS; } static ssize_t bc_num_compare(BcDig *restrict a, BcDig *restrict b, size_t len) { size_t i; int c = 0; - for (i = len - 1; !bcg.signe && i < len && !(c = a[i] - b[i]); --i); + for (i = len - 1; !G.signe && i < len && !(c = a[i] - b[i]); --i); return BC_NUM_NEG(i + 1, c < 0); } @@ -1537,7 +1530,7 @@ static ssize_t bc_num_cmp(BcNum *a, BcNum *b) cmp = bc_num_compare(max_num, min_num, b_int + min); if (cmp != 0) return BC_NUM_NEG(cmp, (!a_max) != neg); - for (max_num -= diff, i = diff - 1; !bcg.signe && i < diff; --i) { + for (max_num -= diff, i = diff - 1; !G.signe && i < diff; --i) { if (max_num[i]) return BC_NUM_NEG(1, (!a_max) != neg); } @@ -1696,13 +1689,13 @@ static BcStatus bc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) ptr = ptr_b; } - for (carry = 0, i = 0; !bcg.signe && i < min_rdx + min_int; ++i, ++c->len) { + for (carry = 0, i = 0; !G.signe && i < min_rdx + min_int; ++i, ++c->len) { in = ((int) ptr_a[i]) + ((int) ptr_b[i]) + carry; carry = in / 10; ptr_c[i] = (BcDig)(in % 10); } - for (; !bcg.signe && i < max + min_rdx; ++i, ++c->len) { + for (; !G.signe && i < max + min_rdx; ++i, ++c->len) { in = ((int) ptr[i]) + carry; carry = in / 10; ptr_c[i] = (BcDig)(in % 10); @@ -1710,7 +1703,7 @@ static BcStatus bc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) if (carry != 0) c->num[c->len++] = (BcDig) carry; - return bcg.signe ? BC_STATUS_EXEC_SIGNAL : BC_STATUS_SUCCESS; + return G.signe ? BC_STATUS_EXEC_SIGNAL : BC_STATUS_SUCCESS; } static BcStatus bc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) @@ -1785,7 +1778,7 @@ static BcStatus bc_num_k(BcNum *restrict a, BcNum *restrict b, BcNum l1, h1, l2, h2, m2, m1, z0, z1, z2, temp; bool aone = BC_NUM_ONE(a); - if (bcg.signe) return BC_STATUS_EXEC_SIGNAL; + if (G.signe) return BC_STATUS_EXEC_SIGNAL; if (a->len == 0 || b->len == 0) { bc_num_zero(c); return BC_STATUS_SUCCESS; @@ -1803,9 +1796,9 @@ static BcStatus bc_num_k(BcNum *restrict a, BcNum *restrict b, memset(c->num, 0, sizeof(BcDig) * c->cap); c->len = carry = len = 0; - for (i = 0; !bcg.signe && i < b->len; ++i) { + for (i = 0; !G.signe && i < b->len; ++i) { - for (j = 0; !bcg.signe && j < a->len; ++j) { + for (j = 0; !G.signe && j < a->len; ++j) { int in = (int) c->num[i + j]; in += ((int) a->num[j]) * ((int) b->num[i]) + carry; carry = in / 10; @@ -1819,7 +1812,7 @@ static BcStatus bc_num_k(BcNum *restrict a, BcNum *restrict b, c->len = len; - return bcg.signe ? BC_STATUS_EXEC_SIGNAL : BC_STATUS_SUCCESS; + return G.signe ? BC_STATUS_EXEC_SIGNAL : BC_STATUS_SUCCESS; } bc_num_init(&l1, max); @@ -1969,7 +1962,7 @@ static BcStatus bc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) c->len = cp.len; p = b->num; - for (i = end - 1; !bcg.signe && !s && i < end; --i) { + for (i = end - 1; !G.signe && !s && i < end; --i) { n = cp.num + i; for (q = 0; (!s && n[len] != 0) || bc_num_compare(n, p, len) >= 0; ++q) s = bc_num_subArrays(n, p, len); @@ -2069,20 +2062,20 @@ static BcStatus bc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) b->neg = neg; - for (powrdx = a->rdx; !bcg.signe && !(pow & 1); pow >>= 1) { + for (powrdx = a->rdx; !G.signe && !(pow & 1); pow >>= 1) { powrdx <<= 1; s = bc_num_mul(©, ©, ©, powrdx); if (s) goto err; } - if (bcg.signe) { + if (G.signe) { s = BC_STATUS_EXEC_SIGNAL; goto err; } bc_num_copy(c, ©); - for (resrdx = powrdx, pow >>= 1; !bcg.signe && pow != 0; pow >>= 1) { + for (resrdx = powrdx, pow >>= 1; !G.signe && pow != 0; pow >>= 1) { powrdx <<= 1; s = bc_num_mul(©, ©, ©, powrdx); @@ -2100,7 +2093,7 @@ static BcStatus bc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) if (s) goto err; } - if (bcg.signe) { + if (G.signe) { s = BC_STATUS_EXEC_SIGNAL; goto err; } @@ -2657,7 +2650,7 @@ static BcStatus bc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale) resrdx = scale + 2; len = BC_NUM_INT(x0) + resrdx - 1; - while (!bcg.signe && (cmp != 0 || digs < len)) { + while (!G.signe && (cmp != 0 || digs < len)) { s = bc_num_div(a, x0, &f, resrdx); if (s) goto err; @@ -2685,7 +2678,7 @@ static BcStatus bc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale) x1 = temp; } - if (bcg.signe) { + if (G.signe) { s = BC_STATUS_EXEC_SIGNAL; goto err; } @@ -3461,7 +3454,7 @@ static BcStatus dc_lex_register(BcLex *l) if (isspace(l->buf[l->i - 1])) { bc_lex_whitespace(l); ++l->i; - if (!bcg.exreg) + if (!G_exreg) s = BC_STATUS_LEX_EXTENDED_REG; else s = bc_lex_name(l); @@ -4782,7 +4775,7 @@ static BcStatus bc_parse_parse(BcParse *p) else s = bc_parse_stmt(p); - if ((s && s != BC_STATUS_QUIT && s != BC_STATUS_LIMITS) || bcg.signe) + if ((s && s != BC_STATUS_QUIT && s != BC_STATUS_LIMITS) || G.signe) s = bc_parse_reset(p, s); return s; @@ -4802,7 +4795,7 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) paren_expr = rprn = done = get_token = assign = false; bin_last = true; - for (; !bcg.signe && !s && !done && bc_parse_exprs[t]; t = p->l.t.t) { + for (; !G.signe && !s && !done && bc_parse_exprs[t]; t = p->l.t.t) { switch (t) { case BC_LEX_OP_INC: @@ -4996,7 +4989,7 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) } if (s) return s; - if (bcg.signe) return BC_STATUS_EXEC_SIGNAL; + if (G.signe) return BC_STATUS_EXEC_SIGNAL; while (p->ops.len > ops_bgn) { @@ -5256,7 +5249,7 @@ static BcStatus dc_parse_parse(BcParse *p) else s = dc_parse_expr(p, 0); - if (s || bcg.signe) s = bc_parse_reset(p, s); + if (s || G.signe) s = bc_parse_reset(p, s); return s; } @@ -6639,13 +6632,13 @@ static BcStatus bc_program_reset(BcProgram *p, BcStatus s) ip = bc_vec_top(&p->stack); ip->idx = f->code.len; - if (!s && bcg.signe && !bcg.tty) return BC_STATUS_QUIT; + if (!s && G.signe && !G.tty) return BC_STATUS_QUIT; - bcg.sigc += bcg.signe; - bcg.signe = bcg.sig != bcg.sigc; + G.sigc += G.signe; + G.signe = G.sig != G.sigc; if (!s || s == BC_STATUS_EXEC_SIGNAL) { - if (bcg.ttyin) { + if (G.ttyin) { fputs(bc_program_ready_msg, stderr); fflush(stderr); s = BC_STATUS_SUCCESS; @@ -6966,7 +6959,7 @@ static BcStatus bc_program_exec(BcProgram *p) #endif // ENABLE_DC } - if ((s && s != BC_STATUS_QUIT) || bcg.signe) s = bc_program_reset(p, s); + if ((s && s != BC_STATUS_QUIT) || G.signe) s = bc_program_reset(p, s); // If the stack has changed, pointers may be invalid. ip = bc_vec_top(&p->stack); @@ -6981,10 +6974,10 @@ static BcStatus bc_program_exec(BcProgram *p) static void bc_vm_sig(int sig) { int err = errno; - size_t len = strlen(bcg.sig_msg); - if (sig == SIGINT && write(2, bcg.sig_msg, len) == (ssize_t) len) { - bcg.signe = bcg.sig == bcg.sigc; - bcg.sig += bcg.signe; + size_t len = strlen(G.sig_msg); + if (sig == SIGINT && write(2, G.sig_msg, len) == (ssize_t) len) { + G.signe = G.sig == G.sigc; + G.sig += G.signe; } errno = err; } @@ -7007,14 +7000,14 @@ static BcStatus bc_vm_error(BcStatus s, const char *file, size_t line) fprintf(stderr, " %s", file); fprintf(stderr, bc_err_line + 4 * !line, line); - return s * (!bcg.ttyin || !!strcmp(file, bc_program_stdin_name)); + return s * (!G.ttyin || !!strcmp(file, bc_program_stdin_name)); } #if ENABLE_BC static BcStatus bc_vm_posixError(BcStatus s, const char *file, size_t line, const char *msg) { - int p = (int) bcg.posix, w = (int) bcg.warn; + int p = (int) G_posix, w = (int) G_warn; const char *const fmt = p ? bc_err_fmt : bc_warn_fmt; if (!(p || w) || s < BC_STATUS_POSIX_NAME_LEN) return BC_STATUS_SUCCESS; @@ -7024,18 +7017,18 @@ static BcStatus bc_vm_posixError(BcStatus s, const char *file, size_t line, fprintf(stderr, " %s", file); fprintf(stderr, bc_err_line + 4 * !line, line); - return s * (!bcg.ttyin && !!p); + return s * (!G.ttyin && !!p); } -static void bc_vm_envArgs(BcVm *vm) +static void bc_vm_envArgs(void) { BcVec v; char *env_args = getenv(bc_args_env_name), *buf; if (!env_args) return; - vm->env_args = xstrdup(env_args); - buf = vm->env_args; + G.env_args = xstrdup(env_args); + buf = G.env_args; bc_vec_init(&v, sizeof(char *), NULL); bc_vec_push(&v, &bc_args_env_name); @@ -7050,7 +7043,7 @@ static void bc_vm_envArgs(BcVm *vm) ++buf; } - bc_args((int) v.len, (char **) v.v, &vm->flags, &vm->files); + bc_args((int) v.len, (char **) v.v, &G.flags, &G.files); bc_vec_free(&v); } @@ -7077,16 +7070,16 @@ static size_t bc_vm_envLen(const char *var) return len; } -static BcStatus bc_vm_process(BcVm *vm, const char *text) +static BcStatus bc_vm_process(const char *text) { - BcStatus s = bc_parse_text(&vm->prs, text); + BcStatus s = bc_parse_text(&G.prs, text); - s = bc_vm_error(s, vm->prs.l.f, vm->prs.l.line); + s = bc_vm_error(s, G.prs.l.f, G.prs.l.line); if (s) return s; - while (vm->prs.l.t.t != BC_LEX_EOF) { + while (G.prs.l.t.t != BC_LEX_EOF) { - s = vm->prs.parse(&vm->prs); + s = G.prs.parse(&G.prs); if (s == BC_STATUS_LIMITS) { @@ -7105,38 +7098,38 @@ static BcStatus bc_vm_process(BcVm *vm, const char *text) } else { if (s == BC_STATUS_QUIT) return s; - s = bc_vm_error(s, vm->prs.l.f, vm->prs.l.line); + s = bc_vm_error(s, G.prs.l.f, G.prs.l.line); if (s) return s; } } - if (BC_PARSE_CAN_EXEC(&vm->prs)) { - s = bc_program_exec(&vm->prog); - if (!s && bcg.tty) fflush(stdout); + if (BC_PARSE_CAN_EXEC(&G.prs)) { + s = bc_program_exec(&G.prog); + if (!s && G.tty) fflush(stdout); if (s && s != BC_STATUS_QUIT) - s = bc_vm_error(bc_program_reset(&vm->prog, s), vm->prs.l.f, 0); + s = bc_vm_error(bc_program_reset(&G.prog, s), G.prs.l.f, 0); } return s; } -static BcStatus bc_vm_file(BcVm *vm, const char *file) +static BcStatus bc_vm_file(const char *file) { BcStatus s; char *data; BcFunc *main_func; BcInstPtr *ip; - vm->prog.file = file; + G.prog.file = file; s = bc_read_file(file, &data); if (s) return bc_vm_error(s, file, 0); - bc_lex_file(&vm->prs.l, file); - s = bc_vm_process(vm, data); + bc_lex_file(&G.prs.l, file); + s = bc_vm_process(data); if (s) goto err; - main_func = bc_vec_item(&vm->prog.fns, BC_PROG_MAIN); - ip = bc_vec_item(&vm->prog.stack, 0); + main_func = bc_vec_item(&G.prog.fns, BC_PROG_MAIN); + ip = bc_vec_item(&G.prog.stack, 0); if (main_func->code.len < ip->idx) s = BC_STATUS_EXEC_FILE_NOT_EXECUTABLE; @@ -7145,7 +7138,7 @@ err: return s; } -static BcStatus bc_vm_stdin(BcVm *vm) +static BcStatus bc_vm_stdin(void) { BcStatus s = BC_STATUS_SUCCESS; BcVec buf, buffer; @@ -7153,8 +7146,8 @@ static BcStatus bc_vm_stdin(BcVm *vm) size_t len, i, str = 0; bool comment = false, notend; - vm->prog.file = bc_program_stdin_name; - bc_lex_file(&vm->prs.l, bc_program_stdin_name); + G.prog.file = bc_program_stdin_name; + bc_lex_file(&G.prs.l, bc_program_stdin_name); bc_vec_init(&buffer, sizeof(char), NULL); bc_vec_init(&buf, sizeof(char), NULL); @@ -7171,9 +7164,9 @@ static BcStatus bc_vm_stdin(BcVm *vm) len = buf.len - 1; if (len == 1) { - if (str && buf.v[0] == vm->exe.send) + if (str && buf.v[0] == G.send) str -= 1; - else if (buf.v[0] == vm->exe.sbgn) + else if (buf.v[0] == G.sbgn) str += 1; } else if (len > 1 || comment) { @@ -7184,11 +7177,11 @@ static BcStatus bc_vm_stdin(BcVm *vm) c = string[i]; if (i - 1 > len || string[i - 1] != '\\') { - if (vm->exe.sbgn == vm->exe.send) - str ^= c == vm->exe.sbgn; - else if (c == vm->exe.send) + if (G.sbgn == G.send) + str ^= c == G.sbgn; + else if (c == G.send) str -= 1; - else if (c == vm->exe.sbgn) + else if (c == G.sbgn) str += 1; } @@ -7207,13 +7200,13 @@ static BcStatus bc_vm_stdin(BcVm *vm) } bc_vec_concat(&buffer, buf.v); - s = bc_vm_process(vm, buffer.v); + s = bc_vm_process(buffer.v); if (s) goto err; bc_vec_npop(&buffer, buffer.len); } - if (s == BC_STATUS_BIN_FILE) s = bc_vm_error(s, vm->prs.l.f, 0); + if (s == BC_STATUS_BIN_FILE) s = bc_vm_error(s, G.prs.l.f, 0); // INPUT_EOF will always happen when stdin is // closed. It's not a problem in that case. @@ -7221,11 +7214,11 @@ static BcStatus bc_vm_stdin(BcVm *vm) s = BC_STATUS_SUCCESS; if (str) - s = bc_vm_error(BC_STATUS_LEX_NO_STRING_END, vm->prs.l.f, - vm->prs.l.line); + s = bc_vm_error(BC_STATUS_LEX_NO_STRING_END, G.prs.l.f, + G.prs.l.line); else if (comment) - s = bc_vm_error(BC_STATUS_LEX_NO_COMMENT_END, vm->prs.l.f, - vm->prs.l.line); + s = bc_vm_error(BC_STATUS_LEX_NO_COMMENT_END, G.prs.l.f, + G.prs.l.line); err: bc_vec_free(&buf); @@ -7233,46 +7226,46 @@ err: return s; } -static BcStatus bc_vm_exec(BcVm *vm) +static BcStatus bc_vm_exec(void) { BcStatus s = BC_STATUS_SUCCESS; size_t i; #if ENABLE_BC - if (vm->flags & BC_FLAG_L) { + if (G.flags & BC_FLAG_L) { - bc_lex_file(&vm->prs.l, bc_lib_name); - s = bc_parse_text(&vm->prs, bc_lib); + bc_lex_file(&G.prs.l, bc_lib_name); + s = bc_parse_text(&G.prs, bc_lib); - while (!s && vm->prs.l.t.t != BC_LEX_EOF) s = vm->prs.parse(&vm->prs); + while (!s && G.prs.l.t.t != BC_LEX_EOF) s = G.prs.parse(&G.prs); if (s) return s; - s = bc_program_exec(&vm->prog); + s = bc_program_exec(&G.prog); if (s) return s; } #endif - for (i = 0; !s && i < vm->files.len; ++i) - s = bc_vm_file(vm, *((char **) bc_vec_item(&vm->files, i))); + for (i = 0; !s && i < G.files.len; ++i) + s = bc_vm_file(*((char **) bc_vec_item(&G.files, i))); if (s && s != BC_STATUS_QUIT) return s; - if (IS_BC || !vm->files.len) s = bc_vm_stdin(vm); - if (!s && !BC_PARSE_CAN_EXEC(&vm->prs)) s = bc_vm_process(vm, ""); + if (IS_BC || !G.files.len) s = bc_vm_stdin(); + if (!s && !BC_PARSE_CAN_EXEC(&G.prs)) s = bc_vm_process(""); if (s == BC_STATUS_QUIT) s = BC_STATUS_SUCCESS; return s; } -static void bc_vm_free(BcVm *vm) +static void bc_vm_free(void) { - bc_vec_free(&vm->files); - bc_program_free(&vm->prog); - bc_parse_free(&vm->prs); - free(vm->env_args); + bc_vec_free(&G.files); + bc_program_free(&G.prog); + bc_parse_free(&G.prs); + free(G.env_args); } -static void bc_vm_init(BcVm *vm, BcVmExe exe, const char *env_len) +static void bc_vm_init(const char *env_len) { size_t len = bc_vm_envLen(env_len); #if ENABLE_FEATURE_BC_SIGNALS @@ -7284,47 +7277,32 @@ static void bc_vm_init(BcVm *vm, BcVmExe exe, const char *env_len) sigaction(SIGINT, &sa, NULL); #endif - memset(vm, 0, sizeof(BcVm)); - - vm->exe = exe; - vm->flags = 0; - vm->env_args = NULL; - - bc_vec_init(&vm->files, sizeof(char *), NULL); + bc_vec_init(&G.files, sizeof(char *), NULL); #if ENABLE_BC - vm->flags |= BC_FLAG_S * IS_BC * (getenv("POSIXLY_CORRECT") != NULL); - if (IS_BC) bc_vm_envArgs(vm); + G.flags |= BC_FLAG_S * IS_BC * (getenv("POSIXLY_CORRECT") != NULL); + if (IS_BC) bc_vm_envArgs(); #endif - bc_program_init(&vm->prog, len, exe.init, exe.exp); - exe.init(&vm->prs, &vm->prog, BC_PROG_MAIN); + bc_program_init(&G.prog, len, G.init, G.exp); + G.init(&G.prs, &G.prog, BC_PROG_MAIN); } -static BcStatus bc_vm_run(int argc, char *argv[], BcVmExe exe, +static BcStatus bc_vm_run(int argc, char *argv[], const char *env_len) { BcStatus st; - BcVm vm; - bc_vm_init(&vm, exe, env_len); - bc_args(argc, argv, &vm.flags, &vm.files); + bc_vm_init(env_len); + bc_args(argc, argv, &G.flags, &G.files); - bcg.ttyin = isatty(0); - bcg.tty = bcg.ttyin || (vm.flags & BC_FLAG_I) || isatty(1); + G.ttyin = isatty(0); + G.tty = G.ttyin || (G.flags & BC_FLAG_I) || isatty(1); -#if ENABLE_BC - bcg.posix = vm.flags & BC_FLAG_S; - bcg.warn = vm.flags & BC_FLAG_W; -#endif -#if ENABLE_DC - bcg.exreg = vm.flags & BC_FLAG_X; -#endif + if (G.ttyin && !(G.flags & BC_FLAG_Q)) bc_vm_info(); + st = bc_vm_exec(); - if (bcg.ttyin && !(vm.flags & BC_FLAG_Q)) bc_vm_info(); - st = bc_vm_exec(&vm); - - bc_vm_free(&vm); + bc_vm_free(); return st; } @@ -7332,17 +7310,15 @@ static BcStatus bc_vm_run(int argc, char *argv[], BcVmExe exe, int bc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int bc_main(int argc, char **argv) { - BcVmExe exec; - + INIT_G(); # if ENABLE_FEATURE_BC_SIGNALS - bcg.sig_msg = "\ninterrupt (type \"quit\" to exit)\n"; + G.sig_msg = "\ninterrupt (type \"quit\" to exit)\n"; # endif + G.init = bc_parse_init; + G.exp = bc_parse_expression; + G.sbgn = G.send = '"'; - exec.init = bc_parse_init; - exec.exp = bc_parse_expression; - exec.sbgn = exec.send = '"'; - - return bc_vm_run(argc, argv, exec, "BC_LINE_LENGTH"); + return bc_vm_run(argc, argv, "BC_LINE_LENGTH"); } #endif @@ -7350,17 +7326,15 @@ int bc_main(int argc, char **argv) int dc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int dc_main(int argc, char **argv) { - BcVmExe exec; - + INIT_G(); # if ENABLE_FEATURE_BC_SIGNALS - bcg.sig_msg = "\ninterrupt (type \"q\" to exit)\n"; + G.sig_msg = "\ninterrupt (type \"q\" to exit)\n"; # endif + G.init = dc_parse_init; + G.exp = dc_parse_expr; + G.sbgn = '['; + G.send = ']'; - exec.init = dc_parse_init; - exec.exp = dc_parse_expr; - exec.sbgn = '['; - exec.send = ']'; - - return bc_vm_run(argc, argv, exec, "DC_LINE_LENGTH"); + return bc_vm_run(argc, argv, "DC_LINE_LENGTH"); } #endif -- cgit v1.2.3-55-g6feb From ab3c568fd869e84a7862f3450a4690d3d7b60704 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 2 Dec 2018 16:32:36 +0100 Subject: bc: simplify ^C handling It's still buggy: if SIGINT would interrupt e.g. output write(), the result would not be as intended: >>> while ( 1 ) print 1 ... 11111111111111111111111111111111111111111111111111111111111111111111\ 11111111111111111111111111111111111111111111111111111111111111111111\ ^Cready for more input interrupt (type "quit" to exit) >>> bc: output error function old new delta dc_parse_parse 58 53 -5 bc_parse_parse 476 471 -5 bc_num_d 609 604 -5 bc_num_cmp 299 294 -5 bc_num_compare 90 84 -6 bc_parse_expr 2222 2215 -7 bc_num_subArrays 82 74 -8 dc_main 72 62 -10 bc_main 72 62 -10 bc_program_exec 4413 4401 -12 bc_num_a 491 474 -17 bc_read_line 364 344 -20 bc_num_p 540 518 -22 bc_program_reset 192 168 -24 bc_num_k 1031 1005 -26 bc_vm_run 2382 2317 -65 bc_vm_sig 97 - -97 ------------------------------------------------------------------------------ (add/remove: 0/1 grow/shrink: 0/16 up/down: 0/-344) Total: -344 bytes text data bss dec hex filename 989372 485 7296 997153 f3721 busybox_old 989028 485 7296 996809 f35c9 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 139 ++++++++++++++++++++++++--------------------------------- 1 file changed, 59 insertions(+), 80 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index e13b2283c..72afb6808 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -826,16 +826,8 @@ struct globals { char *env_args; - unsigned sig; //counter? - unsigned sigc; //counter? - smallint signe; //flag - smallint tty; smallint ttyin; - -#if ENABLE_FEATURE_BC_SIGNALS - const char *sig_msg; -#endif } FIX_ALIASING; #define G (*ptr_to_globals) #define INIT_G() do { \ @@ -844,6 +836,7 @@ struct globals { #define G_posix (ENABLE_BC && (G.flags & BC_FLAG_S)) #define G_warn (ENABLE_BC && (G.flags & BC_FLAG_W)) #define G_exreg (ENABLE_DC && (G.flags & BC_FLAG_X)) +#define G_interrupt (ENABLE_FEATURE_BC_SIGNALS ? bb_got_signal : 0) #define IS_BC (ENABLE_BC && (!ENABLE_DC || applet_name[0] == 'b')) @@ -1349,36 +1342,47 @@ static BcStatus bc_read_line(BcVec *vec, const char *prompt) int i; signed char c; - if (G.ttyin && !G_posix) { - fputs(prompt, stderr); - fflush(stderr); - } - bc_vec_npop(vec, vec->len); + fflush(stdout); +#if ENABLE_FEATURE_BC_SIGNALS + if (bb_got_signal) { /* ^C was pressed */ + intr: + fputs(IS_BC + ? "\ninterrupt (type \"quit\" to exit)\n" + : "\ninterrupt (type \"q\" to exit)\n" + , stderr); + } + bb_got_signal = 0; /* resets G_interrupt to zero */ +#endif + if (G.ttyin && !G_posix) + fputs(prompt, stderr); + fflush(stderr); + +#if ENABLE_FEATURE_BC_SIGNALS + again: + errno = 0; +#endif do { if (ferror(stdout) || ferror(stderr)) bb_perror_msg_and_die("output error"); - errno = 0; i = fgetc(stdin); +#if ENABLE_FEATURE_BC_SIGNALS + if (bb_got_signal) /* ^C was pressed */ + goto intr; +#endif + if (i == EOF) { #if ENABLE_FEATURE_BC_SIGNALS if (errno == EINTR) { - G.sigc = G.sig; - G.signe = 0; - if (G.ttyin) { - fputs(bc_program_ready_msg, stderr); - if (!G_posix) fputs(prompt, stderr); - fflush(stderr); - } clearerr(stdin); - continue; + goto again; } +#endif if (ferror(stdin)) bb_perror_msg_and_die("input error"); -#endif return BC_STATUS_INPUT_EOF; } @@ -1471,20 +1475,20 @@ static BcStatus bc_num_subArrays(BcDig *restrict a, BcDig *restrict b, size_t len) { size_t i, j; - for (i = 0; !G.signe && i < len; ++i) { - for (a[i] -= b[i], j = 0; !G.signe && a[i + j] < 0;) { + for (i = 0; !G_interrupt && i < len; ++i) { + for (a[i] -= b[i], j = 0; !G_interrupt && a[i + j] < 0;) { a[i + j++] += 10; a[i + j] -= 1; } } - return G.signe ? BC_STATUS_EXEC_SIGNAL : BC_STATUS_SUCCESS; + return G_interrupt ? BC_STATUS_EXEC_SIGNAL : BC_STATUS_SUCCESS; } static ssize_t bc_num_compare(BcDig *restrict a, BcDig *restrict b, size_t len) { size_t i; int c = 0; - for (i = len - 1; !G.signe && i < len && !(c = a[i] - b[i]); --i); + for (i = len - 1; !G_interrupt && i < len && !(c = a[i] - b[i]); --i); return BC_NUM_NEG(i + 1, c < 0); } @@ -1530,7 +1534,7 @@ static ssize_t bc_num_cmp(BcNum *a, BcNum *b) cmp = bc_num_compare(max_num, min_num, b_int + min); if (cmp != 0) return BC_NUM_NEG(cmp, (!a_max) != neg); - for (max_num -= diff, i = diff - 1; !G.signe && i < diff; --i) { + for (max_num -= diff, i = diff - 1; !G_interrupt && i < diff; --i) { if (max_num[i]) return BC_NUM_NEG(1, (!a_max) != neg); } @@ -1689,13 +1693,13 @@ static BcStatus bc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) ptr = ptr_b; } - for (carry = 0, i = 0; !G.signe && i < min_rdx + min_int; ++i, ++c->len) { + for (carry = 0, i = 0; !G_interrupt && i < min_rdx + min_int; ++i, ++c->len) { in = ((int) ptr_a[i]) + ((int) ptr_b[i]) + carry; carry = in / 10; ptr_c[i] = (BcDig)(in % 10); } - for (; !G.signe && i < max + min_rdx; ++i, ++c->len) { + for (; !G_interrupt && i < max + min_rdx; ++i, ++c->len) { in = ((int) ptr[i]) + carry; carry = in / 10; ptr_c[i] = (BcDig)(in % 10); @@ -1703,7 +1707,7 @@ static BcStatus bc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) if (carry != 0) c->num[c->len++] = (BcDig) carry; - return G.signe ? BC_STATUS_EXEC_SIGNAL : BC_STATUS_SUCCESS; + return G_interrupt ? BC_STATUS_EXEC_SIGNAL : BC_STATUS_SUCCESS; } static BcStatus bc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) @@ -1778,7 +1782,7 @@ static BcStatus bc_num_k(BcNum *restrict a, BcNum *restrict b, BcNum l1, h1, l2, h2, m2, m1, z0, z1, z2, temp; bool aone = BC_NUM_ONE(a); - if (G.signe) return BC_STATUS_EXEC_SIGNAL; + if (G_interrupt) return BC_STATUS_EXEC_SIGNAL; if (a->len == 0 || b->len == 0) { bc_num_zero(c); return BC_STATUS_SUCCESS; @@ -1796,9 +1800,9 @@ static BcStatus bc_num_k(BcNum *restrict a, BcNum *restrict b, memset(c->num, 0, sizeof(BcDig) * c->cap); c->len = carry = len = 0; - for (i = 0; !G.signe && i < b->len; ++i) { + for (i = 0; !G_interrupt && i < b->len; ++i) { - for (j = 0; !G.signe && j < a->len; ++j) { + for (j = 0; !G_interrupt && j < a->len; ++j) { int in = (int) c->num[i + j]; in += ((int) a->num[j]) * ((int) b->num[i]) + carry; carry = in / 10; @@ -1812,7 +1816,7 @@ static BcStatus bc_num_k(BcNum *restrict a, BcNum *restrict b, c->len = len; - return G.signe ? BC_STATUS_EXEC_SIGNAL : BC_STATUS_SUCCESS; + return G_interrupt ? BC_STATUS_EXEC_SIGNAL : BC_STATUS_SUCCESS; } bc_num_init(&l1, max); @@ -1962,7 +1966,7 @@ static BcStatus bc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) c->len = cp.len; p = b->num; - for (i = end - 1; !G.signe && !s && i < end; --i) { + for (i = end - 1; !G_interrupt && !s && i < end; --i) { n = cp.num + i; for (q = 0; (!s && n[len] != 0) || bc_num_compare(n, p, len) >= 0; ++q) s = bc_num_subArrays(n, p, len); @@ -2062,20 +2066,20 @@ static BcStatus bc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) b->neg = neg; - for (powrdx = a->rdx; !G.signe && !(pow & 1); pow >>= 1) { + for (powrdx = a->rdx; !G_interrupt && !(pow & 1); pow >>= 1) { powrdx <<= 1; s = bc_num_mul(©, ©, ©, powrdx); if (s) goto err; } - if (G.signe) { + if (G_interrupt) { s = BC_STATUS_EXEC_SIGNAL; goto err; } bc_num_copy(c, ©); - for (resrdx = powrdx, pow >>= 1; !G.signe && pow != 0; pow >>= 1) { + for (resrdx = powrdx, pow >>= 1; !G_interrupt && pow != 0; pow >>= 1) { powrdx <<= 1; s = bc_num_mul(©, ©, ©, powrdx); @@ -2093,7 +2097,7 @@ static BcStatus bc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) if (s) goto err; } - if (G.signe) { + if (G_interrupt) { s = BC_STATUS_EXEC_SIGNAL; goto err; } @@ -2650,7 +2654,7 @@ static BcStatus bc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale) resrdx = scale + 2; len = BC_NUM_INT(x0) + resrdx - 1; - while (!G.signe && (cmp != 0 || digs < len)) { + while (!G_interrupt && (cmp != 0 || digs < len)) { s = bc_num_div(a, x0, &f, resrdx); if (s) goto err; @@ -2678,7 +2682,7 @@ static BcStatus bc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale) x1 = temp; } - if (G.signe) { + if (G_interrupt) { s = BC_STATUS_EXEC_SIGNAL; goto err; } @@ -4775,7 +4779,7 @@ static BcStatus bc_parse_parse(BcParse *p) else s = bc_parse_stmt(p); - if ((s && s != BC_STATUS_QUIT && s != BC_STATUS_LIMITS) || G.signe) + if ((s && s != BC_STATUS_QUIT && s != BC_STATUS_LIMITS) || G_interrupt) s = bc_parse_reset(p, s); return s; @@ -4795,7 +4799,7 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) paren_expr = rprn = done = get_token = assign = false; bin_last = true; - for (; !G.signe && !s && !done && bc_parse_exprs[t]; t = p->l.t.t) { + for (; !G_interrupt && !s && !done && bc_parse_exprs[t]; t = p->l.t.t) { switch (t) { case BC_LEX_OP_INC: @@ -4989,7 +4993,7 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) } if (s) return s; - if (G.signe) return BC_STATUS_EXEC_SIGNAL; + if (G_interrupt) return BC_STATUS_EXEC_SIGNAL; while (p->ops.len > ops_bgn) { @@ -5249,7 +5253,7 @@ static BcStatus dc_parse_parse(BcParse *p) else s = dc_parse_expr(p, 0); - if (s || G.signe) s = bc_parse_reset(p, s); + if (s || G_interrupt) s = bc_parse_reset(p, s); return s; } @@ -6632,13 +6636,11 @@ static BcStatus bc_program_reset(BcProgram *p, BcStatus s) ip = bc_vec_top(&p->stack); ip->idx = f->code.len; - if (!s && G.signe && !G.tty) return BC_STATUS_QUIT; - - G.sigc += G.signe; - G.signe = G.sig != G.sigc; + if (!s && G_interrupt && !G.tty) return BC_STATUS_QUIT; if (!s || s == BC_STATUS_EXEC_SIGNAL) { if (G.ttyin) { + fflush(stdout); fputs(bc_program_ready_msg, stderr); fflush(stderr); s = BC_STATUS_SUCCESS; @@ -6959,7 +6961,7 @@ static BcStatus bc_program_exec(BcProgram *p) #endif // ENABLE_DC } - if ((s && s != BC_STATUS_QUIT) || G.signe) s = bc_program_reset(p, s); + if ((s && s != BC_STATUS_QUIT) || G_interrupt) s = bc_program_reset(p, s); // If the stack has changed, pointers may be invalid. ip = bc_vec_top(&p->stack); @@ -6970,19 +6972,6 @@ static BcStatus bc_program_exec(BcProgram *p) return s; } -#if ENABLE_FEATURE_BC_SIGNALS -static void bc_vm_sig(int sig) -{ - int err = errno; - size_t len = strlen(G.sig_msg); - if (sig == SIGINT && write(2, G.sig_msg, len) == (ssize_t) len) { - G.signe = G.sig == G.sigc; - G.sig += G.signe; - } - errno = err; -} -#endif - static void bc_vm_info(void) { printf("%s "BB_VER"\n" @@ -7268,21 +7257,17 @@ static void bc_vm_free(void) static void bc_vm_init(const char *env_len) { size_t len = bc_vm_envLen(env_len); -#if ENABLE_FEATURE_BC_SIGNALS - struct sigaction sa; - sigemptyset(&sa.sa_mask); - sa.sa_handler = bc_vm_sig; - sa.sa_flags = 0; - sigaction(SIGINT, &sa, NULL); +#if ENABLE_FEATURE_BC_SIGNALS + signal_no_SA_RESTART_empty_mask(SIGINT, record_signo); #endif bc_vec_init(&G.files, sizeof(char *), NULL); -#if ENABLE_BC - G.flags |= BC_FLAG_S * IS_BC * (getenv("POSIXLY_CORRECT") != NULL); - if (IS_BC) bc_vm_envArgs(); -#endif + if (IS_BC) { + G.flags |= BC_FLAG_S * (getenv("POSIXLY_CORRECT") != NULL); + bc_vm_envArgs(); + } bc_program_init(&G.prog, len, G.init, G.exp); G.init(&G.prs, &G.prog, BC_PROG_MAIN); @@ -7311,9 +7296,6 @@ int bc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int bc_main(int argc, char **argv) { INIT_G(); -# if ENABLE_FEATURE_BC_SIGNALS - G.sig_msg = "\ninterrupt (type \"quit\" to exit)\n"; -# endif G.init = bc_parse_init; G.exp = bc_parse_expression; G.sbgn = G.send = '"'; @@ -7327,9 +7309,6 @@ int dc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int dc_main(int argc, char **argv) { INIT_G(); -# if ENABLE_FEATURE_BC_SIGNALS - G.sig_msg = "\ninterrupt (type \"q\" to exit)\n"; -# endif G.init = dc_parse_init; G.exp = dc_parse_expr; G.sbgn = '['; -- cgit v1.2.3-55-g6feb From 785e4b30570ddd772c38f3f8693b686430fc35a3 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 2 Dec 2018 17:18:52 +0100 Subject: bc: propagate fixed arguments into callees Looks like there is only one "BcProgram" object, &G.prog. function old new delta bc_program_exec 4401 4523 +122 bc_program_execStr 579 606 +27 bc_program_read 323 342 +19 bc_args 83 97 +14 bc_vm_process 327 323 -4 bc_num_ulong 95 85 -10 dc_main 62 48 -14 bc_main 62 48 -14 bc_vm_run 2317 1923 -394 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 4/5 up/down: 182/-436) Total: -254 bytes text data bss dec hex filename 989028 485 7296 996809 f35c9 busybox_old 988774 485 7296 996555 f34cb busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 236 ++++++++++++++++++++++++++++++--------------------------- 1 file changed, 125 insertions(+), 111 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 72afb6808..117318bfa 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -790,7 +790,6 @@ typedef unsigned long (*BcProgramBuiltIn)(BcNum *); static void bc_program_addFunc(BcProgram *p, char *name, size_t *idx); static BcStatus bc_program_reset(BcProgram *p, BcStatus s); -static BcStatus bc_program_exec(BcProgram *p); #define BC_FLAG_X (1 << 0) #define BC_FLAG_W (1 << 1) @@ -813,8 +812,6 @@ static BcStatus bc_program_exec(BcProgram *p); #define BC_MAX_VARS ((unsigned long) SIZE_MAX - 1) struct globals { - BcParseInit init; - BcParseExpr exp; char sbgn; char send; @@ -1416,14 +1413,13 @@ read_err: return s; } -static void bc_args(int argc, char *argv[], uint32_t *flags, BcVec *files) +static void bc_args(int argc, char **argv) { int i; - bool do_exit = false; GETOPT_RESET(); #if ENABLE_FEATURE_BC_LONG_OPTIONS - *flags = getopt32long(argv, "xwvsqli", + G.flags = getopt32long(argv, "xwvsqli", "extended-register\0" No_argument "x" "warn\0" No_argument "w" "version\0" No_argument "v" @@ -1433,15 +1429,14 @@ static void bc_args(int argc, char *argv[], uint32_t *flags, BcVec *files) "interactive\0" No_argument "i" ); #else - *flags = getopt32(argv, "xwvsqli"); + G.flags = getopt32(argv, "xwvsqli"); #endif - if ((*flags) & BC_FLAG_V) bc_vm_info(); - if (do_exit) exit(0); + if (G.flags & BC_FLAG_V) bc_vm_info(); // should not be necessary, getopt32() handles this?? //if (argv[optind] && !strcmp(argv[optind], "--")) ++optind; - for (i = optind; i < argc; ++i) bc_vec_push(files, argv + i); + for (i = optind; i < argc; ++i) bc_vec_push(&G.files, argv + i); } static void bc_num_setToZero(BcNum *n, size_t scale) @@ -5452,8 +5447,10 @@ err: return s; } -static BcStatus bc_program_read(BcProgram *p) +static BcStatus bc_program_read(void) { + BcProgram *p = &G.prog; + BcStatus s; BcParse parse; BcVec buf; @@ -5477,6 +5474,7 @@ static BcStatus bc_program_read(BcProgram *p) s = bc_parse_text(&parse, buf.v); if (s) goto exec_err; +/// replace by IS_BC selection s = p->parse_expr(&parse, BC_PARSE_NOREAD); if (s) goto exec_err; @@ -6356,8 +6354,10 @@ static BcStatus bc_program_printStream(BcProgram *p) return s; } -static BcStatus bc_program_nquit(BcProgram *p) +static BcStatus bc_program_nquit(void) { + BcProgram *p = &G.prog; + BcStatus s; BcResult *opnd; BcNum *num = NULL; @@ -6380,9 +6380,11 @@ static BcStatus bc_program_nquit(BcProgram *p) return s; } -static BcStatus bc_program_execStr(BcProgram *p, char *code, size_t *bgn, +static BcStatus bc_program_execStr(char *code, size_t *bgn, bool cond) { + BcProgram *p = &G.prog; + BcStatus s = BC_STATUS_SUCCESS; BcResult *r; char **str; @@ -6451,10 +6453,11 @@ static BcStatus bc_program_execStr(BcProgram *p, char *code, size_t *bgn, f = bc_vec_item(&p->fns, fidx); if (f->code.len == 0) { - +/// replace by IS_BC selection p->parse_init(&prs, p, fidx); s = bc_parse_text(&prs, *str); if (s) goto err; +/// replace by IS_BC selection s = p->parse_expr(&prs, BC_PARSE_NOCALL); if (s) goto err; @@ -6511,88 +6514,6 @@ err: return s; } -static void bc_program_free(BcProgram *p) -{ - bc_num_free(&p->ib); - bc_num_free(&p->ob); - bc_num_free(&p->hexb); -#if ENABLE_DC - bc_num_free(&p->strmb); -#endif - bc_vec_free(&p->fns); - bc_vec_free(&p->fn_map); - bc_vec_free(&p->vars); - bc_vec_free(&p->var_map); - bc_vec_free(&p->arrs); - bc_vec_free(&p->arr_map); - bc_vec_free(&p->strs); - bc_vec_free(&p->consts); - bc_vec_free(&p->results); - bc_vec_free(&p->stack); - bc_num_free(&p->last); - bc_num_free(&p->zero); - bc_num_free(&p->one); -} - -static void bc_program_init(BcProgram *p, size_t line_len, BcParseInit init, - BcParseExpr expr) -{ - size_t idx; - BcInstPtr ip; - - memset(p, 0, sizeof(BcProgram)); - memset(&ip, 0, sizeof(BcInstPtr)); - - p->nchars = p->scale = 0; - p->len = line_len; - p->parse_init = init; - p->parse_expr = expr; - - bc_num_init(&p->ib, BC_NUM_DEF_SIZE); - bc_num_ten(&p->ib); - p->ib_t = 10; - - bc_num_init(&p->ob, BC_NUM_DEF_SIZE); - bc_num_ten(&p->ob); - p->ob_t = 10; - - bc_num_init(&p->hexb, BC_NUM_DEF_SIZE); - bc_num_ten(&p->hexb); - p->hexb.num[0] = 6; - -#if ENABLE_DC - bc_num_init(&p->strmb, BC_NUM_DEF_SIZE); - bc_num_ulong2num(&p->strmb, UCHAR_MAX + 1); -#endif - - bc_num_init(&p->last, BC_NUM_DEF_SIZE); - bc_num_zero(&p->last); - - bc_num_init(&p->zero, BC_NUM_DEF_SIZE); - bc_num_zero(&p->zero); - - bc_num_init(&p->one, BC_NUM_DEF_SIZE); - bc_num_one(&p->one); - - bc_vec_init(&p->fns, sizeof(BcFunc), bc_func_free); - bc_map_init(&p->fn_map); - - bc_program_addFunc(p, xstrdup(bc_func_main), &idx); - bc_program_addFunc(p, xstrdup(bc_func_read), &idx); - - bc_vec_init(&p->vars, sizeof(BcVec), bc_vec_free); - bc_map_init(&p->var_map); - - bc_vec_init(&p->arrs, sizeof(BcVec), bc_vec_free); - bc_map_init(&p->arr_map); - - bc_vec_init(&p->strs, sizeof(char *), bc_string_free); - bc_vec_init(&p->consts, sizeof(char *), bc_string_free); - bc_vec_init(&p->results, sizeof(BcResult), bc_result_free); - bc_vec_init(&p->stack, sizeof(BcInstPtr), NULL); - bc_vec_push(&p->stack, &ip); -} - static void bc_program_addFunc(BcProgram *p, char *name, size_t *idx) { BcStatus s; @@ -6652,8 +6573,10 @@ static BcStatus bc_program_reset(BcProgram *p, BcStatus s) return s; } -static BcStatus bc_program_exec(BcProgram *p) +static BcStatus bc_program_exec(void) { + BcProgram *p = &G.prog; + BcStatus s = BC_STATUS_SUCCESS; size_t idx; BcResult r, *ptr; @@ -6731,7 +6654,7 @@ static BcStatus bc_program_exec(BcProgram *p) case BC_INST_READ: { - s = bc_program_read(p); + s = bc_program_read(); break; } @@ -6869,7 +6792,7 @@ static BcStatus bc_program_exec(BcProgram *p) case BC_INST_EXEC_COND: { cond = inst == BC_INST_EXEC_COND; - s = bc_program_execStr(p, code, &ip->idx, cond); + s = bc_program_execStr(code, &ip->idx, cond); break; } @@ -6955,7 +6878,7 @@ static BcStatus bc_program_exec(BcProgram *p) case BC_INST_NQUIT: { - s = bc_program_nquit(p); + s = bc_program_nquit(); break; } #endif // ENABLE_DC @@ -7032,7 +6955,7 @@ static void bc_vm_envArgs(void) ++buf; } - bc_args((int) v.len, (char **) v.v, &G.flags, &G.files); + bc_args((int) v.len, (char **) v.v); bc_vec_free(&v); } @@ -7093,7 +7016,7 @@ static BcStatus bc_vm_process(const char *text) } if (BC_PARSE_CAN_EXEC(&G.prs)) { - s = bc_program_exec(&G.prog); + s = bc_program_exec(); if (!s && G.tty) fflush(stdout); if (s && s != BC_STATUS_QUIT) s = bc_vm_error(bc_program_reset(&G.prog, s), G.prs.l.f, 0); @@ -7229,7 +7152,7 @@ static BcStatus bc_vm_exec(void) while (!s && G.prs.l.t.t != BC_LEX_EOF) s = G.prs.parse(&G.prs); if (s) return s; - s = bc_program_exec(&G.prog); + s = bc_program_exec(); if (s) return s; } #endif @@ -7246,6 +7169,30 @@ static BcStatus bc_vm_exec(void) return s; } +#if ENABLE_FEATURE_CLEAN_UP +static void bc_program_free(BcProgram *p) +{ + bc_num_free(&p->ib); + bc_num_free(&p->ob); + bc_num_free(&p->hexb); +# if ENABLE_DC + bc_num_free(&p->strmb); +# endif + bc_vec_free(&p->fns); + bc_vec_free(&p->fn_map); + bc_vec_free(&p->vars); + bc_vec_free(&p->var_map); + bc_vec_free(&p->arrs); + bc_vec_free(&p->arr_map); + bc_vec_free(&p->strs); + bc_vec_free(&p->consts); + bc_vec_free(&p->results); + bc_vec_free(&p->stack); + bc_num_free(&p->last); + bc_num_free(&p->zero); + bc_num_free(&p->one); +} + static void bc_vm_free(void) { bc_vec_free(&G.files); @@ -7253,9 +7200,74 @@ static void bc_vm_free(void) bc_parse_free(&G.prs); free(G.env_args); } +#endif + +static void bc_program_init(size_t line_len) +{ + size_t idx; + BcInstPtr ip; + + /* memset(&G.prog, 0, sizeof(G.prog)); - already is */ + memset(&ip, 0, sizeof(BcInstPtr)); + + /* G.prog.nchars = G.prog.scale = 0; - already is */ + G.prog.len = line_len; + if (IS_BC) { + G.prog.parse_init = bc_parse_init; + G.prog.parse_expr = bc_parse_expression; + } else { + G.prog.parse_init = dc_parse_init; + G.prog.parse_expr = dc_parse_expr; + } + + bc_num_init(&G.prog.ib, BC_NUM_DEF_SIZE); + bc_num_ten(&G.prog.ib); + G.prog.ib_t = 10; + + bc_num_init(&G.prog.ob, BC_NUM_DEF_SIZE); + bc_num_ten(&G.prog.ob); + G.prog.ob_t = 10; + + bc_num_init(&G.prog.hexb, BC_NUM_DEF_SIZE); + bc_num_ten(&G.prog.hexb); + G.prog.hexb.num[0] = 6; + +#if ENABLE_DC + bc_num_init(&G.prog.strmb, BC_NUM_DEF_SIZE); + bc_num_ulong2num(&G.prog.strmb, UCHAR_MAX + 1); +#endif + + bc_num_init(&G.prog.last, BC_NUM_DEF_SIZE); + bc_num_zero(&G.prog.last); + + bc_num_init(&G.prog.zero, BC_NUM_DEF_SIZE); + bc_num_zero(&G.prog.zero); + + bc_num_init(&G.prog.one, BC_NUM_DEF_SIZE); + bc_num_one(&G.prog.one); + + bc_vec_init(&G.prog.fns, sizeof(BcFunc), bc_func_free); + bc_map_init(&G.prog.fn_map); + + bc_program_addFunc(&G.prog, xstrdup(bc_func_main), &idx); + bc_program_addFunc(&G.prog, xstrdup(bc_func_read), &idx); + + bc_vec_init(&G.prog.vars, sizeof(BcVec), bc_vec_free); + bc_map_init(&G.prog.var_map); + + bc_vec_init(&G.prog.arrs, sizeof(BcVec), bc_vec_free); + bc_map_init(&G.prog.arr_map); + + bc_vec_init(&G.prog.strs, sizeof(char *), bc_string_free); + bc_vec_init(&G.prog.consts, sizeof(char *), bc_string_free); + bc_vec_init(&G.prog.results, sizeof(BcResult), bc_result_free); + bc_vec_init(&G.prog.stack, sizeof(BcInstPtr), NULL); + bc_vec_push(&G.prog.stack, &ip); +} static void bc_vm_init(const char *env_len) { + BcParseInit init; size_t len = bc_vm_envLen(env_len); #if ENABLE_FEATURE_BC_SIGNALS @@ -7265,12 +7277,16 @@ static void bc_vm_init(const char *env_len) bc_vec_init(&G.files, sizeof(char *), NULL); if (IS_BC) { - G.flags |= BC_FLAG_S * (getenv("POSIXLY_CORRECT") != NULL); + if (getenv("POSIXLY_CORRECT")) + G.flags |= BC_FLAG_S; bc_vm_envArgs(); + init = bc_parse_init; + } else { + init = dc_parse_init; } - bc_program_init(&G.prog, len, G.init, G.exp); - G.init(&G.prs, &G.prog, BC_PROG_MAIN); + bc_program_init(len); + init(&G.prs, &G.prog, BC_PROG_MAIN); } static BcStatus bc_vm_run(int argc, char *argv[], @@ -7279,7 +7295,7 @@ static BcStatus bc_vm_run(int argc, char *argv[], BcStatus st; bc_vm_init(env_len); - bc_args(argc, argv, &G.flags, &G.files); + bc_args(argc, argv); G.ttyin = isatty(0); G.tty = G.ttyin || (G.flags & BC_FLAG_I) || isatty(1); @@ -7287,7 +7303,9 @@ static BcStatus bc_vm_run(int argc, char *argv[], if (G.ttyin && !(G.flags & BC_FLAG_Q)) bc_vm_info(); st = bc_vm_exec(); +#if ENABLE_FEATURE_CLEAN_UP bc_vm_free(); +#endif return st; } @@ -7296,8 +7314,6 @@ int bc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int bc_main(int argc, char **argv) { INIT_G(); - G.init = bc_parse_init; - G.exp = bc_parse_expression; G.sbgn = G.send = '"'; return bc_vm_run(argc, argv, "BC_LINE_LENGTH"); @@ -7309,8 +7325,6 @@ int dc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int dc_main(int argc, char **argv) { INIT_G(); - G.init = dc_parse_init; - G.exp = dc_parse_expr; G.sbgn = '['; G.send = ']'; -- cgit v1.2.3-55-g6feb From f6c1da5ff38c7f1cf3f3d04875330e56d0937894 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 2 Dec 2018 17:36:00 +0100 Subject: bc: select parse_init() and parse_expr() using IS_BC, not function pointers function old new delta common_parse_expr - 62 +62 common_parse_init - 29 +29 dc_parse_parse 53 52 -1 dc_parse_expr 723 719 -4 bc_program_execStr 606 594 -12 dc_parse_init 33 18 -15 bc_parse_init 33 18 -15 bc_parse_expression 39 - -39 bc_vm_run 1923 1872 -51 ------------------------------------------------------------------------------ (add/remove: 2/1 grow/shrink: 0/6 up/down: 91/-137) Total: -46 bytes text data bss dec hex filename 988774 485 7296 996555 f34cb busybox_old 988728 485 7296 996509 f349d busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 52 +++++++++++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 117318bfa..18d388bd3 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -662,9 +662,7 @@ struct BcParse; struct BcProgram; -typedef void (*BcParseInit)(struct BcParse *, struct BcProgram *, size_t); typedef BcStatus (*BcParseParse)(struct BcParse *); -typedef BcStatus (*BcParseExpr)(struct BcParse *, uint8_t); typedef struct BcParse { @@ -724,7 +722,6 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next); static BcStatus dc_lex_token(BcLex *l); -static void dc_parse_init(BcParse *p, struct BcProgram *prog, size_t func); static BcStatus dc_parse_expr(BcParse *p, uint8_t flags); #endif // ENABLE_DC @@ -768,9 +765,6 @@ typedef struct BcProgram { size_t nchars; - BcParseInit parse_init; - BcParseExpr parse_expr; - } BcProgram; #define BC_PROG_STACK(s, n) ((s)->len >= ((size_t) n)) @@ -5259,6 +5253,24 @@ static void dc_parse_init(BcParse *p, BcProgram *prog, size_t func) } #endif // ENABLE_DC +static void common_parse_init(BcParse *p, BcProgram *prog, size_t func) +{ + if (IS_BC) { + bc_parse_init(p, prog, func); + } else { + dc_parse_init(p, prog, func); + } +} + +static BcStatus common_parse_expr(BcParse *p, uint8_t flags) +{ + if (IS_BC) { + return bc_parse_expression(p, flags); + } else { + return dc_parse_expr(p, flags); + } +} + static void bc_program_search(BcProgram *p, char *id, BcVec **ret, bool var) { BcStatus s; @@ -5469,13 +5481,12 @@ static BcStatus bc_program_read(void) s = bc_read_line(&buf, "read> "); if (s) goto io_err; - p->parse_init(&parse, p, BC_PROG_READ); + common_parse_init(&parse, p, BC_PROG_READ); bc_lex_file(&parse.l, bc_program_stdin_name); s = bc_parse_text(&parse, buf.v); if (s) goto exec_err; -/// replace by IS_BC selection - s = p->parse_expr(&parse, BC_PARSE_NOREAD); + s = common_parse_expr(&parse, BC_PARSE_NOREAD); if (s) goto exec_err; if (parse.l.t.t != BC_LEX_NLINE && parse.l.t.t != BC_LEX_EOF) { @@ -6453,12 +6464,10 @@ static BcStatus bc_program_execStr(char *code, size_t *bgn, f = bc_vec_item(&p->fns, fidx); if (f->code.len == 0) { -/// replace by IS_BC selection - p->parse_init(&prs, p, fidx); + common_parse_init(&prs, p, fidx); s = bc_parse_text(&prs, *str); if (s) goto err; -/// replace by IS_BC selection - s = p->parse_expr(&prs, BC_PARSE_NOCALL); + s = common_parse_expr(&prs, BC_PARSE_NOCALL); if (s) goto err; if (prs.l.t.t != BC_LEX_EOF) { @@ -7212,13 +7221,6 @@ static void bc_program_init(size_t line_len) /* G.prog.nchars = G.prog.scale = 0; - already is */ G.prog.len = line_len; - if (IS_BC) { - G.prog.parse_init = bc_parse_init; - G.prog.parse_expr = bc_parse_expression; - } else { - G.prog.parse_init = dc_parse_init; - G.prog.parse_expr = dc_parse_expr; - } bc_num_init(&G.prog.ib, BC_NUM_DEF_SIZE); bc_num_ten(&G.prog.ib); @@ -7267,7 +7269,6 @@ static void bc_program_init(size_t line_len) static void bc_vm_init(const char *env_len) { - BcParseInit init; size_t len = bc_vm_envLen(env_len); #if ENABLE_FEATURE_BC_SIGNALS @@ -7280,13 +7281,14 @@ static void bc_vm_init(const char *env_len) if (getenv("POSIXLY_CORRECT")) G.flags |= BC_FLAG_S; bc_vm_envArgs(); - init = bc_parse_init; - } else { - init = dc_parse_init; } bc_program_init(len); - init(&G.prs, &G.prog, BC_PROG_MAIN); + if (IS_BC) { + bc_parse_init(&G.prs, &G.prog, BC_PROG_MAIN); + } else { + dc_parse_init(&G.prs, &G.prog, BC_PROG_MAIN); + } } static BcStatus bc_vm_run(int argc, char *argv[], -- cgit v1.2.3-55-g6feb From a1d3ca24559254e10549746833a878a3a3273cbe Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 2 Dec 2018 18:26:38 +0100 Subject: bc: stop passing around pointers to G.prog, they are all constant function old new delta bc_program_exec 4523 4562 +39 bc_program_assign 450 482 +32 bc_program_assignStr 131 159 +28 bc_program_print 762 775 +13 bc_program_num 1134 1147 +13 bc_program_search 154 164 +10 bc_num_ulong 85 95 +10 dc_parse_expr 719 727 +8 bc_program_retire 34 40 +6 bc_program_reset 168 174 +6 bc_program_binOpRetire 50 56 +6 bc_program_addFunc 220 226 +6 bc_program_prep 88 89 +1 dc_parse_init 18 17 -1 bc_program_copyToVar 355 354 -1 bc_parse_text 142 141 -1 bc_parse_number 88 87 -1 bc_parse_init 18 17 -1 bc_parse_endBody 423 422 -1 common_parse_init 29 26 -3 bc_parse_string 103 100 -3 bc_parse_addFunc 44 41 -3 bc_program_call 371 366 -5 bc_program_binOpPrep 301 296 -5 bc_program_read 342 336 -6 bc_parse_create 198 192 -6 bc_program_pushArray 143 136 -7 bc_parse_reset 194 187 -7 bc_vm_process 323 315 -8 bc_program_pushVar 236 225 -11 bc_vm_run 1872 1854 -18 bc_parse_name 590 570 -20 bc_program_execStr 594 573 -21 bc_program_modexp 793 763 -30 bc_program_printStream 172 - -172 ------------------------------------------------------------------------------ (add/remove: 0/1 grow/shrink: 13/21 up/down: 178/-331) Total: -153 bytes text data bss dec hex filename 988728 485 7296 996509 f349d busybox_old 988575 485 7296 996356 f3404 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 577 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 284 insertions(+), 293 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 18d388bd3..221e1529f 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -599,7 +599,7 @@ typedef struct BcLex { #define bc_parse_push(p, i) (bc_vec_pushByte(&(p)->func->code, (char) (i))) #define bc_parse_updateFunc(p, f) \ - ((p)->func = bc_vec_item(&(p)->prog->fns, ((p)->fidx = (f)))) + ((p)->func = bc_vec_item(&G.prog.fns, ((p)->fidx = (f)))) #define BC_PARSE_REL (1 << 0) #define BC_PARSE_PRINT (1 << 1) @@ -677,7 +677,6 @@ typedef struct BcParse { BcVec ops; - struct BcProgram *prog; BcFunc *func; size_t fidx; @@ -782,8 +781,8 @@ typedef struct BcProgram { typedef unsigned long (*BcProgramBuiltIn)(BcNum *); -static void bc_program_addFunc(BcProgram *p, char *name, size_t *idx); -static BcStatus bc_program_reset(BcProgram *p, BcStatus s); +static void bc_program_addFunc(char *name, size_t *idx); +static BcStatus bc_program_reset(BcStatus s); #define BC_FLAG_X (1 << 0) #define BC_FLAG_W (1 << 1) @@ -3603,8 +3602,8 @@ static BcStatus dc_lex_token(BcLex *l) static void bc_parse_addFunc(BcParse *p, char *name, size_t *idx) { - bc_program_addFunc(p->prog, name, idx); - p->func = bc_vec_item(&p->prog->fns, p->fidx); + bc_program_addFunc(name, idx); + p->func = bc_vec_item(&G.prog.fns, p->fidx); } static void bc_parse_pushName(BcParse *p, char *name) @@ -3633,9 +3632,9 @@ static void bc_parse_pushIndex(BcParse *p, size_t idx) static void bc_parse_number(BcParse *p, BcInst *prev, size_t *nexs) { char *num = xstrdup(p->l.t.v.v); - size_t idx = p->prog->consts.len; + size_t idx = G.prog.consts.len; - bc_vec_push(&p->prog->consts, &num); + bc_vec_push(&G.prog.consts, &num); bc_parse_push(p, BC_INST_NUM); bc_parse_pushIndex(p, idx); @@ -3648,7 +3647,7 @@ static BcStatus bc_parse_text(BcParse *p, const char *text) { BcStatus s; - p->func = bc_vec_item(&p->prog->fns, p->fidx); + p->func = bc_vec_item(&G.prog.fns, p->fidx); if (!strcmp(text, "") && !BC_PARSE_CAN_EXEC(p)) { p->l.t.t = BC_LEX_INVALID; @@ -3681,7 +3680,7 @@ static BcStatus bc_parse_reset(BcParse *p, BcStatus s) bc_vec_npop(&p->conds, p->conds.len); bc_vec_npop(&p->ops, p->ops.len); - return bc_program_reset(p->prog, s); + return bc_program_reset(s); } static void bc_parse_free(BcParse *p) @@ -3693,7 +3692,7 @@ static void bc_parse_free(BcParse *p) bc_lex_free(&p->l); } -static void bc_parse_create(BcParse *p, BcProgram *prog, size_t func, +static void bc_parse_create(BcParse *p, size_t func, BcParseParse parse, BcLexNext next) { memset(p, 0, sizeof(BcParse)); @@ -3706,7 +3705,6 @@ static void bc_parse_create(BcParse *p, BcProgram *prog, size_t func, bc_vec_init(&p->ops, sizeof(BcLexType), NULL); p->parse = parse; - p->prog = prog; p->auto_part = (p->nbraces = 0); bc_parse_updateFunc(p, func); } @@ -3810,18 +3808,18 @@ static BcStatus bc_parse_call(BcParse *p, char *name, uint8_t flags) goto err; } - idx = bc_map_index(&p->prog->fn_map, &entry); + idx = bc_map_index(&G.prog.fn_map, &entry); if (idx == BC_VEC_INVALID_IDX) { name = xstrdup(entry.name); bc_parse_addFunc(p, name, &idx); - idx = bc_map_index(&p->prog->fn_map, &entry); + idx = bc_map_index(&G.prog.fn_map, &entry); free(entry.name); } else free(name); - entry_ptr = bc_vec_item(&p->prog->fn_map, idx); + entry_ptr = bc_vec_item(&G.prog.fn_map, idx); bc_parse_pushIndex(p, entry_ptr->idx); return bc_lex_next(&p->l); @@ -4061,8 +4059,8 @@ static BcStatus bc_parse_string(BcParse *p, char inst) char *str = xstrdup(p->l.t.v.v); bc_parse_push(p, BC_INST_STR); - bc_parse_pushIndex(p, p->prog->strs.len); - bc_vec_push(&p->prog->strs, &str); + bc_parse_pushIndex(p, G.prog.strs.len); + bc_vec_push(&G.prog.strs, &str); bc_parse_push(p, inst); return bc_lex_next(&p->l); @@ -5021,9 +5019,9 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) return s; } -static void bc_parse_init(BcParse *p, BcProgram *prog, size_t func) +static void bc_parse_init(BcParse *p, size_t func) { - bc_parse_create(p, prog, func, bc_parse_parse, bc_lex_token); + bc_parse_create(p, func, bc_parse_parse, bc_lex_token); } static BcStatus bc_parse_expression(BcParse *p, uint8_t flags) @@ -5051,7 +5049,7 @@ static BcStatus dc_parse_register(BcParse *p) static BcStatus dc_parse_string(BcParse *p) { char *str, *name, b[DC_PARSE_BUF_LEN + 1]; - size_t idx, len = p->prog->strs.len; + size_t idx, len = G.prog.strs.len; sprintf(b, "%0*zu", DC_PARSE_BUF_LEN, len); name = xstrdup(b); @@ -5059,7 +5057,7 @@ static BcStatus dc_parse_string(BcParse *p) str = xstrdup(p->l.t.v.v); bc_parse_push(p, BC_INST_STR); bc_parse_pushIndex(p, len); - bc_vec_push(&p->prog->strs, &str); + bc_vec_push(&G.prog.strs, &str); bc_parse_addFunc(p, name, &idx); return bc_lex_next(&p->l); @@ -5213,7 +5211,7 @@ static BcStatus dc_parse_expr(BcParse *p, uint8_t flags) BcInst inst; BcLexType t; - if (flags & BC_PARSE_NOCALL) p->nbraces = p->prog->results.len; + if (flags & BC_PARSE_NOCALL) p->nbraces = G.prog.results.len; for (t = p->l.t.t; !s && t != BC_LEX_EOF; t = p->l.t.t) { @@ -5247,18 +5245,18 @@ static BcStatus dc_parse_parse(BcParse *p) return s; } -static void dc_parse_init(BcParse *p, BcProgram *prog, size_t func) +static void dc_parse_init(BcParse *p, size_t func) { - bc_parse_create(p, prog, func, dc_parse_parse, dc_lex_token); + bc_parse_create(p, func, dc_parse_parse, dc_lex_token); } #endif // ENABLE_DC -static void common_parse_init(BcParse *p, BcProgram *prog, size_t func) +static void common_parse_init(BcParse *p, size_t func) { if (IS_BC) { - bc_parse_init(p, prog, func); + bc_parse_init(p, func); } else { - dc_parse_init(p, prog, func); + dc_parse_init(p, func); } } @@ -5271,7 +5269,7 @@ static BcStatus common_parse_expr(BcParse *p, uint8_t flags) } } -static void bc_program_search(BcProgram *p, char *id, BcVec **ret, bool var) +static void bc_program_search(char *id, BcVec **ret, bool var) { BcStatus s; BcId e, *ptr; @@ -5280,8 +5278,8 @@ static void bc_program_search(BcProgram *p, char *id, BcVec **ret, bool var) BcResultData data; bool new; - v = var ? &p->vars : &p->arrs; - map = var ? &p->var_map : &p->arr_map; + v = var ? &G.prog.vars : &G.prog.arrs; + map = var ? &G.prog.var_map : &G.prog.arr_map; e.name = id; e.idx = v->len; @@ -5296,9 +5294,10 @@ static void bc_program_search(BcProgram *p, char *id, BcVec **ret, bool var) ptr = bc_vec_item(map, i); if (new) ptr->name = xstrdup(e.name); *ret = bc_vec_item(v, ptr->idx); +/// convert to better return convention } -static BcStatus bc_program_num(BcProgram *p, BcResult *r, BcNum **num, bool hex) +static BcStatus bc_program_num(BcResult *r, BcNum **num, bool hex) { BcStatus s = BC_STATUS_SUCCESS; @@ -5316,15 +5315,15 @@ static BcStatus bc_program_num(BcProgram *p, BcResult *r, BcNum **num, bool hex) case BC_RESULT_CONSTANT: { - char **str = bc_vec_item(&p->consts, r->d.id.idx); + char **str = bc_vec_item(&G.prog.consts, r->d.id.idx); size_t base_t, len = strlen(*str); BcNum *base; bc_num_init(&r->d.n, len); hex = hex && len == 1; - base = hex ? &p->hexb : &p->ib; - base_t = hex ? BC_NUM_MAX_IBASE : p->ib_t; + base = hex ? &G.prog.hexb : &G.prog.ib; + base_t = hex ? BC_NUM_MAX_IBASE : G.prog.ib_t; s = bc_num_parse(&r->d.n, *str, base, base_t); if (s) { @@ -5344,7 +5343,7 @@ static BcStatus bc_program_num(BcProgram *p, BcResult *r, BcNum **num, bool hex) { BcVec *v; - bc_program_search(p, r->d.id.name, &v, r->t == BC_RESULT_VAR); + bc_program_search(r->d.id.name, &v, r->t == BC_RESULT_VAR); if (r->t == BC_RESULT_ARRAY_ELEM) { v = bc_vec_top(v); @@ -5359,13 +5358,13 @@ static BcStatus bc_program_num(BcProgram *p, BcResult *r, BcNum **num, bool hex) case BC_RESULT_LAST: { - *num = &p->last; + *num = &G.prog.last; break; } case BC_RESULT_ONE: { - *num = &p->one; + *num = &G.prog.one; break; } } @@ -5373,31 +5372,31 @@ static BcStatus bc_program_num(BcProgram *p, BcResult *r, BcNum **num, bool hex) return s; } -static BcStatus bc_program_binOpPrep(BcProgram *p, BcResult **l, BcNum **ln, +static BcStatus bc_program_binOpPrep(BcResult **l, BcNum **ln, BcResult **r, BcNum **rn, bool assign) { BcStatus s; bool hex; BcResultType lt, rt; - if (!BC_PROG_STACK(&p->results, 2)) return BC_STATUS_EXEC_STACK; + if (!BC_PROG_STACK(&G.prog.results, 2)) return BC_STATUS_EXEC_STACK; - *r = bc_vec_item_rev(&p->results, 0); - *l = bc_vec_item_rev(&p->results, 1); + *r = bc_vec_item_rev(&G.prog.results, 0); + *l = bc_vec_item_rev(&G.prog.results, 1); lt = (*l)->t; rt = (*r)->t; hex = assign && (lt == BC_RESULT_IBASE || lt == BC_RESULT_OBASE); - s = bc_program_num(p, *l, ln, false); + s = bc_program_num(*l, ln, false); if (s) return s; - s = bc_program_num(p, *r, rn, hex); + s = bc_program_num(*r, rn, hex); if (s) return s; // We run this again under these conditions in case any vector has been // reallocated out from under the BcNums or arrays we had. if (lt == rt && (lt == BC_RESULT_VAR || lt == BC_RESULT_ARRAY_ELEM)) { - s = bc_program_num(p, *l, ln, false); + s = bc_program_num(*l, ln, false); if (s) return s; } @@ -5408,22 +5407,22 @@ static BcStatus bc_program_binOpPrep(BcProgram *p, BcResult **l, BcNum **ln, return s; } -static void bc_program_binOpRetire(BcProgram *p, BcResult *r) +static void bc_program_binOpRetire(BcResult *r) { r->t = BC_RESULT_TEMP; - bc_vec_pop(&p->results); - bc_vec_pop(&p->results); - bc_vec_push(&p->results, r); + bc_vec_pop(&G.prog.results); + bc_vec_pop(&G.prog.results); + bc_vec_push(&G.prog.results, r); } -static BcStatus bc_program_prep(BcProgram *p, BcResult **r, BcNum **n) +static BcStatus bc_program_prep(BcResult **r, BcNum **n) { BcStatus s; - if (!BC_PROG_STACK(&p->results, 1)) return BC_STATUS_EXEC_STACK; - *r = bc_vec_top(&p->results); + if (!BC_PROG_STACK(&G.prog.results, 1)) return BC_STATUS_EXEC_STACK; + *r = bc_vec_top(&G.prog.results); - s = bc_program_num(p, *r, n, false); + s = bc_program_num(*r, n, false); if (s) return s; if (!BC_PROG_NUM((*r), (*n))) return BC_STATUS_EXEC_BAD_TYPE; @@ -5431,26 +5430,26 @@ static BcStatus bc_program_prep(BcProgram *p, BcResult **r, BcNum **n) return s; } -static void bc_program_retire(BcProgram *p, BcResult *r, BcResultType t) +static void bc_program_retire(BcResult *r, BcResultType t) { r->t = t; - bc_vec_pop(&p->results); - bc_vec_push(&p->results, r); + bc_vec_pop(&G.prog.results); + bc_vec_push(&G.prog.results, r); } -static BcStatus bc_program_op(BcProgram *p, char inst) +static BcStatus bc_program_op(char inst) { BcStatus s; BcResult *opd1, *opd2, res; BcNum *n1, *n2 = NULL; - s = bc_program_binOpPrep(p, &opd1, &n1, &opd2, &n2, false); + s = bc_program_binOpPrep(&opd1, &n1, &opd2, &n2, false); if (s) return s; bc_num_init(&res.d.n, BC_NUM_DEF_SIZE); - s = bc_program_ops[inst - BC_INST_POWER](n1, n2, &res.d.n, p->scale); + s = bc_program_ops[inst - BC_INST_POWER](n1, n2, &res.d.n, G.prog.scale); if (s) goto err; - bc_program_binOpRetire(p, &res); + bc_program_binOpRetire(&res); return s; @@ -5461,17 +5460,15 @@ err: static BcStatus bc_program_read(void) { - BcProgram *p = &G.prog; - BcStatus s; BcParse parse; BcVec buf; BcInstPtr ip; size_t i; - BcFunc *f = bc_vec_item(&p->fns, BC_PROG_READ); + BcFunc *f = bc_vec_item(&G.prog.fns, BC_PROG_READ); - for (i = 0; i < p->stack.len; ++i) { - BcInstPtr *ip_ptr = bc_vec_item(&p->stack, i); + for (i = 0; i < G.prog.stack.len; ++i) { + BcInstPtr *ip_ptr = bc_vec_item(&G.prog.stack, i); if (ip_ptr->func == BC_PROG_READ) return BC_STATUS_EXEC_REC_READ; } @@ -5481,7 +5478,7 @@ static BcStatus bc_program_read(void) s = bc_read_line(&buf, "read> "); if (s) goto io_err; - common_parse_init(&parse, p, BC_PROG_READ); + common_parse_init(&parse, BC_PROG_READ); bc_lex_file(&parse.l, bc_program_stdin_name); s = bc_parse_text(&parse, buf.v); @@ -5496,13 +5493,13 @@ static BcStatus bc_program_read(void) ip.func = BC_PROG_READ; ip.idx = 0; - ip.len = p->results.len; + ip.len = G.prog.results.len; // Update this pointer, just in case. - f = bc_vec_item(&p->fns, BC_PROG_READ); + f = bc_vec_item(&G.prog.fns, BC_PROG_READ); bc_vec_pushByte(&f->code, BC_INST_POP_EXEC); - bc_vec_push(&p->stack, &ip); + bc_vec_push(&G.prog.stack, &ip); exec_err: bc_parse_free(&parse); @@ -5624,7 +5621,7 @@ static void bc_program_printString(const char *str, size_t *nchars) } } -static BcStatus bc_program_print(BcProgram *p, char inst, size_t idx) +static BcStatus bc_program_print(char inst, size_t idx) { BcStatus s = BC_STATUS_SUCCESS; BcResult *r; @@ -5633,59 +5630,59 @@ static BcStatus bc_program_print(BcProgram *p, char inst, size_t idx) BcNum *num = NULL; bool pop = inst != BC_INST_PRINT; - if (!BC_PROG_STACK(&p->results, idx + 1)) return BC_STATUS_EXEC_STACK; + if (!BC_PROG_STACK(&G.prog.results, idx + 1)) return BC_STATUS_EXEC_STACK; - r = bc_vec_item_rev(&p->results, idx); - s = bc_program_num(p, r, &num, false); + r = bc_vec_item_rev(&G.prog.results, idx); + s = bc_program_num(r, &num, false); if (s) return s; if (BC_PROG_NUM(r, num)) { - s = bc_num_print(num, &p->ob, p->ob_t, !pop, &p->nchars, p->len); - if (!s) bc_num_copy(&p->last, num); + s = bc_num_print(num, &G.prog.ob, G.prog.ob_t, !pop, &G.prog.nchars, G.prog.len); + if (!s) bc_num_copy(&G.prog.last, num); } else { idx = (r->t == BC_RESULT_STR) ? r->d.id.idx : num->rdx; - str = *((char **) bc_vec_item(&p->strs, idx)); + str = *((char **) bc_vec_item(&G.prog.strs, idx)); if (inst == BC_INST_PRINT_STR) { for (i = 0, len = strlen(str); i < len; ++i) { char c = str[i]; bb_putchar(c); - if (c == '\n') p->nchars = SIZE_MAX; - ++p->nchars; + if (c == '\n') G.prog.nchars = SIZE_MAX; + ++G.prog.nchars; } } else { - bc_program_printString(str, &p->nchars); + bc_program_printString(str, &G.prog.nchars); if (inst == BC_INST_PRINT) bb_putchar('\n'); } } - if (!s && pop) bc_vec_pop(&p->results); + if (!s && pop) bc_vec_pop(&G.prog.results); return s; } -static BcStatus bc_program_negate(BcProgram *p) +static BcStatus bc_program_negate(void) { BcStatus s; BcResult res, *ptr; BcNum *num = NULL; - s = bc_program_prep(p, &ptr, &num); + s = bc_program_prep(&ptr, &num); if (s) return s; bc_num_init(&res.d.n, num->len); bc_num_copy(&res.d.n, num); if (res.d.n.len) res.d.n.neg = !res.d.n.neg; - bc_program_retire(p, &res, BC_RESULT_TEMP); + bc_program_retire(&res, BC_RESULT_TEMP); return s; } -static BcStatus bc_program_logical(BcProgram *p, char inst) +static BcStatus bc_program_logical(char inst) { BcStatus s; BcResult *opd1, *opd2, res; @@ -5693,14 +5690,14 @@ static BcStatus bc_program_logical(BcProgram *p, char inst) bool cond = 0; ssize_t cmp; - s = bc_program_binOpPrep(p, &opd1, &n1, &opd2, &n2, false); + s = bc_program_binOpPrep(&opd1, &n1, &opd2, &n2, false); if (s) return s; bc_num_init(&res.d.n, BC_NUM_DEF_SIZE); if (inst == BC_INST_BOOL_AND) - cond = bc_num_cmp(n1, &p->zero) && bc_num_cmp(n2, &p->zero); + cond = bc_num_cmp(n1, &G.prog.zero) && bc_num_cmp(n2, &G.prog.zero); else if (inst == BC_INST_BOOL_OR) - cond = bc_num_cmp(n1, &p->zero) || bc_num_cmp(n2, &p->zero); + cond = bc_num_cmp(n1, &G.prog.zero) || bc_num_cmp(n2, &G.prog.zero); else { cmp = bc_num_cmp(n1, n2); @@ -5747,13 +5744,13 @@ static BcStatus bc_program_logical(BcProgram *p, char inst) (cond ? bc_num_one : bc_num_zero)(&res.d.n); - bc_program_binOpRetire(p, &res); + bc_program_binOpRetire(&res); return s; } #if ENABLE_DC -static BcStatus bc_program_assignStr(BcProgram *p, BcResult *r, BcVec *v, +static BcStatus bc_program_assignStr(BcResult *r, BcVec *v, bool push) { BcNum n2; @@ -5764,43 +5761,43 @@ static BcStatus bc_program_assignStr(BcProgram *p, BcResult *r, BcVec *v, res.t = BC_RESULT_STR; if (!push) { - if (!BC_PROG_STACK(&p->results, 2)) return BC_STATUS_EXEC_STACK; + if (!BC_PROG_STACK(&G.prog.results, 2)) return BC_STATUS_EXEC_STACK; bc_vec_pop(v); - bc_vec_pop(&p->results); + bc_vec_pop(&G.prog.results); } - bc_vec_pop(&p->results); + bc_vec_pop(&G.prog.results); - bc_vec_push(&p->results, &res); + bc_vec_push(&G.prog.results, &res); bc_vec_push(v, &n2); return BC_STATUS_SUCCESS; } #endif // ENABLE_DC -static BcStatus bc_program_copyToVar(BcProgram *p, char *name, bool var) +static BcStatus bc_program_copyToVar(char *name, bool var) { BcStatus s; BcResult *ptr, r; BcVec *v; BcNum *n; - if (!BC_PROG_STACK(&p->results, 1)) return BC_STATUS_EXEC_STACK; + if (!BC_PROG_STACK(&G.prog.results, 1)) return BC_STATUS_EXEC_STACK; - ptr = bc_vec_top(&p->results); + ptr = bc_vec_top(&G.prog.results); if ((ptr->t == BC_RESULT_ARRAY) != !var) return BC_STATUS_EXEC_BAD_TYPE; - bc_program_search(p, name, &v, var); + bc_program_search(name, &v, var); #if ENABLE_DC if (ptr->t == BC_RESULT_STR && !var) return BC_STATUS_EXEC_BAD_TYPE; - if (ptr->t == BC_RESULT_STR) return bc_program_assignStr(p, ptr, v, true); + if (ptr->t == BC_RESULT_STR) return bc_program_assignStr(ptr, v, true); #endif - s = bc_program_num(p, ptr, &n, false); + s = bc_program_num(ptr, &n, false); if (s) return s; // Do this once more to make sure that pointers were not invalidated. - bc_program_search(p, name, &v, var); + bc_program_search(name, &v, var); if (var) { bc_num_init(&r.d.n, BC_NUM_DEF_SIZE); @@ -5812,12 +5809,12 @@ static BcStatus bc_program_copyToVar(BcProgram *p, char *name, bool var) } bc_vec_push(v, &r.d); - bc_vec_pop(&p->results); + bc_vec_pop(&G.prog.results); return s; } -static BcStatus bc_program_assign(BcProgram *p, char inst) +static BcStatus bc_program_assign(char inst) { BcStatus s; BcResult *left, *right, res; @@ -5825,7 +5822,7 @@ static BcStatus bc_program_assign(BcProgram *p, char inst) unsigned long val, max; bool assign = inst == BC_INST_ASSIGN, ib, sc; - s = bc_program_binOpPrep(p, &left, &l, &right, &r, assign); + s = bc_program_binOpPrep(&left, &l, &right, &r, assign); if (s) return s; ib = left->t == BC_RESULT_IBASE; @@ -5838,9 +5835,9 @@ static BcStatus bc_program_assign(BcProgram *p, char inst) BcVec *v; if (left->t != BC_RESULT_VAR) return BC_STATUS_EXEC_BAD_TYPE; - bc_program_search(p, left->d.id.name, &v, true); + bc_program_search(left->d.id.name, &v, true); - return bc_program_assignStr(p, right, v, false); + return bc_program_assignStr(right, v, false); } #endif @@ -5848,13 +5845,13 @@ static BcStatus bc_program_assign(BcProgram *p, char inst) return BC_STATUS_PARSE_BAD_ASSIGN; #if ENABLE_BC - if (inst == BC_INST_ASSIGN_DIVIDE && !bc_num_cmp(r, &p->zero)) + if (inst == BC_INST_ASSIGN_DIVIDE && !bc_num_cmp(r, &G.prog.zero)) return BC_STATUS_MATH_DIVIDE_BY_ZERO; if (assign) bc_num_copy(l, r); else - s = bc_program_ops[inst - BC_INST_ASSIGN_POWER](l, r, l, p->scale); + s = bc_program_ops[inst - BC_INST_ASSIGN_POWER](l, r, l, G.prog.scale); if (s) return s; #else @@ -5871,16 +5868,16 @@ static BcStatus bc_program_assign(BcProgram *p, char inst) if (sc) { max = BC_MAX_SCALE; - ptr = &p->scale; + ptr = &G.prog.scale; } else { if (val < BC_NUM_MIN_BASE) return s; max = ib ? BC_NUM_MAX_IBASE : BC_MAX_OBASE; - ptr = ib ? &p->ib_t : &p->ob_t; + ptr = ib ? &G.prog.ib_t : &G.prog.ob_t; } if (val > max) return s; - if (!sc) bc_num_copy(ib ? &p->ib : &p->ob, l); + if (!sc) bc_num_copy(ib ? &G.prog.ib : &G.prog.ob, l); *ptr = (size_t) val; s = BC_STATUS_SUCCESS; @@ -5888,12 +5885,12 @@ static BcStatus bc_program_assign(BcProgram *p, char inst) bc_num_init(&res.d.n, l->len); bc_num_copy(&res.d.n, l); - bc_program_binOpRetire(p, &res); + bc_program_binOpRetire(&res); return s; } -static BcStatus bc_program_pushVar(BcProgram *p, char *code, size_t *bgn, +static BcStatus bc_program_pushVar(char *code, size_t *bgn, bool pop, bool copy) { BcStatus s = BC_STATUS_SUCCESS; @@ -5910,7 +5907,7 @@ static BcStatus bc_program_pushVar(BcProgram *p, char *code, size_t *bgn, r.d.id.name = name; #if ENABLE_DC - bc_program_search(p, name, &v, true); + bc_program_search(name, &v, true); num = bc_vec_top(v); if (pop || copy) { @@ -5939,12 +5936,12 @@ static BcStatus bc_program_pushVar(BcProgram *p, char *code, size_t *bgn, } #endif // ENABLE_DC - bc_vec_push(&p->results, &r); + bc_vec_push(&G.prog.results, &r); return s; } -static BcStatus bc_program_pushArray(BcProgram *p, char *code, size_t *bgn, +static BcStatus bc_program_pushArray(char *code, size_t *bgn, char inst) { BcStatus s = BC_STATUS_SUCCESS; @@ -5955,14 +5952,14 @@ static BcStatus bc_program_pushArray(BcProgram *p, char *code, size_t *bgn, if (inst == BC_INST_ARRAY) { r.t = BC_RESULT_ARRAY; - bc_vec_push(&p->results, &r); + bc_vec_push(&G.prog.results, &r); } else { BcResult *operand; unsigned long temp; - s = bc_program_prep(p, &operand, &num); + s = bc_program_prep(&operand, &num); if (s) goto err; s = bc_num_ulong(num, &temp); if (s) goto err; @@ -5973,7 +5970,7 @@ static BcStatus bc_program_pushArray(BcProgram *p, char *code, size_t *bgn, } r.d.id.idx = (size_t) temp; - bc_program_retire(p, &r, BC_RESULT_ARRAY_ELEM); + bc_program_retire(&r, BC_RESULT_ARRAY_ELEM); } err: @@ -5982,14 +5979,14 @@ err: } #if ENABLE_BC -static BcStatus bc_program_incdec(BcProgram *p, char inst) +static BcStatus bc_program_incdec(char inst) { BcStatus s; BcResult *ptr, res, copy; BcNum *num = NULL; char inst2 = inst; - s = bc_program_prep(p, &ptr, &num); + s = bc_program_prep(&ptr, &num); if (s) return s; if (inst == BC_INST_INC_POST || inst == BC_INST_DEC_POST) { @@ -6003,18 +6000,18 @@ static BcStatus bc_program_incdec(BcProgram *p, char inst) BC_INST_ASSIGN_PLUS : BC_INST_ASSIGN_MINUS; - bc_vec_push(&p->results, &res); - bc_program_assign(p, inst); + bc_vec_push(&G.prog.results, &res); + bc_program_assign(inst); if (inst2 == BC_INST_INC_POST || inst2 == BC_INST_DEC_POST) { - bc_vec_pop(&p->results); - bc_vec_push(&p->results, ©); + bc_vec_pop(&G.prog.results); + bc_vec_push(&G.prog.results, ©); } return s; } -static BcStatus bc_program_call(BcProgram *p, char *code, size_t *idx) +static BcStatus bc_program_call(char *code, size_t *idx) { BcStatus s = BC_STATUS_SUCCESS; BcInstPtr ip; @@ -6027,28 +6024,28 @@ static BcStatus bc_program_call(BcProgram *p, char *code, size_t *idx) ip.idx = 0; ip.func = bc_program_index(code, idx); - func = bc_vec_item(&p->fns, ip.func); + func = bc_vec_item(&G.prog.fns, ip.func); if (func->code.len == 0) return BC_STATUS_EXEC_UNDEFINED_FUNC; if (nparams != func->nparams) return BC_STATUS_EXEC_MISMATCHED_PARAMS; - ip.len = p->results.len - nparams; + ip.len = G.prog.results.len - nparams; for (i = 0; i < nparams; ++i) { a = bc_vec_item(&func->autos, nparams - 1 - i); - arg = bc_vec_top(&p->results); + arg = bc_vec_top(&G.prog.results); if ((!a->idx) != (arg->t == BC_RESULT_ARRAY) || arg->t == BC_RESULT_STR) return BC_STATUS_EXEC_BAD_TYPE; - s = bc_program_copyToVar(p, a->name, a->idx); + s = bc_program_copyToVar(a->name, a->idx); if (s) return s; } for (; i < func->autos.len; ++i) { a = bc_vec_item(&func->autos, i); - bc_program_search(p, a->name, &v, a->idx); + bc_program_search(a->name, &v, a->idx); if (a->idx) { bc_num_init(¶m.n, BC_NUM_DEF_SIZE); @@ -6060,31 +6057,31 @@ static BcStatus bc_program_call(BcProgram *p, char *code, size_t *idx) } } - bc_vec_push(&p->stack, &ip); + bc_vec_push(&G.prog.stack, &ip); return BC_STATUS_SUCCESS; } -static BcStatus bc_program_return(BcProgram *p, char inst) +static BcStatus bc_program_return(char inst) { BcStatus s; BcResult res; BcFunc *f; size_t i; - BcInstPtr *ip = bc_vec_top(&p->stack); + BcInstPtr *ip = bc_vec_top(&G.prog.stack); - if (!BC_PROG_STACK(&p->results, ip->len + inst == BC_INST_RET)) + if (!BC_PROG_STACK(&G.prog.results, ip->len + inst == BC_INST_RET)) return BC_STATUS_EXEC_STACK; - f = bc_vec_item(&p->fns, ip->func); + f = bc_vec_item(&G.prog.fns, ip->func); res.t = BC_RESULT_TEMP; if (inst == BC_INST_RET) { BcNum *num; - BcResult *operand = bc_vec_top(&p->results); + BcResult *operand = bc_vec_top(&G.prog.results); - s = bc_program_num(p, operand, &num, false); + s = bc_program_num(operand, &num, false); if (s) return s; bc_num_init(&res.d.n, num->len); bc_num_copy(&res.d.n, num); @@ -6100,13 +6097,13 @@ static BcStatus bc_program_return(BcProgram *p, char inst) BcVec *v; BcId *a = bc_vec_item(&f->autos, i); - bc_program_search(p, a->name, &v, a->idx); + bc_program_search(a->name, &v, a->idx); bc_vec_pop(v); } - bc_vec_npop(&p->results, p->results.len - ip->len); - bc_vec_push(&p->results, &res); - bc_vec_pop(&p->stack); + bc_vec_npop(&G.prog.results, G.prog.results.len - ip->len); + bc_vec_push(&G.prog.results, &res); + bc_vec_pop(&G.prog.stack); return BC_STATUS_SUCCESS; } @@ -6128,7 +6125,7 @@ static unsigned long bc_program_len(BcNum *n) return len; } -static BcStatus bc_program_builtin(BcProgram *p, char inst) +static BcStatus bc_program_builtin(char inst) { BcStatus s; BcResult *opnd; @@ -6136,10 +6133,10 @@ static BcStatus bc_program_builtin(BcProgram *p, char inst) BcResult res; bool len = inst == BC_INST_LENGTH; - if (!BC_PROG_STACK(&p->results, 1)) return BC_STATUS_EXEC_STACK; - opnd = bc_vec_top(&p->results); + if (!BC_PROG_STACK(&G.prog.results, 1)) return BC_STATUS_EXEC_STACK; + opnd = bc_vec_top(&G.prog.results); - s = bc_program_num(p, opnd, &num, false); + s = bc_program_num(opnd, &num, false); if (s) return s; #if ENABLE_DC @@ -6148,7 +6145,7 @@ static BcStatus bc_program_builtin(BcProgram *p, char inst) bc_num_init(&res.d.n, BC_NUM_DEF_SIZE); - if (inst == BC_INST_SQRT) s = bc_num_sqrt(num, &res.d.n, p->scale); + if (inst == BC_INST_SQRT) s = bc_num_sqrt(num, &res.d.n, G.prog.scale); #if ENABLE_BC else if (len != 0 && opnd->t == BC_RESULT_ARRAY) { s = bc_num_ulong2num(&res.d.n, (unsigned long) ((BcVec *) num)->len); @@ -6160,7 +6157,7 @@ static BcStatus bc_program_builtin(BcProgram *p, char inst) char **str; size_t idx = opnd->t == BC_RESULT_STR ? opnd->d.id.idx : num->rdx; - str = bc_vec_item(&p->strs, idx); + str = bc_vec_item(&G.prog.strs, idx); s = bc_num_ulong2num(&res.d.n, strlen(*str)); if (s) goto err; } @@ -6171,7 +6168,7 @@ static BcStatus bc_program_builtin(BcProgram *p, char inst) if (s) goto err; } - bc_program_retire(p, &res, BC_RESULT_TEMP); + bc_program_retire(&res, BC_RESULT_TEMP); return s; @@ -6181,24 +6178,24 @@ err: } #if ENABLE_DC -static BcStatus bc_program_divmod(BcProgram *p) +static BcStatus bc_program_divmod(void) { BcStatus s; BcResult *opd1, *opd2, res, res2; BcNum *n1, *n2 = NULL; - s = bc_program_binOpPrep(p, &opd1, &n1, &opd2, &n2, false); + s = bc_program_binOpPrep(&opd1, &n1, &opd2, &n2, false); if (s) return s; bc_num_init(&res.d.n, BC_NUM_DEF_SIZE); bc_num_init(&res2.d.n, n2->len); - s = bc_num_divmod(n1, n2, &res2.d.n, &res.d.n, p->scale); + s = bc_num_divmod(n1, n2, &res2.d.n, &res.d.n, G.prog.scale); if (s) goto err; - bc_program_binOpRetire(p, &res2); + bc_program_binOpRetire(&res2); res.t = BC_RESULT_TEMP; - bc_vec_push(&p->results, &res); + bc_vec_push(&G.prog.results, &res); return s; @@ -6208,18 +6205,18 @@ err: return s; } -static BcStatus bc_program_modexp(BcProgram *p) +static BcStatus bc_program_modexp(void) { BcStatus s; BcResult *r1, *r2, *r3, res; BcNum *n1, *n2, *n3; - if (!BC_PROG_STACK(&p->results, 3)) return BC_STATUS_EXEC_STACK; - s = bc_program_binOpPrep(p, &r2, &n2, &r3, &n3, false); + if (!BC_PROG_STACK(&G.prog.results, 3)) return BC_STATUS_EXEC_STACK; + s = bc_program_binOpPrep(&r2, &n2, &r3, &n3, false); if (s) return s; - r1 = bc_vec_item_rev(&p->results, 2); - s = bc_program_num(p, r1, &n1, false); + r1 = bc_vec_item_rev(&G.prog.results, 2); + s = bc_program_num(r1, &n1, false); if (s) return s; if (!BC_PROG_NUM(r1, n1)) return BC_STATUS_EXEC_BAD_TYPE; @@ -6227,12 +6224,12 @@ static BcStatus bc_program_modexp(BcProgram *p) if (r1->t == BC_RESULT_VAR || r1->t == BC_RESULT_ARRAY_ELEM) { if (r1->t == r2->t) { - s = bc_program_num(p, r2, &n2, false); + s = bc_program_num(r2, &n2, false); if (s) return s; } if (r1->t == r3->t) { - s = bc_program_num(p, r3, &n3, false); + s = bc_program_num(r3, &n3, false); if (s) return s; } } @@ -6241,8 +6238,8 @@ static BcStatus bc_program_modexp(BcProgram *p) s = bc_num_modexp(n1, n2, n3, &res.d.n); if (s) goto err; - bc_vec_pop(&p->results); - bc_program_binOpRetire(p, &res); + bc_vec_pop(&G.prog.results); + bc_program_binOpRetire(&res); return s; @@ -6251,18 +6248,18 @@ err: return s; } -static BcStatus bc_program_stackLen(BcProgram *p) +static BcStatus bc_program_stackLen(void) { BcStatus s; BcResult res; - size_t len = p->results.len; + size_t len = G.prog.results.len; res.t = BC_RESULT_TEMP; bc_num_init(&res.d.n, BC_NUM_DEF_SIZE); s = bc_num_ulong2num(&res.d.n, len); if (s) goto err; - bc_vec_push(&p->results, &res); + bc_vec_push(&G.prog.results, &res); return s; @@ -6271,19 +6268,19 @@ err: return s; } -static BcStatus bc_program_asciify(BcProgram *p) +static BcStatus bc_program_asciify(void) { BcStatus s; BcResult *r, res; BcNum *num = NULL, n; char *str, *str2, c; - size_t len = p->strs.len, idx; + size_t len = G.prog.strs.len, idx; unsigned long val; - if (!BC_PROG_STACK(&p->results, 1)) return BC_STATUS_EXEC_STACK; - r = bc_vec_top(&p->results); + if (!BC_PROG_STACK(&G.prog.results, 1)) return BC_STATUS_EXEC_STACK; + r = bc_vec_top(&G.prog.results); - s = bc_program_num(p, r, &num, false); + s = bc_program_num(r, &num, false); if (s) return s; if (BC_PROG_NUM(r, num)) { @@ -6292,7 +6289,7 @@ static BcStatus bc_program_asciify(BcProgram *p) bc_num_copy(&n, num); bc_num_truncate(&n, n.rdx); - s = bc_num_mod(&n, &p->strmb, &n, 0); + s = bc_num_mod(&n, &G.prog.strmb, &n, 0); if (s) goto num_err; s = bc_num_ulong(&n, &val); if (s) goto num_err; @@ -6303,7 +6300,7 @@ static BcStatus bc_program_asciify(BcProgram *p) } else { idx = (r->t == BC_RESULT_STR) ? r->d.id.idx : num->rdx; - str2 = *((char **) bc_vec_item(&p->strs, idx)); + str2 = *((char **) bc_vec_item(&G.prog.strs, idx)); c = str2[0]; } @@ -6312,12 +6309,12 @@ static BcStatus bc_program_asciify(BcProgram *p) str[1] = '\0'; str2 = xstrdup(str); - bc_program_addFunc(p, str2, &idx); + bc_program_addFunc(str2, &idx); if (idx != len + BC_PROG_REQ_FUNCS) { - for (idx = 0; idx < p->strs.len; ++idx) { - if (!strcmp(*((char **) bc_vec_item(&p->strs, idx)), str)) { + for (idx = 0; idx < G.prog.strs.len; ++idx) { + if (!strcmp(*((char **) bc_vec_item(&G.prog.strs, idx)), str)) { len = idx; break; } @@ -6326,12 +6323,12 @@ static BcStatus bc_program_asciify(BcProgram *p) free(str); } else - bc_vec_push(&p->strs, &str); + bc_vec_push(&G.prog.strs, &str); res.t = BC_RESULT_STR; res.d.id.idx = len; - bc_vec_pop(&p->results); - bc_vec_push(&p->results, &res); + bc_vec_pop(&G.prog.results); + bc_vec_push(&G.prog.results, &res); return BC_STATUS_SUCCESS; @@ -6340,7 +6337,7 @@ num_err: return s; } -static BcStatus bc_program_printStream(BcProgram *p) +static BcStatus bc_program_printStream(void) { BcStatus s; BcResult *r; @@ -6348,17 +6345,17 @@ static BcStatus bc_program_printStream(BcProgram *p) size_t idx; char *str; - if (!BC_PROG_STACK(&p->results, 1)) return BC_STATUS_EXEC_STACK; - r = bc_vec_top(&p->results); + if (!BC_PROG_STACK(&G.prog.results, 1)) return BC_STATUS_EXEC_STACK; + r = bc_vec_top(&G.prog.results); - s = bc_program_num(p, r, &n, false); + s = bc_program_num(r, &n, false); if (s) return s; if (BC_PROG_NUM(r, n)) - s = bc_num_stream(n, &p->strmb, &p->nchars, p->len); + s = bc_num_stream(n, &G.prog.strmb, &G.prog.nchars, G.prog.len); else { idx = (r->t == BC_RESULT_STR) ? r->d.id.idx : n->rdx; - str = *((char **) bc_vec_item(&p->strs, idx)); + str = *((char **) bc_vec_item(&G.prog.strs, idx)); printf("%s", str); } @@ -6367,26 +6364,24 @@ static BcStatus bc_program_printStream(BcProgram *p) static BcStatus bc_program_nquit(void) { - BcProgram *p = &G.prog; - BcStatus s; BcResult *opnd; BcNum *num = NULL; unsigned long val; - s = bc_program_prep(p, &opnd, &num); + s = bc_program_prep(&opnd, &num); if (s) return s; s = bc_num_ulong(num, &val); if (s) return s; - bc_vec_pop(&p->results); + bc_vec_pop(&G.prog.results); - if (p->stack.len < val) + if (G.prog.stack.len < val) return BC_STATUS_EXEC_STACK; - else if (p->stack.len == val) + else if (G.prog.stack.len == val) return BC_STATUS_QUIT; - bc_vec_npop(&p->stack, val); + bc_vec_npop(&G.prog.stack, val); return s; } @@ -6394,8 +6389,6 @@ static BcStatus bc_program_nquit(void) static BcStatus bc_program_execStr(char *code, size_t *bgn, bool cond) { - BcProgram *p = &G.prog; - BcStatus s = BC_STATUS_SUCCESS; BcResult *r; char **str; @@ -6406,9 +6399,9 @@ static BcStatus bc_program_execStr(char *code, size_t *bgn, BcNum *n; bool exec; - if (!BC_PROG_STACK(&p->results, 1)) return BC_STATUS_EXEC_STACK; + if (!BC_PROG_STACK(&G.prog.results, 1)) return BC_STATUS_EXEC_STACK; - r = bc_vec_top(&p->results); + r = bc_vec_top(&G.prog.results); if (cond) { @@ -6430,7 +6423,7 @@ static BcStatus bc_program_execStr(char *code, size_t *bgn, } if (exec) { - bc_program_search(p, name, &v, true); + bc_program_search(name, &v, true); n = bc_vec_top(v); } @@ -6450,7 +6443,7 @@ static BcStatus bc_program_execStr(char *code, size_t *bgn, if (r->t == BC_RESULT_STR) sidx = r->d.id.idx; else if (r->t == BC_RESULT_VAR) { - s = bc_program_num(p, r, &n, false); + s = bc_program_num(r, &n, false); if (s || !BC_PROG_STR(n)) goto exit; sidx = n->rdx; } @@ -6460,11 +6453,11 @@ static BcStatus bc_program_execStr(char *code, size_t *bgn, fidx = sidx + BC_PROG_REQ_FUNCS; - str = bc_vec_item(&p->strs, sidx); - f = bc_vec_item(&p->fns, fidx); + str = bc_vec_item(&G.prog.strs, sidx); + f = bc_vec_item(&G.prog.fns, fidx); if (f->code.len == 0) { - common_parse_init(&prs, p, fidx); + common_parse_init(&prs, fidx); s = bc_parse_text(&prs, *str); if (s) goto err; s = common_parse_expr(&prs, BC_PARSE_NOCALL); @@ -6479,25 +6472,25 @@ static BcStatus bc_program_execStr(char *code, size_t *bgn, } ip.idx = 0; - ip.len = p->results.len; + ip.len = G.prog.results.len; ip.func = fidx; - bc_vec_pop(&p->results); - bc_vec_push(&p->stack, &ip); + bc_vec_pop(&G.prog.results); + bc_vec_push(&G.prog.stack, &ip); return BC_STATUS_SUCCESS; err: bc_parse_free(&prs); - f = bc_vec_item(&p->fns, fidx); + f = bc_vec_item(&G.prog.fns, fidx); bc_vec_npop(&f->code, f->code.len); exit: - bc_vec_pop(&p->results); + bc_vec_pop(&G.prog.results); return s; } #endif // ENABLE_DC -static BcStatus bc_program_pushGlobal(BcProgram *p, char inst) +static BcStatus bc_program_pushGlobal(char inst) { BcStatus s; BcResult res; @@ -6505,16 +6498,16 @@ static BcStatus bc_program_pushGlobal(BcProgram *p, char inst) res.t = inst - BC_INST_IBASE + BC_RESULT_IBASE; if (inst == BC_INST_IBASE) - val = (unsigned long) p->ib_t; + val = (unsigned long) G.prog.ib_t; else if (inst == BC_INST_SCALE) - val = (unsigned long) p->scale; + val = (unsigned long) G.prog.scale; else - val = (unsigned long) p->ob_t; + val = (unsigned long) G.prog.ob_t; bc_num_init(&res.d.n, BC_NUM_DEF_SIZE); s = bc_num_ulong2num(&res.d.n, val); if (s) goto err; - bc_vec_push(&p->results, &res); + bc_vec_push(&G.prog.results, &res); return s; @@ -6523,24 +6516,24 @@ err: return s; } -static void bc_program_addFunc(BcProgram *p, char *name, size_t *idx) +static void bc_program_addFunc(char *name, size_t *idx) { BcStatus s; BcId entry, *entry_ptr; BcFunc f; entry.name = name; - entry.idx = p->fns.len; + entry.idx = G.prog.fns.len; - s = bc_map_insert(&p->fn_map, &entry, idx); + s = bc_map_insert(&G.prog.fn_map, &entry, idx); if (s) free(name); - entry_ptr = bc_vec_item(&p->fn_map, *idx); + entry_ptr = bc_vec_item(&G.prog.fn_map, *idx); *idx = entry_ptr->idx; if (s == BC_STATUS_VEC_ITEM_EXISTS) { - BcFunc *func = bc_vec_item(&p->fns, entry_ptr->idx); + BcFunc *func = bc_vec_item(&G.prog.fns, entry_ptr->idx); // We need to reset these, so the function can be repopulated. func->nparams = 0; @@ -6550,20 +6543,20 @@ static void bc_program_addFunc(BcProgram *p, char *name, size_t *idx) } else { bc_func_init(&f); - bc_vec_push(&p->fns, &f); + bc_vec_push(&G.prog.fns, &f); } } -static BcStatus bc_program_reset(BcProgram *p, BcStatus s) +static BcStatus bc_program_reset(BcStatus s) { BcFunc *f; BcInstPtr *ip; - bc_vec_npop(&p->stack, p->stack.len - 1); - bc_vec_npop(&p->results, p->results.len); + bc_vec_npop(&G.prog.stack, G.prog.stack.len - 1); + bc_vec_npop(&G.prog.results, G.prog.results.len); - f = bc_vec_item(&p->fns, 0); - ip = bc_vec_top(&p->stack); + f = bc_vec_item(&G.prog.fns, 0); + ip = bc_vec_top(&G.prog.stack); ip->idx = f->code.len; if (!s && G_interrupt && !G.tty) return BC_STATUS_QUIT; @@ -6584,14 +6577,12 @@ static BcStatus bc_program_reset(BcProgram *p, BcStatus s) static BcStatus bc_program_exec(void) { - BcProgram *p = &G.prog; - BcStatus s = BC_STATUS_SUCCESS; size_t idx; BcResult r, *ptr; BcNum *num; - BcInstPtr *ip = bc_vec_top(&p->stack); - BcFunc *func = bc_vec_item(&p->fns, ip->func); + BcInstPtr *ip = bc_vec_top(&G.prog.stack); + BcFunc *func = bc_vec_item(&G.prog.fns, ip->func); char *code = func->code.v; bool cond = false; @@ -6604,10 +6595,10 @@ static BcStatus bc_program_exec(void) #if ENABLE_BC case BC_INST_JUMP_ZERO: { - s = bc_program_prep(p, &ptr, &num); + s = bc_program_prep(&ptr, &num); if (s) return s; - cond = !bc_num_cmp(num, &p->zero); - bc_vec_pop(&p->results); + cond = !bc_num_cmp(num, &G.prog.zero); + bc_vec_pop(&G.prog.results); } // Fallthrough. case BC_INST_JUMP: @@ -6621,7 +6612,7 @@ static BcStatus bc_program_exec(void) case BC_INST_CALL: { - s = bc_program_call(p, code, &ip->idx); + s = bc_program_call(code, &ip->idx); break; } @@ -6630,7 +6621,7 @@ static BcStatus bc_program_exec(void) case BC_INST_INC_POST: case BC_INST_DEC_POST: { - s = bc_program_incdec(p, inst); + s = bc_program_incdec(inst); break; } @@ -6643,7 +6634,7 @@ static BcStatus bc_program_exec(void) case BC_INST_RET: case BC_INST_RET0: { - s = bc_program_return(p, inst); + s = bc_program_return(inst); break; } @@ -6657,7 +6648,7 @@ static BcStatus bc_program_exec(void) case BC_INST_REL_LT: case BC_INST_REL_GT: { - s = bc_program_logical(p, inst); + s = bc_program_logical(inst); break; } @@ -6669,21 +6660,21 @@ static BcStatus bc_program_exec(void) case BC_INST_VAR: { - s = bc_program_pushVar(p, code, &ip->idx, false, false); + s = bc_program_pushVar(code, &ip->idx, false, false); break; } case BC_INST_ARRAY_ELEM: case BC_INST_ARRAY: { - s = bc_program_pushArray(p, code, &ip->idx, inst); + s = bc_program_pushArray(code, &ip->idx, inst); break; } case BC_INST_LAST: { r.t = BC_RESULT_LAST; - bc_vec_push(&p->results, &r); + bc_vec_push(&G.prog.results, &r); break; } @@ -6691,7 +6682,7 @@ static BcStatus bc_program_exec(void) case BC_INST_SCALE: case BC_INST_OBASE: { - s = bc_program_pushGlobal(p, inst); + s = bc_program_pushGlobal(inst); break; } @@ -6699,7 +6690,7 @@ static BcStatus bc_program_exec(void) case BC_INST_LENGTH: case BC_INST_SQRT: { - s = bc_program_builtin(p, inst); + s = bc_program_builtin(inst); break; } @@ -6707,22 +6698,22 @@ static BcStatus bc_program_exec(void) { r.t = BC_RESULT_CONSTANT; r.d.id.idx = bc_program_index(code, &ip->idx); - bc_vec_push(&p->results, &r); + bc_vec_push(&G.prog.results, &r); break; } case BC_INST_POP: { - if (!BC_PROG_STACK(&p->results, 1)) + if (!BC_PROG_STACK(&G.prog.results, 1)) s = BC_STATUS_EXEC_STACK; else - bc_vec_pop(&p->results); + bc_vec_pop(&G.prog.results); break; } case BC_INST_POP_EXEC: { - bc_vec_pop(&p->stack); + bc_vec_pop(&G.prog.stack); break; } @@ -6730,7 +6721,7 @@ static BcStatus bc_program_exec(void) case BC_INST_PRINT_POP: case BC_INST_PRINT_STR: { - s = bc_program_print(p, inst, 0); + s = bc_program_print(inst, 0); break; } @@ -6738,7 +6729,7 @@ static BcStatus bc_program_exec(void) { r.t = BC_RESULT_STR; r.d.id.idx = bc_program_index(code, &ip->idx); - bc_vec_push(&p->results, &r); + bc_vec_push(&G.prog.results, &r); break; } @@ -6749,25 +6740,25 @@ static BcStatus bc_program_exec(void) case BC_INST_PLUS: case BC_INST_MINUS: { - s = bc_program_op(p, inst); + s = bc_program_op(inst); break; } case BC_INST_BOOL_NOT: { - s = bc_program_prep(p, &ptr, &num); + s = bc_program_prep(&ptr, &num); if (s) return s; bc_num_init(&r.d.n, BC_NUM_DEF_SIZE); - (!bc_num_cmp(num, &p->zero) ? bc_num_one : bc_num_zero)(&r.d.n); - bc_program_retire(p, &r, BC_RESULT_TEMP); + (!bc_num_cmp(num, &G.prog.zero) ? bc_num_one : bc_num_zero)(&r.d.n); + bc_program_retire(&r, BC_RESULT_TEMP); break; } case BC_INST_NEG: { - s = bc_program_negate(p); + s = bc_program_negate(); break; } @@ -6781,19 +6772,19 @@ static BcStatus bc_program_exec(void) #endif case BC_INST_ASSIGN: { - s = bc_program_assign(p, inst); + s = bc_program_assign(inst); break; } #if ENABLE_DC case BC_INST_MODEXP: { - s = bc_program_modexp(p); + s = bc_program_modexp(); break; } case BC_INST_DIVMOD: { - s = bc_program_divmod(p); + s = bc_program_divmod(); break; } @@ -6807,29 +6798,29 @@ static BcStatus bc_program_exec(void) case BC_INST_PRINT_STACK: { - for (idx = 0; !s && idx < p->results.len; ++idx) - s = bc_program_print(p, BC_INST_PRINT, idx); + for (idx = 0; !s && idx < G.prog.results.len; ++idx) + s = bc_program_print(BC_INST_PRINT, idx); break; } case BC_INST_CLEAR_STACK: { - bc_vec_npop(&p->results, p->results.len); + bc_vec_npop(&G.prog.results, G.prog.results.len); break; } case BC_INST_STACK_LEN: { - s = bc_program_stackLen(p); + s = bc_program_stackLen(); break; } case BC_INST_DUPLICATE: { - if (!BC_PROG_STACK(&p->results, 1)) return BC_STATUS_EXEC_STACK; - ptr = bc_vec_top(&p->results); + if (!BC_PROG_STACK(&G.prog.results, 1)) return BC_STATUS_EXEC_STACK; + ptr = bc_vec_top(&G.prog.results); bc_result_copy(&r, ptr); - bc_vec_push(&p->results, &r); + bc_vec_push(&G.prog.results, &r); break; } @@ -6837,10 +6828,10 @@ static BcStatus bc_program_exec(void) { BcResult *ptr2; - if (!BC_PROG_STACK(&p->results, 2)) return BC_STATUS_EXEC_STACK; + if (!BC_PROG_STACK(&G.prog.results, 2)) return BC_STATUS_EXEC_STACK; - ptr = bc_vec_item_rev(&p->results, 0); - ptr2 = bc_vec_item_rev(&p->results, 1); + ptr = bc_vec_item_rev(&G.prog.results, 0); + ptr2 = bc_vec_item_rev(&G.prog.results, 1); memcpy(&r, ptr, sizeof(BcResult)); memcpy(ptr, ptr2, sizeof(BcResult)); memcpy(ptr2, &r, sizeof(BcResult)); @@ -6850,13 +6841,13 @@ static BcStatus bc_program_exec(void) case BC_INST_ASCIIFY: { - s = bc_program_asciify(p); + s = bc_program_asciify(); break; } case BC_INST_PRINT_STREAM: { - s = bc_program_printStream(p); + s = bc_program_printStream(); break; } @@ -6864,24 +6855,24 @@ static BcStatus bc_program_exec(void) case BC_INST_PUSH_VAR: { bool copy = inst == BC_INST_LOAD; - s = bc_program_pushVar(p, code, &ip->idx, true, copy); + s = bc_program_pushVar(code, &ip->idx, true, copy); break; } case BC_INST_PUSH_TO_VAR: { char *name = bc_program_name(code, &ip->idx); - s = bc_program_copyToVar(p, name, true); + s = bc_program_copyToVar(name, true); free(name); break; } case BC_INST_QUIT: { - if (p->stack.len <= 2) + if (G.prog.stack.len <= 2) s = BC_STATUS_QUIT; else - bc_vec_npop(&p->stack, 2); + bc_vec_npop(&G.prog.stack, 2); break; } @@ -6893,11 +6884,11 @@ static BcStatus bc_program_exec(void) #endif // ENABLE_DC } - if ((s && s != BC_STATUS_QUIT) || G_interrupt) s = bc_program_reset(p, s); + if ((s && s != BC_STATUS_QUIT) || G_interrupt) s = bc_program_reset(s); // If the stack has changed, pointers may be invalid. - ip = bc_vec_top(&p->stack); - func = bc_vec_item(&p->fns, ip->func); + ip = bc_vec_top(&G.prog.stack); + func = bc_vec_item(&G.prog.fns, ip->func); code = func->code.v; } @@ -7028,7 +7019,7 @@ static BcStatus bc_vm_process(const char *text) s = bc_program_exec(); if (!s && G.tty) fflush(stdout); if (s && s != BC_STATUS_QUIT) - s = bc_vm_error(bc_program_reset(&G.prog, s), G.prs.l.f, 0); + s = bc_vm_error(bc_program_reset(s), G.prs.l.f, 0); } return s; @@ -7179,33 +7170,33 @@ static BcStatus bc_vm_exec(void) } #if ENABLE_FEATURE_CLEAN_UP -static void bc_program_free(BcProgram *p) +static void bc_program_free() { - bc_num_free(&p->ib); - bc_num_free(&p->ob); - bc_num_free(&p->hexb); + bc_num_free(&G.prog.ib); + bc_num_free(&G.prog.ob); + bc_num_free(&G.prog.hexb); # if ENABLE_DC - bc_num_free(&p->strmb); + bc_num_free(&G.prog.strmb); # endif - bc_vec_free(&p->fns); - bc_vec_free(&p->fn_map); - bc_vec_free(&p->vars); - bc_vec_free(&p->var_map); - bc_vec_free(&p->arrs); - bc_vec_free(&p->arr_map); - bc_vec_free(&p->strs); - bc_vec_free(&p->consts); - bc_vec_free(&p->results); - bc_vec_free(&p->stack); - bc_num_free(&p->last); - bc_num_free(&p->zero); - bc_num_free(&p->one); + bc_vec_free(&G.prog.fns); + bc_vec_free(&G.prog.fn_map); + bc_vec_free(&G.prog.vars); + bc_vec_free(&G.prog.var_map); + bc_vec_free(&G.prog.arrs); + bc_vec_free(&G.prog.arr_map); + bc_vec_free(&G.prog.strs); + bc_vec_free(&G.prog.consts); + bc_vec_free(&G.prog.results); + bc_vec_free(&G.prog.stack); + bc_num_free(&G.prog.last); + bc_num_free(&G.prog.zero); + bc_num_free(&G.prog.one); } static void bc_vm_free(void) { bc_vec_free(&G.files); - bc_program_free(&G.prog); + bc_program_free(); bc_parse_free(&G.prs); free(G.env_args); } @@ -7251,8 +7242,8 @@ static void bc_program_init(size_t line_len) bc_vec_init(&G.prog.fns, sizeof(BcFunc), bc_func_free); bc_map_init(&G.prog.fn_map); - bc_program_addFunc(&G.prog, xstrdup(bc_func_main), &idx); - bc_program_addFunc(&G.prog, xstrdup(bc_func_read), &idx); + bc_program_addFunc(xstrdup(bc_func_main), &idx); + bc_program_addFunc(xstrdup(bc_func_read), &idx); bc_vec_init(&G.prog.vars, sizeof(BcVec), bc_vec_free); bc_map_init(&G.prog.var_map); @@ -7285,9 +7276,9 @@ static void bc_vm_init(const char *env_len) bc_program_init(len); if (IS_BC) { - bc_parse_init(&G.prs, &G.prog, BC_PROG_MAIN); + bc_parse_init(&G.prs, BC_PROG_MAIN); } else { - dc_parse_init(&G.prs, &G.prog, BC_PROG_MAIN); + dc_parse_init(&G.prs, BC_PROG_MAIN); } } -- cgit v1.2.3-55-g6feb From e3b4f23cf301c7fe525d58caf66ad0dd136275fe Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 2 Dec 2018 18:44:40 +0100 Subject: bc: bc_num_ulong2num(), bc_program_pushGlobal(), bc_program_stackLen() never fail function old new delta bc_num_ulong2num 66 62 -4 bc_num_printNum 572 563 -9 bc_program_exec 4562 4544 -18 bc_program_num 1147 1126 -21 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/4 up/down: 0/-52) Total: -52 bytes text data bss dec hex filename 988575 485 7296 996356 f3404 busybox_old 988523 485 7296 996304 f33d0 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 68 ++++++++++++++++++++++------------------------------------ 1 file changed, 26 insertions(+), 42 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 221e1529f..25b03a95d 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -299,7 +299,7 @@ static void bc_num_copy(BcNum *d, BcNum *s); static void bc_num_free(void *num); static BcStatus bc_num_ulong(BcNum *n, unsigned long *result); -static BcStatus bc_num_ulong2num(BcNum *n, unsigned long val); +static void bc_num_ulong2num(BcNum *n, unsigned long val); static BcStatus bc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale); static BcStatus bc_num_sub(BcNum *a, BcNum *b, BcNum *c, size_t scale); @@ -1404,6 +1404,7 @@ static BcStatus bc_read_file(const char *path, char **buf) read_err: free(*buf); return s; +///convert to better return convention } static void bc_args(int argc, char **argv) @@ -1469,6 +1470,7 @@ static BcStatus bc_num_subArrays(BcDig *restrict a, BcDig *restrict b, a[i + j] -= 1; } } +///move ^C detection to bc_num_binary() (can make bc_num_s() return void) return G_interrupt ? BC_STATUS_EXEC_SIGNAL : BC_STATUS_SUCCESS; } @@ -1695,6 +1697,7 @@ static BcStatus bc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) if (carry != 0) c->num[c->len++] = (BcDig) carry; +///move ^C detection to bc_num_binary() return G_interrupt ? BC_STATUS_EXEC_SIGNAL : BC_STATUS_SUCCESS; } @@ -1770,6 +1773,7 @@ static BcStatus bc_num_k(BcNum *restrict a, BcNum *restrict b, BcNum l1, h1, l2, h2, m2, m1, z0, z1, z2, temp; bool aone = BC_NUM_ONE(a); +///move ^C detection to bc_num_binary() if (G_interrupt) return BC_STATUS_EXEC_SIGNAL; if (a->len == 0 || b->len == 0) { bc_num_zero(c); @@ -1804,6 +1808,7 @@ static BcStatus bc_num_k(BcNum *restrict a, BcNum *restrict b, c->len = len; +///move ^C detection to bc_num_binary() return G_interrupt ? BC_STATUS_EXEC_SIGNAL : BC_STATUS_SUCCESS; } @@ -2061,6 +2066,7 @@ static BcStatus bc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) } if (G_interrupt) { +///move ^C detection to bc_num_binary() s = BC_STATUS_EXEC_SIGNAL; goto err; } @@ -2086,6 +2092,7 @@ static BcStatus bc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) } if (G_interrupt) { +///move ^C detection to bc_num_binary() s = BC_STATUS_EXEC_SIGNAL; goto err; } @@ -2135,6 +2142,8 @@ static BcStatus bc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale, if (init) bc_num_free(&num2); +///move ^C detection here: +// if (s == 0 && G_interrupt) s = BC_STATUS_EXEC_SIGNAL; return s; } @@ -2222,8 +2231,7 @@ static void bc_num_parseBase(BcNum *n, const char *val, BcNum *base) s = bc_num_mul(n, base, &mult, 0); if (s) goto int_err; - s = bc_num_ulong2num(&temp, v); - if (s) goto int_err; + bc_num_ulong2num(&temp, v); s = bc_num_add(&mult, &temp, n, 0); if (s) goto int_err; } @@ -2246,8 +2254,7 @@ static void bc_num_parseBase(BcNum *n, const char *val, BcNum *base) s = bc_num_mul(&result, base, &result, 0); if (s) goto err; - s = bc_num_ulong2num(&temp, v); - if (s) goto err; + bc_num_ulong2num(&temp, v); s = bc_num_add(&result, &temp, &result, 0); if (s) goto err; s = bc_num_mul(&mult, base, &mult, 0); @@ -2385,8 +2392,7 @@ static BcStatus bc_num_printNum(BcNum *n, BcNum *base, size_t width, if (s) goto err; s = bc_num_ulong(&fracp, &dig); if (s) goto err; - s = bc_num_ulong2num(&intp, dig); - if (s) goto err; + bc_num_ulong2num(&intp, dig); s = bc_num_sub(&fracp, &intp, &fracp, 0); if (s) goto err; print(dig, width, radix, nchars, len); @@ -2528,7 +2534,7 @@ static BcStatus bc_num_ulong(BcNum *n, unsigned long *result) return BC_STATUS_SUCCESS; } -static BcStatus bc_num_ulong2num(BcNum *n, unsigned long val) +static void bc_num_ulong2num(BcNum *n, unsigned long val) { size_t len; BcDig *ptr; @@ -2536,12 +2542,10 @@ static BcStatus bc_num_ulong2num(BcNum *n, unsigned long val) bc_num_zero(n); - if (val == 0) return BC_STATUS_SUCCESS; + if (val == 0) return; for (len = 1, i = ULONG_MAX; i != 0; i /= 10, ++len) bc_num_expand(n, len); for (ptr = n->num, i = 0; val; ++i, ++n->len, val /= 10) ptr[i] = val % 10; - - return BC_STATUS_SUCCESS; } static BcStatus bc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale) @@ -2642,6 +2646,7 @@ static BcStatus bc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale) resrdx = scale + 2; len = BC_NUM_INT(x0) + resrdx - 1; +///move ^C detection to callers while (!G_interrupt && (cmp != 0 || digs < len)) { s = bc_num_div(a, x0, &f, resrdx); @@ -2671,6 +2676,7 @@ static BcStatus bc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale) } if (G_interrupt) { +///move ^C detection to callers s = BC_STATUS_EXEC_SIGNAL; goto err; } @@ -6148,7 +6154,7 @@ static BcStatus bc_program_builtin(char inst) if (inst == BC_INST_SQRT) s = bc_num_sqrt(num, &res.d.n, G.prog.scale); #if ENABLE_BC else if (len != 0 && opnd->t == BC_RESULT_ARRAY) { - s = bc_num_ulong2num(&res.d.n, (unsigned long) ((BcVec *) num)->len); + bc_num_ulong2num(&res.d.n, (unsigned long) ((BcVec *) num)->len); } #endif #if ENABLE_DC @@ -6158,23 +6164,17 @@ static BcStatus bc_program_builtin(char inst) size_t idx = opnd->t == BC_RESULT_STR ? opnd->d.id.idx : num->rdx; str = bc_vec_item(&G.prog.strs, idx); - s = bc_num_ulong2num(&res.d.n, strlen(*str)); - if (s) goto err; + bc_num_ulong2num(&res.d.n, strlen(*str)); } #endif else { BcProgramBuiltIn f = len ? bc_program_len : bc_program_scale; - s = bc_num_ulong2num(&res.d.n, f(num)); - if (s) goto err; + bc_num_ulong2num(&res.d.n, f(num)); } bc_program_retire(&res, BC_RESULT_TEMP); return s; - -err: - bc_num_free(&res.d.n); - return s; } #if ENABLE_DC @@ -6248,24 +6248,16 @@ err: return s; } -static BcStatus bc_program_stackLen(void) +static void bc_program_stackLen(void) { - BcStatus s; BcResult res; size_t len = G.prog.results.len; res.t = BC_RESULT_TEMP; bc_num_init(&res.d.n, BC_NUM_DEF_SIZE); - s = bc_num_ulong2num(&res.d.n, len); - if (s) goto err; + bc_num_ulong2num(&res.d.n, len); bc_vec_push(&G.prog.results, &res); - - return s; - -err: - bc_num_free(&res.d.n); - return s; } static BcStatus bc_program_asciify(void) @@ -6490,9 +6482,8 @@ exit: } #endif // ENABLE_DC -static BcStatus bc_program_pushGlobal(char inst) +static void bc_program_pushGlobal(char inst) { - BcStatus s; BcResult res; unsigned long val; @@ -6505,15 +6496,8 @@ static BcStatus bc_program_pushGlobal(char inst) val = (unsigned long) G.prog.ob_t; bc_num_init(&res.d.n, BC_NUM_DEF_SIZE); - s = bc_num_ulong2num(&res.d.n, val); - if (s) goto err; + bc_num_ulong2num(&res.d.n, val); bc_vec_push(&G.prog.results, &res); - - return s; - -err: - bc_num_free(&res.d.n); - return s; } static void bc_program_addFunc(char *name, size_t *idx) @@ -6682,7 +6666,7 @@ static BcStatus bc_program_exec(void) case BC_INST_SCALE: case BC_INST_OBASE: { - s = bc_program_pushGlobal(inst); + bc_program_pushGlobal(inst); break; } @@ -6811,7 +6795,7 @@ static BcStatus bc_program_exec(void) case BC_INST_STACK_LEN: { - s = bc_program_stackLen(); + bc_program_stackLen(); break; } -- cgit v1.2.3-55-g6feb From df51539ed0ceaa0556a509b25dafdec11437e645 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 2 Dec 2018 19:27:48 +0100 Subject: bc: simpler calling convention for bc_read_file(), bc_program_search() function old new delta bc_vm_run 1854 2020 +166 bc_program_assign 482 476 -6 bc_program_pushVar 225 215 -10 bc_program_call 366 356 -10 bc_program_num 1126 1115 -11 bc_program_copyToVar 354 343 -11 bc_program_search 164 152 -12 bc_program_execStr 573 559 -14 bc_program_exec 4544 4530 -14 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/8 up/down: 166/-88) Total: 78 bytes text data bss dec hex filename 988523 485 7296 996304 f33d0 busybox_old 988601 485 7296 996382 f341e busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 49 +++++++++++++++++++++++-------------------------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 25b03a95d..7e72ab28f 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1386,25 +1386,23 @@ static BcStatus bc_read_line(BcVec *vec, const char *prompt) return BC_STATUS_SUCCESS; } -static BcStatus bc_read_file(const char *path, char **buf) +static char* bc_read_file(const char *path) { - BcStatus s = BC_STATUS_BIN_FILE; + char *buf; size_t size = ((size_t) -1); size_t i; - *buf = xmalloc_open_read_close(path, &size); + buf = xmalloc_open_read_close(path, &size); for (i = 0; i < size; ++i) { - if (BC_READ_BIN_CHAR((*buf)[i])) - goto read_err; + if (BC_READ_BIN_CHAR(buf[i])) { + free(buf); + buf = NULL; + break; + } } - return BC_STATUS_SUCCESS; - -read_err: - free(*buf); - return s; -///convert to better return convention + return buf; } static void bc_args(int argc, char **argv) @@ -5275,7 +5273,7 @@ static BcStatus common_parse_expr(BcParse *p, uint8_t flags) } } -static void bc_program_search(char *id, BcVec **ret, bool var) +static BcVec* bc_program_search(char *id, bool var) { BcStatus s; BcId e, *ptr; @@ -5299,8 +5297,7 @@ static void bc_program_search(char *id, BcVec **ret, bool var) ptr = bc_vec_item(map, i); if (new) ptr->name = xstrdup(e.name); - *ret = bc_vec_item(v, ptr->idx); -/// convert to better return convention + return bc_vec_item(v, ptr->idx); } static BcStatus bc_program_num(BcResult *r, BcNum **num, bool hex) @@ -5349,7 +5346,7 @@ static BcStatus bc_program_num(BcResult *r, BcNum **num, bool hex) { BcVec *v; - bc_program_search(r->d.id.name, &v, r->t == BC_RESULT_VAR); + v = bc_program_search(r->d.id.name, r->t == BC_RESULT_VAR); if (r->t == BC_RESULT_ARRAY_ELEM) { v = bc_vec_top(v); @@ -5792,7 +5789,7 @@ static BcStatus bc_program_copyToVar(char *name, bool var) ptr = bc_vec_top(&G.prog.results); if ((ptr->t == BC_RESULT_ARRAY) != !var) return BC_STATUS_EXEC_BAD_TYPE; - bc_program_search(name, &v, var); + v = bc_program_search(name, var); #if ENABLE_DC if (ptr->t == BC_RESULT_STR && !var) return BC_STATUS_EXEC_BAD_TYPE; @@ -5803,7 +5800,7 @@ static BcStatus bc_program_copyToVar(char *name, bool var) if (s) return s; // Do this once more to make sure that pointers were not invalidated. - bc_program_search(name, &v, var); + v = bc_program_search(name, var); if (var) { bc_num_init(&r.d.n, BC_NUM_DEF_SIZE); @@ -5841,7 +5838,7 @@ static BcStatus bc_program_assign(char inst) BcVec *v; if (left->t != BC_RESULT_VAR) return BC_STATUS_EXEC_BAD_TYPE; - bc_program_search(left->d.id.name, &v, true); + v = bc_program_search(left->d.id.name, true); return bc_program_assignStr(right, v, false); } @@ -5913,7 +5910,7 @@ static BcStatus bc_program_pushVar(char *code, size_t *bgn, r.d.id.name = name; #if ENABLE_DC - bc_program_search(name, &v, true); + v = bc_program_search(name, true); num = bc_vec_top(v); if (pop || copy) { @@ -6023,7 +6020,6 @@ static BcStatus bc_program_call(char *code, size_t *idx) BcInstPtr ip; size_t i, nparams = bc_program_index(code, idx); BcFunc *func; - BcVec *v; BcId *a; BcResultData param; BcResult *arg; @@ -6049,9 +6045,10 @@ static BcStatus bc_program_call(char *code, size_t *idx) } for (; i < func->autos.len; ++i) { + BcVec *v; a = bc_vec_item(&func->autos, i); - bc_program_search(a->name, &v, a->idx); + v = bc_program_search(a->name, a->idx); if (a->idx) { bc_num_init(¶m.n, BC_NUM_DEF_SIZE); @@ -6103,7 +6100,7 @@ static BcStatus bc_program_return(char inst) BcVec *v; BcId *a = bc_vec_item(&f->autos, i); - bc_program_search(a->name, &v, a->idx); + v = bc_program_search(a->name, a->idx); bc_vec_pop(v); } @@ -6397,7 +6394,6 @@ static BcStatus bc_program_execStr(char *code, size_t *bgn, if (cond) { - BcVec *v; char *name, *then_name = bc_program_name(code, bgn), *else_name = NULL; if (code[*bgn] == BC_PARSE_STREND) @@ -6415,7 +6411,8 @@ static BcStatus bc_program_execStr(char *code, size_t *bgn, } if (exec) { - bc_program_search(name, &v, true); + BcVec *v; + v = bc_program_search(name, true); n = bc_vec_top(v); } @@ -7017,8 +7014,8 @@ static BcStatus bc_vm_file(const char *file) BcInstPtr *ip; G.prog.file = file; - s = bc_read_file(file, &data); - if (s) return bc_vm_error(s, file, 0); + data = bc_read_file(file); + if (!data) return bc_vm_error(BC_STATUS_BIN_FILE, file, 0); bc_lex_file(&G.prs.l, file); s = bc_vm_process(data); -- cgit v1.2.3-55-g6feb From 71e1fc6b376e1fde2c3b0dbcf94c4261eed9c6c5 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 2 Dec 2018 19:43:34 +0100 Subject: bc: only check for ^C in bc_program_exec() main loop Checking it in individual operations such as SQRT is not necessary since they usually do not take very long to complete. We repeatedly return to main loop. TODO: re-add more fine-grained ^C checks - but only with examples where it is actually needed. E.g. I suspect simplest ops like addition or compare won't need it. function old new delta bc_program_index 66 64 -2 bc_num_s 258 246 -12 bc_num_cmp 294 275 -19 bc_num_compare 84 59 -25 bc_num_subArrays 74 47 -27 bc_num_a 474 445 -29 bc_program_exec 4530 4500 -30 bc_num_p 518 472 -46 bc_num_d 604 558 -46 bc_num_k 1005 957 -48 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/10 up/down: 0/-284) Total: -284 bytes text data bss dec hex filename 988601 485 7296 996382 f341e busybox_old 988317 485 7296 996098 f3302 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 70 ++++++++++++++++++---------------------------------------- 1 file changed, 21 insertions(+), 49 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 7e72ab28f..63b745dc7 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1338,12 +1338,12 @@ static BcStatus bc_read_line(BcVec *vec, const char *prompt) #if ENABLE_FEATURE_BC_SIGNALS if (bb_got_signal) { /* ^C was pressed */ intr: + bb_got_signal = 0; /* resets G_interrupt to zero */ fputs(IS_BC ? "\ninterrupt (type \"quit\" to exit)\n" : "\ninterrupt (type \"q\" to exit)\n" , stderr); } - bb_got_signal = 0; /* resets G_interrupt to zero */ #endif if (G.ttyin && !G_posix) fputs(prompt, stderr); @@ -1458,25 +1458,23 @@ static void bc_num_ten(BcNum *n) n->num[1] = 1; } -static BcStatus bc_num_subArrays(BcDig *restrict a, BcDig *restrict b, +static void bc_num_subArrays(BcDig *restrict a, BcDig *restrict b, size_t len) { size_t i, j; - for (i = 0; !G_interrupt && i < len; ++i) { - for (a[i] -= b[i], j = 0; !G_interrupt && a[i + j] < 0;) { + for (i = 0; i < len; ++i) { + for (a[i] -= b[i], j = 0; a[i + j] < 0;) { a[i + j++] += 10; a[i + j] -= 1; } } -///move ^C detection to bc_num_binary() (can make bc_num_s() return void) - return G_interrupt ? BC_STATUS_EXEC_SIGNAL : BC_STATUS_SUCCESS; } static ssize_t bc_num_compare(BcDig *restrict a, BcDig *restrict b, size_t len) { size_t i; int c = 0; - for (i = len - 1; !G_interrupt && i < len && !(c = a[i] - b[i]); --i); + for (i = len - 1; i < len && !(c = a[i] - b[i]); --i); return BC_NUM_NEG(i + 1, c < 0); } @@ -1522,7 +1520,7 @@ static ssize_t bc_num_cmp(BcNum *a, BcNum *b) cmp = bc_num_compare(max_num, min_num, b_int + min); if (cmp != 0) return BC_NUM_NEG(cmp, (!a_max) != neg); - for (max_num -= diff, i = diff - 1; !G_interrupt && i < diff; --i) { + for (max_num -= diff, i = diff - 1; i < diff; --i) { if (max_num[i]) return BC_NUM_NEG(1, (!a_max) != neg); } @@ -1681,13 +1679,13 @@ static BcStatus bc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) ptr = ptr_b; } - for (carry = 0, i = 0; !G_interrupt && i < min_rdx + min_int; ++i, ++c->len) { + for (carry = 0, i = 0; i < min_rdx + min_int; ++i, ++c->len) { in = ((int) ptr_a[i]) + ((int) ptr_b[i]) + carry; carry = in / 10; ptr_c[i] = (BcDig)(in % 10); } - for (; !G_interrupt && i < max + min_rdx; ++i, ++c->len) { + for (; i < max + min_rdx; ++i, ++c->len) { in = ((int) ptr[i]) + carry; carry = in / 10; ptr_c[i] = (BcDig)(in % 10); @@ -1695,13 +1693,11 @@ static BcStatus bc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) if (carry != 0) c->num[c->len++] = (BcDig) carry; -///move ^C detection to bc_num_binary() - return G_interrupt ? BC_STATUS_EXEC_SIGNAL : BC_STATUS_SUCCESS; + return BC_STATUS_SUCCESS; // can't make void, see bc_num_binary() } static BcStatus bc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) { - BcStatus s; ssize_t cmp; BcNum *minuend, *subtrahend; size_t start; @@ -1755,11 +1751,11 @@ static BcStatus bc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) else start = c->rdx - subtrahend->rdx; - s = bc_num_subArrays(c->num + start, subtrahend->num, subtrahend->len); + bc_num_subArrays(c->num + start, subtrahend->num, subtrahend->len); bc_num_clean(c); - return s; + return BC_STATUS_SUCCESS; // can't make void, see bc_num_binary() } static BcStatus bc_num_k(BcNum *restrict a, BcNum *restrict b, @@ -1771,8 +1767,6 @@ static BcStatus bc_num_k(BcNum *restrict a, BcNum *restrict b, BcNum l1, h1, l2, h2, m2, m1, z0, z1, z2, temp; bool aone = BC_NUM_ONE(a); -///move ^C detection to bc_num_binary() - if (G_interrupt) return BC_STATUS_EXEC_SIGNAL; if (a->len == 0 || b->len == 0) { bc_num_zero(c); return BC_STATUS_SUCCESS; @@ -1790,9 +1784,9 @@ static BcStatus bc_num_k(BcNum *restrict a, BcNum *restrict b, memset(c->num, 0, sizeof(BcDig) * c->cap); c->len = carry = len = 0; - for (i = 0; !G_interrupt && i < b->len; ++i) { + for (i = 0; i < b->len; ++i) { - for (j = 0; !G_interrupt && j < a->len; ++j) { + for (j = 0; j < a->len; ++j) { int in = (int) c->num[i + j]; in += ((int) a->num[j]) * ((int) b->num[i]) + carry; carry = in / 10; @@ -1806,8 +1800,7 @@ static BcStatus bc_num_k(BcNum *restrict a, BcNum *restrict b, c->len = len; -///move ^C detection to bc_num_binary() - return G_interrupt ? BC_STATUS_EXEC_SIGNAL : BC_STATUS_SUCCESS; + return BC_STATUS_SUCCESS; } bc_num_init(&l1, max); @@ -1957,17 +1950,17 @@ static BcStatus bc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) c->len = cp.len; p = b->num; - for (i = end - 1; !G_interrupt && !s && i < end; --i) { + for (i = end - 1; !s && i < end; --i) { n = cp.num + i; for (q = 0; (!s && n[len] != 0) || bc_num_compare(n, p, len) >= 0; ++q) - s = bc_num_subArrays(n, p, len); + bc_num_subArrays(n, p, len); c->num[i] = q; } - if (!s) bc_num_retireMul(c, scale, a->neg, b->neg); + bc_num_retireMul(c, scale, a->neg, b->neg); bc_num_free(&cp); - return s; + return BC_STATUS_SUCCESS; // can't make void, see bc_num_binary() } static BcStatus bc_num_r(BcNum *a, BcNum *b, BcNum *restrict c, @@ -2057,21 +2050,15 @@ static BcStatus bc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) b->neg = neg; - for (powrdx = a->rdx; !G_interrupt && !(pow & 1); pow >>= 1) { + for (powrdx = a->rdx; !(pow & 1); pow >>= 1) { powrdx <<= 1; s = bc_num_mul(©, ©, ©, powrdx); if (s) goto err; } - if (G_interrupt) { -///move ^C detection to bc_num_binary() - s = BC_STATUS_EXEC_SIGNAL; - goto err; - } - bc_num_copy(c, ©); - for (resrdx = powrdx, pow >>= 1; !G_interrupt && pow != 0; pow >>= 1) { + for (resrdx = powrdx, pow >>= 1; pow != 0; pow >>= 1) { powrdx <<= 1; s = bc_num_mul(©, ©, ©, powrdx); @@ -2089,12 +2076,6 @@ static BcStatus bc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) if (s) goto err; } - if (G_interrupt) { -///move ^C detection to bc_num_binary() - s = BC_STATUS_EXEC_SIGNAL; - goto err; - } - if (c->rdx > scale) bc_num_truncate(c, c->rdx - scale); // We can't use bc_num_clean() here. @@ -2140,8 +2121,6 @@ static BcStatus bc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale, if (init) bc_num_free(&num2); -///move ^C detection here: -// if (s == 0 && G_interrupt) s = BC_STATUS_EXEC_SIGNAL; return s; } @@ -2644,8 +2623,7 @@ static BcStatus bc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale) resrdx = scale + 2; len = BC_NUM_INT(x0) + resrdx - 1; -///move ^C detection to callers - while (!G_interrupt && (cmp != 0 || digs < len)) { + while (cmp != 0 || digs < len) { s = bc_num_div(a, x0, &f, resrdx); if (s) goto err; @@ -2673,12 +2651,6 @@ static BcStatus bc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale) x1 = temp; } - if (G_interrupt) { -///move ^C detection to callers - s = BC_STATUS_EXEC_SIGNAL; - goto err; - } - bc_num_copy(b, x0); scale -= 1; if (b->rdx > scale) bc_num_truncate(b, b->rdx - scale); -- cgit v1.2.3-55-g6feb From a0c421c118abde7636d4d2b9bee93ca78e656d30 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 2 Dec 2018 20:16:52 +0100 Subject: bc: simplify bc_vm_stdin() function old new delta bc_vm_run 2020 2006 -14 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 63b745dc7..78c64355b 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -7005,11 +7005,10 @@ err: static BcStatus bc_vm_stdin(void) { - BcStatus s = BC_STATUS_SUCCESS; + BcStatus s; BcVec buf, buffer; - char c; size_t len, i, str = 0; - bool comment = false, notend; + bool comment = false; G.prog.file = bc_program_stdin_name; bc_lex_file(&G.prs.l, bc_program_stdin_name); @@ -7022,7 +7021,7 @@ static BcStatus bc_vm_stdin(void) // with a backslash to the parser. The reason for that is because the parser // treats a backslash+newline combo as whitespace, per the bc spec. In that // case, and for strings and comments, the parser will expect more stuff. - for (s = bc_read_line(&buf, ">>> "); !s; s = bc_read_line(&buf, ">>> ")) { + while ((s = bc_read_line(&buf, ">>> ")) == BC_STATUS_SUCCESS) { char *string = buf.v; @@ -7038,8 +7037,8 @@ static BcStatus bc_vm_stdin(void) for (i = 0; i < len; ++i) { - notend = len > i + 1; - c = string[i]; + bool notend = len > i + 1; + char c = string[i]; if (i - 1 > len || string[i - 1] != '\\') { if (G.sbgn == G.send) -- cgit v1.2.3-55-g6feb From 9721f6c8b0b5a22313fb546af5959d69ac6b59ef Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 2 Dec 2018 20:34:03 +0100 Subject: bc: tweak help text -v is supported but not shown Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 78c64355b..4257511f0 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -114,12 +114,19 @@ //kbuild:lib-$(CONFIG_BC) += bc.o //kbuild:lib-$(CONFIG_DC) += bc.o +//See www.gnu.org/software/bc/manual/bc.html //usage:#define bc_trivial_usage -//usage: "EXPRESSION...\n" -//usage: "function_definition\n" +//usage: "[-sqli] FILE..." //usage: -//usage:#define bc_full_usage "\n\n" -//usage: "See www.gnu.org/software/bc/manual/bc.html\n" +//usage:#define bc_full_usage "\n" +//usage: "\nArbitrary precision calculator" +//usage: "\n" +//usage: "\n -i Interactive" +//usage: "\n -l Load standard math library" +//usage: "\n -s Be POSIX compatible" +//usage: "\n -q Quiet" +//usage: "\n -w Warn if extensions are used" +///////: "\n -v Version" //usage: //usage:#define bc_example_usage //usage: "3 + 4.129\n" -- cgit v1.2.3-55-g6feb From 416ce76bcd26084099f430367f88387fced1c34e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 2 Dec 2018 20:57:17 +0100 Subject: bc: better handle optional args of bc_program_pushVar() Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 49 +++++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 4257511f0..ee05cd4b4 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -5872,49 +5872,50 @@ static BcStatus bc_program_assign(char inst) return s; } +#if !ENABLE_DC +#define bc_program_pushVar(code, bgn, pop, copy) \ + bc_program_pushVar(code, bgn) +// for bc, 'pop' and 'copy' are always false +#endif static BcStatus bc_program_pushVar(char *code, size_t *bgn, bool pop, bool copy) { BcStatus s = BC_STATUS_SUCCESS; BcResult r; char *name = bc_program_name(code, bgn); -#if ENABLE_DC // Exclude - BcNum *num; - BcVec *v; -#else - (void) pop, (void) copy; -#endif r.t = BC_RESULT_VAR; r.d.id.name = name; #if ENABLE_DC - v = bc_program_search(name, true); - num = bc_vec_top(v); + { + BcVec *v = bc_program_search(name, true); + BcNum *num = bc_vec_top(v); - if (pop || copy) { + if (pop || copy) { + + if (!BC_PROG_STACK(v, 2 - copy)) { + free(name); + return BC_STATUS_EXEC_STACK; + } - if (!BC_PROG_STACK(v, 2 - copy)) { free(name); - return BC_STATUS_EXEC_STACK; - } + name = NULL; - free(name); - name = NULL; + if (!BC_PROG_STR(num)) { - if (!BC_PROG_STR(num)) { + r.t = BC_RESULT_TEMP; - r.t = BC_RESULT_TEMP; + bc_num_init(&r.d.n, BC_NUM_DEF_SIZE); + bc_num_copy(&r.d.n, num); + } + else { + r.t = BC_RESULT_STR; + r.d.id.idx = num->rdx; + } - bc_num_init(&r.d.n, BC_NUM_DEF_SIZE); - bc_num_copy(&r.d.n, num); - } - else { - r.t = BC_RESULT_STR; - r.d.id.idx = num->rdx; + if (!copy) bc_vec_pop(v); } - - if (!copy) bc_vec_pop(v); } #endif // ENABLE_DC -- cgit v1.2.3-55-g6feb From d9d66556d74f14982daa34b70c0aeb8c6456117d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 2 Dec 2018 21:02:54 +0100 Subject: bc: use smaller datatypes for limits, match GNU bc 'limits' output function old new delta bc_vm_process 315 291 -24 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-24) Total: -24 bytes text data bss dec hex filename 988303 485 7296 996084 f32f4 busybox_old 988273 485 7296 996054 f32d6 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index ee05cd4b4..7c88a4ba0 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -802,14 +802,14 @@ static BcStatus bc_program_reset(BcStatus s); #define BC_MAX(a, b) ((a) > (b) ? (a) : (b)) #define BC_MIN(a, b) ((a) < (b) ? (a) : (b)) -#define BC_MAX_OBASE ((unsigned long) 999) -#define BC_MAX_DIM ((unsigned long) INT_MAX) -#define BC_MAX_SCALE ((unsigned long) UINT_MAX) -#define BC_MAX_STRING ((unsigned long) UINT_MAX - 1) -#define BC_MAX_NAME BC_MAX_STRING -#define BC_MAX_NUM BC_MAX_STRING -#define BC_MAX_EXP ((unsigned long) LONG_MAX) -#define BC_MAX_VARS ((unsigned long) SIZE_MAX - 1) +#define BC_MAX_OBASE ((unsigned) 999) +#define BC_MAX_DIM ((unsigned) INT_MAX) +#define BC_MAX_SCALE ((unsigned) UINT_MAX) +#define BC_MAX_STRING ((unsigned) UINT_MAX - 1) +#define BC_MAX_NAME BC_MAX_STRING +#define BC_MAX_NUM BC_MAX_STRING +#define BC_MAX_EXP ((unsigned long) LONG_MAX) +#define BC_MAX_VARS ((unsigned long) SIZE_MAX - 1) struct globals { char sbgn; @@ -6956,16 +6956,14 @@ static BcStatus bc_vm_process(const char *text) if (s == BC_STATUS_LIMITS) { - bb_putchar('\n'); - printf("BC_BASE_MAX = %lu\n", BC_MAX_OBASE); - printf("BC_DIM_MAX = %lu\n", BC_MAX_DIM); - printf("BC_SCALE_MAX = %lu\n", BC_MAX_SCALE); - printf("BC_STRING_MAX = %lu\n", BC_MAX_STRING); - printf("BC_NAME_MAX = %lu\n", BC_MAX_NAME); - printf("BC_NUM_MAX = %lu\n", BC_MAX_NUM); - printf("Max Exponent = %lu\n", BC_MAX_EXP); - printf("Number of Vars = %lu\n", BC_MAX_VARS); - bb_putchar('\n'); + printf("BC_BASE_MAX = %u\n", BC_MAX_OBASE); + printf("BC_DIM_MAX = %u\n", BC_MAX_DIM); + printf("BC_SCALE_MAX = %u\n", BC_MAX_SCALE); + printf("BC_STRING_MAX = %u\n", BC_MAX_STRING); + printf("BC_NAME_MAX = %u\n", BC_MAX_NAME); + printf("BC_NUM_MAX = %u\n", BC_MAX_NUM); + printf("MAX Exponent = %lu\n", BC_MAX_EXP); + printf("Number of vars = %lu\n", BC_MAX_VARS); s = BC_STATUS_SUCCESS; } -- cgit v1.2.3-55-g6feb From 1f67e935ac7c4e8812deb97e3e81d0973634fa93 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 3 Dec 2018 00:08:59 +0100 Subject: bc: reduce forward declarations Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 7c88a4ba0..e224c8dd4 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -717,7 +717,6 @@ static BcStatus bc_lex_token(BcLex *l); // first in the expr enum. Note: This only works for binary operators. #define BC_PARSE_TOKEN_INST(t) ((char) ((t) -BC_LEX_NEG + BC_INST_NEG)) -static BcStatus bc_parse_parse(BcParse *p); static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next); #endif // ENABLE_BC @@ -845,8 +844,6 @@ static BcStatus bc_vm_posixError(BcStatus s, const char *file, size_t line, static void bc_vm_info(void); -static const char* const bc_args_env_name = "BC_ENV_ARGS"; - static const char bc_err_fmt[] = "\n%s error: %s\n"; static const char bc_warn_fmt[] = "\n%s warning: %s\n"; static const char bc_err_line[] = ":%zu\n\n"; @@ -960,9 +957,6 @@ static const char *bc_err_msgs[] = { }; -static const char bc_func_main[] = "(main)"; -static const char bc_func_read[] = "(read)"; - #if ENABLE_BC static const BcLexKeyword bc_lex_kws[20] = { BC_LEX_KW_ENTRY("auto", 4, true), @@ -6895,6 +6889,8 @@ static BcStatus bc_vm_posixError(BcStatus s, const char *file, size_t line, static void bc_vm_envArgs(void) { + static const char* const bc_args_env_name = "BC_ENV_ARGS"; + BcVec v; char *env_args = getenv(bc_args_env_name), *buf; @@ -7200,8 +7196,8 @@ static void bc_program_init(size_t line_len) bc_vec_init(&G.prog.fns, sizeof(BcFunc), bc_func_free); bc_map_init(&G.prog.fn_map); - bc_program_addFunc(xstrdup(bc_func_main), &idx); - bc_program_addFunc(xstrdup(bc_func_read), &idx); + bc_program_addFunc(xstrdup("(main)"), &idx); + bc_program_addFunc(xstrdup("(read)"), &idx); bc_vec_init(&G.prog.vars, sizeof(BcVec), bc_vec_free); bc_map_init(&G.prog.var_map); -- cgit v1.2.3-55-g6feb From b8860a8892f077091177170fe483d545d33789a6 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 3 Dec 2018 00:26:12 +0100 Subject: bc: remove "error ids": serve no useful purpose, error message should be explanatory enough function old new delta bc_warn_fmt 17 14 -3 bc_err_fmt 15 12 -3 bc_vm_posixError 205 189 -16 bc_vm_error 156 138 -18 bc_errs 28 - -28 bc_err_ids 58 - -58 ------------------------------------------------------------------------------ (add/remove: 0/2 grow/shrink: 0/4 up/down: 0/-126) Total: -126 bytes text data bss dec hex filename 988288 485 7296 996069 f32e5 busybox_old 988122 485 7296 995903 f323f busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 68 ++++++++++------------------------------------------------ 1 file changed, 11 insertions(+), 57 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index e224c8dd4..a8b170f0c 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -242,16 +242,6 @@ typedef enum BcStatus { } BcStatus; -#define BC_ERR_IDX_VM (0) -#define BC_ERR_IDX_LEX (1) -#define BC_ERR_IDX_PARSE (2) -#define BC_ERR_IDX_MATH (3) -#define BC_ERR_IDX_EXEC (4) -#define BC_ERR_IDX_VEC (5) -#if ENABLE_BC -#define BC_ERR_IDX_POSIX (6) -#endif - #define BC_VEC_INVALID_IDX ((size_t) -1) #define BC_VEC_START_CAP (1 << 5) @@ -844,49 +834,10 @@ static BcStatus bc_vm_posixError(BcStatus s, const char *file, size_t line, static void bc_vm_info(void); -static const char bc_err_fmt[] = "\n%s error: %s\n"; -static const char bc_warn_fmt[] = "\n%s warning: %s\n"; +static const char bc_err_fmt[] = "\nerror: %s\n"; +static const char bc_warn_fmt[] = "\nwarning: %s\n"; static const char bc_err_line[] = ":%zu\n\n"; -static const char *bc_errs[] = { - "VM", - "Lex", - "Parse", - "Math", - "Runtime", - "Vector", -#if ENABLE_BC - "POSIX", -#endif -}; - -static const uint8_t bc_err_ids[] = { - BC_ERR_IDX_VM, BC_ERR_IDX_VM, BC_ERR_IDX_VM, BC_ERR_IDX_VM, BC_ERR_IDX_VM, - BC_ERR_IDX_LEX, BC_ERR_IDX_LEX, BC_ERR_IDX_LEX, BC_ERR_IDX_LEX, -#if ENABLE_DC - BC_ERR_IDX_LEX, -#endif - BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, - BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, BC_ERR_IDX_PARSE, - BC_ERR_IDX_MATH, BC_ERR_IDX_MATH, BC_ERR_IDX_MATH, BC_ERR_IDX_MATH, - BC_ERR_IDX_MATH, -#if ENABLE_DC - BC_ERR_IDX_MATH, -#endif - BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, - BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, - BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, - BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, BC_ERR_IDX_EXEC, - BC_ERR_IDX_EXEC, - BC_ERR_IDX_VEC, BC_ERR_IDX_VEC, -#if ENABLE_BC - BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX, - BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX, - BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX, BC_ERR_IDX_POSIX, -#endif - BC_ERR_IDX_VM, BC_ERR_IDX_VM, BC_ERR_IDX_VM, -}; - static const char *bc_err_msgs[] = { NULL, @@ -6863,7 +6814,7 @@ static BcStatus bc_vm_error(BcStatus s, const char *file, size_t line) { if (!s || s > BC_STATUS_VEC_ITEM_EXISTS) return s; - fprintf(stderr, bc_err_fmt, bc_errs[bc_err_ids[s]], bc_err_msgs[s]); + fprintf(stderr, bc_err_fmt, bc_err_msgs[s]); fprintf(stderr, " %s", file); fprintf(stderr, bc_err_line + 4 * !line, line); @@ -6874,17 +6825,20 @@ static BcStatus bc_vm_error(BcStatus s, const char *file, size_t line) static BcStatus bc_vm_posixError(BcStatus s, const char *file, size_t line, const char *msg) { - int p = (int) G_posix, w = (int) G_warn; - const char *const fmt = p ? bc_err_fmt : bc_warn_fmt; + const char *fmt; - if (!(p || w) || s < BC_STATUS_POSIX_NAME_LEN) return BC_STATUS_SUCCESS; + if (!(G.flags & (BC_FLAG_S|BC_FLAG_W))) return BC_STATUS_SUCCESS; + if (s < BC_STATUS_POSIX_NAME_LEN) return BC_STATUS_SUCCESS; - fprintf(stderr, fmt, bc_errs[bc_err_ids[s]], bc_err_msgs[s]); + fmt = G_posix ? bc_err_fmt : bc_warn_fmt; + fprintf(stderr, fmt, bc_err_msgs[s]); if (msg) fprintf(stderr, " %s\n", msg); fprintf(stderr, " %s", file); fprintf(stderr, bc_err_line + 4 * !line, line); - return s * (!G.ttyin && !!p); + if (G.ttyin || !G_posix) + s = BC_STATUS_SUCCESS; + return s; } static void bc_vm_envArgs(void) -- cgit v1.2.3-55-g6feb From 01cabafd05410548bd7f539fb09dc3a8a9f48e08 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 3 Dec 2018 00:51:25 +0100 Subject: bc": drop unused error codes and strings function old new delta bc_err_msgs 216 192 -24 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-24) Total: -24 bytes text data bss dec hex filename 988122 485 7296 995903 f323f busybox_old 987936 485 7296 995717 f3185 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 155 +++++++++++++++++++++++++++------------------------------ 1 file changed, 73 insertions(+), 82 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index a8b170f0c..ee6cc47ce 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -168,13 +168,12 @@ #include "libbb.h" typedef enum BcStatus { - BC_STATUS_SUCCESS, - BC_STATUS_ALLOC_ERR, +// BC_STATUS_ALLOC_ERR, BC_STATUS_INPUT_EOF, BC_STATUS_BIN_FILE, - BC_STATUS_PATH_IS_DIR, +// BC_STATUS_PATH_IS_DIR, BC_STATUS_LEX_BAD_CHAR, BC_STATUS_LEX_NO_STRING_END, @@ -183,7 +182,6 @@ typedef enum BcStatus { #if ENABLE_DC BC_STATUS_LEX_EXTENDED_REG, #endif - BC_STATUS_PARSE_BAD_TOKEN, BC_STATUS_PARSE_BAD_EXP, BC_STATUS_PARSE_EMPTY_EXP, @@ -200,7 +198,7 @@ typedef enum BcStatus { BC_STATUS_MATH_DIVIDE_BY_ZERO, BC_STATUS_MATH_BAD_STRING, - BC_STATUS_EXEC_FILE_ERR, +// BC_STATUS_EXEC_FILE_ERR, BC_STATUS_EXEC_MISMATCHED_PARAMS, BC_STATUS_EXEC_UNDEFINED_FUNC, BC_STATUS_EXEC_FILE_NOT_EXECUTABLE, @@ -209,17 +207,16 @@ typedef enum BcStatus { BC_STATUS_EXEC_STRING_LEN, BC_STATUS_EXEC_ARRAY_LEN, BC_STATUS_EXEC_BAD_IBASE, - BC_STATUS_EXEC_BAD_SCALE, +// BC_STATUS_EXEC_BAD_SCALE, BC_STATUS_EXEC_BAD_READ_EXPR, BC_STATUS_EXEC_REC_READ, BC_STATUS_EXEC_BAD_TYPE, - BC_STATUS_EXEC_BAD_OBASE, +// BC_STATUS_EXEC_BAD_OBASE, BC_STATUS_EXEC_SIGNAL, BC_STATUS_EXEC_STACK, - BC_STATUS_VEC_OUT_OF_BOUNDS, +// BC_STATUS_VEC_OUT_OF_BOUNDS, BC_STATUS_VEC_ITEM_EXISTS, - #if ENABLE_BC BC_STATUS_POSIX_NAME_LEN, BC_STATUS_POSIX_COMMENT, @@ -234,13 +231,77 @@ typedef enum BcStatus { BC_STATUS_POSIX_FOR3, BC_STATUS_POSIX_BRACE, #endif - BC_STATUS_QUIT, BC_STATUS_LIMITS, - BC_STATUS_INVALID_OPTION, - +// BC_STATUS_INVALID_OPTION, } BcStatus; +// Keep enum above and messages below in sync! +static const char *const bc_err_msgs[] = { + NULL, +// "memory allocation error", + "I/O error", + "file is not text:", +// "path is a directory:", + + "bad character", + "string end could not be found", + "comment end could not be found", + "end of file", +#if ENABLE_DC + "extended register", +#endif + "bad token", + "bad expression", + "empty expression", + "bad print statement", + "bad function definition", + "bad assignment: left side must be scale, ibase, " + "obase, last, var, or array element", + "no auto variable found", + "function parameter or auto var has the same name as another", + "block end could not be found", + + "negative number", + "non integer number", + "overflow", + "divide by zero", + "bad number string", + +// "could not open file:", + "mismatched parameters", // wrong number of them, to be exact + "undefined function", + "file is not executable:", + "number too long: must be [1, BC_NUM_MAX]", + "name too long: must be [1, BC_NAME_MAX]", + "string too long: must be [1, BC_STRING_MAX]", + "array too long; must be [1, BC_DIM_MAX]", + "bad ibase; must be [2, 16]", +// "bad scale; must be [0, BC_SCALE_MAX]", + "bad read() expression", + "read() call inside of a read() call", + "variable is wrong type", +// "bad obase; must be [2, BC_BASE_MAX]", + "signal caught and not handled", + "stack has too few elements", + +// "index is out of bounds", + "item already exists", +#if ENABLE_BC + "POSIX only allows one character names; the following is bad:", + "POSIX does not allow '#' script comments", + "POSIX does not allow the following keyword:", + "POSIX does not allow a period ('.') as a shortcut for the last result", + "POSIX requires parentheses around return expressions", + "POSIX does not allow boolean operators; the following is bad:", + "POSIX does not allow comparison operators outside if or loops", + "POSIX requires exactly one comparison operator per condition", + "POSIX does not allow an empty init expression in a for loop", + "POSIX does not allow an empty condition expression in a for loop", + "POSIX does not allow an empty update expression in a for loop", + "POSIX requires the left brace be on the same line as the function header", +#endif +}; #define BC_VEC_INVALID_IDX ((size_t) -1) #define BC_VEC_START_CAP (1 << 5) @@ -838,76 +899,6 @@ static const char bc_err_fmt[] = "\nerror: %s\n"; static const char bc_warn_fmt[] = "\nwarning: %s\n"; static const char bc_err_line[] = ":%zu\n\n"; -static const char *bc_err_msgs[] = { - - NULL, - "memory allocation error", - "I/O error", - "file is not text:", - "path is a directory:", - - "bad character", - "string end could not be found", - "comment end could not be found", - "end of file", -#if ENABLE_DC - "extended register", -#endif - - "bad token", - "bad expression", - "empty expression", - "bad print statement", - "bad function definition", - "bad assignment: left side must be scale, ibase, " - "obase, last, var, or array element", - "no auto variable found", - "function parameter or auto var has the same name as another", - "block end could not be found", - - "negative number", - "non integer number", - "overflow", - "divide by zero", - "bad number string", - - "could not open file:", - "mismatched parameters", - "undefined function", - "file is not executable:", - "number too long: must be [1, BC_NUM_MAX]", - "name too long: must be [1, BC_NAME_MAX]", - "string too long: must be [1, BC_STRING_MAX]", - "array too long; must be [1, BC_DIM_MAX]", - "bad ibase; must be [2, 16]", - "bad scale; must be [0, BC_SCALE_MAX]", - "bad read() expression", - "read() call inside of a read() call", - "variable is wrong type", - "bad obase; must be [2, BC_BASE_MAX]", - "signal caught and not handled", - "stack has too few elements", - - "index is out of bounds", - "item already exists", - -#if ENABLE_BC - "POSIX only allows one character names; the following is bad:", - "POSIX does not allow '#' script comments", - "POSIX does not allow the following keyword:", - "POSIX does not allow a period ('.') as a shortcut for the last result", - "POSIX requires parentheses around return expressions", - "POSIX does not allow boolean operators; the following is bad:", - "POSIX does not allow comparison operators outside if or loops", - "POSIX requires exactly one comparison operator per condition", - "POSIX does not allow an empty init expression in a for loop", - "POSIX does not allow an empty condition expression in a for loop", - "POSIX does not allow an empty update expression in a for loop", - "POSIX requires the left brace be on the same line as the function header", -#endif - -}; - #if ENABLE_BC static const BcLexKeyword bc_lex_kws[20] = { BC_LEX_KW_ENTRY("auto", 4, true), -- cgit v1.2.3-55-g6feb From cfdc1334c3e0cfbbe41f850e426c51c37a653dfb Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 3 Dec 2018 14:02:35 +0100 Subject: bc: handle "limits" and "quit" immediately at parse time No need to propagate a special exit code. function old new delta bc_parse_stmt 2197 2301 +104 quit - 38 +38 bc_read_line 344 349 +5 bc_program_reset 174 172 -2 bc_num_s 252 246 -6 bc_num_a 454 445 -9 bc_parse_parse 471 461 -10 bc_num_ulong 95 85 -10 bc_program_exec 4500 4478 -22 bc_vm_run 2006 1978 -28 bc_vm_process 291 139 -152 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 2/8 up/down: 147/-239) Total: -92 bytes text data bss dec hex filename 987936 485 7296 995717 f3185 busybox_old 987844 485 7296 995625 f3129 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 107 ++++++++++++++++++++++++++------------------------------- 1 file changed, 49 insertions(+), 58 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index ee6cc47ce..c3d118417 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -231,8 +231,8 @@ typedef enum BcStatus { BC_STATUS_POSIX_FOR3, BC_STATUS_POSIX_BRACE, #endif - BC_STATUS_QUIT, - BC_STATUS_LIMITS, +// BC_STATUS_QUIT, +// BC_STATUS_LIMITS, // BC_STATUS_INVALID_OPTION, } BcStatus; @@ -1121,6 +1121,13 @@ static const char bc_lib[] = { }; #endif // ENABLE_BC +static void quit(void) NORETURN; +static void quit(void) +{ + fflush_all(); + exit(ferror(stdout) || ferror(stderr)); +} + static void bc_vec_grow(BcVec *v, size_t n) { size_t cap = v->cap * 2; @@ -1279,9 +1286,9 @@ static BcStatus bc_read_line(BcVec *vec, const char *prompt) fflush(stdout); #if ENABLE_FEATURE_BC_SIGNALS - if (bb_got_signal) { /* ^C was pressed */ + if (bb_got_signal) { // ^C was pressed intr: - bb_got_signal = 0; /* resets G_interrupt to zero */ + bb_got_signal = 0; // resets G_interrupt to zero fputs(IS_BC ? "\ninterrupt (type \"quit\" to exit)\n" : "\ninterrupt (type \"q\" to exit)\n" @@ -1293,7 +1300,6 @@ static BcStatus bc_read_line(BcVec *vec, const char *prompt) fflush(stderr); #if ENABLE_FEATURE_BC_SIGNALS - again: errno = 0; #endif do { @@ -1302,16 +1308,13 @@ static BcStatus bc_read_line(BcVec *vec, const char *prompt) i = fgetc(stdin); -#if ENABLE_FEATURE_BC_SIGNALS - if (bb_got_signal) /* ^C was pressed */ - goto intr; -#endif - if (i == EOF) { #if ENABLE_FEATURE_BC_SIGNALS - if (errno == EINTR) { + // Both conditions appear simultaneously, check both just in case + if (errno == EINTR || bb_got_signal) { + // ^C was pressed clearerr(stdin); - goto again; + goto intr; } #endif if (ferror(stdin)) @@ -4630,9 +4633,18 @@ static BcStatus bc_parse_stmt(BcParse *p) case BC_LEX_KEY_LIMITS: { + // "limits" is a compile-time command, + // the output is produced at _parse time_. s = bc_lex_next(&p->l); if (s) return s; - s = BC_STATUS_LIMITS; + printf("BC_BASE_MAX = %u\n", BC_MAX_OBASE); + printf("BC_DIM_MAX = %u\n", BC_MAX_DIM); + printf("BC_SCALE_MAX = %u\n", BC_MAX_SCALE); + printf("BC_STRING_MAX = %u\n", BC_MAX_STRING); + printf("BC_NAME_MAX = %u\n", BC_MAX_NAME); + printf("BC_NUM_MAX = %u\n", BC_MAX_NUM); + printf("MAX Exponent = %lu\n", BC_MAX_EXP); + printf("Number of vars = %lu\n", BC_MAX_VARS); break; } @@ -4644,10 +4656,10 @@ static BcStatus bc_parse_stmt(BcParse *p) case BC_LEX_KEY_QUIT: { - // Quit is a compile-time command. We don't exit directly, - // so the vm can clean up. Limits do the same thing. - s = BC_STATUS_QUIT; - break; + // "quit" is a compile-time command. For example, + // "if (0 == 1) quit" terminates when parsing the statement, + // not when it is executed + quit(); } case BC_LEX_KEY_RETURN: @@ -4685,7 +4697,7 @@ static BcStatus bc_parse_parse(BcParse *p) else s = bc_parse_stmt(p); - if ((s && s != BC_STATUS_QUIT && s != BC_STATUS_LIMITS) || G_interrupt) + if (s || G_interrupt) s = bc_parse_reset(p, s); return s; @@ -6283,8 +6295,8 @@ static BcStatus bc_program_nquit(void) if (G.prog.stack.len < val) return BC_STATUS_EXEC_STACK; - else if (G.prog.stack.len == val) - return BC_STATUS_QUIT; + if (G.prog.stack.len == val) + quit(); bc_vec_npop(&G.prog.stack, val); @@ -6456,17 +6468,15 @@ static BcStatus bc_program_reset(BcStatus s) ip = bc_vec_top(&G.prog.stack); ip->idx = f->code.len; - if (!s && G_interrupt && !G.tty) return BC_STATUS_QUIT; + if (!s && G_interrupt && !G.tty) quit(); if (!s || s == BC_STATUS_EXEC_SIGNAL) { - if (G.ttyin) { - fflush(stdout); - fputs(bc_program_ready_msg, stderr); - fflush(stderr); - s = BC_STATUS_SUCCESS; - } - else - s = BC_STATUS_QUIT; + if (!G.ttyin) + quit(); + fflush(stdout); + fputs(bc_program_ready_msg, stderr); + fflush(stderr); + s = BC_STATUS_SUCCESS; } return s; @@ -6524,7 +6534,7 @@ static BcStatus bc_program_exec(void) case BC_INST_HALT: { - s = BC_STATUS_QUIT; + quit(); break; } @@ -6767,9 +6777,8 @@ static BcStatus bc_program_exec(void) case BC_INST_QUIT: { if (G.prog.stack.len <= 2) - s = BC_STATUS_QUIT; - else - bc_vec_npop(&G.prog.stack, 2); + quit(); + bc_vec_npop(&G.prog.stack, 2); break; } @@ -6781,7 +6790,7 @@ static BcStatus bc_program_exec(void) #endif // ENABLE_DC } - if ((s && s != BC_STATUS_QUIT) || G_interrupt) s = bc_program_reset(s); + if (s || G_interrupt) s = bc_program_reset(s); // If the stack has changed, pointers may be invalid. ip = bc_vec_top(&G.prog.stack); @@ -6895,30 +6904,14 @@ static BcStatus bc_vm_process(const char *text) s = G.prs.parse(&G.prs); - if (s == BC_STATUS_LIMITS) { - - printf("BC_BASE_MAX = %u\n", BC_MAX_OBASE); - printf("BC_DIM_MAX = %u\n", BC_MAX_DIM); - printf("BC_SCALE_MAX = %u\n", BC_MAX_SCALE); - printf("BC_STRING_MAX = %u\n", BC_MAX_STRING); - printf("BC_NAME_MAX = %u\n", BC_MAX_NAME); - printf("BC_NUM_MAX = %u\n", BC_MAX_NUM); - printf("MAX Exponent = %lu\n", BC_MAX_EXP); - printf("Number of vars = %lu\n", BC_MAX_VARS); - - s = BC_STATUS_SUCCESS; - } - else { - if (s == BC_STATUS_QUIT) return s; - s = bc_vm_error(s, G.prs.l.f, G.prs.l.line); - if (s) return s; - } + s = bc_vm_error(s, G.prs.l.f, G.prs.l.line); + if (s) return s; } if (BC_PARSE_CAN_EXEC(&G.prs)) { s = bc_program_exec(); - if (!s && G.tty) fflush(stdout); - if (s && s != BC_STATUS_QUIT) + fflush(stdout); + if (s) s = bc_vm_error(bc_program_reset(s), G.prs.l.f, 0); } @@ -7021,7 +7014,7 @@ static BcStatus bc_vm_stdin(void) // INPUT_EOF will always happen when stdin is // closed. It's not a problem in that case. - if (s == BC_STATUS_INPUT_EOF || s == BC_STATUS_QUIT) + if (s == BC_STATUS_INPUT_EOF) s = BC_STATUS_SUCCESS; if (str) @@ -7058,13 +7051,11 @@ static BcStatus bc_vm_exec(void) for (i = 0; !s && i < G.files.len; ++i) s = bc_vm_file(*((char **) bc_vec_item(&G.files, i))); - if (s && s != BC_STATUS_QUIT) return s; + if (s) return s; if (IS_BC || !G.files.len) s = bc_vm_stdin(); if (!s && !BC_PARSE_CAN_EXEC(&G.prs)) s = bc_vm_process(""); - if (s == BC_STATUS_QUIT) - s = BC_STATUS_SUCCESS; return s; } -- cgit v1.2.3-55-g6feb From d4744adf35c678554e609a74eeebc7b7603ee25d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 3 Dec 2018 14:28:51 +0100 Subject: bc: eliminate BC_STATUS_INPUT_EOF function old new delta fflush_and_check - 36 +36 bc_num_a 445 456 +11 bc_num_ulong 85 95 +10 bc_vm_run 1978 1984 +6 bc_num_s 246 252 +6 bc_err_msgs 192 188 -4 quit 38 32 -6 bc_vm_process 139 132 -7 bc_program_reset 172 159 -13 bc_parse_create 192 175 -17 bc_read_line 349 311 -38 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 4/6 up/down: 69/-85) Total: -16 bytes text data bss dec hex filename 987844 485 7296 995625 f3129 busybox_old 987828 485 7296 995609 f3119 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 48 +++++++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index c3d118417..c819decff 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -171,7 +171,7 @@ typedef enum BcStatus { BC_STATUS_SUCCESS, // BC_STATUS_ALLOC_ERR, - BC_STATUS_INPUT_EOF, +// BC_STATUS_INPUT_EOF, BC_STATUS_BIN_FILE, // BC_STATUS_PATH_IS_DIR, @@ -240,7 +240,7 @@ typedef enum BcStatus { static const char *const bc_err_msgs[] = { NULL, // "memory allocation error", - "I/O error", +// "I/O error", "file is not text:", // "path is a directory:", @@ -875,6 +875,7 @@ struct globals { smallint tty; smallint ttyin; + smallint eof; } FIX_ALIASING; #define G (*ptr_to_globals) #define INIT_G() do { \ @@ -1121,11 +1122,20 @@ static const char bc_lib[] = { }; #endif // ENABLE_BC +static void fflush_and_check(void) +{ + fflush_all(); + if (ferror(stdout) || ferror(stderr)) + bb_perror_msg_and_die("output error"); +} + static void quit(void) NORETURN; static void quit(void) { - fflush_all(); - exit(ferror(stdout) || ferror(stderr)); + if (ferror(stdin)) + bb_perror_msg_and_die("input error"); + fflush_and_check(); + exit(0); } static void bc_vec_grow(BcVec *v, size_t n) @@ -1284,7 +1294,7 @@ static BcStatus bc_read_line(BcVec *vec, const char *prompt) bc_vec_npop(vec, vec->len); - fflush(stdout); + fflush_and_check(); #if ENABLE_FEATURE_BC_SIGNALS if (bb_got_signal) { // ^C was pressed intr: @@ -1297,15 +1307,12 @@ static BcStatus bc_read_line(BcVec *vec, const char *prompt) #endif if (G.ttyin && !G_posix) fputs(prompt, stderr); - fflush(stderr); + fflush_and_check(); #if ENABLE_FEATURE_BC_SIGNALS errno = 0; #endif do { - if (ferror(stdout) || ferror(stderr)) - bb_perror_msg_and_die("output error"); - i = fgetc(stdin); if (i == EOF) { @@ -1318,8 +1325,12 @@ static BcStatus bc_read_line(BcVec *vec, const char *prompt) } #endif if (ferror(stdin)) - bb_perror_msg_and_die("input error"); - return BC_STATUS_INPUT_EOF; + quit(); // this emits error message + G.eof = 1; + // Note: EOF does not append '\n', therefore: + // printf 'print 123\n' | bc - works + // printf 'print 123' | bc - fails (syntax error) + break; } c = (signed char) i; @@ -3627,7 +3638,7 @@ static void bc_parse_create(BcParse *p, size_t func, bc_vec_init(&p->ops, sizeof(BcLexType), NULL); p->parse = parse; - p->auto_part = (p->nbraces = 0); + // p->auto_part = p->nbraces = 0; - already is bc_parse_updateFunc(p, func); } @@ -6473,9 +6484,9 @@ static BcStatus bc_program_reset(BcStatus s) if (!s || s == BC_STATUS_EXEC_SIGNAL) { if (!G.ttyin) quit(); - fflush(stdout); + fflush_and_check(); // make sure buffered stdout is printed fputs(bc_program_ready_msg, stderr); - fflush(stderr); + fflush_and_check(); s = BC_STATUS_SUCCESS; } @@ -6910,7 +6921,7 @@ static BcStatus bc_vm_process(const char *text) if (BC_PARSE_CAN_EXEC(&G.prs)) { s = bc_program_exec(); - fflush(stdout); + fflush_and_check(); if (s) s = bc_vm_error(bc_program_reset(s), G.prs.l.f, 0); } @@ -6961,7 +6972,7 @@ static BcStatus bc_vm_stdin(void) // with a backslash to the parser. The reason for that is because the parser // treats a backslash+newline combo as whitespace, per the bc spec. In that // case, and for strings and comments, the parser will expect more stuff. - while ((s = bc_read_line(&buf, ">>> ")) == BC_STATUS_SUCCESS) { + while (!G.eof && (s = bc_read_line(&buf, ">>> ")) == BC_STATUS_SUCCESS) { char *string = buf.v; @@ -7012,11 +7023,6 @@ static BcStatus bc_vm_stdin(void) if (s == BC_STATUS_BIN_FILE) s = bc_vm_error(s, G.prs.l.f, 0); - // INPUT_EOF will always happen when stdin is - // closed. It's not a problem in that case. - if (s == BC_STATUS_INPUT_EOF) - s = BC_STATUS_SUCCESS; - if (str) s = bc_vm_error(BC_STATUS_LEX_NO_STRING_END, G.prs.l.f, G.prs.l.line); -- cgit v1.2.3-55-g6feb From c1c2470f843c0b8218dd3611330a941b00d0cc34 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 3 Dec 2018 16:06:02 +0100 Subject: bc: handle BIN_FILE and LEX_BAD_CHAR errors at the site of detection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The most informative message can be generated at the location where error is detected. The "error codes" are stupid: print error meesage immediately, then just return "there was an error" indicator. All error codes will be converted. For now, converting these two. For now, this and following changes will degrade error messages quality. For example, file name and line number printouts may be lost. This will be re-added later. This change anlso fixes handling of invalid stdin input: this used to cause interactive bc to exit: .... >>> ς bc: illegal character 0xcf bc: illegal character 0x82 >>> _ function old new delta bc_error - 42 +42 bc_lex_token 1333 1369 +36 dc_lex_token 675 695 +20 bc_read_line 311 325 +14 bc_num_a 456 454 -2 bc_err_msgs 188 184 -4 bc_num_ulong 95 85 -10 bc_vm_run 1984 1955 -29 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 3/4 up/down: 112/-45) Total: 67 bytes text data bss dec hex filename 987828 485 7296 995609 f3119 busybox_old 987929 485 7296 995710 f317e busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 130 +++++++++++++++++++++++++++++++++------------------------ 1 file changed, 76 insertions(+), 54 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index c819decff..dd01f5409 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -169,13 +169,14 @@ typedef enum BcStatus { BC_STATUS_SUCCESS, + BC_STATUS_FAILURE, // BC_STATUS_ALLOC_ERR, // BC_STATUS_INPUT_EOF, - BC_STATUS_BIN_FILE, +// BC_STATUS_BIN_FILE, // BC_STATUS_PATH_IS_DIR, - BC_STATUS_LEX_BAD_CHAR, +// BC_STATUS_LEX_BAD_CHAR, BC_STATUS_LEX_NO_STRING_END, BC_STATUS_LEX_NO_COMMENT_END, BC_STATUS_LEX_EOF, @@ -239,12 +240,13 @@ typedef enum BcStatus { // Keep enum above and messages below in sync! static const char *const bc_err_msgs[] = { NULL, + "", // "memory allocation error", // "I/O error", - "file is not text:", +// "file is not text:", // "path is a directory:", - "bad character", +// "bad character", "string end could not be found", "comment end could not be found", "end of file", @@ -321,8 +323,6 @@ typedef struct BcVec { #define bc_map_init(v) (bc_vec_init((v), sizeof(BcId), bc_id_free)) -#define BC_READ_BIN_CHAR(c) ((((c) < ' ' && !isspace((c))) || (c) > '~')) - typedef signed char BcDig; typedef struct BcNum { @@ -1138,6 +1138,18 @@ static void quit(void) exit(0); } +static int bc_error(const char *fmt, ...) +{ + va_list p; + + va_start(p, fmt); + bb_verror_msg(fmt, p, NULL); + va_end(p); + if (!G.ttyin) + exit(1); + return BC_STATUS_FAILURE; +} + static void bc_vec_grow(BcVec *v, size_t n) { size_t cap = v->cap * 2; @@ -1289,54 +1301,63 @@ static size_t bc_map_index(const BcVec *v, const void *ptr) static BcStatus bc_read_line(BcVec *vec, const char *prompt) { - int i; - signed char c; + bool bad_chars; - bc_vec_npop(vec, vec->len); + do { + int i; + char c; - fflush_and_check(); + bad_chars = 0; + bc_vec_npop(vec, vec->len); + + fflush_and_check(); #if ENABLE_FEATURE_BC_SIGNALS - if (bb_got_signal) { // ^C was pressed + if (bb_got_signal) { // ^C was pressed intr: - bb_got_signal = 0; // resets G_interrupt to zero - fputs(IS_BC - ? "\ninterrupt (type \"quit\" to exit)\n" - : "\ninterrupt (type \"q\" to exit)\n" - , stderr); - } + bb_got_signal = 0; // resets G_interrupt to zero + fputs(IS_BC + ? "\ninterrupt (type \"quit\" to exit)\n" + : "\ninterrupt (type \"q\" to exit)\n" + , stderr); + } #endif - if (G.ttyin && !G_posix) - fputs(prompt, stderr); - fflush_and_check(); + if (G.ttyin && !G_posix) + fputs(prompt, stderr); #if ENABLE_FEATURE_BC_SIGNALS - errno = 0; + errno = 0; #endif - do { - i = fgetc(stdin); - - if (i == EOF) { + do { + i = fgetc(stdin); + if (i == EOF) { #if ENABLE_FEATURE_BC_SIGNALS - // Both conditions appear simultaneously, check both just in case - if (errno == EINTR || bb_got_signal) { - // ^C was pressed - clearerr(stdin); - goto intr; - } + // Both conditions appear simultaneously, check both just in case + if (errno == EINTR || bb_got_signal) { + // ^C was pressed + clearerr(stdin); + goto intr; + } #endif - if (ferror(stdin)) - quit(); // this emits error message - G.eof = 1; - // Note: EOF does not append '\n', therefore: - // printf 'print 123\n' | bc - works - // printf 'print 123' | bc - fails (syntax error) - break; - } + if (ferror(stdin)) + quit(); // this emits error message + G.eof = 1; + // Note: EOF does not append '\n', therefore: + // printf 'print 123\n' | bc - works + // printf 'print 123' | bc - fails (syntax error) + break; + } - c = (signed char) i; - if (i > UCHAR_MAX || BC_READ_BIN_CHAR(c)) return BC_STATUS_BIN_FILE; - bc_vec_push(vec, &c); - } while (c != '\n'); + if ((i < ' ' && i != '\t' && i != '\r' && i != '\n') // also allow '\v' '\f'? + || i > 0x7e + ) { + // Bad chars on this line, ignore entire line + bc_error("illegal character 0x%02x", i); + bad_chars = 1; + } + c = (char) i; + bc_vec_push(vec, &c); + } while (i != '\n'); + } while (bad_chars); bc_vec_pushByte(vec, '\0'); @@ -1352,7 +1373,10 @@ static char* bc_read_file(const char *path) buf = xmalloc_open_read_close(path, &size); for (i = 0; i < size; ++i) { - if (BC_READ_BIN_CHAR(buf[i])) { + char c = buf[i]; + if ((c < ' ' && c != '\t' && c != '\r' && c != '\n') // also allow '\v' '\f'? + || c > 0x7e + ) { free(buf); buf = NULL; break; @@ -3162,7 +3186,7 @@ static BcStatus bc_lex_token(BcLex *l) } else { l->t.t = BC_LEX_INVALID; - s = BC_STATUS_LEX_BAD_CHAR; + s = bc_error("bad character '%c'", '&'); } break; @@ -3291,7 +3315,7 @@ static BcStatus bc_lex_token(BcLex *l) ++l->i; } else - s = BC_STATUS_LEX_BAD_CHAR; + s = bc_error("bad character '%c'", c); break; } @@ -3353,7 +3377,7 @@ static BcStatus bc_lex_token(BcLex *l) } else { l->t.t = BC_LEX_INVALID; - s = BC_STATUS_LEX_BAD_CHAR; + s = bc_error("bad character '%c'", c); } break; @@ -3362,7 +3386,7 @@ static BcStatus bc_lex_token(BcLex *l) default: { l->t.t = BC_LEX_INVALID; - s = BC_STATUS_LEX_BAD_CHAR; + s = bc_error("bad character '%c'", c); break; } } @@ -3473,7 +3497,7 @@ static BcStatus dc_lex_token(BcLex *l) else if (c2 == '>') l->t.t = BC_LEX_OP_REL_GE; else - return BC_STATUS_LEX_BAD_CHAR; + return bc_error("bad character '%c'", c); ++l->i; break; @@ -3490,7 +3514,7 @@ static BcStatus dc_lex_token(BcLex *l) if (isdigit(l->buf[l->i])) s = bc_lex_number(l, c); else - s = BC_STATUS_LEX_BAD_CHAR; + s = bc_error("bad character '%c'", c); break; } @@ -3524,7 +3548,7 @@ static BcStatus dc_lex_token(BcLex *l) default: { l->t.t = BC_LEX_INVALID; - s = BC_STATUS_LEX_BAD_CHAR; + s = bc_error("bad character '%c'", c); break; } } @@ -6938,7 +6962,7 @@ static BcStatus bc_vm_file(const char *file) G.prog.file = file; data = bc_read_file(file); - if (!data) return bc_vm_error(BC_STATUS_BIN_FILE, file, 0); + if (!data) return bc_error("file '%s' is not text", file); bc_lex_file(&G.prs.l, file); s = bc_vm_process(data); @@ -7021,8 +7045,6 @@ static BcStatus bc_vm_stdin(void) bc_vec_npop(&buffer, buffer.len); } - if (s == BC_STATUS_BIN_FILE) s = bc_vm_error(s, G.prs.l.f, 0); - if (str) s = bc_vm_error(BC_STATUS_LEX_NO_STRING_END, G.prs.l.f, G.prs.l.line); -- cgit v1.2.3-55-g6feb From bc5ce66617b6aa32b0ff7b51435cfc2c00c8ea89 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 3 Dec 2018 19:12:29 +0100 Subject: bc: simplify bc_lex_comment() function old new delta bc_lex_token 1369 1344 -25 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index dd01f5409..ecd19cb0b 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -3090,24 +3090,27 @@ static BcStatus bc_lex_comment(BcLex *l) { size_t i, nls = 0; const char *buf = l->buf; - bool end = false; - char c; l->t.t = BC_LEX_WHITESPACE; - - for (i = ++l->i; !end; i += !end) { - - for (c = buf[i]; c != '*' && c != 0; c = buf[++i]) nls += (c == '\n'); - - if (c == 0 || buf[i + 1] == '\0') { + i = ++l->i; + for (;;) { + char c = buf[i]; + check_star: + if (c == '*') { + c = buf[++i]; + if (c == '/') + break; + goto check_star; + } + if (c == '\0') { l->i = i; return BC_STATUS_LEX_NO_COMMENT_END; } - - end = buf[i + 1] == '/'; + nls += (c == '\n'); + i++; } - l->i = i + 2; + l->i = i + 1; l->line += nls; return BC_STATUS_SUCCESS; -- cgit v1.2.3-55-g6feb From a02f84472a9508e499f0eecd748929a44f5d3869 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 3 Dec 2018 20:35:16 +0100 Subject: bc: BC_STATUS_VEC_ITEM_EXISTS is not a real error code, its message was never used It was only used to indicate rusult of bc_map_insert() - did we insert, or did we find that this key is already in the map? function old new delta bc_map_insert 142 145 +3 bc_program_addFunc 226 225 -1 bc_err_msgs 184 180 -4 bc_program_search 152 143 -9 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/3 up/down: 3/-14) Total: -11 bytes text data bss dec hex filename 987904 485 7296 995685 f3165 busybox_old 987873 485 7296 995654 f3146 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 38 +++++++++++++++++--------------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index ecd19cb0b..b57f741d6 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -217,7 +217,8 @@ typedef enum BcStatus { BC_STATUS_EXEC_STACK, // BC_STATUS_VEC_OUT_OF_BOUNDS, - BC_STATUS_VEC_ITEM_EXISTS, +// BC_STATUS_VEC_ITEM_EXISTS, + BC_STATUS_BEFORE_POSIX = BC_STATUS_EXEC_STACK, #if ENABLE_BC BC_STATUS_POSIX_NAME_LEN, BC_STATUS_POSIX_COMMENT, @@ -288,7 +289,7 @@ static const char *const bc_err_msgs[] = { "stack has too few elements", // "index is out of bounds", - "item already exists", +// "item already exists", #if ENABLE_BC "POSIX only allows one character names; the following is bad:", "POSIX does not allow '#' script comments", @@ -1276,20 +1277,17 @@ static size_t bc_map_find(const BcVec *v, const void *ptr) return low; } -static BcStatus bc_map_insert(BcVec *v, const void *ptr, size_t *i) +static int bc_map_insert(BcVec *v, const void *ptr, size_t *i) { - BcStatus s = BC_STATUS_SUCCESS; - - *i = bc_map_find(v, ptr); + size_t n = *i = bc_map_find(v, ptr); - if (*i == v->len) + if (n == v->len) bc_vec_push(v, ptr); - else if (!bc_id_cmp(ptr, bc_vec_item(v, *i))) - s = BC_STATUS_VEC_ITEM_EXISTS; + else if (!bc_id_cmp(ptr, bc_vec_item(v, n))) + return 0; // "was not inserted" else - bc_vec_pushAt(v, ptr, *i); - - return s; + bc_vec_pushAt(v, ptr, n); + return 1; // "was inserted" } static size_t bc_map_index(const BcVec *v, const void *ptr) @@ -5240,20 +5238,18 @@ static BcStatus common_parse_expr(BcParse *p, uint8_t flags) static BcVec* bc_program_search(char *id, bool var) { - BcStatus s; BcId e, *ptr; BcVec *v, *map; size_t i; BcResultData data; - bool new; + int new; v = var ? &G.prog.vars : &G.prog.arrs; map = var ? &G.prog.var_map : &G.prog.arr_map; e.name = id; e.idx = v->len; - s = bc_map_insert(map, &e, &i); - new = s != BC_STATUS_VEC_ITEM_EXISTS; + new = bc_map_insert(map, &e, &i); // 1 if insertion was successful if (new) { bc_array_init(&data.v, var); @@ -6465,20 +6461,20 @@ static void bc_program_pushGlobal(char inst) static void bc_program_addFunc(char *name, size_t *idx) { - BcStatus s; BcId entry, *entry_ptr; BcFunc f; + int inserted; entry.name = name; entry.idx = G.prog.fns.len; - s = bc_map_insert(&G.prog.fn_map, &entry, idx); - if (s) free(name); + inserted = bc_map_insert(&G.prog.fn_map, &entry, idx); + if (!inserted) free(name); entry_ptr = bc_vec_item(&G.prog.fn_map, *idx); *idx = entry_ptr->idx; - if (s == BC_STATUS_VEC_ITEM_EXISTS) { + if (!inserted) { BcFunc *func = bc_vec_item(&G.prog.fns, entry_ptr->idx); @@ -6850,7 +6846,7 @@ static void bc_vm_info(void) static BcStatus bc_vm_error(BcStatus s, const char *file, size_t line) { - if (!s || s > BC_STATUS_VEC_ITEM_EXISTS) return s; + if (!s || s > BC_STATUS_BEFORE_POSIX) return s; fprintf(stderr, bc_err_fmt, bc_err_msgs[s]); fprintf(stderr, " %s", file); -- cgit v1.2.3-55-g6feb From 04a1c763a621f6995e6875f0a4674314ff21c44d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 3 Dec 2018 21:10:57 +0100 Subject: bc: convert BC_STATUS_EXEC_MISMATCHED_PARAMS and BC_STATUS_EXEC_UNDEFINED_FUNC Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index b57f741d6..0d81e13cf 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -200,8 +200,8 @@ typedef enum BcStatus { BC_STATUS_MATH_BAD_STRING, // BC_STATUS_EXEC_FILE_ERR, - BC_STATUS_EXEC_MISMATCHED_PARAMS, - BC_STATUS_EXEC_UNDEFINED_FUNC, +// BC_STATUS_EXEC_MISMATCHED_PARAMS, +// BC_STATUS_EXEC_UNDEFINED_FUNC, BC_STATUS_EXEC_FILE_NOT_EXECUTABLE, BC_STATUS_EXEC_NUM_LEN, BC_STATUS_EXEC_NAME_LEN, @@ -241,7 +241,7 @@ typedef enum BcStatus { // Keep enum above and messages below in sync! static const char *const bc_err_msgs[] = { NULL, - "", + NULL, // "memory allocation error", // "I/O error", // "file is not text:", @@ -272,8 +272,8 @@ static const char *const bc_err_msgs[] = { "bad number string", // "could not open file:", - "mismatched parameters", // wrong number of them, to be exact - "undefined function", +// "mismatched parameters", // wrong number of them, to be exact +// "undefined function", "file is not executable:", "number too long: must be [1, BC_NUM_MAX]", "name too long: must be [1, BC_NAME_MAX]", @@ -5990,8 +5990,12 @@ static BcStatus bc_program_call(char *code, size_t *idx) ip.func = bc_program_index(code, idx); func = bc_vec_item(&G.prog.fns, ip.func); - if (func->code.len == 0) return BC_STATUS_EXEC_UNDEFINED_FUNC; - if (nparams != func->nparams) return BC_STATUS_EXEC_MISMATCHED_PARAMS; + if (func->code.len == 0) { + return bc_error("undefined function"); + } + if (nparams != func->nparams) { + return bc_error("function has %u parameters, but called with %u", func->nparams, nparams); + } ip.len = G.prog.results.len - nparams; for (i = 0; i < nparams; ++i) { @@ -6848,9 +6852,11 @@ static BcStatus bc_vm_error(BcStatus s, const char *file, size_t line) { if (!s || s > BC_STATUS_BEFORE_POSIX) return s; - fprintf(stderr, bc_err_fmt, bc_err_msgs[s]); - fprintf(stderr, " %s", file); - fprintf(stderr, bc_err_line + 4 * !line, line); + if (bc_err_msgs[s]) { + fprintf(stderr, bc_err_fmt, bc_err_msgs[s]); + fprintf(stderr, " %s", file); + fprintf(stderr, bc_err_line + 4 * !line, line); + } return s * (!G.ttyin || !!strcmp(file, bc_program_stdin_name)); } -- cgit v1.2.3-55-g6feb From abbc433d29307ee1e42f3a98c55b3d8e75a42350 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 3 Dec 2018 21:46:41 +0100 Subject: bc: convert BC_STATUS_PARSE_NO_AUTO function old new delta bc_parse_auto 275 291 +16 bc_err_msgs 172 168 -4 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/1 up/down: 16/-4) Total: 12 bytes text data bss dec hex filename 987911 485 7296 995692 f316c busybox_old 987923 485 7296 995704 f3178 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 0d81e13cf..2bde51521 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -189,7 +189,7 @@ typedef enum BcStatus { BC_STATUS_PARSE_BAD_PRINT, BC_STATUS_PARSE_BAD_FUNC, BC_STATUS_PARSE_BAD_ASSIGN, - BC_STATUS_PARSE_NO_AUTO, +// BC_STATUS_PARSE_NO_AUTO, BC_STATUS_PARSE_DUPLICATE_LOCAL, BC_STATUS_PARSE_NO_BLOCK_END, @@ -261,7 +261,7 @@ static const char *const bc_err_msgs[] = { "bad function definition", "bad assignment: left side must be scale, ibase, " "obase, last, var, or array element", - "no auto variable found", +// "no auto variable found", "function parameter or auto var has the same name as another", "block end could not be found", @@ -4509,7 +4509,7 @@ static BcStatus bc_parse_auto(BcParse *p) } if (comma) return BC_STATUS_PARSE_BAD_FUNC; - if (!one) return BC_STATUS_PARSE_NO_AUTO; + if (!one) return bc_error("no auto variable found"); if (p->l.t.t != BC_LEX_NLINE && p->l.t.t != BC_LEX_SCOLON) return BC_STATUS_PARSE_BAD_TOKEN; -- cgit v1.2.3-55-g6feb From d38af48e0ae96fc4dc4a794ae8129372ed7c593f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 4 Dec 2018 19:11:02 +0100 Subject: bc: convert BC_STATUS_EXEC_SIGNAL - its message string was never used function old new delta bc_vm_process 132 130 -2 bc_err_msgs 168 164 -4 dc_parse_parse 52 47 -5 bc_parse_reset 187 181 -6 bc_program_ready_msg 22 - -22 bc_program_exec 4478 4453 -25 bc_parse_parse 461 432 -29 bc_program_reset 159 105 -54 ------------------------------------------------------------------------------ (add/remove: 0/1 grow/shrink: 0/7 up/down: 0/-147) Total: -147 bytes text data bss dec hex filename 987923 485 7296 995704 f3178 busybox_old 987766 485 7296 995547 f30db busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 69 +++++++++++++++++++++++++++++++++------------------------- 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 2bde51521..bd70670d5 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -213,7 +213,7 @@ typedef enum BcStatus { BC_STATUS_EXEC_REC_READ, BC_STATUS_EXEC_BAD_TYPE, // BC_STATUS_EXEC_BAD_OBASE, - BC_STATUS_EXEC_SIGNAL, +// BC_STATUS_EXEC_SIGNAL, BC_STATUS_EXEC_STACK, // BC_STATUS_VEC_OUT_OF_BOUNDS, @@ -285,7 +285,7 @@ static const char *const bc_err_msgs[] = { "read() call inside of a read() call", "variable is wrong type", // "bad obase; must be [2, BC_BASE_MAX]", - "signal caught and not handled", +// "signal caught and not handled", "stack has too few elements", // "index is out of bounds", @@ -840,7 +840,7 @@ typedef struct BcProgram { typedef unsigned long (*BcProgramBuiltIn)(BcNum *); static void bc_program_addFunc(char *name, size_t *idx); -static BcStatus bc_program_reset(BcStatus s); +static void bc_program_reset(void); #define BC_FLAG_X (1 << 0) #define BC_FLAG_W (1 << 1) @@ -1034,7 +1034,6 @@ static const BcNumBinaryOp bc_program_ops[] = { }; static const char bc_program_stdin_name[] = ""; -static const char bc_program_ready_msg[] = "ready for more input\n"; #if ENABLE_BC static const char *bc_lib_name = "gen/lib.bc"; @@ -3617,7 +3616,9 @@ static BcStatus bc_parse_text(BcParse *p, const char *text) return bc_lex_text(&p->l, text); } -static BcStatus bc_parse_reset(BcParse *p, BcStatus s) +// Called when bc/dc_parse_parse() detects a failure, +// resets parsing structures. +static void bc_parse_reset(BcParse *p) { if (p->fidx != BC_PROG_MAIN) { @@ -3638,7 +3639,7 @@ static BcStatus bc_parse_reset(BcParse *p, BcStatus s) bc_vec_npop(&p->conds, p->conds.len); bc_vec_npop(&p->ops, p->ops.len); - return bc_program_reset(s); + bc_program_reset(); } static void bc_parse_free(BcParse *p) @@ -4733,8 +4734,10 @@ static BcStatus bc_parse_parse(BcParse *p) else s = bc_parse_stmt(p); - if (s || G_interrupt) - s = bc_parse_reset(p, s); + if (s || G_interrupt) { + bc_parse_reset(p); + s = BC_STATUS_FAILURE; + } return s; } @@ -4947,7 +4950,7 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) } if (s) return s; - if (G_interrupt) return BC_STATUS_EXEC_SIGNAL; + if (G_interrupt) return BC_STATUS_FAILURE; // ^C: stop parsing while (p->ops.len > ops_bgn) { @@ -5207,7 +5210,10 @@ static BcStatus dc_parse_parse(BcParse *p) else s = dc_parse_expr(p, 0); - if (s || G_interrupt) s = bc_parse_reset(p, s); + if (s || G_interrupt) { + bc_parse_reset(p); + s = BC_STATUS_FAILURE; + } return s; } @@ -6494,7 +6500,9 @@ static void bc_program_addFunc(char *name, size_t *idx) } } -static BcStatus bc_program_reset(BcStatus s) +// Called when parsing or execution detects a failure, +// resets execution structures. +static void bc_program_reset(void) { BcFunc *f; BcInstPtr *ip; @@ -6506,18 +6514,12 @@ static BcStatus bc_program_reset(BcStatus s) ip = bc_vec_top(&G.prog.stack); ip->idx = f->code.len; - if (!s && G_interrupt && !G.tty) quit(); + // If !tty, no need to check for ^C: we don't have ^C handler, + // we would be killed by a signal and won't reach this place - if (!s || s == BC_STATUS_EXEC_SIGNAL) { - if (!G.ttyin) - quit(); - fflush_and_check(); // make sure buffered stdout is printed - fputs(bc_program_ready_msg, stderr); - fflush_and_check(); - s = BC_STATUS_SUCCESS; - } - - return s; + fflush_and_check(); // make sure buffered stdout is printed + fputs("ready for more input\n", stderr); + fflush_and_check(); } static BcStatus bc_program_exec(void) @@ -6828,7 +6830,10 @@ static BcStatus bc_program_exec(void) #endif // ENABLE_DC } - if (s || G_interrupt) s = bc_program_reset(s); + if (s || G_interrupt) { + bc_program_reset(); + break; + } // If the stack has changed, pointers may be invalid. ip = bc_vec_top(&G.prog.stack); @@ -6951,8 +6956,10 @@ static BcStatus bc_vm_process(const char *text) if (BC_PARSE_CAN_EXEC(&G.prs)) { s = bc_program_exec(); fflush_and_check(); - if (s) - s = bc_vm_error(bc_program_reset(s), G.prs.l.f, 0); + if (s) { + bc_program_reset(); + s = bc_vm_error(s, G.prs.l.f, 0); + } } return s; @@ -7185,10 +7192,6 @@ static void bc_vm_init(const char *env_len) { size_t len = bc_vm_envLen(env_len); -#if ENABLE_FEATURE_BC_SIGNALS - signal_no_SA_RESTART_empty_mask(SIGINT, record_signo); -#endif - bc_vec_init(&G.files, sizeof(char *), NULL); if (IS_BC) { @@ -7216,7 +7219,13 @@ static BcStatus bc_vm_run(int argc, char *argv[], G.ttyin = isatty(0); G.tty = G.ttyin || (G.flags & BC_FLAG_I) || isatty(1); - if (G.ttyin && !(G.flags & BC_FLAG_Q)) bc_vm_info(); + if (G.ttyin) { +#if ENABLE_FEATURE_BC_SIGNALS + signal_no_SA_RESTART_empty_mask(SIGINT, record_signo); +#endif + if (!(G.flags & BC_FLAG_Q)) + bc_vm_info(); + } st = bc_vm_exec(); #if ENABLE_FEATURE_CLEAN_UP -- cgit v1.2.3-55-g6feb From 60cf747b6c234958387298068da658cfee9c42cb Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 4 Dec 2018 20:05:28 +0100 Subject: bc: convert all non-POSIX BC_STATUS_foo codes function old new delta bc_program_asciify - 469 +469 bc_parse_parse 432 495 +63 dc_parse_expr 727 775 +48 bc_vm_run 1955 1995 +40 bc_program_num 1115 1147 +32 bc_program_binOpPrep 296 324 +28 static.msg - 24 +24 bc_parse_name 570 593 +23 bc_lex_token 1344 1367 +23 dc_lex_token 695 714 +19 bc_num_ulong 85 103 +18 bc_program_read 336 353 +17 dc_parse_parse 47 60 +13 bc_parse_stmt 2301 2313 +12 bc_parse_auto 291 302 +11 bc_program_prep 89 99 +10 bc_lex_next 71 81 +10 dc_parse_register 52 61 +9 bc_program_print 775 784 +9 bc_func_insert 89 98 +9 bc_program_assignStr 159 167 +8 bc_program_assign 476 484 +8 bc_parse_body 116 124 +8 bc_lex_name 83 91 +8 bc_program_pushVar 215 221 +6 bc_parse_text 141 147 +6 bc_num_shift 68 74 +6 bc_num_p 472 478 +6 bc_program_execStr 559 564 +5 bc_parse_else 139 143 +4 bc_lex_number 301 305 +4 bc_num_d 558 561 +3 bc_parse_endBody 422 424 +2 bc_num_r 231 230 -1 bc_program_copyToVar 343 340 -3 bc_program_call 372 367 -5 bc_parse_expr 2215 2210 -5 bc_program_modexp 763 756 -7 bc_err_msgs 164 60 -104 bc_program_pushArray 136 - -136 bc_program_exec 4453 4153 -300 ------------------------------------------------------------------------------ (add/remove: 2/1 grow/shrink: 31/7 up/down: 961/-561) Total: 400 bytes text data bss dec hex filename 987766 485 7296 995547 f30db busybox_old 988258 485 7296 996039 f32c7 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 475 ++++++++++++++++++++++++++++++++------------------------- 1 file changed, 271 insertions(+), 204 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index bd70670d5..7b20a94cc 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -168,8 +168,9 @@ #include "libbb.h" typedef enum BcStatus { - BC_STATUS_SUCCESS, - BC_STATUS_FAILURE, + BC_STATUS_SUCCESS = 0, + BC_STATUS_FAILURE = 1, + BC_STATUS_PARSE_EMPTY_EXP = 2, // bc_parse_expr() uses this // BC_STATUS_ALLOC_ERR, // BC_STATUS_INPUT_EOF, @@ -177,48 +178,47 @@ typedef enum BcStatus { // BC_STATUS_PATH_IS_DIR, // BC_STATUS_LEX_BAD_CHAR, - BC_STATUS_LEX_NO_STRING_END, - BC_STATUS_LEX_NO_COMMENT_END, - BC_STATUS_LEX_EOF, +// BC_STATUS_LEX_NO_STRING_END, +// BC_STATUS_LEX_NO_COMMENT_END, +// BC_STATUS_LEX_EOF, #if ENABLE_DC - BC_STATUS_LEX_EXTENDED_REG, +// BC_STATUS_LEX_EXTENDED_REG, #endif - BC_STATUS_PARSE_BAD_TOKEN, - BC_STATUS_PARSE_BAD_EXP, - BC_STATUS_PARSE_EMPTY_EXP, - BC_STATUS_PARSE_BAD_PRINT, - BC_STATUS_PARSE_BAD_FUNC, - BC_STATUS_PARSE_BAD_ASSIGN, +// BC_STATUS_PARSE_BAD_TOKEN, +// BC_STATUS_PARSE_BAD_EXP, +// BC_STATUS_PARSE_BAD_PRINT, +// BC_STATUS_PARSE_BAD_FUNC, +// BC_STATUS_PARSE_BAD_ASSIGN, // BC_STATUS_PARSE_NO_AUTO, - BC_STATUS_PARSE_DUPLICATE_LOCAL, - BC_STATUS_PARSE_NO_BLOCK_END, +// BC_STATUS_PARSE_DUPLICATE_LOCAL, +// BC_STATUS_PARSE_NO_BLOCK_END, - BC_STATUS_MATH_NEGATIVE, - BC_STATUS_MATH_NON_INTEGER, - BC_STATUS_MATH_OVERFLOW, - BC_STATUS_MATH_DIVIDE_BY_ZERO, - BC_STATUS_MATH_BAD_STRING, +// BC_STATUS_MATH_NEGATIVE, +// BC_STATUS_MATH_NON_INTEGER, +// BC_STATUS_MATH_OVERFLOW, +// BC_STATUS_MATH_DIVIDE_BY_ZERO, +// BC_STATUS_MATH_BAD_STRING, // BC_STATUS_EXEC_FILE_ERR, // BC_STATUS_EXEC_MISMATCHED_PARAMS, // BC_STATUS_EXEC_UNDEFINED_FUNC, - BC_STATUS_EXEC_FILE_NOT_EXECUTABLE, - BC_STATUS_EXEC_NUM_LEN, - BC_STATUS_EXEC_NAME_LEN, - BC_STATUS_EXEC_STRING_LEN, - BC_STATUS_EXEC_ARRAY_LEN, - BC_STATUS_EXEC_BAD_IBASE, +// BC_STATUS_EXEC_FILE_NOT_EXECUTABLE, +// BC_STATUS_EXEC_NUM_LEN, +// BC_STATUS_EXEC_NAME_LEN, +// BC_STATUS_EXEC_STRING_LEN, +// BC_STATUS_EXEC_ARRAY_LEN, +// BC_STATUS_EXEC_BAD_IBASE, // BC_STATUS_EXEC_BAD_SCALE, - BC_STATUS_EXEC_BAD_READ_EXPR, - BC_STATUS_EXEC_REC_READ, - BC_STATUS_EXEC_BAD_TYPE, +// BC_STATUS_EXEC_BAD_READ_EXPR, +// BC_STATUS_EXEC_REC_READ, +// BC_STATUS_EXEC_BAD_TYPE, // BC_STATUS_EXEC_BAD_OBASE, // BC_STATUS_EXEC_SIGNAL, - BC_STATUS_EXEC_STACK, +// BC_STATUS_EXEC_STACK, // BC_STATUS_VEC_OUT_OF_BOUNDS, // BC_STATUS_VEC_ITEM_EXISTS, - BC_STATUS_BEFORE_POSIX = BC_STATUS_EXEC_STACK, + BC_STATUS_BEFORE_POSIX = BC_STATUS_PARSE_EMPTY_EXP, #if ENABLE_BC BC_STATUS_POSIX_NAME_LEN, BC_STATUS_POSIX_COMMENT, @@ -242,51 +242,52 @@ typedef enum BcStatus { static const char *const bc_err_msgs[] = { NULL, NULL, + NULL, + // "memory allocation error", // "I/O error", // "file is not text:", // "path is a directory:", // "bad character", - "string end could not be found", - "comment end could not be found", - "end of file", +// "string end could not be found", +// "comment end could not be found", +// "end of file", #if ENABLE_DC - "extended register", +// "extended register", #endif - "bad token", - "bad expression", - "empty expression", - "bad print statement", - "bad function definition", - "bad assignment: left side must be scale, ibase, " - "obase, last, var, or array element", +// "bad token", +// "bad expression", +// "bad print statement", +// "bad function definition", +// "bad assignment: left side must be scale, ibase, " +// "obase, last, var, or array element", // "no auto variable found", - "function parameter or auto var has the same name as another", - "block end could not be found", +// "function parameter or auto var has the same name as another", +// "block end could not be found", - "negative number", - "non integer number", - "overflow", - "divide by zero", - "bad number string", +// "negative number", +// "non integer number", +// "overflow", +// "divide by zero", +// "bad number string", // "could not open file:", // "mismatched parameters", // wrong number of them, to be exact // "undefined function", - "file is not executable:", - "number too long: must be [1, BC_NUM_MAX]", - "name too long: must be [1, BC_NAME_MAX]", - "string too long: must be [1, BC_STRING_MAX]", - "array too long; must be [1, BC_DIM_MAX]", - "bad ibase; must be [2, 16]", +// "file is not executable:", +// "number too long: must be [1, BC_NUM_MAX]", +// "name too long: must be [1, BC_NAME_MAX]", +// "string too long: must be [1, BC_STRING_MAX]", +// "array too long; must be [1, BC_DIM_MAX]", +// "bad ibase; must be [2, 16]", // "bad scale; must be [0, BC_SCALE_MAX]", - "bad read() expression", - "read() call inside of a read() call", - "variable is wrong type", +// "bad read() expression", +// "read() call inside of a read() call", +// "variable is wrong type", // "bad obase; must be [2, BC_BASE_MAX]", // "signal caught and not handled", - "stack has too few elements", +// "stack has too few elements", // "index is out of bounds", // "item already exists", @@ -1577,7 +1578,8 @@ static void bc_num_split(BcNum *restrict n, size_t idx, BcNum *restrict a, static BcStatus bc_num_shift(BcNum *n, size_t places) { if (places == 0 || n->len == 0) return BC_STATUS_SUCCESS; - if (places + n->len > BC_MAX_NUM) return BC_STATUS_EXEC_NUM_LEN; + if (places + n->len > BC_MAX_NUM) + return bc_error("number too long: must be [1, BC_NUM_MAX]"); if (n->rdx >= places) n->rdx -= places; @@ -1885,7 +1887,7 @@ static BcStatus bc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) bool zero = true; if (b->len == 0) - return BC_STATUS_MATH_DIVIDE_BY_ZERO; + return bc_error("divide by zero"); else if (a->len == 0) { bc_num_setToZero(c, scale); return BC_STATUS_SUCCESS; @@ -1948,7 +1950,8 @@ static BcStatus bc_num_r(BcNum *a, BcNum *b, BcNum *restrict c, BcNum temp; bool neg; - if (b->len == 0) return BC_STATUS_MATH_DIVIDE_BY_ZERO; + if (b->len == 0) + return bc_error("divide by zero"); if (a->len == 0) { bc_num_setToZero(d, ts); @@ -1997,7 +2000,7 @@ static BcStatus bc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) size_t i, powrdx, resrdx; bool neg, zero; - if (b->rdx) return BC_STATUS_MATH_NON_INTEGER; + if (b->rdx) return bc_error("non integer number"); if (b->len == 0) { bc_num_one(c); @@ -2435,7 +2438,8 @@ static void bc_num_copy(BcNum *d, BcNum *s) static BcStatus bc_num_parse(BcNum *n, const char *val, BcNum *base, size_t base_t) { - if (!bc_num_strValid(val, base_t)) return BC_STATUS_MATH_BAD_STRING; + if (!bc_num_strValid(val, base_t)) + return bc_error("bad number string"); if (base_t == 10) bc_num_parseDecimal(n, val); @@ -2474,7 +2478,7 @@ static BcStatus bc_num_ulong(BcNum *n, unsigned long *result) size_t i; unsigned long pow; - if (n->neg) return BC_STATUS_MATH_NEGATIVE; + if (n->neg) return bc_error("negative number"); for (*result = 0, pow = 1, i = n->rdx; i < n->len; ++i) { @@ -2483,7 +2487,8 @@ static BcStatus bc_num_ulong(BcNum *n, unsigned long *result) *result += ((unsigned long) n->num[i]) * pow; pow *= 10; - if (*result < prev || pow < powprev) return BC_STATUS_MATH_OVERFLOW; + if (*result < prev || pow < powprev) + return bc_error("overflow"); } return BC_STATUS_SUCCESS; @@ -2555,7 +2560,7 @@ static BcStatus bc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale) return BC_STATUS_SUCCESS; } else if (a->neg) - return BC_STATUS_MATH_NEGATIVE; + return bc_error("negative number"); else if (BC_NUM_ONE(a)) { bc_num_one(b); bc_num_extend(b, scale); @@ -2674,9 +2679,12 @@ static BcStatus bc_num_modexp(BcNum *a, BcNum *b, BcNum *c, BcNum *restrict d) BcStatus s; BcNum base, exp, two, temp; - if (c->len == 0) return BC_STATUS_MATH_DIVIDE_BY_ZERO; - if (a->rdx || b->rdx || c->rdx) return BC_STATUS_MATH_NON_INTEGER; - if (b->neg) return BC_STATUS_MATH_NEGATIVE; + if (c->len == 0) + return bc_error("divide by zero"); + if (a->rdx || b->rdx || c->rdx) + return bc_error("non integer number"); + if (b->neg) + return bc_error("negative number"); bc_num_expand(d, c->len); bc_num_init(&base, c->len); @@ -2735,8 +2743,8 @@ static BcStatus bc_func_insert(BcFunc *f, char *name, bool var) size_t i; for (i = 0; i < f->autos.len; ++i) { - if (!strcmp(name, ((BcId *) bc_vec_item(&f->autos, i))->name)) - return BC_STATUS_PARSE_DUPLICATE_LOCAL; + if (strcmp(name, ((BcId *) bc_vec_item(&f->autos, i))->name) == 0) + return bc_error("function parameter or auto var has the same name as another"); } a.idx = var; @@ -2918,7 +2926,8 @@ static BcStatus bc_lex_number(BcLex *l, char start) } len = i + 1 * !last_pt - bslashes * 2; - if (len > BC_MAX_NUM) return BC_STATUS_EXEC_NUM_LEN; + if (len > BC_MAX_NUM) + return bc_error("number too long: must be [1, BC_NUM_MAX]"); bc_vec_npop(&l->t.v, l->t.v.len); bc_vec_expand(&l->t.v, len + 1); @@ -2955,7 +2964,8 @@ static BcStatus bc_lex_name(BcLex *l) while ((c >= 'a' && c <= 'z') || isdigit(c) || c == '_') c = buf[++i]; - if (i > BC_MAX_STRING) return BC_STATUS_EXEC_NAME_LEN; + if (i > BC_MAX_STRING) + return bc_error("name too long: must be [1, BC_NAME_MAX]"); bc_vec_string(&l->t.v, i, buf); // Increment the index. We minus 1 because it has already been incremented. @@ -2987,7 +2997,7 @@ static BcStatus bc_lex_next(BcLex *l) BcStatus s; l->t.last = l->t.t; - if (l->t.last == BC_LEX_EOF) return BC_STATUS_LEX_EOF; + if (l->t.last == BC_LEX_EOF) return bc_error("end of file"); l->line += l->newline; l->t.t = BC_LEX_EOF; @@ -3060,11 +3070,12 @@ static BcStatus bc_lex_string(BcLex *l) if (c == '\0') { l->i = i; - return BC_STATUS_LEX_NO_STRING_END; + return bc_error("string end could not be found"); } len = i - l->i; - if (len > BC_MAX_STRING) return BC_STATUS_EXEC_STRING_LEN; + if (len > BC_MAX_STRING) + return bc_error("string too long: must be [1, BC_STRING_MAX]"); bc_vec_string(&l->t.v, len, l->buf + l->i); l->i = i + 1; @@ -3101,7 +3112,7 @@ static BcStatus bc_lex_comment(BcLex *l) } if (c == '\0') { l->i = i; - return BC_STATUS_LEX_NO_COMMENT_END; + return bc_error("comment end could not be found"); } nls += (c == '\n'); i++; @@ -3404,7 +3415,7 @@ static BcStatus dc_lex_register(BcLex *l) bc_lex_whitespace(l); ++l->i; if (!G_exreg) - s = BC_STATUS_LEX_EXTENDED_REG; + s = bc_error("extended register"); else s = bc_lex_name(l); } @@ -3437,11 +3448,12 @@ static BcStatus dc_lex_string(BcLex *l) if (c == '\0') { l->i = i; - return BC_STATUS_LEX_NO_STRING_END; + return bc_error("string end could not be found"); } bc_vec_pushByte(&l->t.v, '\0'); - if (i - l->i > BC_MAX_STRING) return BC_STATUS_EXEC_STRING_LEN; + if (i - l->i > BC_MAX_STRING) + return bc_error("string too long: must be [1, BC_STRING_MAX]"); l->i = i; l->line += nls; @@ -3606,11 +3618,12 @@ static BcStatus bc_parse_text(BcParse *p, const char *text) p->func = bc_vec_item(&G.prog.fns, p->fidx); - if (!strcmp(text, "") && !BC_PARSE_CAN_EXEC(p)) { + if (!text[0] && !BC_PARSE_CAN_EXEC(p)) { p->l.t.t = BC_LEX_INVALID; s = p->parse(p); if (s) return s; - if (!BC_PARSE_CAN_EXEC(p)) return BC_STATUS_EXEC_FILE_NOT_EXECUTABLE; + if (!BC_PARSE_CAN_EXEC(p)) + return bc_error("file is not executable"); } return bc_lex_text(&p->l, text); @@ -3703,7 +3716,8 @@ static BcStatus bc_parse_rightParen(BcParse *p, size_t ops_bgn, size_t *nexs) { BcLexType top; - if (p->ops.len <= ops_bgn) return BC_STATUS_PARSE_BAD_EXP; + if (p->ops.len <= ops_bgn) + return bc_error("bad expression"); top = BC_PARSE_TOP_OP(p); while (top != BC_LEX_LPAREN) { @@ -3713,7 +3727,8 @@ static BcStatus bc_parse_rightParen(BcParse *p, size_t ops_bgn, size_t *nexs) bc_vec_pop(&p->ops); *nexs -= top != BC_LEX_OP_BOOL_NOT && top != BC_LEX_NEG; - if (p->ops.len <= ops_bgn) return BC_STATUS_PARSE_BAD_EXP; + if (p->ops.len <= ops_bgn) + return bc_error("bad expression"); top = BC_PARSE_TOP_OP(p); } @@ -3744,7 +3759,7 @@ static BcStatus bc_parse_params(BcParse *p, uint8_t flags) } } - if (comma) return BC_STATUS_PARSE_BAD_TOKEN; + if (comma) return bc_error("bad token"); bc_parse_push(p, BC_INST_CALL); bc_parse_pushIndex(p, nparams); @@ -3763,7 +3778,7 @@ static BcStatus bc_parse_call(BcParse *p, char *name, uint8_t flags) if (s) goto err; if (p->l.t.t != BC_LEX_RPAREN) { - s = BC_STATUS_PARSE_BAD_TOKEN; + s = bc_error("bad token"); goto err; } @@ -3805,7 +3820,7 @@ static BcStatus bc_parse_name(BcParse *p, BcInst *type, uint8_t flags) if (p->l.t.t == BC_LEX_RBRACKET) { if (!(flags & BC_PARSE_ARRAY)) { - s = BC_STATUS_PARSE_BAD_EXP; + s = bc_error("bad expression"); goto err; } @@ -3828,7 +3843,7 @@ static BcStatus bc_parse_name(BcParse *p, BcInst *type, uint8_t flags) else if (p->l.t.t == BC_LEX_LPAREN) { if (flags & BC_PARSE_NOCALL) { - s = BC_STATUS_PARSE_BAD_TOKEN; + s = bc_error("bad token"); goto err; } @@ -3854,11 +3869,11 @@ static BcStatus bc_parse_read(BcParse *p) s = bc_lex_next(&p->l); if (s) return s; - if (p->l.t.t != BC_LEX_LPAREN) return BC_STATUS_PARSE_BAD_TOKEN; + if (p->l.t.t != BC_LEX_LPAREN) return bc_error("bad token"); s = bc_lex_next(&p->l); if (s) return s; - if (p->l.t.t != BC_LEX_RPAREN) return BC_STATUS_PARSE_BAD_TOKEN; + if (p->l.t.t != BC_LEX_RPAREN) return bc_error("bad token"); bc_parse_push(p, BC_INST_READ); @@ -3872,7 +3887,7 @@ static BcStatus bc_parse_builtin(BcParse *p, BcLexType type, uint8_t flags, s = bc_lex_next(&p->l); if (s) return s; - if (p->l.t.t != BC_LEX_LPAREN) return BC_STATUS_PARSE_BAD_TOKEN; + if (p->l.t.t != BC_LEX_LPAREN) return bc_error("bad token"); flags = (flags & ~(BC_PARSE_PRINT | BC_PARSE_REL)) | BC_PARSE_ARRAY; @@ -3882,7 +3897,7 @@ static BcStatus bc_parse_builtin(BcParse *p, BcLexType type, uint8_t flags, s = bc_parse_expr(p, flags, bc_parse_next_rel); if (s) return s; - if (p->l.t.t != BC_LEX_RPAREN) return BC_STATUS_PARSE_BAD_TOKEN; + if (p->l.t.t != BC_LEX_RPAREN) return bc_error("bad token"); *prev = (type == BC_LEX_KEY_LENGTH) ? BC_INST_LENGTH : BC_INST_SQRT; bc_parse_push(p, *prev); @@ -3911,7 +3926,7 @@ static BcStatus bc_parse_scale(BcParse *p, BcInst *type, uint8_t flags) s = bc_parse_expr(p, flags, bc_parse_next_rel); if (s) return s; - if (p->l.t.t != BC_LEX_RPAREN) return BC_STATUS_PARSE_BAD_TOKEN; + if (p->l.t.t != BC_LEX_RPAREN) return bc_error("bad token"); bc_parse_push(p, BC_INST_SCALE_FUNC); return bc_lex_next(&p->l); @@ -3968,7 +3983,7 @@ static BcStatus bc_parse_incdec(BcParse *p, BcInst *prev, bool *paren_expr, s = bc_lex_next(&p->l); if (s) return s; if (p->l.t.t == BC_LEX_LPAREN) - s = BC_STATUS_PARSE_BAD_TOKEN; + s = bc_error("bad token"); else bc_parse_push(p, BC_INST_SCALE); break; @@ -3976,7 +3991,7 @@ static BcStatus bc_parse_incdec(BcParse *p, BcInst *prev, bool *paren_expr, default: { - s = BC_STATUS_PARSE_BAD_TOKEN; + s = bc_error("bad token"); break; } } @@ -4037,7 +4052,7 @@ static BcStatus bc_parse_print(BcParse *p) type = p->l.t.t; if (type == BC_LEX_SCOLON || type == BC_LEX_NLINE) - return BC_STATUS_PARSE_BAD_PRINT; + return bc_error("bad print statement"); while (!s && type != BC_LEX_SCOLON && type != BC_LEX_NLINE) { @@ -4057,7 +4072,7 @@ static BcStatus bc_parse_print(BcParse *p) } if (s) return s; - if (comma) return BC_STATUS_PARSE_BAD_TOKEN; + if (comma) return bc_error("bad token"); return bc_lex_next(&p->l); } @@ -4068,7 +4083,7 @@ static BcStatus bc_parse_return(BcParse *p) BcLexType t; bool paren; - if (!BC_PARSE_FUNC(p)) return BC_STATUS_PARSE_BAD_TOKEN; + if (!BC_PARSE_FUNC(p)) return bc_error("bad token"); s = bc_lex_next(&p->l); if (s) return s; @@ -4083,7 +4098,8 @@ static BcStatus bc_parse_return(BcParse *p) s = bc_parse_expr(p, 0, bc_parse_next_expr); if (s && s != BC_STATUS_PARSE_EMPTY_EXP) return s; - else if (s == BC_STATUS_PARSE_EMPTY_EXP) { + + if (s == BC_STATUS_PARSE_EMPTY_EXP) { bc_parse_push(p, BC_INST_RET0); s = bc_lex_next(&p->l); if (s) return s; @@ -4105,18 +4121,18 @@ static BcStatus bc_parse_endBody(BcParse *p, bool brace) BcStatus s = BC_STATUS_SUCCESS; if (p->flags.len <= 1 || (brace && p->nbraces == 0)) - return BC_STATUS_PARSE_BAD_TOKEN; + return bc_error("bad token"); if (brace) { if (p->l.t.t == BC_LEX_RBRACE) { - if (!p->nbraces) return BC_STATUS_PARSE_BAD_TOKEN; + if (!p->nbraces) return bc_error("bad token"); --p->nbraces; s = bc_lex_next(&p->l); if (s) return s; } else - return BC_STATUS_PARSE_BAD_TOKEN; + return bc_error("bad token"); } if (BC_PARSE_IF(p)) { @@ -4202,13 +4218,13 @@ static BcStatus bc_parse_if(BcParse *p) s = bc_lex_next(&p->l); if (s) return s; - if (p->l.t.t != BC_LEX_LPAREN) return BC_STATUS_PARSE_BAD_TOKEN; + if (p->l.t.t != BC_LEX_LPAREN) return bc_error("bad token"); s = bc_lex_next(&p->l); if (s) return s; s = bc_parse_expr(p, BC_PARSE_REL, bc_parse_next_rel); if (s) return s; - if (p->l.t.t != BC_LEX_RPAREN) return BC_STATUS_PARSE_BAD_TOKEN; + if (p->l.t.t != BC_LEX_RPAREN) return bc_error("bad token"); s = bc_lex_next(&p->l); if (s) return s; @@ -4229,7 +4245,7 @@ static BcStatus bc_parse_else(BcParse *p) { BcInstPtr ip; - if (!BC_PARSE_IF_END(p)) return BC_STATUS_PARSE_BAD_TOKEN; + if (!BC_PARSE_IF_END(p)) return bc_error("bad token"); ip.idx = p->func->labels.len; ip.func = ip.len = 0; @@ -4253,7 +4269,7 @@ static BcStatus bc_parse_while(BcParse *p) s = bc_lex_next(&p->l); if (s) return s; - if (p->l.t.t != BC_LEX_LPAREN) return BC_STATUS_PARSE_BAD_TOKEN; + if (p->l.t.t != BC_LEX_LPAREN) return bc_error("bad token"); s = bc_lex_next(&p->l); if (s) return s; @@ -4271,7 +4287,7 @@ static BcStatus bc_parse_while(BcParse *p) s = bc_parse_expr(p, BC_PARSE_REL, bc_parse_next_rel); if (s) return s; - if (p->l.t.t != BC_LEX_RPAREN) return BC_STATUS_PARSE_BAD_TOKEN; + if (p->l.t.t != BC_LEX_RPAREN) return bc_error("bad token"); s = bc_lex_next(&p->l); if (s) return s; @@ -4290,7 +4306,7 @@ static BcStatus bc_parse_for(BcParse *p) s = bc_lex_next(&p->l); if (s) return s; - if (p->l.t.t != BC_LEX_LPAREN) return BC_STATUS_PARSE_BAD_TOKEN; + if (p->l.t.t != BC_LEX_LPAREN) return bc_error("bad token"); s = bc_lex_next(&p->l); if (s) return s; @@ -4300,7 +4316,7 @@ static BcStatus bc_parse_for(BcParse *p) s = bc_vm_posixError(BC_STATUS_POSIX_FOR1, p->l.f, p->l.line, NULL); if (s) return s; - if (p->l.t.t != BC_LEX_SCOLON) return BC_STATUS_PARSE_BAD_TOKEN; + if (p->l.t.t != BC_LEX_SCOLON) return bc_error("bad token"); s = bc_lex_next(&p->l); if (s) return s; @@ -4317,7 +4333,7 @@ static BcStatus bc_parse_for(BcParse *p) s = bc_vm_posixError(BC_STATUS_POSIX_FOR2, p->l.f, p->l.line, NULL); if (s) return s; - if (p->l.t.t != BC_LEX_SCOLON) return BC_STATUS_PARSE_BAD_TOKEN; + if (p->l.t.t != BC_LEX_SCOLON) return bc_error("bad token"); s = bc_lex_next(&p->l); if (s) return s; @@ -4339,7 +4355,7 @@ static BcStatus bc_parse_for(BcParse *p) if (s) return s; - if (p->l.t.t != BC_LEX_RPAREN) return BC_STATUS_PARSE_BAD_TOKEN; + if (p->l.t.t != BC_LEX_RPAREN) return bc_error("bad token"); bc_parse_push(p, BC_INST_JUMP); bc_parse_pushIndex(p, cond_idx); bc_vec_push(&p->func->labels, &p->func->code.len); @@ -4362,17 +4378,17 @@ static BcStatus bc_parse_loopExit(BcParse *p, BcLexType type) size_t i; BcInstPtr *ip; - if (!BC_PARSE_LOOP(p)) return BC_STATUS_PARSE_BAD_TOKEN; + if (!BC_PARSE_LOOP(p)) return bc_error("bad token"); if (type == BC_LEX_KEY_BREAK) { - if (p->exits.len == 0) return BC_STATUS_PARSE_BAD_TOKEN; + if (p->exits.len == 0) return bc_error("bad token"); i = p->exits.len - 1; ip = bc_vec_item(&p->exits, i); while (!ip->func && i < p->exits.len) ip = bc_vec_item(&p->exits, i--); - if (i >= p->exits.len && !ip->func) return BC_STATUS_PARSE_BAD_TOKEN; + if (i >= p->exits.len && !ip->func) return bc_error("bad token"); i = ip->idx; } @@ -4386,7 +4402,7 @@ static BcStatus bc_parse_loopExit(BcParse *p, BcLexType type) if (s) return s; if (p->l.t.t != BC_LEX_SCOLON && p->l.t.t != BC_LEX_NLINE) - return BC_STATUS_PARSE_BAD_TOKEN; + return bc_error("bad token"); return bc_lex_next(&p->l); } @@ -4400,20 +4416,23 @@ static BcStatus bc_parse_func(BcParse *p) s = bc_lex_next(&p->l); if (s) return s; - if (p->l.t.t != BC_LEX_NAME) return BC_STATUS_PARSE_BAD_FUNC; + if (p->l.t.t != BC_LEX_NAME) + return bc_error("bad function definition"); name = xstrdup(p->l.t.v.v); bc_parse_addFunc(p, name, &p->fidx); s = bc_lex_next(&p->l); if (s) return s; - if (p->l.t.t != BC_LEX_LPAREN) return BC_STATUS_PARSE_BAD_FUNC; + if (p->l.t.t != BC_LEX_LPAREN) + return bc_error("bad function definition"); s = bc_lex_next(&p->l); if (s) return s; while (p->l.t.t != BC_LEX_RPAREN) { - if (p->l.t.t != BC_LEX_NAME) return BC_STATUS_PARSE_BAD_FUNC; + if (p->l.t.t != BC_LEX_NAME) + return bc_error("bad function definition"); ++p->func->nparams; @@ -4429,7 +4448,7 @@ static BcStatus bc_parse_func(BcParse *p) if (s) goto err; if (p->l.t.t != BC_LEX_RBRACKET) { - s = BC_STATUS_PARSE_BAD_FUNC; + s = bc_error("bad function definition"); goto err; } @@ -4447,7 +4466,7 @@ static BcStatus bc_parse_func(BcParse *p) if (s) goto err; } - if (comma) return BC_STATUS_PARSE_BAD_FUNC; + if (comma) return bc_error("bad function definition"); flags = BC_PARSE_FLAG_FUNC | BC_PARSE_FLAG_FUNC_INNER | BC_PARSE_FLAG_BODY; bc_parse_startBody(p, flags); @@ -4471,7 +4490,7 @@ static BcStatus bc_parse_auto(BcParse *p) bool comma, var, one; char *name; - if (!p->auto_part) return BC_STATUS_PARSE_BAD_TOKEN; + if (!p->auto_part) return bc_error("bad token"); s = bc_lex_next(&p->l); if (s) return s; @@ -4491,7 +4510,7 @@ static BcStatus bc_parse_auto(BcParse *p) if (s) goto err; if (p->l.t.t != BC_LEX_RBRACKET) { - s = BC_STATUS_PARSE_BAD_FUNC; + s = bc_error("bad function definition"); goto err; } @@ -4509,11 +4528,11 @@ static BcStatus bc_parse_auto(BcParse *p) if (s) goto err; } - if (comma) return BC_STATUS_PARSE_BAD_FUNC; + if (comma) return bc_error("bad function definition"); if (!one) return bc_error("no auto variable found"); if (p->l.t.t != BC_LEX_NLINE && p->l.t.t != BC_LEX_SCOLON) - return BC_STATUS_PARSE_BAD_TOKEN; + return bc_error("bad token"); return bc_lex_next(&p->l); @@ -4531,7 +4550,7 @@ static BcStatus bc_parse_body(BcParse *p, bool brace) if (*flag_ptr & BC_PARSE_FLAG_FUNC_INNER) { - if (!brace) return BC_STATUS_PARSE_BAD_TOKEN; + if (!brace) return bc_error("bad token"); p->auto_part = p->l.t.t != BC_LEX_KEY_AUTO; if (!p->auto_part) { @@ -4568,7 +4587,7 @@ static BcStatus bc_parse_stmt(BcParse *p) case BC_LEX_LBRACE: { - if (!BC_PARSE_BODY(p)) return BC_STATUS_PARSE_BAD_TOKEN; + if (!BC_PARSE_BODY(p)) return bc_error("bad token"); ++p->nbraces; s = bc_lex_next(&p->l); @@ -4713,7 +4732,7 @@ static BcStatus bc_parse_stmt(BcParse *p) default: { - s = BC_STATUS_PARSE_BAD_TOKEN; + s = bc_error("bad token"); break; } } @@ -4726,9 +4745,9 @@ static BcStatus bc_parse_parse(BcParse *p) BcStatus s; if (p->l.t.t == BC_LEX_EOF) - s = p->flags.len > 0 ? BC_STATUS_PARSE_NO_BLOCK_END : BC_STATUS_LEX_EOF; + s = p->flags.len > 0 ? bc_error("block end could not be found") : bc_error("end of file"); else if (p->l.t.t == BC_LEX_KEY_DEFINE) { - if (!BC_PARSE_CAN_EXEC(p)) return BC_STATUS_PARSE_BAD_TOKEN; + if (!BC_PARSE_CAN_EXEC(p)) return bc_error("bad token"); s = bc_parse_func(p); } else @@ -4787,7 +4806,11 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) prev != BC_INST_SCALE && prev != BC_INST_IBASE && prev != BC_INST_OBASE && prev != BC_INST_LAST) { - s = BC_STATUS_PARSE_BAD_ASSIGN; + s = bc_error("bad assignment:" + " left side must be scale," + " ibase, obase, last, var," + " or array element" + ); break; } } @@ -4807,10 +4830,10 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) case BC_LEX_OP_BOOL_OR: case BC_LEX_OP_BOOL_AND: { - if (((t == BC_LEX_OP_BOOL_NOT) != bin_last) || - (t != BC_LEX_OP_BOOL_NOT && prev == BC_INST_BOOL_NOT)) - { - return BC_STATUS_PARSE_BAD_EXP; + if (((t == BC_LEX_OP_BOOL_NOT) != bin_last) + || (t != BC_LEX_OP_BOOL_NOT && prev == BC_INST_BOOL_NOT) + ) { + return bc_error("bad expression"); } nrelops += t >= BC_LEX_OP_REL_EQ && t <= BC_LEX_OP_REL_GT; @@ -4824,8 +4847,8 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) case BC_LEX_LPAREN: { - if (BC_PARSE_LEAF(prev, rprn)) return BC_STATUS_PARSE_BAD_EXP; - + if (BC_PARSE_LEAF(prev, rprn)) + return bc_error("bad expression"); ++nparens; paren_expr = rprn = bin_last = false; get_token = true; @@ -4837,7 +4860,7 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) case BC_LEX_RPAREN: { if (bin_last || prev == BC_INST_BOOL_NOT) - return BC_STATUS_PARSE_BAD_EXP; + return bc_error("bad expression"); if (nparens == 0) { s = BC_STATUS_SUCCESS; @@ -4859,8 +4882,8 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) case BC_LEX_NAME: { - if (BC_PARSE_LEAF(prev, rprn)) return BC_STATUS_PARSE_BAD_EXP; - + if (BC_PARSE_LEAF(prev, rprn)) + return bc_error("bad expression"); paren_expr = true; rprn = get_token = bin_last = false; s = bc_parse_name(p, &prev, flags & ~BC_PARSE_NOCALL); @@ -4871,8 +4894,8 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) case BC_LEX_NUMBER: { - if (BC_PARSE_LEAF(prev, rprn)) return BC_STATUS_PARSE_BAD_EXP; - + if (BC_PARSE_LEAF(prev, rprn)) + return bc_error("bad expression"); bc_parse_number(p, &prev, &nexprs); paren_expr = get_token = true; rprn = bin_last = false; @@ -4884,8 +4907,8 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) case BC_LEX_KEY_LAST: case BC_LEX_KEY_OBASE: { - if (BC_PARSE_LEAF(prev, rprn)) return BC_STATUS_PARSE_BAD_EXP; - + if (BC_PARSE_LEAF(prev, rprn)) + return bc_error("bad expression"); prev = (char) (t - BC_LEX_KEY_IBASE + BC_INST_IBASE); bc_parse_push(p, (char) prev); @@ -4899,8 +4922,8 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) case BC_LEX_KEY_LENGTH: case BC_LEX_KEY_SQRT: { - if (BC_PARSE_LEAF(prev, rprn)) return BC_STATUS_PARSE_BAD_EXP; - + if (BC_PARSE_LEAF(prev, rprn)) + return bc_error("bad expression"); s = bc_parse_builtin(p, t, flags, &prev); paren_expr = true; rprn = get_token = bin_last = false; @@ -4912,9 +4935,9 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) case BC_LEX_KEY_READ: { if (BC_PARSE_LEAF(prev, rprn)) - return BC_STATUS_PARSE_BAD_EXP; + return bc_error("bad expression"); else if (flags & BC_PARSE_NOREAD) - s = BC_STATUS_EXEC_REC_READ; + s = bc_error("read() call inside of a read() call"); else s = bc_parse_read(p); @@ -4928,8 +4951,8 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) case BC_LEX_KEY_SCALE: { - if (BC_PARSE_LEAF(prev, rprn)) return BC_STATUS_PARSE_BAD_EXP; - + if (BC_PARSE_LEAF(prev, rprn)) + return bc_error("bad expression"); s = bc_parse_scale(p, &prev, flags); paren_expr = true; rprn = get_token = bin_last = false; @@ -4941,7 +4964,7 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) default: { - s = BC_STATUS_PARSE_BAD_TOKEN; + s = bc_error("bad token"); break; } } @@ -4958,7 +4981,7 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) assign = top >= BC_LEX_OP_ASSIGN_POWER && top <= BC_LEX_OP_ASSIGN; if (top == BC_LEX_LPAREN || top == BC_LEX_RPAREN) - return BC_STATUS_PARSE_BAD_EXP; + return bc_error("bad expression"); bc_parse_push(p, BC_PARSE_TOKEN_INST(top)); @@ -4966,11 +4989,14 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) bc_vec_pop(&p->ops); } - s = BC_STATUS_PARSE_BAD_EXP; - if (prev == BC_INST_BOOL_NOT || nexprs != 1) return s; + if (prev == BC_INST_BOOL_NOT || nexprs != 1) + return bc_error("bad expression"); - for (i = 0; s && i < next.len; ++i) s *= t != next.tokens[i]; - if (s) return s; + for (i = 0; i < next.len; ++i) + if (t == next.tokens[i]) + goto ok; + return bc_error("bad expression"); + ok: if (!(flags & BC_PARSE_REL) && nrelops) { s = bc_vm_posixError(BC_STATUS_POSIX_REL_POS, p->l.f, p->l.line, NULL); @@ -5008,7 +5034,7 @@ static BcStatus dc_parse_register(BcParse *p) s = bc_lex_next(&p->l); if (s) return s; - if (p->l.t.t != BC_LEX_NAME) return BC_STATUS_PARSE_BAD_TOKEN; + if (p->l.t.t != BC_LEX_NAME) return bc_error("bad token"); name = xstrdup(p->l.t.v.v); bc_parse_pushName(p, name); @@ -5115,7 +5141,8 @@ static BcStatus dc_parse_token(BcParse *p, BcLexType t, uint8_t flags) if (t == BC_LEX_NEG) { s = bc_lex_next(&p->l); if (s) return s; - if (p->l.t.t != BC_LEX_NUMBER) return BC_STATUS_PARSE_BAD_TOKEN; + if (p->l.t.t != BC_LEX_NUMBER) + return bc_error("bad token"); } bc_parse_number(p, &prev, &p->nbraces); @@ -5129,7 +5156,7 @@ static BcStatus dc_parse_token(BcParse *p, BcLexType t, uint8_t flags) case BC_LEX_KEY_READ: { if (flags & BC_PARSE_NOREAD) - s = BC_STATUS_EXEC_REC_READ; + s = bc_error("read() call inside of a read() call"); else bc_parse_push(p, BC_INST_READ); get_token = true; @@ -5164,7 +5191,7 @@ static BcStatus dc_parse_token(BcParse *p, BcLexType t, uint8_t flags) default: { - s = BC_STATUS_PARSE_BAD_TOKEN; + s = bc_error("bad token"); get_token = true; break; } @@ -5206,7 +5233,7 @@ static BcStatus dc_parse_parse(BcParse *p) BcStatus s; if (p->l.t.t == BC_LEX_EOF) - s = BC_STATUS_LEX_EOF; + s = bc_error("end of file"); else s = dc_parse_expr(p, 0); @@ -5349,7 +5376,8 @@ static BcStatus bc_program_binOpPrep(BcResult **l, BcNum **ln, bool hex; BcResultType lt, rt; - if (!BC_PROG_STACK(&G.prog.results, 2)) return BC_STATUS_EXEC_STACK; + if (!BC_PROG_STACK(&G.prog.results, 2)) + return bc_error("stack has too few elements"); *r = bc_vec_item_rev(&G.prog.results, 0); *l = bc_vec_item_rev(&G.prog.results, 1); @@ -5371,8 +5399,9 @@ static BcStatus bc_program_binOpPrep(BcResult **l, BcNum **ln, } if (!BC_PROG_NUM((*l), (*ln)) && (!assign || (*l)->t != BC_RESULT_VAR)) - return BC_STATUS_EXEC_BAD_TYPE; - if (!assign && !BC_PROG_NUM((*r), (*ln))) return BC_STATUS_EXEC_BAD_TYPE; + return bc_error("variable is wrong type"); + if (!assign && !BC_PROG_NUM((*r), (*ln))) + return bc_error("variable is wrong type"); return s; } @@ -5389,13 +5418,15 @@ static BcStatus bc_program_prep(BcResult **r, BcNum **n) { BcStatus s; - if (!BC_PROG_STACK(&G.prog.results, 1)) return BC_STATUS_EXEC_STACK; + if (!BC_PROG_STACK(&G.prog.results, 1)) + return bc_error("stack has too few elements"); *r = bc_vec_top(&G.prog.results); s = bc_program_num(*r, n, false); if (s) return s; - if (!BC_PROG_NUM((*r), (*n))) return BC_STATUS_EXEC_BAD_TYPE; + if (!BC_PROG_NUM((*r), (*n))) + return bc_error("variable is wrong type"); return s; } @@ -5439,7 +5470,8 @@ static BcStatus bc_program_read(void) for (i = 0; i < G.prog.stack.len; ++i) { BcInstPtr *ip_ptr = bc_vec_item(&G.prog.stack, i); - if (ip_ptr->func == BC_PROG_READ) return BC_STATUS_EXEC_REC_READ; + if (ip_ptr->func == BC_PROG_READ) + return bc_error("read() call inside of a read() call"); } bc_vec_npop(&f->code, f->code.len); @@ -5457,7 +5489,7 @@ static BcStatus bc_program_read(void) if (s) goto exec_err; if (parse.l.t.t != BC_LEX_NLINE && parse.l.t.t != BC_LEX_EOF) { - s = BC_STATUS_EXEC_BAD_READ_EXPR; + s = bc_error("bad read() expression"); goto exec_err; } @@ -5600,7 +5632,8 @@ static BcStatus bc_program_print(char inst, size_t idx) BcNum *num = NULL; bool pop = inst != BC_INST_PRINT; - if (!BC_PROG_STACK(&G.prog.results, idx + 1)) return BC_STATUS_EXEC_STACK; + if (!BC_PROG_STACK(&G.prog.results, idx + 1)) + return bc_error("stack has too few elements"); r = bc_vec_item_rev(&G.prog.results, idx); s = bc_program_num(r, &num, false); @@ -5731,7 +5764,8 @@ static BcStatus bc_program_assignStr(BcResult *r, BcVec *v, res.t = BC_RESULT_STR; if (!push) { - if (!BC_PROG_STACK(&G.prog.results, 2)) return BC_STATUS_EXEC_STACK; + if (!BC_PROG_STACK(&G.prog.results, 2)) + return bc_error("stack has too few elements"); bc_vec_pop(v); bc_vec_pop(&G.prog.results); } @@ -5752,14 +5786,17 @@ static BcStatus bc_program_copyToVar(char *name, bool var) BcVec *v; BcNum *n; - if (!BC_PROG_STACK(&G.prog.results, 1)) return BC_STATUS_EXEC_STACK; + if (!BC_PROG_STACK(&G.prog.results, 1)) + return bc_error("stack has too few elements"); ptr = bc_vec_top(&G.prog.results); - if ((ptr->t == BC_RESULT_ARRAY) != !var) return BC_STATUS_EXEC_BAD_TYPE; + if ((ptr->t == BC_RESULT_ARRAY) != !var) + return bc_error("variable is wrong type"); v = bc_program_search(name, var); #if ENABLE_DC - if (ptr->t == BC_RESULT_STR && !var) return BC_STATUS_EXEC_BAD_TYPE; + if (ptr->t == BC_RESULT_STR && !var) + return bc_error("variable is wrong type"); if (ptr->t == BC_RESULT_STR) return bc_program_assignStr(ptr, v, true); #endif @@ -5804,7 +5841,8 @@ static BcStatus bc_program_assign(char inst) BcVec *v; - if (left->t != BC_RESULT_VAR) return BC_STATUS_EXEC_BAD_TYPE; + if (left->t != BC_RESULT_VAR) + return bc_error("variable is wrong type"); v = bc_program_search(left->d.id.name, true); return bc_program_assignStr(right, v, false); @@ -5812,11 +5850,15 @@ static BcStatus bc_program_assign(char inst) #endif if (left->t == BC_RESULT_CONSTANT || left->t == BC_RESULT_TEMP) - return BC_STATUS_PARSE_BAD_ASSIGN; + return bc_error("bad assignment:" + " left side must be scale," + " ibase, obase, last, var," + " or array element" + ); #if ENABLE_BC if (inst == BC_INST_ASSIGN_DIVIDE && !bc_num_cmp(r, &G.prog.zero)) - return BC_STATUS_MATH_DIVIDE_BY_ZERO; + return bc_error("divide by zero"); if (assign) bc_num_copy(l, r); @@ -5829,25 +5871,35 @@ static BcStatus bc_program_assign(char inst) #endif if (ib || sc || left->t == BC_RESULT_OBASE) { - + static const char *const msg[] = { + "bad ibase; must be [2, 16]", //BC_RESULT_IBASE + "bad scale; must be [0, BC_SCALE_MAX]", //BC_RESULT_SCALE + "?1", //BC_RESULT_LAST + "?2", //BC_RESULT_CONSTANT + "?3", //BC_RESULT_ONE + "bad obase; must be [2, BC_BASE_MAX]", //BC_RESULT_OBASE + }; size_t *ptr; s = bc_num_ulong(l, &val); - if (s) return s; - s = left->t - BC_RESULT_IBASE + BC_STATUS_EXEC_BAD_IBASE; - + if (s) + return s; + s = left->t - BC_RESULT_IBASE; if (sc) { max = BC_MAX_SCALE; ptr = &G.prog.scale; } else { - if (val < BC_NUM_MIN_BASE) return s; + if (val < BC_NUM_MIN_BASE) + return bc_error(msg[s]); max = ib ? BC_NUM_MAX_IBASE : BC_MAX_OBASE; ptr = ib ? &G.prog.ib_t : &G.prog.ob_t; } - if (val > max) return s; - if (!sc) bc_num_copy(ib ? &G.prog.ib : &G.prog.ob, l); + if (val > max) + return bc_error(msg[s]); + if (!sc) + bc_num_copy(ib ? &G.prog.ib : &G.prog.ob, l); *ptr = (size_t) val; s = BC_STATUS_SUCCESS; @@ -5884,7 +5936,7 @@ static BcStatus bc_program_pushVar(char *code, size_t *bgn, if (!BC_PROG_STACK(v, 2 - copy)) { free(name); - return BC_STATUS_EXEC_STACK; + return bc_error("stack has too few elements"); } free(name); @@ -5936,7 +5988,7 @@ static BcStatus bc_program_pushArray(char *code, size_t *bgn, if (s) goto err; if (temp > BC_MAX_DIM) { - s = BC_STATUS_EXEC_ARRAY_LEN; + s = bc_error("array too long; must be [1, BC_DIM_MAX]"); goto err; } @@ -6010,7 +6062,7 @@ static BcStatus bc_program_call(char *code, size_t *idx) arg = bc_vec_top(&G.prog.results); if ((!a->idx) != (arg->t == BC_RESULT_ARRAY) || arg->t == BC_RESULT_STR) - return BC_STATUS_EXEC_BAD_TYPE; + return bc_error("variable is wrong type"); s = bc_program_copyToVar(a->name, a->idx); if (s) return s; @@ -6046,7 +6098,7 @@ static BcStatus bc_program_return(char inst) BcInstPtr *ip = bc_vec_top(&G.prog.stack); if (!BC_PROG_STACK(&G.prog.results, ip->len + inst == BC_INST_RET)) - return BC_STATUS_EXEC_STACK; + return bc_error("stack has too few elements"); f = bc_vec_item(&G.prog.fns, ip->func); res.t = BC_RESULT_TEMP; @@ -6108,14 +6160,16 @@ static BcStatus bc_program_builtin(char inst) BcResult res; bool len = inst == BC_INST_LENGTH; - if (!BC_PROG_STACK(&G.prog.results, 1)) return BC_STATUS_EXEC_STACK; + if (!BC_PROG_STACK(&G.prog.results, 1)) + return bc_error("stack has too few elements"); opnd = bc_vec_top(&G.prog.results); s = bc_program_num(opnd, &num, false); if (s) return s; #if ENABLE_DC - if (!BC_PROG_NUM(opnd, num) && !len) return BC_STATUS_EXEC_BAD_TYPE; + if (!BC_PROG_NUM(opnd, num) && !len) + return bc_error("variable is wrong type"); #endif bc_num_init(&res.d.n, BC_NUM_DEF_SIZE); @@ -6180,14 +6234,16 @@ static BcStatus bc_program_modexp(void) BcResult *r1, *r2, *r3, res; BcNum *n1, *n2, *n3; - if (!BC_PROG_STACK(&G.prog.results, 3)) return BC_STATUS_EXEC_STACK; + if (!BC_PROG_STACK(&G.prog.results, 3)) + return bc_error("stack has too few elements"); s = bc_program_binOpPrep(&r2, &n2, &r3, &n3, false); if (s) return s; r1 = bc_vec_item_rev(&G.prog.results, 2); s = bc_program_num(r1, &n1, false); if (s) return s; - if (!BC_PROG_NUM(r1, n1)) return BC_STATUS_EXEC_BAD_TYPE; + if (!BC_PROG_NUM(r1, n1)) + return bc_error("variable is wrong type"); // Make sure that the values have their pointers updated, if necessary. if (r1->t == BC_RESULT_VAR || r1->t == BC_RESULT_ARRAY_ELEM) { @@ -6238,7 +6294,8 @@ static BcStatus bc_program_asciify(void) size_t len = G.prog.strs.len, idx; unsigned long val; - if (!BC_PROG_STACK(&G.prog.results, 1)) return BC_STATUS_EXEC_STACK; + if (!BC_PROG_STACK(&G.prog.results, 1)) + return bc_error("stack has too few elements"); r = bc_vec_top(&G.prog.results); s = bc_program_num(r, &num, false); @@ -6306,7 +6363,8 @@ static BcStatus bc_program_printStream(void) size_t idx; char *str; - if (!BC_PROG_STACK(&G.prog.results, 1)) return BC_STATUS_EXEC_STACK; + if (!BC_PROG_STACK(&G.prog.results, 1)) + return bc_error("stack has too few elements"); r = bc_vec_top(&G.prog.results); s = bc_program_num(r, &n, false); @@ -6338,7 +6396,7 @@ static BcStatus bc_program_nquit(void) bc_vec_pop(&G.prog.results); if (G.prog.stack.len < val) - return BC_STATUS_EXEC_STACK; + return bc_error("stack has too few elements"); if (G.prog.stack.len == val) quit(); @@ -6360,7 +6418,8 @@ static BcStatus bc_program_execStr(char *code, size_t *bgn, BcNum *n; bool exec; - if (!BC_PROG_STACK(&G.prog.results, 1)) return BC_STATUS_EXEC_STACK; + if (!BC_PROG_STACK(&G.prog.results, 1)) + return bc_error("stack has too few elements"); r = bc_vec_top(&G.prog.results); @@ -6393,7 +6452,7 @@ static BcStatus bc_program_execStr(char *code, size_t *bgn, if (!exec) goto exit; if (!BC_PROG_STR(n)) { - s = BC_STATUS_EXEC_BAD_TYPE; + s = bc_error("variable is wrong type"); goto exit; } @@ -6425,7 +6484,7 @@ static BcStatus bc_program_execStr(char *code, size_t *bgn, if (s) goto err; if (prs.l.t.t != BC_LEX_EOF) { - s = BC_STATUS_PARSE_BAD_EXP; + s = bc_error("bad expression"); goto err; } @@ -6652,7 +6711,7 @@ static BcStatus bc_program_exec(void) case BC_INST_POP: { if (!BC_PROG_STACK(&G.prog.results, 1)) - s = BC_STATUS_EXEC_STACK; + s = bc_error("stack has too few elements"); else bc_vec_pop(&G.prog.results); break; @@ -6764,7 +6823,8 @@ static BcStatus bc_program_exec(void) case BC_INST_DUPLICATE: { - if (!BC_PROG_STACK(&G.prog.results, 1)) return BC_STATUS_EXEC_STACK; + if (!BC_PROG_STACK(&G.prog.results, 1)) + return bc_error("stack has too few elements"); ptr = bc_vec_top(&G.prog.results); bc_result_copy(&r, ptr); bc_vec_push(&G.prog.results, &r); @@ -6775,7 +6835,8 @@ static BcStatus bc_program_exec(void) { BcResult *ptr2; - if (!BC_PROG_STACK(&G.prog.results, 2)) return BC_STATUS_EXEC_STACK; + if (!BC_PROG_STACK(&G.prog.results, 2)) + return bc_error("stack has too few elements"); ptr = bc_vec_item_rev(&G.prog.results, 0); ptr2 = bc_vec_item_rev(&G.prog.results, 1); @@ -6863,6 +6924,7 @@ static BcStatus bc_vm_error(BcStatus s, const char *file, size_t line) fprintf(stderr, bc_err_line + 4 * !line, line); } +/// return s * (!G.ttyin || !!strcmp(file, bc_program_stdin_name)); } @@ -6983,7 +7045,8 @@ static BcStatus bc_vm_file(const char *file) main_func = bc_vec_item(&G.prog.fns, BC_PROG_MAIN); ip = bc_vec_item(&G.prog.stack, 0); - if (main_func->code.len < ip->idx) s = BC_STATUS_EXEC_FILE_NOT_EXECUTABLE; + if (main_func->code.len < ip->idx) + s = bc_error("file '%s' is not executable", file); err: free(data); @@ -7057,12 +7120,16 @@ static BcStatus bc_vm_stdin(void) bc_vec_npop(&buffer, buffer.len); } - if (str) - s = bc_vm_error(BC_STATUS_LEX_NO_STRING_END, G.prs.l.f, + if (str) { + bc_error("string end could not be found"); + s = bc_vm_error(BC_STATUS_FAILURE, G.prs.l.f, G.prs.l.line); - else if (comment) - s = bc_vm_error(BC_STATUS_LEX_NO_COMMENT_END, G.prs.l.f, + } + else if (comment) { + bc_error("comment end could not be found"); + s = bc_vm_error(BC_STATUS_FAILURE, G.prs.l.f, G.prs.l.line); + } err: bc_vec_free(&buf); -- cgit v1.2.3-55-g6feb From 9b70f197b4dd5be47c5d0d4479525efe012964ee Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 4 Dec 2018 20:51:40 +0100 Subject: bc: convert all status codes, remove bc_err_msgs[], bc_vm_error(), bc_vm_posixError() function old new delta bc_posix_error - 65 +65 bc_vm_run 1995 2039 +44 bc_err_line 7 - -7 bc_num_ulong 103 93 -10 bc_parse_parse 495 483 -12 bc_err_fmt 12 - -12 bc_warn_fmt 14 - -14 bc_parse_expr 2210 2194 -16 bc_program_reset 105 78 -27 bc_vm_process 130 94 -36 bc_parse_stmt 2313 2277 -36 bc_err_msgs 60 - -60 bc_lex_token 1367 1282 -85 bc_vm_error 143 - -143 bc_vm_posixError 189 - -189 ------------------------------------------------------------------------------ (add/remove: 1/6 grow/shrink: 1/7 up/down: 109/-647) Total: -538 bytes text data bss dec hex filename 988258 485 7296 996039 f32c7 busybox_old 987717 485 7296 995498 f30aa busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 267 +++++++++++---------------------------------------------- 1 file changed, 52 insertions(+), 215 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 7b20a94cc..bc5501d91 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -171,141 +171,7 @@ typedef enum BcStatus { BC_STATUS_SUCCESS = 0, BC_STATUS_FAILURE = 1, BC_STATUS_PARSE_EMPTY_EXP = 2, // bc_parse_expr() uses this - -// BC_STATUS_ALLOC_ERR, -// BC_STATUS_INPUT_EOF, -// BC_STATUS_BIN_FILE, -// BC_STATUS_PATH_IS_DIR, - -// BC_STATUS_LEX_BAD_CHAR, -// BC_STATUS_LEX_NO_STRING_END, -// BC_STATUS_LEX_NO_COMMENT_END, -// BC_STATUS_LEX_EOF, -#if ENABLE_DC -// BC_STATUS_LEX_EXTENDED_REG, -#endif -// BC_STATUS_PARSE_BAD_TOKEN, -// BC_STATUS_PARSE_BAD_EXP, -// BC_STATUS_PARSE_BAD_PRINT, -// BC_STATUS_PARSE_BAD_FUNC, -// BC_STATUS_PARSE_BAD_ASSIGN, -// BC_STATUS_PARSE_NO_AUTO, -// BC_STATUS_PARSE_DUPLICATE_LOCAL, -// BC_STATUS_PARSE_NO_BLOCK_END, - -// BC_STATUS_MATH_NEGATIVE, -// BC_STATUS_MATH_NON_INTEGER, -// BC_STATUS_MATH_OVERFLOW, -// BC_STATUS_MATH_DIVIDE_BY_ZERO, -// BC_STATUS_MATH_BAD_STRING, - -// BC_STATUS_EXEC_FILE_ERR, -// BC_STATUS_EXEC_MISMATCHED_PARAMS, -// BC_STATUS_EXEC_UNDEFINED_FUNC, -// BC_STATUS_EXEC_FILE_NOT_EXECUTABLE, -// BC_STATUS_EXEC_NUM_LEN, -// BC_STATUS_EXEC_NAME_LEN, -// BC_STATUS_EXEC_STRING_LEN, -// BC_STATUS_EXEC_ARRAY_LEN, -// BC_STATUS_EXEC_BAD_IBASE, -// BC_STATUS_EXEC_BAD_SCALE, -// BC_STATUS_EXEC_BAD_READ_EXPR, -// BC_STATUS_EXEC_REC_READ, -// BC_STATUS_EXEC_BAD_TYPE, -// BC_STATUS_EXEC_BAD_OBASE, -// BC_STATUS_EXEC_SIGNAL, -// BC_STATUS_EXEC_STACK, - -// BC_STATUS_VEC_OUT_OF_BOUNDS, -// BC_STATUS_VEC_ITEM_EXISTS, - BC_STATUS_BEFORE_POSIX = BC_STATUS_PARSE_EMPTY_EXP, -#if ENABLE_BC - BC_STATUS_POSIX_NAME_LEN, - BC_STATUS_POSIX_COMMENT, - BC_STATUS_POSIX_BAD_KW, - BC_STATUS_POSIX_DOT, - BC_STATUS_POSIX_RET, - BC_STATUS_POSIX_BOOL, - BC_STATUS_POSIX_REL_POS, - BC_STATUS_POSIX_MULTIREL, - BC_STATUS_POSIX_FOR1, - BC_STATUS_POSIX_FOR2, - BC_STATUS_POSIX_FOR3, - BC_STATUS_POSIX_BRACE, -#endif -// BC_STATUS_QUIT, -// BC_STATUS_LIMITS, - -// BC_STATUS_INVALID_OPTION, } BcStatus; -// Keep enum above and messages below in sync! -static const char *const bc_err_msgs[] = { - NULL, - NULL, - NULL, - -// "memory allocation error", -// "I/O error", -// "file is not text:", -// "path is a directory:", - -// "bad character", -// "string end could not be found", -// "comment end could not be found", -// "end of file", -#if ENABLE_DC -// "extended register", -#endif -// "bad token", -// "bad expression", -// "bad print statement", -// "bad function definition", -// "bad assignment: left side must be scale, ibase, " -// "obase, last, var, or array element", -// "no auto variable found", -// "function parameter or auto var has the same name as another", -// "block end could not be found", - -// "negative number", -// "non integer number", -// "overflow", -// "divide by zero", -// "bad number string", - -// "could not open file:", -// "mismatched parameters", // wrong number of them, to be exact -// "undefined function", -// "file is not executable:", -// "number too long: must be [1, BC_NUM_MAX]", -// "name too long: must be [1, BC_NAME_MAX]", -// "string too long: must be [1, BC_STRING_MAX]", -// "array too long; must be [1, BC_DIM_MAX]", -// "bad ibase; must be [2, 16]", -// "bad scale; must be [0, BC_SCALE_MAX]", -// "bad read() expression", -// "read() call inside of a read() call", -// "variable is wrong type", -// "bad obase; must be [2, BC_BASE_MAX]", -// "signal caught and not handled", -// "stack has too few elements", - -// "index is out of bounds", -// "item already exists", -#if ENABLE_BC - "POSIX only allows one character names; the following is bad:", - "POSIX does not allow '#' script comments", - "POSIX does not allow the following keyword:", - "POSIX does not allow a period ('.') as a shortcut for the last result", - "POSIX requires parentheses around return expressions", - "POSIX does not allow boolean operators; the following is bad:", - "POSIX does not allow comparison operators outside if or loops", - "POSIX requires exactly one comparison operator per condition", - "POSIX does not allow an empty init expression in a for loop", - "POSIX does not allow an empty condition expression in a for loop", - "POSIX does not allow an empty update expression in a for loop", - "POSIX requires the left brace be on the same line as the function header", -#endif -}; #define BC_VEC_INVALID_IDX ((size_t) -1) #define BC_VEC_START_CAP (1 << 5) @@ -891,17 +757,8 @@ struct globals { #define IS_BC (ENABLE_BC && (!ENABLE_DC || applet_name[0] == 'b')) -#if ENABLE_BC -static BcStatus bc_vm_posixError(BcStatus s, const char *file, size_t line, - const char *msg); -#endif - static void bc_vm_info(void); -static const char bc_err_fmt[] = "\nerror: %s\n"; -static const char bc_warn_fmt[] = "\nwarning: %s\n"; -static const char bc_err_line[] = ":%zu\n\n"; - #if ENABLE_BC static const BcLexKeyword bc_lex_kws[20] = { BC_LEX_KW_ENTRY("auto", 4, true), @@ -1151,6 +1008,25 @@ static int bc_error(const char *fmt, ...) return BC_STATUS_FAILURE; } +static int bc_posix_error(const char *fmt, ...) +{ + va_list p; + + if (!(G.flags & (BC_FLAG_S|BC_FLAG_W))) + return BC_STATUS_SUCCESS; + + va_start(p, fmt); + bb_verror_msg(fmt, p, NULL); + va_end(p); + + // Do we treat non-POSIX constructs as errors? + if (!(G.flags & BC_FLAG_S)) + return BC_STATUS_SUCCESS; // no, it's a warning + if (!G.ttyin) + exit(1); + return BC_STATUS_FAILURE; +} + static void bc_vec_grow(BcVec *v, size_t n) { size_t cap = v->cap * 2; @@ -3039,8 +2915,7 @@ static BcStatus bc_lex_identifier(BcLex *l) l->t.t = BC_LEX_KEY_AUTO + (BcLexType) i; if (!bc_lex_kws[i].posix) { - s = bc_vm_posixError(BC_STATUS_POSIX_BAD_KW, l->f, l->line, - bc_lex_kws[i].name); + s = bc_posix_error("POSIX does not allow the following keyword:"); // bc_lex_kws[i].name if (s) return s; } @@ -3054,7 +2929,7 @@ static BcStatus bc_lex_identifier(BcLex *l) if (s) return s; if (l->t.v.len - 1 > 1) - s = bc_vm_posixError(BC_STATUS_POSIX_NAME_LEN, l->f, l->line, buf); + s = bc_posix_error("POSIX only allows one character names; the following is bad:"); // buf return s; } @@ -3155,7 +3030,7 @@ static BcStatus bc_lex_token(BcLex *l) bc_lex_assign(l, BC_LEX_OP_REL_NE, BC_LEX_OP_BOOL_NOT); if (l->t.t == BC_LEX_OP_BOOL_NOT) { - s = bc_vm_posixError(BC_STATUS_POSIX_BOOL, l->f, l->line, "!"); + s = bc_posix_error("POSIX does not allow boolean operators; the following is bad:"); // "!" if (s) return s; } @@ -3170,7 +3045,7 @@ static BcStatus bc_lex_token(BcLex *l) case '#': { - s = bc_vm_posixError(BC_STATUS_POSIX_COMMENT, l->f, l->line, NULL); + s = bc_posix_error("POSIX does not allow '#' script comments"); if (s) return s; bc_lex_lineComment(l); @@ -3189,7 +3064,7 @@ static BcStatus bc_lex_token(BcLex *l) c2 = l->buf[l->i]; if (c2 == '&') { - s = bc_vm_posixError(BC_STATUS_POSIX_BOOL, l->f, l->line, "&&"); + s = bc_posix_error("POSIX does not allow boolean operators; the following is bad:"); // "&&" if (s) return s; ++l->i; @@ -3252,7 +3127,7 @@ static BcStatus bc_lex_token(BcLex *l) s = bc_lex_number(l, c); else { l->t.t = BC_LEX_KEY_LAST; - s = bc_vm_posixError(BC_STATUS_POSIX_DOT, l->f, l->line, NULL); + s = bc_posix_error("POSIX does not allow a period ('.') as a shortcut for the last result"); } break; } @@ -3379,8 +3254,7 @@ static BcStatus bc_lex_token(BcLex *l) c2 = l->buf[l->i]; if (c2 == '|') { - - s = bc_vm_posixError(BC_STATUS_POSIX_BOOL, l->f, l->line, "||"); + s = bc_posix_error("POSIX does not allow boolean operators; the following is bad:"); // "||" if (s) return s; ++l->i; @@ -4106,7 +3980,7 @@ static BcStatus bc_parse_return(BcParse *p) } if (!paren || p->l.t.last != BC_LEX_RPAREN) { - s = bc_vm_posixError(BC_STATUS_POSIX_RET, p->l.f, p->l.line, NULL); + s = bc_posix_error("POSIX requires parentheses around return expressions"); if (s) return s; } @@ -4313,7 +4187,7 @@ static BcStatus bc_parse_for(BcParse *p) if (p->l.t.t != BC_LEX_SCOLON) s = bc_parse_expr(p, 0, bc_parse_next_for); else - s = bc_vm_posixError(BC_STATUS_POSIX_FOR1, p->l.f, p->l.line, NULL); + s = bc_posix_error("POSIX does not allow an empty init expression in a for loop"); if (s) return s; if (p->l.t.t != BC_LEX_SCOLON) return bc_error("bad token"); @@ -4330,7 +4204,7 @@ static BcStatus bc_parse_for(BcParse *p) if (p->l.t.t != BC_LEX_SCOLON) s = bc_parse_expr(p, BC_PARSE_REL, bc_parse_next_for); else - s = bc_vm_posixError(BC_STATUS_POSIX_FOR2, p->l.f, p->l.line, NULL); + s = bc_posix_error("POSIX does not allow an empty condition expression in a for loop"); if (s) return s; if (p->l.t.t != BC_LEX_SCOLON) return bc_error("bad token"); @@ -4351,7 +4225,7 @@ static BcStatus bc_parse_for(BcParse *p) if (p->l.t.t != BC_LEX_RPAREN) s = bc_parse_expr(p, 0, bc_parse_next_rel); else - s = bc_vm_posixError(BC_STATUS_POSIX_FOR3, p->l.f, p->l.line, NULL); + s = bc_posix_error("POSIX does not allow an empty update expression in a for loop"); if (s) return s; @@ -4475,7 +4349,7 @@ static BcStatus bc_parse_func(BcParse *p) if (s) return s; if (p->l.t.t != BC_LEX_LBRACE) - s = bc_vm_posixError(BC_STATUS_POSIX_BRACE, p->l.f, p->l.line, NULL); + s = bc_posix_error("POSIX requires the left brace be on the same line as the function header"); return s; @@ -4999,11 +4873,11 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) ok: if (!(flags & BC_PARSE_REL) && nrelops) { - s = bc_vm_posixError(BC_STATUS_POSIX_REL_POS, p->l.f, p->l.line, NULL); + s = bc_posix_error("POSIX does not allow comparison operators outside if or loops"); if (s) return s; } else if ((flags & BC_PARSE_REL) && nrelops > 1) { - s = bc_vm_posixError(BC_STATUS_POSIX_MULTIREL, p->l.f, p->l.line, NULL); + s = bc_posix_error("POSIX requires exactly one comparison operator per condition"); if (s) return s; } @@ -6575,10 +6449,6 @@ static void bc_program_reset(void) // If !tty, no need to check for ^C: we don't have ^C handler, // we would be killed by a signal and won't reach this place - - fflush_and_check(); // make sure buffered stdout is printed - fputs("ready for more input\n", stderr); - fflush_and_check(); } static BcStatus bc_program_exec(void) @@ -6914,40 +6784,7 @@ static void bc_vm_info(void) , applet_name); } -static BcStatus bc_vm_error(BcStatus s, const char *file, size_t line) -{ - if (!s || s > BC_STATUS_BEFORE_POSIX) return s; - - if (bc_err_msgs[s]) { - fprintf(stderr, bc_err_fmt, bc_err_msgs[s]); - fprintf(stderr, " %s", file); - fprintf(stderr, bc_err_line + 4 * !line, line); - } - -/// - return s * (!G.ttyin || !!strcmp(file, bc_program_stdin_name)); -} - #if ENABLE_BC -static BcStatus bc_vm_posixError(BcStatus s, const char *file, size_t line, - const char *msg) -{ - const char *fmt; - - if (!(G.flags & (BC_FLAG_S|BC_FLAG_W))) return BC_STATUS_SUCCESS; - if (s < BC_STATUS_POSIX_NAME_LEN) return BC_STATUS_SUCCESS; - - fmt = G_posix ? bc_err_fmt : bc_warn_fmt; - fprintf(stderr, fmt, bc_err_msgs[s]); - if (msg) fprintf(stderr, " %s\n", msg); - fprintf(stderr, " %s", file); - fprintf(stderr, bc_err_line + 4 * !line, line); - - if (G.ttyin || !G_posix) - s = BC_STATUS_SUCCESS; - return s; -} - static void bc_vm_envArgs(void) { static const char* const bc_args_env_name = "BC_ENV_ARGS"; @@ -7004,24 +6841,18 @@ static BcStatus bc_vm_process(const char *text) { BcStatus s = bc_parse_text(&G.prs, text); - s = bc_vm_error(s, G.prs.l.f, G.prs.l.line); if (s) return s; while (G.prs.l.t.t != BC_LEX_EOF) { - s = G.prs.parse(&G.prs); - - s = bc_vm_error(s, G.prs.l.f, G.prs.l.line); if (s) return s; } if (BC_PARSE_CAN_EXEC(&G.prs)) { s = bc_program_exec(); fflush_and_check(); - if (s) { + if (s) bc_program_reset(); - s = bc_vm_error(s, G.prs.l.f, 0); - } } return s; @@ -7115,23 +6946,21 @@ static BcStatus bc_vm_stdin(void) bc_vec_concat(&buffer, buf.v); s = bc_vm_process(buffer.v); - if (s) goto err; + if (s) { + fflush_and_check(); + fputs("ready for more input\n", stderr); + } bc_vec_npop(&buffer, buffer.len); } if (str) { - bc_error("string end could not be found"); - s = bc_vm_error(BC_STATUS_FAILURE, G.prs.l.f, - G.prs.l.line); + s = bc_error("string end could not be found"); } else if (comment) { - bc_error("comment end could not be found"); - s = bc_vm_error(BC_STATUS_FAILURE, G.prs.l.f, - G.prs.l.line); + s = bc_error("comment end could not be found"); } -err: bc_vec_free(&buf); bc_vec_free(&buffer); return s; @@ -7148,7 +6977,8 @@ static BcStatus bc_vm_exec(void) bc_lex_file(&G.prs.l, bc_lib_name); s = bc_parse_text(&G.prs, bc_lib); - while (!s && G.prs.l.t.t != BC_LEX_EOF) s = G.prs.parse(&G.prs); + while (!s && G.prs.l.t.t != BC_LEX_EOF) + s = G.prs.parse(&G.prs); if (s) return s; s = bc_program_exec(); @@ -7158,10 +6988,17 @@ static BcStatus bc_vm_exec(void) for (i = 0; !s && i < G.files.len; ++i) s = bc_vm_file(*((char **) bc_vec_item(&G.files, i))); - if (s) return s; + if (s) { + if (!G.tty) + return s; + fflush_and_check(); + fputs("ready for more input\n", stderr); + } - if (IS_BC || !G.files.len) s = bc_vm_stdin(); - if (!s && !BC_PARSE_CAN_EXEC(&G.prs)) s = bc_vm_process(""); + if (IS_BC || !G.files.len) + s = bc_vm_stdin(); + if (!s && !BC_PARSE_CAN_EXEC(&G.prs)) + s = bc_vm_process(""); return s; } -- cgit v1.2.3-55-g6feb From d70d4a023586b9e9835258acda58cdfaf9131e5e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 4 Dec 2018 20:58:40 +0100 Subject: bc: get rid of G.tty and G.flags G.flags == option_mask32 function old new delta bc_args 97 120 +23 dc_main 48 49 +1 bc_main 48 49 +1 bc_error 42 38 -4 bc_posix_error 65 60 -5 bc_read_line 325 317 -8 dc_lex_token 714 705 -9 bc_vm_run 2039 1942 -97 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 3/5 up/down: 25/-123) Total: -98 bytes text data bss dec hex filename 987717 485 7296 995498 f30aa busybox_old 987619 485 7296 995400 f3048 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 38 +++++++++++++++++--------------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index bc5501d91..15089314f 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -730,28 +730,25 @@ static void bc_program_reset(void); #define BC_MAX_VARS ((unsigned long) SIZE_MAX - 1) struct globals { + smallint ttyin; + smallint eof; char sbgn; char send; BcParse prs; BcProgram prog; - unsigned flags; BcVec files; char *env_args; - - smallint tty; - smallint ttyin; - smallint eof; } FIX_ALIASING; #define G (*ptr_to_globals) #define INIT_G() do { \ SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ } while (0) -#define G_posix (ENABLE_BC && (G.flags & BC_FLAG_S)) -#define G_warn (ENABLE_BC && (G.flags & BC_FLAG_W)) -#define G_exreg (ENABLE_DC && (G.flags & BC_FLAG_X)) +#define G_posix (ENABLE_BC && (option_mask32 & BC_FLAG_S)) +#define G_warn (ENABLE_BC && (option_mask32 & BC_FLAG_W)) +#define G_exreg (ENABLE_DC && (option_mask32 & BC_FLAG_X)) #define G_interrupt (ENABLE_FEATURE_BC_SIGNALS ? bb_got_signal : 0) @@ -1012,7 +1009,7 @@ static int bc_posix_error(const char *fmt, ...) { va_list p; - if (!(G.flags & (BC_FLAG_S|BC_FLAG_W))) + if (!(option_mask32 & (BC_FLAG_S|BC_FLAG_W))) return BC_STATUS_SUCCESS; va_start(p, fmt); @@ -1020,7 +1017,7 @@ static int bc_posix_error(const char *fmt, ...) va_end(p); // Do we treat non-POSIX constructs as errors? - if (!(G.flags & BC_FLAG_S)) + if (!(option_mask32 & BC_FLAG_S)) return BC_STATUS_SUCCESS; // no, it's a warning if (!G.ttyin) exit(1); @@ -1262,11 +1259,12 @@ static char* bc_read_file(const char *path) static void bc_args(int argc, char **argv) { + unsigned opts; int i; GETOPT_RESET(); #if ENABLE_FEATURE_BC_LONG_OPTIONS - G.flags = getopt32long(argv, "xwvsqli", + opts = getopt32long(argv, "xwvsqli", "extended-register\0" No_argument "x" "warn\0" No_argument "w" "version\0" No_argument "v" @@ -1276,14 +1274,17 @@ static void bc_args(int argc, char **argv) "interactive\0" No_argument "i" ); #else - G.flags = getopt32(argv, "xwvsqli"); + opts = getopt32(argv, "xwvsqli"); #endif + if (getenv("POSIXLY_CORRECT")) + option_mask32 |= BC_FLAG_S; - if (G.flags & BC_FLAG_V) bc_vm_info(); + if (opts & BC_FLAG_V) bc_vm_info(); // should not be necessary, getopt32() handles this?? //if (argv[optind] && !strcmp(argv[optind], "--")) ++optind; - for (i = optind; i < argc; ++i) bc_vec_push(&G.files, argv + i); + for (i = optind; i < argc; ++i) + bc_vec_push(&G.files, argv + i); } static void bc_num_setToZero(BcNum *n, size_t scale) @@ -6972,7 +6973,7 @@ static BcStatus bc_vm_exec(void) size_t i; #if ENABLE_BC - if (G.flags & BC_FLAG_L) { + if (option_mask32 & BC_FLAG_L) { bc_lex_file(&G.prs.l, bc_lib_name); s = bc_parse_text(&G.prs, bc_lib); @@ -6989,8 +6990,6 @@ static BcStatus bc_vm_exec(void) for (i = 0; !s && i < G.files.len; ++i) s = bc_vm_file(*((char **) bc_vec_item(&G.files, i))); if (s) { - if (!G.tty) - return s; fflush_and_check(); fputs("ready for more input\n", stderr); } @@ -7099,8 +7098,6 @@ static void bc_vm_init(const char *env_len) bc_vec_init(&G.files, sizeof(char *), NULL); if (IS_BC) { - if (getenv("POSIXLY_CORRECT")) - G.flags |= BC_FLAG_S; bc_vm_envArgs(); } @@ -7121,13 +7118,12 @@ static BcStatus bc_vm_run(int argc, char *argv[], bc_args(argc, argv); G.ttyin = isatty(0); - G.tty = G.ttyin || (G.flags & BC_FLAG_I) || isatty(1); if (G.ttyin) { #if ENABLE_FEATURE_BC_SIGNALS signal_no_SA_RESTART_empty_mask(SIGINT, record_signo); #endif - if (!(G.flags & BC_FLAG_Q)) + if (!(option_mask32 & BC_FLAG_Q)) bc_vm_info(); } st = bc_vm_exec(); -- cgit v1.2.3-55-g6feb From 17c5472c5a3eb548e9d06555a8863f83eaee9f26 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 4 Dec 2018 21:21:32 +0100 Subject: bc: switch to SA_RESTART signal handling Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 15089314f..148e340a5 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -7121,7 +7121,23 @@ static BcStatus bc_vm_run(int argc, char *argv[], if (G.ttyin) { #if ENABLE_FEATURE_BC_SIGNALS - signal_no_SA_RESTART_empty_mask(SIGINT, record_signo); + // With SA_RESTART, most system calls will restart + // (IOW: they won't fail with EINTR). + // In particular, this means ^C won't cause + // stdout to get into "error state" if SIGINT hits + // within write() syscall. + // The downside is that ^C while line input is taken + // will only be handled after [Enter] since read() + // from stdin is not interrupted by ^C either, + // it restarts, thus fgetc() does not return on ^C. + signal_SA_RESTART_empty_mask(SIGINT, record_signo); + + // Without SA_RESTART, this exhibits a bug: + // "while (1) print 1" and try ^C-ing it. + // Intermittently, instead of returning to input line, + // you'll get "output error: Interrupted system call" + // and exit. + //signal_no_SA_RESTART_empty_mask(SIGINT, record_signo); #endif if (!(option_mask32 & BC_FLAG_Q)) bc_vm_info(); -- cgit v1.2.3-55-g6feb From d5f7703abb5a0868fd0e9fa3e8c0509ed99ce330 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 4 Dec 2018 21:37:56 +0100 Subject: bc: rewrite "BOOL * EXPR" idiom as if() statement function old new delta bc_program_index 66 64 -2 bc_program_num 1147 1130 -17 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-19) Total: -19 bytes text data bss dec hex filename 987619 485 7296 995400 f3048 busybox_old 987600 485 7296 995381 f3035 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 148e340a5..d208a0cc6 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -2031,8 +2031,9 @@ static void bc_num_parseDecimal(BcNum *n, const char *val) ptr = strchr(val, '.'); - // Explicitly test for NULL here to produce either a 0 or 1. - n->rdx = (size_t)((ptr != NULL) * ((val + len) - (ptr + 1))); + n->rdx = 0; + if (ptr != NULL) + n->rdx = (size_t)((val + len) - (ptr + 1)); if (!zero) { for (i = len - 1; i < len; ++n->len, i -= 1 + (i && val[i - 1] == '.')) @@ -2802,7 +2803,7 @@ static BcStatus bc_lex_number(BcLex *l, char start) c = buf[++i]; } - len = i + 1 * !last_pt - bslashes * 2; + len = i + !last_pt - bslashes * 2; if (len > BC_MAX_NUM) return bc_error("number too long: must be [1, BC_NUM_MAX]"); -- cgit v1.2.3-55-g6feb From 7d62801db938c72ee629ebe133768e41ba3e4667 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 4 Dec 2018 21:46:47 +0100 Subject: bc: create a few common functions function old new delta bc_char_vec_init - 12 +12 bc_vec_pop_all - 8 +8 bc_program_index 64 66 +2 bc_vec_string 64 61 -3 bc_vec_free 27 24 -3 bc_read_line 317 314 -3 bc_program_execStr 564 561 -3 bc_program_exec 4153 4150 -3 bc_program_copyToVar 340 336 -4 bc_parse_create 175 170 -5 dc_lex_token 705 699 -6 bc_program_reset 78 72 -6 bc_lex_number 305 299 -6 bc_program_read 353 343 -10 bc_program_addFunc 225 209 -16 bc_vm_run 1942 1924 -18 bc_parse_reset 181 163 -18 ------------------------------------------------------------------------------ (add/remove: 2/0 grow/shrink: 1/14 up/down: 22/-104) Total: -82 bytes text data bss dec hex filename 987600 485 7296 995381 f3035 busybox_old 987518 485 7296 995299 f2fe3 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 63 +++++++++++++++++++++++++++++++++------------------------- 1 file changed, 36 insertions(+), 27 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index d208a0cc6..e05700fb6 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1041,6 +1041,11 @@ static void bc_vec_init(BcVec *v, size_t esize, BcVecFree dtor) v->v = xmalloc(esize * BC_VEC_START_CAP); } +static void bc_char_vec_init(BcVec *v) +{ + bc_vec_init(v, sizeof(char), NULL); +} + static void bc_vec_expand(BcVec *v, size_t req) { if (v->cap < req) { @@ -1059,6 +1064,11 @@ static void bc_vec_npop(BcVec *v, size_t n) } } +static void bc_vec_pop_all(BcVec *v) +{ + bc_vec_npop(v, v->len); +} + static void bc_vec_push(BcVec *v, const void *data) { if (v->len + 1 > v->cap) bc_vec_grow(v, 1); @@ -1090,7 +1100,7 @@ static void bc_vec_pushAt(BcVec *v, const void *data, size_t idx) static void bc_vec_string(BcVec *v, size_t len, const char *str) { - bc_vec_npop(v, v->len); + bc_vec_pop_all(v); bc_vec_expand(v, len + 1); memcpy(v->v, str, len); v->len = len; @@ -1125,7 +1135,7 @@ static void *bc_vec_item_rev(const BcVec *v, size_t idx) static void bc_vec_free(void *vec) { BcVec *v = (BcVec *) vec; - bc_vec_npop(v, v->len); + bc_vec_pop_all(v); free(v->v); } @@ -1179,7 +1189,7 @@ static BcStatus bc_read_line(BcVec *vec, const char *prompt) char c; bad_chars = 0; - bc_vec_npop(vec, vec->len); + bc_vec_pop_all(vec); fflush_and_check(); #if ENABLE_FEATURE_BC_SIGNALS @@ -2635,7 +2645,7 @@ static BcStatus bc_func_insert(BcFunc *f, char *name, bool var) static void bc_func_init(BcFunc *f) { - bc_vec_init(&f->code, sizeof(char), NULL); + bc_char_vec_init(&f->code); bc_vec_init(&f->autos, sizeof(BcId), bc_id_free); bc_vec_init(&f->labels, sizeof(size_t), NULL); f->nparams = 0; @@ -2662,7 +2672,7 @@ static void bc_array_copy(BcVec *d, const BcVec *s) { size_t i; - bc_vec_npop(d, d->len); + bc_vec_pop_all(d); bc_vec_expand(d, s->cap); d->len = s->len; @@ -2807,7 +2817,7 @@ static BcStatus bc_lex_number(BcLex *l, char start) if (len > BC_MAX_NUM) return bc_error("number too long: must be [1, BC_NUM_MAX]"); - bc_vec_npop(&l->t.v, l->t.v.len); + bc_vec_pop_all(&l->t.v); bc_vec_expand(&l->t.v, len + 1); bc_vec_push(&l->t.v, &start); @@ -2855,7 +2865,7 @@ static BcStatus bc_lex_name(BcLex *l) static void bc_lex_init(BcLex *l, BcLexNext next) { l->next = next; - bc_vec_init(&l->t.v, sizeof(char), NULL); + bc_char_vec_init(&l->t.v); } static void bc_lex_free(BcLex *l) @@ -3296,7 +3306,7 @@ static BcStatus dc_lex_register(BcLex *l) s = bc_lex_name(l); } else { - bc_vec_npop(&l->t.v, l->t.v.len); + bc_vec_pop_all(&l->t.v); bc_vec_pushByte(&l->t.v, l->buf[l->i - 1]); bc_vec_pushByte(&l->t.v, '\0'); l->t.t = BC_LEX_NAME; @@ -3311,7 +3321,7 @@ static BcStatus dc_lex_string(BcLex *l) char c; l->t.t = BC_LEX_STR; - bc_vec_npop(&l->t.v, l->t.v.len); + bc_vec_pop_all(&l->t.v); for (c = l->buf[i]; c != 0 && depth; c = l->buf[++i]) { @@ -3510,11 +3520,10 @@ static BcStatus bc_parse_text(BcParse *p, const char *text) static void bc_parse_reset(BcParse *p) { if (p->fidx != BC_PROG_MAIN) { - p->func->nparams = 0; - bc_vec_npop(&p->func->code, p->func->code.len); - bc_vec_npop(&p->func->autos, p->func->autos.len); - bc_vec_npop(&p->func->labels, p->func->labels.len); + bc_vec_pop_all(&p->func->code); + bc_vec_pop_all(&p->func->autos); + bc_vec_pop_all(&p->func->labels); bc_parse_updateFunc(p, BC_PROG_MAIN); } @@ -3524,9 +3533,9 @@ static void bc_parse_reset(BcParse *p) p->auto_part = (p->nbraces = 0); bc_vec_npop(&p->flags, p->flags.len - 1); - bc_vec_npop(&p->exits, p->exits.len); - bc_vec_npop(&p->conds, p->conds.len); - bc_vec_npop(&p->ops, p->ops.len); + bc_vec_pop_all(&p->exits); + bc_vec_pop_all(&p->conds); + bc_vec_pop_all(&p->ops); bc_program_reset(); } @@ -5350,8 +5359,8 @@ static BcStatus bc_program_read(void) return bc_error("read() call inside of a read() call"); } - bc_vec_npop(&f->code, f->code.len); - bc_vec_init(&buf, sizeof(char), NULL); + bc_vec_pop_all(&f->code); + bc_char_vec_init(&buf); s = bc_read_line(&buf, "read> "); if (s) goto io_err; @@ -6379,7 +6388,7 @@ static BcStatus bc_program_execStr(char *code, size_t *bgn, err: bc_parse_free(&prs); f = bc_vec_item(&G.prog.fns, fidx); - bc_vec_npop(&f->code, f->code.len); + bc_vec_pop_all(&f->code); exit: bc_vec_pop(&G.prog.results); return s; @@ -6425,9 +6434,9 @@ static void bc_program_addFunc(char *name, size_t *idx) // We need to reset these, so the function can be repopulated. func->nparams = 0; - bc_vec_npop(&func->autos, func->autos.len); - bc_vec_npop(&func->code, func->code.len); - bc_vec_npop(&func->labels, func->labels.len); + bc_vec_pop_all(&func->autos); + bc_vec_pop_all(&func->code); + bc_vec_pop_all(&func->labels); } else { bc_func_init(&f); @@ -6443,7 +6452,7 @@ static void bc_program_reset(void) BcInstPtr *ip; bc_vec_npop(&G.prog.stack, G.prog.stack.len - 1); - bc_vec_npop(&G.prog.results, G.prog.results.len); + bc_vec_pop_all(&G.prog.results); f = bc_vec_item(&G.prog.fns, 0); ip = bc_vec_top(&G.prog.stack); @@ -6683,7 +6692,7 @@ static BcStatus bc_program_exec(void) case BC_INST_CLEAR_STACK: { - bc_vec_npop(&G.prog.results, G.prog.results.len); + bc_vec_pop_all(&G.prog.results); break; } @@ -6896,8 +6905,8 @@ static BcStatus bc_vm_stdin(void) G.prog.file = bc_program_stdin_name; bc_lex_file(&G.prs.l, bc_program_stdin_name); - bc_vec_init(&buffer, sizeof(char), NULL); - bc_vec_init(&buf, sizeof(char), NULL); + bc_char_vec_init(&buffer); + bc_char_vec_init(&buf); bc_vec_pushByte(&buffer, '\0'); // This loop is complex because the vm tries not to send any lines that end @@ -6953,7 +6962,7 @@ static BcStatus bc_vm_stdin(void) fputs("ready for more input\n", stderr); } - bc_vec_npop(&buffer, buffer.len); + bc_vec_pop_all(&buffer); } if (str) { -- cgit v1.2.3-55-g6feb From cb9a99f3bb883e319e674a45f906fd3a85c235f7 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 4 Dec 2018 21:54:33 +0100 Subject: bc: drop bc_map_init() macro Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index e05700fb6..7a11e63de 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -189,8 +189,6 @@ typedef struct BcVec { #define bc_vec_pop(v) (bc_vec_npop((v), 1)) #define bc_vec_top(v) (bc_vec_item_rev((v), 0)) -#define bc_map_init(v) (bc_vec_init((v), sizeof(BcId), bc_id_free)) - typedef signed char BcDig; typedef struct BcNum { @@ -7083,16 +7081,16 @@ static void bc_program_init(size_t line_len) bc_num_one(&G.prog.one); bc_vec_init(&G.prog.fns, sizeof(BcFunc), bc_func_free); - bc_map_init(&G.prog.fn_map); + bc_vec_init(&G.prog.fn_map, sizeof(BcId), bc_id_free); bc_program_addFunc(xstrdup("(main)"), &idx); bc_program_addFunc(xstrdup("(read)"), &idx); bc_vec_init(&G.prog.vars, sizeof(BcVec), bc_vec_free); - bc_map_init(&G.prog.var_map); + bc_vec_init(&G.prog.var_map, sizeof(BcId), bc_id_free); bc_vec_init(&G.prog.arrs, sizeof(BcVec), bc_vec_free); - bc_map_init(&G.prog.arr_map); + bc_vec_init(&G.prog.arr_map, sizeof(BcId), bc_id_free); bc_vec_init(&G.prog.strs, sizeof(char *), bc_string_free); bc_vec_init(&G.prog.consts, sizeof(char *), bc_string_free); -- cgit v1.2.3-55-g6feb From 51fb8aa5c132446b188196cd6b3d55ff255461dd Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 5 Dec 2018 00:22:34 +0100 Subject: bc: store library in ASCII, shrink keyword parsing code Also, use ARRAY_SIZE() where appropriate function old new delta bc_lib 1878 1877 -1 bc_program_index 66 64 -2 bc_lex_token 1282 1266 -16 bc_lex_kws 220 160 -60 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/4 up/down: 0/-79) Total: -79 bytes text data bss dec hex filename 987518 485 7296 995299 f2fe3 busybox_old 987440 485 7296 995221 f2f95 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 403 +++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 263 insertions(+), 140 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 7a11e63de..45680c139 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -445,19 +445,21 @@ typedef enum BcLexType { BC_LEX_NAME, BC_LEX_NUMBER, - BC_LEX_KEY_AUTO, + BC_LEX_KEY_1st_keyword, + BC_LEX_KEY_AUTO = BC_LEX_KEY_1st_keyword, BC_LEX_KEY_BREAK, BC_LEX_KEY_CONTINUE, BC_LEX_KEY_DEFINE, BC_LEX_KEY_ELSE, BC_LEX_KEY_FOR, BC_LEX_KEY_HALT, - BC_LEX_KEY_IBASE, + // code uses "type - BC_LEX_KEY_IBASE + BC_INST_IBASE" construct, + BC_LEX_KEY_IBASE, // relative order should match for: BC_INST_IBASE BC_LEX_KEY_IF, - BC_LEX_KEY_LAST, + BC_LEX_KEY_LAST, // relative order should match for: BC_INST_LAST BC_LEX_KEY_LENGTH, BC_LEX_KEY_LIMITS, - BC_LEX_KEY_OBASE, + BC_LEX_KEY_OBASE, // relative order should match for: BC_INST_OBASE BC_LEX_KEY_PRINT, BC_LEX_KEY_QUIT, BC_LEX_KEY_READ, @@ -494,8 +496,68 @@ typedef enum BcLexType { BC_LEX_NQUIT, BC_LEX_SCALE_FACTOR, #endif - } BcLexType; +// must match order of BC_LEX_KEY_foo etc above +#if ENABLE_BC +struct BcLexKeyword { + char name8[8]; +}; +#define BC_LEX_KW_ENTRY(a, b, c) \ + { .name8 = a /*, .len = b, .posix = c*/ } +static const struct BcLexKeyword bc_lex_kws[20] = { + BC_LEX_KW_ENTRY("auto" , 4, 1), // 0 + BC_LEX_KW_ENTRY("break" , 5, 1), // 1 + BC_LEX_KW_ENTRY("continue", 8, 0), // 2 note: this one has no terminating NUL + BC_LEX_KW_ENTRY("define" , 6, 1), // 3 + + BC_LEX_KW_ENTRY("else" , 4, 0), // 4 + BC_LEX_KW_ENTRY("for" , 3, 1), // 5 + BC_LEX_KW_ENTRY("halt" , 4, 0), // 6 + BC_LEX_KW_ENTRY("ibase" , 5, 1), // 7 + + BC_LEX_KW_ENTRY("if" , 2, 1), // 8 + BC_LEX_KW_ENTRY("last" , 4, 0), // 9 + BC_LEX_KW_ENTRY("length" , 6, 1), // 10 + BC_LEX_KW_ENTRY("limits" , 6, 0), // 11 + + BC_LEX_KW_ENTRY("obase" , 5, 1), // 12 + BC_LEX_KW_ENTRY("print" , 5, 0), // 13 + BC_LEX_KW_ENTRY("quit" , 4, 1), // 14 + BC_LEX_KW_ENTRY("read" , 4, 0), // 15 + + BC_LEX_KW_ENTRY("return" , 6, 1), // 16 + BC_LEX_KW_ENTRY("scale" , 5, 1), // 17 + BC_LEX_KW_ENTRY("sqrt" , 4, 1), // 18 + BC_LEX_KW_ENTRY("while" , 5, 1), // 19 +}; +enum { + POSIX_KWORD_MASK = 0 + | (1 << 0) + | (1 << 1) + | (0 << 2) + | (1 << 3) + \ + | (0 << 4) + | (1 << 5) + | (0 << 6) + | (1 << 7) + \ + | (1 << 8) + | (0 << 9) + | (1 << 10) + | (0 << 11) + \ + | (1 << 12) + | (0 << 13) + | (1 << 14) + | (0 << 15) + \ + | (1 << 16) + | (1 << 17) + | (1 << 18) + | (1 << 19) +}; +#endif struct BcLex; typedef BcStatus (*BcLexNext)(struct BcLex *); @@ -611,17 +673,6 @@ typedef struct BcParse { #if ENABLE_BC -typedef struct BcLexKeyword { - const char name[9]; - const char len; - const bool posix; -} BcLexKeyword; - -#define BC_LEX_KW_ENTRY(a, b, c) \ - { \ - .name = a, .len = (b), .posix = (c) \ - } - static BcStatus bc_lex_token(BcLex *l); #define BC_PARSE_TOP_OP(p) (*((BcLexType *) bc_vec_top(&(p)->ops))) @@ -755,28 +806,6 @@ struct globals { static void bc_vm_info(void); #if ENABLE_BC -static const BcLexKeyword bc_lex_kws[20] = { - BC_LEX_KW_ENTRY("auto", 4, true), - BC_LEX_KW_ENTRY("break", 5, true), - BC_LEX_KW_ENTRY("continue", 8, false), - BC_LEX_KW_ENTRY("define", 6, true), - BC_LEX_KW_ENTRY("else", 4, false), - BC_LEX_KW_ENTRY("for", 3, true), - BC_LEX_KW_ENTRY("halt", 4, false), - BC_LEX_KW_ENTRY("ibase", 5, true), - BC_LEX_KW_ENTRY("if", 2, true), - BC_LEX_KW_ENTRY("last", 4, false), - BC_LEX_KW_ENTRY("length", 6, true), - BC_LEX_KW_ENTRY("limits", 6, false), - BC_LEX_KW_ENTRY("obase", 5, true), - BC_LEX_KW_ENTRY("print", 5, false), - BC_LEX_KW_ENTRY("quit", 4, true), - BC_LEX_KW_ENTRY("read", 4, false), - BC_LEX_KW_ENTRY("return", 6, true), - BC_LEX_KW_ENTRY("scale", 5, true), - BC_LEX_KW_ENTRY("sqrt", 4, true), - BC_LEX_KW_ENTRY("while", 5, true), -}; // This is an array that corresponds to token types. An entry is // true if the token is valid in an expression, false otherwise. @@ -825,8 +854,6 @@ static const BcLexType dc_lex_regs[] = { BC_LEX_STORE_PUSH, }; -static const size_t dc_lex_regs_len = sizeof(dc_lex_regs) / sizeof(BcLexType); - static const BcLexType dc_lex_tokens[] = { BC_LEX_OP_MODULUS, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_LPAREN, BC_LEX_INVALID, BC_LEX_OP_MULTIPLY, BC_LEX_OP_PLUS, BC_LEX_INVALID, @@ -892,86 +919,178 @@ static const char bc_program_stdin_name[] = ""; static const char *bc_lib_name = "gen/lib.bc"; static const char bc_lib[] = { - 115,99,97,108,101,61,50,48,10,100,101,102,105,110,101,32,101,40,120,41,123, - 10,9,97,117,116,111,32,98,44,115,44,110,44,114,44,100,44,105,44,112,44,102, - 44,118,10,9,98,61,105,98,97,115,101,10,9,105,98,97,115,101,61,65,10,9,105,102, - 40,120,60,48,41,123,10,9,9,110,61,49,10,9,9,120,61,45,120,10,9,125,10,9,115, - 61,115,99,97,108,101,10,9,114,61,54,43,115,43,48,46,52,52,42,120,10,9,115,99, - 97,108,101,61,115,99,97,108,101,40,120,41,43,49,10,9,119,104,105,108,101,40, - 120,62,49,41,123,10,9,9,100,43,61,49,10,9,9,120,47,61,50,10,9,9,115,99,97,108, - 101,43,61,49,10,9,125,10,9,115,99,97,108,101,61,114,10,9,114,61,120,43,49,10, - 9,112,61,120,10,9,102,61,118,61,49,10,9,102,111,114,40,105,61,50,59,118,33, - 61,48,59,43,43,105,41,123,10,9,9,112,42,61,120,10,9,9,102,42,61,105,10,9,9, - 118,61,112,47,102,10,9,9,114,43,61,118,10,9,125,10,9,119,104,105,108,101,40, - 40,100,45,45,41,33,61,48,41,114,42,61,114,10,9,115,99,97,108,101,61,115,10, - 9,105,98,97,115,101,61,98,10,9,105,102,40,110,33,61,48,41,114,101,116,117,114, - 110,40,49,47,114,41,10,9,114,101,116,117,114,110,40,114,47,49,41,10,125,10, - 100,101,102,105,110,101,32,108,40,120,41,123,10,9,97,117,116,111,32,98,44,115, - 44,114,44,112,44,97,44,113,44,105,44,118,10,9,98,61,105,98,97,115,101,10,9, - 105,98,97,115,101,61,65,10,9,105,102,40,120,60,61,48,41,123,10,9,9,114,61,40, - 49,45,49,48,94,115,99,97,108,101,41,47,49,10,9,9,105,98,97,115,101,61,98,10, - 9,9,114,101,116,117,114,110,40,114,41,10,9,125,10,9,115,61,115,99,97,108,101, - 10,9,115,99,97,108,101,43,61,54,10,9,112,61,50,10,9,119,104,105,108,101,40, - 120,62,61,50,41,123,10,9,9,112,42,61,50,10,9,9,120,61,115,113,114,116,40,120, - 41,10,9,125,10,9,119,104,105,108,101,40,120,60,61,48,46,53,41,123,10,9,9,112, - 42,61,50,10,9,9,120,61,115,113,114,116,40,120,41,10,9,125,10,9,114,61,97,61, - 40,120,45,49,41,47,40,120,43,49,41,10,9,113,61,97,42,97,10,9,118,61,49,10,9, - 102,111,114,40,105,61,51,59,118,33,61,48,59,105,43,61,50,41,123,10,9,9,97,42, - 61,113,10,9,9,118,61,97,47,105,10,9,9,114,43,61,118,10,9,125,10,9,114,42,61, - 112,10,9,115,99,97,108,101,61,115,10,9,105,98,97,115,101,61,98,10,9,114,101, - 116,117,114,110,40,114,47,49,41,10,125,10,100,101,102,105,110,101,32,115,40, - 120,41,123,10,9,97,117,116,111,32,98,44,115,44,114,44,110,44,97,44,113,44,105, - 10,9,98,61,105,98,97,115,101,10,9,105,98,97,115,101,61,65,10,9,115,61,115,99, - 97,108,101,10,9,115,99,97,108,101,61,49,46,49,42,115,43,50,10,9,97,61,97,40, - 49,41,10,9,105,102,40,120,60,48,41,123,10,9,9,110,61,49,10,9,9,120,61,45,120, - 10,9,125,10,9,115,99,97,108,101,61,48,10,9,113,61,40,120,47,97,43,50,41,47, - 52,10,9,120,61,120,45,52,42,113,42,97,10,9,105,102,40,113,37,50,33,61,48,41, - 120,61,45,120,10,9,115,99,97,108,101,61,115,43,50,10,9,114,61,97,61,120,10, - 9,113,61,45,120,42,120,10,9,102,111,114,40,105,61,51,59,97,33,61,48,59,105, - 43,61,50,41,123,10,9,9,97,42,61,113,47,40,105,42,40,105,45,49,41,41,10,9,9, - 114,43,61,97,10,9,125,10,9,115,99,97,108,101,61,115,10,9,105,98,97,115,101, - 61,98,10,9,105,102,40,110,33,61,48,41,114,101,116,117,114,110,40,45,114,47, - 49,41,10,9,114,101,116,117,114,110,40,114,47,49,41,10,125,10,100,101,102,105, - 110,101,32,99,40,120,41,123,10,9,97,117,116,111,32,98,44,115,10,9,98,61,105, - 98,97,115,101,10,9,105,98,97,115,101,61,65,10,9,115,61,115,99,97,108,101,10, - 9,115,99,97,108,101,42,61,49,46,50,10,9,120,61,115,40,50,42,97,40,49,41,43, - 120,41,10,9,115,99,97,108,101,61,115,10,9,105,98,97,115,101,61,98,10,9,114, - 101,116,117,114,110,40,120,47,49,41,10,125,10,100,101,102,105,110,101,32,97, - 40,120,41,123,10,9,97,117,116,111,32,98,44,115,44,114,44,110,44,97,44,109,44, - 116,44,102,44,105,44,117,10,9,98,61,105,98,97,115,101,10,9,105,98,97,115,101, - 61,65,10,9,110,61,49,10,9,105,102,40,120,60,48,41,123,10,9,9,110,61,45,49,10, - 9,9,120,61,45,120,10,9,125,10,9,105,102,40,120,61,61,49,41,123,10,9,9,105,102, - 40,115,99,97,108,101,60,54,53,41,123,10,9,9,9,114,101,116,117,114,110,40,46, - 55,56,53,51,57,56,49,54,51,51,57,55,52,52,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,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,47,110,41,10,9,9,125,10,9,125,10, - 9,105,102,40,120,61,61,46,50,41,123,10,9,9,105,102,40,115,99,97,108,101,60, - 54,53,41,123,10,9,9,9,114,101,116,117,114,110,40,46,49,57,55,51,57,53,53,53, - 57,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,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,56,57,52,48,50,47,110,41,10,9,9,125,10,9,125,10,9,115,61,115,99,97,108,101, - 10,9,105,102,40,120,62,46,50,41,123,10,9,9,115,99,97,108,101,43,61,53,10,9, - 9,97,61,97,40,46,50,41,10,9,125,10,9,115,99,97,108,101,61,115,43,51,10,9,119, - 104,105,108,101,40,120,62,46,50,41,123,10,9,9,109,43,61,49,10,9,9,120,61,40, - 120,45,46,50,41,47,40,49,43,46,50,42,120,41,10,9,125,10,9,114,61,117,61,120, - 10,9,102,61,45,120,42,120,10,9,116,61,49,10,9,102,111,114,40,105,61,51,59,116, - 33,61,48,59,105,43,61,50,41,123,10,9,9,117,42,61,102,10,9,9,116,61,117,47,105, - 10,9,9,114,43,61,116,10,9,125,10,9,115,99,97,108,101,61,115,10,9,105,98,97, - 115,101,61,98,10,9,114,101,116,117,114,110,40,40,109,42,97,43,114,41,47,110, - 41,10,125,10,100,101,102,105,110,101,32,106,40,110,44,120,41,123,10,9,97,117, - 116,111,32,98,44,115,44,111,44,97,44,105,44,118,44,102,10,9,98,61,105,98,97, - 115,101,10,9,105,98,97,115,101,61,65,10,9,115,61,115,99,97,108,101,10,9,115, - 99,97,108,101,61,48,10,9,110,47,61,49,10,9,105,102,40,110,60,48,41,123,10,9, - 9,110,61,45,110,10,9,9,105,102,40,110,37,50,61,61,49,41,111,61,49,10,9,125, - 10,9,97,61,49,10,9,102,111,114,40,105,61,50,59,105,60,61,110,59,43,43,105,41, - 97,42,61,105,10,9,115,99,97,108,101,61,49,46,53,42,115,10,9,97,61,40,120,94, - 110,41,47,50,94,110,47,97,10,9,114,61,118,61,49,10,9,102,61,45,120,42,120,47, - 52,10,9,115,99,97,108,101,61,115,99,97,108,101,43,108,101,110,103,116,104,40, - 97,41,45,115,99,97,108,101,40,97,41,10,9,102,111,114,40,105,61,49,59,118,33, - 61,48,59,43,43,105,41,123,10,9,9,118,61,118,42,102,47,105,47,40,110,43,105, - 41,10,9,9,114,43,61,118,10,9,125,10,9,115,99,97,108,101,61,115,10,9,105,98, - 97,115,101,61,98,10,9,105,102,40,111,33,61,48,41,97,61,45,97,10,9,114,101,116, - 117,114,110,40,97,42,114,47,49,41,10,125,10,0 + "scale=20" +"\ndefine e(x){" +"\n auto b,s,n,r,d,i,p,f,v" +"\n b=ibase" +"\n ibase=A" +"\n if(x<0){" +"\n n=1" +"\n x=-x" +"\n }" +"\n s=scale" +"\n r=6+s+0.44*x" +"\n scale=scale(x)+1" +"\n while(x>1){" +"\n d+=1" +"\n x/=2" +"\n scale+=1" +"\n }" +"\n scale=r" +"\n r=x+1" +"\n p=x" +"\n f=v=1" +"\n for(i=2;v!=0;++i){" +"\n p*=x" +"\n f*=i" +"\n v=p/f" +"\n r+=v" +"\n }" +"\n while((d--)!=0)r*=r" +"\n scale=s" +"\n ibase=b" +"\n if(n!=0)return(1/r)" +"\n return(r/1)" +"\n}" +"\ndefine l(x){" +"\n auto b,s,r,p,a,q,i,v" +"\n b=ibase" +"\n ibase=A" +"\n if(x<=0){" +"\n r=(1-10^scale)/1" +"\n ibase=b" +"\n return(r)" +"\n }" +"\n s=scale" +"\n scale+=6" +"\n p=2" +"\n while(x>=2){" +"\n p*=2" +"\n x=sqrt(x)" +"\n }" +"\n while(x<=0.5){" +"\n p*=2" +"\n x=sqrt(x)" +"\n }" +"\n r=a=(x-1)/(x+1)" +"\n q=a*a" +"\n v=1" +"\n for(i=3;v!=0;i+=2){" +"\n a*=q" +"\n v=a/i" +"\n r+=v" +"\n }" +"\n r*=p" +"\n scale=s" +"\n ibase=b" +"\n return(r/1)" +"\n}" +"\ndefine s(x){" +"\n auto b,s,r,n,a,q,i" +"\n b=ibase" +"\n ibase=A" +"\n s=scale" +"\n scale=1.1*s+2" +"\n a=a(1)" +"\n if(x<0){" +"\n n=1" +"\n x=-x" +"\n }" +"\n scale=0" +"\n q=(x/a+2)/4" +"\n x=x-4*q*a" +"\n if(q%2!=0)x=-x" +"\n scale=s+2" +"\n r=a=x" +"\n q=-x*x" +"\n for(i=3;a!=0;i+=2){" +"\n a*=q/(i*(i-1))" +"\n r+=a" +"\n }" +"\n scale=s" +"\n ibase=b" +"\n if(n!=0)return(-r/1)" +"\n return(r/1)" +"\n}" +"\ndefine c(x){" +"\n auto b,s" +"\n b=ibase" +"\n ibase=A" +"\n s=scale" +"\n scale*=1.2" +"\n x=s(2*a(1)+x)" +"\n scale=s" +"\n ibase=b" +"\n return(x/1)" +"\n}" +"\ndefine a(x){" +"\n auto b,s,r,n,a,m,t,f,i,u" +"\n b=ibase" +"\n ibase=A" +"\n n=1" +"\n if(x<0){" +"\n n=-1" +"\n x=-x" +"\n }" +"\n if(x==1){" +"\n if(scale<65){" +"\n return(.7853981633974483096156608458198757210492923498437764552437361480/n)" +"\n }" +"\n }" +"\n if(x==.2){" +"\n if(scale<65){" +"\n return(.1973955598498807583700497651947902934475851037878521015176889402/n)" +"\n }" +"\n }" +"\n s=scale" +"\n if(x>.2){" +"\n scale+=5" +"\n a=a(.2)" +"\n }" +"\n scale=s+3" +"\n while(x>.2){" +"\n m+=1" +"\n x=(x-.2)/(1+.2*x)" +"\n }" +"\n r=u=x" +"\n f=-x*x" +"\n t=1" +"\n for(i=3;t!=0;i+=2){" +"\n u*=f" +"\n t=u/i" +"\n r+=t" +"\n }" +"\n scale=s" +"\n ibase=b" +"\n return((m*a+r)/n)" +"\n}" +"\ndefine j(n,x){" +"\n auto b,s,o,a,i,v,f" +"\n b=ibase" +"\n ibase=A" +"\n s=scale" +"\n scale=0" +"\n n/=1" +"\n if(n<0){" +"\n n=-n" +"\n if(n%2==1)o=1" +"\n }" +"\n a=1" +"\n for(i=2;i<=n;++i)a*=i" +"\n scale=1.5*s" +"\n a=(x^n)/2^n/a" +"\n r=v=1" +"\n f=-x*x/4" +"\n scale=scale+length(a)-scale(a)" +"\n for(i=1;v!=0;++i){" +"\n v=v*f/i/(n+i)" +"\n r+=v" +"\n }" +"\n scale=s" +"\n ibase=b" +"\n if(o!=0)a=-a" +"\n return(a*r/1)" +"\n}" }; #endif // ENABLE_BC @@ -2913,32 +3032,35 @@ static BcStatus bc_lex_text(BcLex *l, const char *text) static BcStatus bc_lex_identifier(BcLex *l) { BcStatus s; - size_t i; + unsigned i; const char *buf = l->buf + l->i - 1; - for (i = 0; i < sizeof(bc_lex_kws) / sizeof(bc_lex_kws[0]); ++i) { - - unsigned long len = (unsigned long) bc_lex_kws[i].len; - - if (strncmp(buf, bc_lex_kws[i].name, len) == 0) { - - l->t.t = BC_LEX_KEY_AUTO + (BcLexType) i; - - if (!bc_lex_kws[i].posix) { - s = bc_posix_error("POSIX does not allow the following keyword:"); // bc_lex_kws[i].name - if (s) return s; - } - - // We minus 1 because the index has already been incremented. - l->i += len - 1; - return BC_STATUS_SUCCESS; + for (i = 0; i < ARRAY_SIZE(bc_lex_kws); ++i) { + const char *keyword8 = bc_lex_kws[i].name8; + unsigned j = 0; + while (buf[j] != '\0' && buf[j] == keyword8[j]) { + j++; + if (j == 8) goto match; + } + if (keyword8[j] != '\0') + continue; + match: + // buf starts with keyword bc_lex_kws[i] + l->t.t = BC_LEX_KEY_1st_keyword + i; + if ((1 << i) & POSIX_KWORD_MASK) { + s = bc_posix_error("POSIX does not allow the following keyword:"); // bc_lex_kws[i].name8 + if (s) return s; } + + // We minus 1 because the index has already been incremented. + l->i += j - 1; + return BC_STATUS_SUCCESS; } s = bc_lex_name(l); if (s) return s; - if (l->t.v.len - 1 > 1) + if (l->t.v.len > 2) s = bc_posix_error("POSIX only allows one character names; the following is bad:"); // buf return s; @@ -3351,8 +3473,9 @@ static BcStatus dc_lex_token(BcLex *l) char c = l->buf[l->i++], c2; size_t i; - for (i = 0; i < dc_lex_regs_len; ++i) { - if (l->t.last == dc_lex_regs[i]) return dc_lex_register(l); + for (i = 0; i < ARRAY_SIZE(dc_lex_regs); ++i) { + if (l->t.last == dc_lex_regs[i]) + return dc_lex_register(l); } if (c >= '%' && c <= '~' && -- cgit v1.2.3-55-g6feb From 68cc0a676eeceffae84a91b73895b5c4d72c2021 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 5 Dec 2018 00:35:49 +0100 Subject: bc: remove tabs from internal library function old new delta bc_lib 1877 1674 -203 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 344 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 172 insertions(+), 172 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 45680c139..866fa3027 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -919,178 +919,178 @@ static const char bc_program_stdin_name[] = ""; static const char *bc_lib_name = "gen/lib.bc"; static const char bc_lib[] = { - "scale=20" -"\ndefine e(x){" -"\n auto b,s,n,r,d,i,p,f,v" -"\n b=ibase" -"\n ibase=A" -"\n if(x<0){" -"\n n=1" -"\n x=-x" -"\n }" -"\n s=scale" -"\n r=6+s+0.44*x" -"\n scale=scale(x)+1" -"\n while(x>1){" -"\n d+=1" -"\n x/=2" -"\n scale+=1" -"\n }" -"\n scale=r" -"\n r=x+1" -"\n p=x" -"\n f=v=1" -"\n for(i=2;v!=0;++i){" -"\n p*=x" -"\n f*=i" -"\n v=p/f" -"\n r+=v" -"\n }" -"\n while((d--)!=0)r*=r" -"\n scale=s" -"\n ibase=b" -"\n if(n!=0)return(1/r)" -"\n return(r/1)" -"\n}" -"\ndefine l(x){" -"\n auto b,s,r,p,a,q,i,v" -"\n b=ibase" -"\n ibase=A" -"\n if(x<=0){" -"\n r=(1-10^scale)/1" -"\n ibase=b" -"\n return(r)" -"\n }" -"\n s=scale" -"\n scale+=6" -"\n p=2" -"\n while(x>=2){" -"\n p*=2" -"\n x=sqrt(x)" -"\n }" -"\n while(x<=0.5){" -"\n p*=2" -"\n x=sqrt(x)" -"\n }" -"\n r=a=(x-1)/(x+1)" -"\n q=a*a" -"\n v=1" -"\n for(i=3;v!=0;i+=2){" -"\n a*=q" -"\n v=a/i" -"\n r+=v" -"\n }" -"\n r*=p" -"\n scale=s" -"\n ibase=b" -"\n return(r/1)" -"\n}" -"\ndefine s(x){" -"\n auto b,s,r,n,a,q,i" -"\n b=ibase" -"\n ibase=A" -"\n s=scale" -"\n scale=1.1*s+2" -"\n a=a(1)" -"\n if(x<0){" -"\n n=1" -"\n x=-x" -"\n }" -"\n scale=0" -"\n q=(x/a+2)/4" -"\n x=x-4*q*a" -"\n if(q%2!=0)x=-x" -"\n scale=s+2" -"\n r=a=x" -"\n q=-x*x" -"\n for(i=3;a!=0;i+=2){" -"\n a*=q/(i*(i-1))" -"\n r+=a" -"\n }" -"\n scale=s" -"\n ibase=b" -"\n if(n!=0)return(-r/1)" -"\n return(r/1)" -"\n}" -"\ndefine c(x){" -"\n auto b,s" -"\n b=ibase" -"\n ibase=A" -"\n s=scale" -"\n scale*=1.2" -"\n x=s(2*a(1)+x)" -"\n scale=s" -"\n ibase=b" -"\n return(x/1)" -"\n}" -"\ndefine a(x){" -"\n auto b,s,r,n,a,m,t,f,i,u" -"\n b=ibase" -"\n ibase=A" -"\n n=1" -"\n if(x<0){" -"\n n=-1" -"\n x=-x" -"\n }" -"\n if(x==1){" -"\n if(scale<65){" -"\n return(.7853981633974483096156608458198757210492923498437764552437361480/n)" -"\n }" -"\n }" -"\n if(x==.2){" -"\n if(scale<65){" -"\n return(.1973955598498807583700497651947902934475851037878521015176889402/n)" -"\n }" -"\n }" -"\n s=scale" -"\n if(x>.2){" -"\n scale+=5" -"\n a=a(.2)" -"\n }" -"\n scale=s+3" -"\n while(x>.2){" -"\n m+=1" -"\n x=(x-.2)/(1+.2*x)" -"\n }" -"\n r=u=x" -"\n f=-x*x" -"\n t=1" -"\n for(i=3;t!=0;i+=2){" -"\n u*=f" -"\n t=u/i" -"\n r+=t" -"\n }" -"\n scale=s" -"\n ibase=b" -"\n return((m*a+r)/n)" -"\n}" -"\ndefine j(n,x){" -"\n auto b,s,o,a,i,v,f" -"\n b=ibase" -"\n ibase=A" -"\n s=scale" -"\n scale=0" -"\n n/=1" -"\n if(n<0){" -"\n n=-n" -"\n if(n%2==1)o=1" -"\n }" -"\n a=1" -"\n for(i=2;i<=n;++i)a*=i" -"\n scale=1.5*s" -"\n a=(x^n)/2^n/a" -"\n r=v=1" -"\n f=-x*x/4" -"\n scale=scale+length(a)-scale(a)" -"\n for(i=1;v!=0;++i){" -"\n v=v*f/i/(n+i)" -"\n r+=v" -"\n }" -"\n scale=s" -"\n ibase=b" -"\n if(o!=0)a=-a" -"\n return(a*r/1)" -"\n}" + "scale=20" +"\n" "define e(x){" +"\n" "auto b,s,n,r,d,i,p,f,v" +"\n" "b=ibase" +"\n" "ibase=A" +"\n" "if(x<0){" +"\n" "n=1" +"\n" "x=-x" +"\n" "}" +"\n" "s=scale" +"\n" "r=6+s+0.44*x" +"\n" "scale=scale(x)+1" +"\n" "while(x>1){" +"\n" "d+=1" +"\n" "x/=2" +"\n" "scale+=1" +"\n" "}" +"\n" "scale=r" +"\n" "r=x+1" +"\n" "p=x" +"\n" "f=v=1" +"\n" "for(i=2;v!=0;++i){" +"\n" "p*=x" +"\n" "f*=i" +"\n" "v=p/f" +"\n" "r+=v" +"\n" "}" +"\n" "while((d--)!=0)r*=r" +"\n" "scale=s" +"\n" "ibase=b" +"\n" "if(n!=0)return(1/r)" +"\n" "return(r/1)" +"\n" "}" +"\n" "define l(x){" +"\n" "auto b,s,r,p,a,q,i,v" +"\n" "b=ibase" +"\n" "ibase=A" +"\n" "if(x<=0){" +"\n" "r=(1-10^scale)/1" +"\n" "ibase=b" +"\n" "return(r)" +"\n" "}" +"\n" "s=scale" +"\n" "scale+=6" +"\n" "p=2" +"\n" "while(x>=2){" +"\n" "p*=2" +"\n" "x=sqrt(x)" +"\n" "}" +"\n" "while(x<=0.5){" +"\n" "p*=2" +"\n" "x=sqrt(x)" +"\n" "}" +"\n" "r=a=(x-1)/(x+1)" +"\n" "q=a*a" +"\n" "v=1" +"\n" "for(i=3;v!=0;i+=2){" +"\n" "a*=q" +"\n" "v=a/i" +"\n" "r+=v" +"\n" "}" +"\n" "r*=p" +"\n" "scale=s" +"\n" "ibase=b" +"\n" "return(r/1)" +"\n" "}" +"\n" "define s(x){" +"\n" "auto b,s,r,n,a,q,i" +"\n" "b=ibase" +"\n" "ibase=A" +"\n" "s=scale" +"\n" "scale=1.1*s+2" +"\n" "a=a(1)" +"\n" "if(x<0){" +"\n" "n=1" +"\n" "x=-x" +"\n" "}" +"\n" "scale=0" +"\n" "q=(x/a+2)/4" +"\n" "x=x-4*q*a" +"\n" "if(q%2!=0)x=-x" +"\n" "scale=s+2" +"\n" "r=a=x" +"\n" "q=-x*x" +"\n" "for(i=3;a!=0;i+=2){" +"\n" "a*=q/(i*(i-1))" +"\n" "r+=a" +"\n" "}" +"\n" "scale=s" +"\n" "ibase=b" +"\n" "if(n!=0)return(-r/1)" +"\n" "return(r/1)" +"\n" "}" +"\n" "define c(x){" +"\n" "auto b,s" +"\n" "b=ibase" +"\n" "ibase=A" +"\n" "s=scale" +"\n" "scale*=1.2" +"\n" "x=s(2*a(1)+x)" +"\n" "scale=s" +"\n" "ibase=b" +"\n" "return(x/1)" +"\n" "}" +"\n" "define a(x){" +"\n" "auto b,s,r,n,a,m,t,f,i,u" +"\n" "b=ibase" +"\n" "ibase=A" +"\n" "n=1" +"\n" "if(x<0){" +"\n" "n=-1" +"\n" "x=-x" +"\n" "}" +"\n" "if(x==1){" +"\n" "if(scale<65){" +"\n" "return(.7853981633974483096156608458198757210492923498437764552437361480/n)" +"\n" "}" +"\n" "}" +"\n" "if(x==.2){" +"\n" "if(scale<65){" +"\n" "return(.1973955598498807583700497651947902934475851037878521015176889402/n)" +"\n" "}" +"\n" "}" +"\n" "s=scale" +"\n" "if(x>.2){" +"\n" "scale+=5" +"\n" "a=a(.2)" +"\n" "}" +"\n" "scale=s+3" +"\n" "while(x>.2){" +"\n" "m+=1" +"\n" "x=(x-.2)/(1+.2*x)" +"\n" "}" +"\n" "r=u=x" +"\n" "f=-x*x" +"\n" "t=1" +"\n" "for(i=3;t!=0;i+=2){" +"\n" "u*=f" +"\n" "t=u/i" +"\n" "r+=t" +"\n" "}" +"\n" "scale=s" +"\n" "ibase=b" +"\n" "return((m*a+r)/n)" +"\n" "}" +"\n" "define j(n,x){" +"\n" "auto b,s,o,a,i,v,f" +"\n" "b=ibase" +"\n" "ibase=A" +"\n" "s=scale" +"\n" "scale=0" +"\n" "n/=1" +"\n" "if(n<0){" +"\n" "n=-n" +"\n" "if(n%2==1)o=1" +"\n" "}" +"\n" "a=1" +"\n" "for(i=2;i<=n;++i)a*=i" +"\n" "scale=1.5*s" +"\n" "a=(x^n)/2^n/a" +"\n" "r=v=1" +"\n" "f=-x*x/4" +"\n" "scale=scale+length(a)-scale(a)" +"\n" "for(i=1;v!=0;++i){" +"\n" "v=v*f/i/(n+i)" +"\n" "r+=v" +"\n" "}" +"\n" "scale=s" +"\n" "ibase=b" +"\n" "if(o!=0)a=-a" +"\n" "return(a*r/1)" +"\n" "}" }; #endif // ENABLE_BC -- cgit v1.2.3-55-g6feb From f359e004b0ce4a5ac361f553c13e876123fd4ebb Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 5 Dec 2018 01:21:59 +0100 Subject: bc: make 2^1000000 interruptible faster Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/miscutils/bc.c b/miscutils/bc.c index 866fa3027..b392b05a3 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -2039,6 +2039,11 @@ static BcStatus bc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) powrdx <<= 1; s = bc_num_mul(©, ©, ©, powrdx); if (s) goto err; + // It is too slow to handle ^C only after entire "2^1000000" completes + if (G_interrupt) { + s = BC_STATUS_FAILURE; + goto err; + } } bc_num_copy(c, ©); @@ -2054,6 +2059,11 @@ static BcStatus bc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) s = bc_num_mul(c, ©, c, resrdx); if (s) goto err; } + // It is too slow to handle ^C only after entire "2^1000000" completes + if (G_interrupt) { + s = BC_STATUS_FAILURE; + goto err; + } } if (neg) { -- cgit v1.2.3-55-g6feb From 24fb2cd62fcc2c422692df4138e0f1e333a52c42 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 5 Dec 2018 16:03:46 +0100 Subject: bc: shrink error handling code by enabling tail-call optimization function old new delta bc_posix_error_fmt - 60 +60 bc_error_fmt - 38 +38 bc_error_bad_character - 17 +17 bc_parse_auto 302 313 +11 bc_num_ulong 93 103 +10 bc_error_variable_is_wrong_type - 10 +10 bc_error_stack_has_too_few_elements - 10 +10 bc_error_nested_read_call - 10 +10 bc_error_bad_token - 10 +10 bc_error_bad_expression - 10 +10 bc_num_d 561 564 +3 bc_program_assign 484 486 +2 dc_parse_parse 60 59 -1 bc_program_num 1130 1129 -1 bc_program_call 367 366 -1 bc_parse_stmt 2277 2276 -1 bc_lex_number 299 298 -1 bc_lex_name 91 90 -1 bc_func_insert 98 97 -1 bc_num_shift 74 72 -2 bc_vm_run 1924 1921 -3 bc_parse_endBody 424 420 -4 bc_lex_next 81 77 -4 bc_program_read 343 338 -5 bc_program_asciify 469 464 -5 bc_program_pushVar 221 215 -6 bc_program_print 784 778 -6 bc_program_prep 99 93 -6 bc_program_assignStr 167 161 -6 bc_parse_else 143 137 -6 bc_parse_body 124 118 -6 dc_parse_register 61 53 -8 dc_lex_token 699 691 -8 bc_program_modexp 756 746 -10 bc_parse_name 593 581 -12 dc_parse_expr 775 762 -13 bc_program_copyToVar 336 323 -13 bc_program_binOpPrep 324 311 -13 bc_program_execStr 561 543 -18 bc_program_exec 4150 4132 -18 bc_parse_parse 483 464 -19 bc_error 38 14 -24 bc_lex_token 1266 1237 -29 bc_posix_error 60 14 -46 bc_parse_expr 2194 2146 -48 ------------------------------------------------------------------------------ (add/remove: 8/0 grow/shrink: 4/33 up/down: 191/-345) Total: -154 bytes text data bss dec hex filename 987226 485 7296 995007 f2ebf busybox_old 987072 485 7296 994853 f2e25 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 233 +++++++++++++++++++++++++++++++++------------------------ 1 file changed, 136 insertions(+), 97 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index b392b05a3..6f2606c79 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1110,7 +1110,7 @@ static void quit(void) exit(0); } -static int bc_error(const char *fmt, ...) +static NOINLINE int bc_error_fmt(const char *fmt, ...) { va_list p; @@ -1122,12 +1122,13 @@ static int bc_error(const char *fmt, ...) return BC_STATUS_FAILURE; } -static int bc_posix_error(const char *fmt, ...) +static NOINLINE int bc_posix_error_fmt(const char *fmt, ...) { va_list p; + // Are non-POSIX constructs totally ok? if (!(option_mask32 & (BC_FLAG_S|BC_FLAG_W))) - return BC_STATUS_SUCCESS; + return BC_STATUS_SUCCESS; // yes va_start(p, fmt); bb_verror_msg(fmt, p, NULL); @@ -1141,6 +1142,44 @@ static int bc_posix_error(const char *fmt, ...) return BC_STATUS_FAILURE; } +// We use error functions with "return bc_error(FMT[, PARAMS])" idiom. +// This idiom begs for tail-call optimization, but for it to work, +// function must not have calller-cleaned parameters on stack. +// Unfortunately, vararg functions do exactly that on most arches. +// Thus, these shims for the cases when we have no PARAMS: +static int bc_error(const char *msg) +{ + return bc_error_fmt("%s", msg); +} +static int bc_posix_error(const char *msg) +{ + return bc_posix_error_fmt("%s", msg); +} +static int bc_error_bad_character(char c) +{ + return bc_error_fmt("bad character '%c'", c); +} +static int bc_error_bad_expression(void) +{ + return bc_error("bad expression"); +} +static int bc_error_bad_token(void) +{ + return bc_error("bad token"); +} +static int bc_error_stack_has_too_few_elements(void) +{ + return bc_error("stack has too few elements"); +} +static int bc_error_variable_is_wrong_type(void) +{ + return bc_error("variable is wrong type"); +} +static int bc_error_nested_read_call(void) +{ + return bc_error("read() call inside of a read() call"); +} + static void bc_vec_grow(BcVec *v, size_t n) { size_t cap = v->cap * 2; @@ -1349,7 +1388,7 @@ static BcStatus bc_read_line(BcVec *vec, const char *prompt) || i > 0x7e ) { // Bad chars on this line, ignore entire line - bc_error("illegal character 0x%02x", i); + bc_error_fmt("illegal character 0x%02x", i); bad_chars = 1; } c = (char) i; @@ -3214,7 +3253,7 @@ static BcStatus bc_lex_token(BcLex *l) } else { l->t.t = BC_LEX_INVALID; - s = bc_error("bad character '%c'", '&'); + s = bc_error_bad_character('&'); } break; @@ -3343,7 +3382,7 @@ static BcStatus bc_lex_token(BcLex *l) ++l->i; } else - s = bc_error("bad character '%c'", c); + s = bc_error_bad_character(c); break; } @@ -3404,7 +3443,7 @@ static BcStatus bc_lex_token(BcLex *l) } else { l->t.t = BC_LEX_INVALID; - s = bc_error("bad character '%c'", c); + s = bc_error_bad_character(c); } break; @@ -3413,7 +3452,7 @@ static BcStatus bc_lex_token(BcLex *l) default: { l->t.t = BC_LEX_INVALID; - s = bc_error("bad character '%c'", c); + s = bc_error_bad_character(c); break; } } @@ -3526,7 +3565,7 @@ static BcStatus dc_lex_token(BcLex *l) else if (c2 == '>') l->t.t = BC_LEX_OP_REL_GE; else - return bc_error("bad character '%c'", c); + return bc_error_bad_character(c); ++l->i; break; @@ -3543,7 +3582,7 @@ static BcStatus dc_lex_token(BcLex *l) if (isdigit(l->buf[l->i])) s = bc_lex_number(l, c); else - s = bc_error("bad character '%c'", c); + s = bc_error_bad_character(c); break; } @@ -3577,7 +3616,7 @@ static BcStatus dc_lex_token(BcLex *l) default: { l->t.t = BC_LEX_INVALID; - s = bc_error("bad character '%c'", c); + s = bc_error_bad_character(c); break; } } @@ -3733,7 +3772,7 @@ static BcStatus bc_parse_rightParen(BcParse *p, size_t ops_bgn, size_t *nexs) BcLexType top; if (p->ops.len <= ops_bgn) - return bc_error("bad expression"); + return bc_error_bad_expression(); top = BC_PARSE_TOP_OP(p); while (top != BC_LEX_LPAREN) { @@ -3744,7 +3783,7 @@ static BcStatus bc_parse_rightParen(BcParse *p, size_t ops_bgn, size_t *nexs) *nexs -= top != BC_LEX_OP_BOOL_NOT && top != BC_LEX_NEG; if (p->ops.len <= ops_bgn) - return bc_error("bad expression"); + return bc_error_bad_expression(); top = BC_PARSE_TOP_OP(p); } @@ -3775,7 +3814,7 @@ static BcStatus bc_parse_params(BcParse *p, uint8_t flags) } } - if (comma) return bc_error("bad token"); + if (comma) return bc_error_bad_token(); bc_parse_push(p, BC_INST_CALL); bc_parse_pushIndex(p, nparams); @@ -3794,7 +3833,7 @@ static BcStatus bc_parse_call(BcParse *p, char *name, uint8_t flags) if (s) goto err; if (p->l.t.t != BC_LEX_RPAREN) { - s = bc_error("bad token"); + s = bc_error_bad_token(); goto err; } @@ -3836,7 +3875,7 @@ static BcStatus bc_parse_name(BcParse *p, BcInst *type, uint8_t flags) if (p->l.t.t == BC_LEX_RBRACKET) { if (!(flags & BC_PARSE_ARRAY)) { - s = bc_error("bad expression"); + s = bc_error_bad_expression(); goto err; } @@ -3859,7 +3898,7 @@ static BcStatus bc_parse_name(BcParse *p, BcInst *type, uint8_t flags) else if (p->l.t.t == BC_LEX_LPAREN) { if (flags & BC_PARSE_NOCALL) { - s = bc_error("bad token"); + s = bc_error_bad_token(); goto err; } @@ -3885,11 +3924,11 @@ static BcStatus bc_parse_read(BcParse *p) s = bc_lex_next(&p->l); if (s) return s; - if (p->l.t.t != BC_LEX_LPAREN) return bc_error("bad token"); + if (p->l.t.t != BC_LEX_LPAREN) return bc_error_bad_token(); s = bc_lex_next(&p->l); if (s) return s; - if (p->l.t.t != BC_LEX_RPAREN) return bc_error("bad token"); + if (p->l.t.t != BC_LEX_RPAREN) return bc_error_bad_token(); bc_parse_push(p, BC_INST_READ); @@ -3903,7 +3942,7 @@ static BcStatus bc_parse_builtin(BcParse *p, BcLexType type, uint8_t flags, s = bc_lex_next(&p->l); if (s) return s; - if (p->l.t.t != BC_LEX_LPAREN) return bc_error("bad token"); + if (p->l.t.t != BC_LEX_LPAREN) return bc_error_bad_token(); flags = (flags & ~(BC_PARSE_PRINT | BC_PARSE_REL)) | BC_PARSE_ARRAY; @@ -3913,7 +3952,7 @@ static BcStatus bc_parse_builtin(BcParse *p, BcLexType type, uint8_t flags, s = bc_parse_expr(p, flags, bc_parse_next_rel); if (s) return s; - if (p->l.t.t != BC_LEX_RPAREN) return bc_error("bad token"); + if (p->l.t.t != BC_LEX_RPAREN) return bc_error_bad_token(); *prev = (type == BC_LEX_KEY_LENGTH) ? BC_INST_LENGTH : BC_INST_SQRT; bc_parse_push(p, *prev); @@ -3942,7 +3981,7 @@ static BcStatus bc_parse_scale(BcParse *p, BcInst *type, uint8_t flags) s = bc_parse_expr(p, flags, bc_parse_next_rel); if (s) return s; - if (p->l.t.t != BC_LEX_RPAREN) return bc_error("bad token"); + if (p->l.t.t != BC_LEX_RPAREN) return bc_error_bad_token(); bc_parse_push(p, BC_INST_SCALE_FUNC); return bc_lex_next(&p->l); @@ -3999,7 +4038,7 @@ static BcStatus bc_parse_incdec(BcParse *p, BcInst *prev, bool *paren_expr, s = bc_lex_next(&p->l); if (s) return s; if (p->l.t.t == BC_LEX_LPAREN) - s = bc_error("bad token"); + s = bc_error_bad_token(); else bc_parse_push(p, BC_INST_SCALE); break; @@ -4007,7 +4046,7 @@ static BcStatus bc_parse_incdec(BcParse *p, BcInst *prev, bool *paren_expr, default: { - s = bc_error("bad token"); + s = bc_error_bad_token(); break; } } @@ -4088,7 +4127,7 @@ static BcStatus bc_parse_print(BcParse *p) } if (s) return s; - if (comma) return bc_error("bad token"); + if (comma) return bc_error_bad_token(); return bc_lex_next(&p->l); } @@ -4099,7 +4138,7 @@ static BcStatus bc_parse_return(BcParse *p) BcLexType t; bool paren; - if (!BC_PARSE_FUNC(p)) return bc_error("bad token"); + if (!BC_PARSE_FUNC(p)) return bc_error_bad_token(); s = bc_lex_next(&p->l); if (s) return s; @@ -4137,18 +4176,18 @@ static BcStatus bc_parse_endBody(BcParse *p, bool brace) BcStatus s = BC_STATUS_SUCCESS; if (p->flags.len <= 1 || (brace && p->nbraces == 0)) - return bc_error("bad token"); + return bc_error_bad_token(); if (brace) { if (p->l.t.t == BC_LEX_RBRACE) { - if (!p->nbraces) return bc_error("bad token"); + if (!p->nbraces) return bc_error_bad_token(); --p->nbraces; s = bc_lex_next(&p->l); if (s) return s; } else - return bc_error("bad token"); + return bc_error_bad_token(); } if (BC_PARSE_IF(p)) { @@ -4234,13 +4273,13 @@ static BcStatus bc_parse_if(BcParse *p) s = bc_lex_next(&p->l); if (s) return s; - if (p->l.t.t != BC_LEX_LPAREN) return bc_error("bad token"); + if (p->l.t.t != BC_LEX_LPAREN) return bc_error_bad_token(); s = bc_lex_next(&p->l); if (s) return s; s = bc_parse_expr(p, BC_PARSE_REL, bc_parse_next_rel); if (s) return s; - if (p->l.t.t != BC_LEX_RPAREN) return bc_error("bad token"); + if (p->l.t.t != BC_LEX_RPAREN) return bc_error_bad_token(); s = bc_lex_next(&p->l); if (s) return s; @@ -4261,7 +4300,7 @@ static BcStatus bc_parse_else(BcParse *p) { BcInstPtr ip; - if (!BC_PARSE_IF_END(p)) return bc_error("bad token"); + if (!BC_PARSE_IF_END(p)) return bc_error_bad_token(); ip.idx = p->func->labels.len; ip.func = ip.len = 0; @@ -4285,7 +4324,7 @@ static BcStatus bc_parse_while(BcParse *p) s = bc_lex_next(&p->l); if (s) return s; - if (p->l.t.t != BC_LEX_LPAREN) return bc_error("bad token"); + if (p->l.t.t != BC_LEX_LPAREN) return bc_error_bad_token(); s = bc_lex_next(&p->l); if (s) return s; @@ -4303,7 +4342,7 @@ static BcStatus bc_parse_while(BcParse *p) s = bc_parse_expr(p, BC_PARSE_REL, bc_parse_next_rel); if (s) return s; - if (p->l.t.t != BC_LEX_RPAREN) return bc_error("bad token"); + if (p->l.t.t != BC_LEX_RPAREN) return bc_error_bad_token(); s = bc_lex_next(&p->l); if (s) return s; @@ -4322,7 +4361,7 @@ static BcStatus bc_parse_for(BcParse *p) s = bc_lex_next(&p->l); if (s) return s; - if (p->l.t.t != BC_LEX_LPAREN) return bc_error("bad token"); + if (p->l.t.t != BC_LEX_LPAREN) return bc_error_bad_token(); s = bc_lex_next(&p->l); if (s) return s; @@ -4332,7 +4371,7 @@ static BcStatus bc_parse_for(BcParse *p) s = bc_posix_error("POSIX does not allow an empty init expression in a for loop"); if (s) return s; - if (p->l.t.t != BC_LEX_SCOLON) return bc_error("bad token"); + if (p->l.t.t != BC_LEX_SCOLON) return bc_error_bad_token(); s = bc_lex_next(&p->l); if (s) return s; @@ -4349,7 +4388,7 @@ static BcStatus bc_parse_for(BcParse *p) s = bc_posix_error("POSIX does not allow an empty condition expression in a for loop"); if (s) return s; - if (p->l.t.t != BC_LEX_SCOLON) return bc_error("bad token"); + if (p->l.t.t != BC_LEX_SCOLON) return bc_error_bad_token(); s = bc_lex_next(&p->l); if (s) return s; @@ -4371,7 +4410,7 @@ static BcStatus bc_parse_for(BcParse *p) if (s) return s; - if (p->l.t.t != BC_LEX_RPAREN) return bc_error("bad token"); + if (p->l.t.t != BC_LEX_RPAREN) return bc_error_bad_token(); bc_parse_push(p, BC_INST_JUMP); bc_parse_pushIndex(p, cond_idx); bc_vec_push(&p->func->labels, &p->func->code.len); @@ -4394,17 +4433,17 @@ static BcStatus bc_parse_loopExit(BcParse *p, BcLexType type) size_t i; BcInstPtr *ip; - if (!BC_PARSE_LOOP(p)) return bc_error("bad token"); + if (!BC_PARSE_LOOP(p)) return bc_error_bad_token(); if (type == BC_LEX_KEY_BREAK) { - if (p->exits.len == 0) return bc_error("bad token"); + if (p->exits.len == 0) return bc_error_bad_token(); i = p->exits.len - 1; ip = bc_vec_item(&p->exits, i); while (!ip->func && i < p->exits.len) ip = bc_vec_item(&p->exits, i--); - if (i >= p->exits.len && !ip->func) return bc_error("bad token"); + if (i >= p->exits.len && !ip->func) return bc_error_bad_token(); i = ip->idx; } @@ -4418,7 +4457,7 @@ static BcStatus bc_parse_loopExit(BcParse *p, BcLexType type) if (s) return s; if (p->l.t.t != BC_LEX_SCOLON && p->l.t.t != BC_LEX_NLINE) - return bc_error("bad token"); + return bc_error_bad_token(); return bc_lex_next(&p->l); } @@ -4506,7 +4545,7 @@ static BcStatus bc_parse_auto(BcParse *p) bool comma, var, one; char *name; - if (!p->auto_part) return bc_error("bad token"); + if (!p->auto_part) return bc_error_bad_token(); s = bc_lex_next(&p->l); if (s) return s; @@ -4548,7 +4587,7 @@ static BcStatus bc_parse_auto(BcParse *p) if (!one) return bc_error("no auto variable found"); if (p->l.t.t != BC_LEX_NLINE && p->l.t.t != BC_LEX_SCOLON) - return bc_error("bad token"); + return bc_error_bad_token(); return bc_lex_next(&p->l); @@ -4566,7 +4605,7 @@ static BcStatus bc_parse_body(BcParse *p, bool brace) if (*flag_ptr & BC_PARSE_FLAG_FUNC_INNER) { - if (!brace) return bc_error("bad token"); + if (!brace) return bc_error_bad_token(); p->auto_part = p->l.t.t != BC_LEX_KEY_AUTO; if (!p->auto_part) { @@ -4603,7 +4642,7 @@ static BcStatus bc_parse_stmt(BcParse *p) case BC_LEX_LBRACE: { - if (!BC_PARSE_BODY(p)) return bc_error("bad token"); + if (!BC_PARSE_BODY(p)) return bc_error_bad_token(); ++p->nbraces; s = bc_lex_next(&p->l); @@ -4748,7 +4787,7 @@ static BcStatus bc_parse_stmt(BcParse *p) default: { - s = bc_error("bad token"); + s = bc_error_bad_token(); break; } } @@ -4763,7 +4802,7 @@ static BcStatus bc_parse_parse(BcParse *p) if (p->l.t.t == BC_LEX_EOF) s = p->flags.len > 0 ? bc_error("block end could not be found") : bc_error("end of file"); else if (p->l.t.t == BC_LEX_KEY_DEFINE) { - if (!BC_PARSE_CAN_EXEC(p)) return bc_error("bad token"); + if (!BC_PARSE_CAN_EXEC(p)) return bc_error_bad_token(); s = bc_parse_func(p); } else @@ -4849,7 +4888,7 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) if (((t == BC_LEX_OP_BOOL_NOT) != bin_last) || (t != BC_LEX_OP_BOOL_NOT && prev == BC_INST_BOOL_NOT) ) { - return bc_error("bad expression"); + return bc_error_bad_expression(); } nrelops += t >= BC_LEX_OP_REL_EQ && t <= BC_LEX_OP_REL_GT; @@ -4864,7 +4903,7 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) case BC_LEX_LPAREN: { if (BC_PARSE_LEAF(prev, rprn)) - return bc_error("bad expression"); + return bc_error_bad_expression(); ++nparens; paren_expr = rprn = bin_last = false; get_token = true; @@ -4876,7 +4915,7 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) case BC_LEX_RPAREN: { if (bin_last || prev == BC_INST_BOOL_NOT) - return bc_error("bad expression"); + return bc_error_bad_expression(); if (nparens == 0) { s = BC_STATUS_SUCCESS; @@ -4899,7 +4938,7 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) case BC_LEX_NAME: { if (BC_PARSE_LEAF(prev, rprn)) - return bc_error("bad expression"); + return bc_error_bad_expression(); paren_expr = true; rprn = get_token = bin_last = false; s = bc_parse_name(p, &prev, flags & ~BC_PARSE_NOCALL); @@ -4911,7 +4950,7 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) case BC_LEX_NUMBER: { if (BC_PARSE_LEAF(prev, rprn)) - return bc_error("bad expression"); + return bc_error_bad_expression(); bc_parse_number(p, &prev, &nexprs); paren_expr = get_token = true; rprn = bin_last = false; @@ -4924,7 +4963,7 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) case BC_LEX_KEY_OBASE: { if (BC_PARSE_LEAF(prev, rprn)) - return bc_error("bad expression"); + return bc_error_bad_expression(); prev = (char) (t - BC_LEX_KEY_IBASE + BC_INST_IBASE); bc_parse_push(p, (char) prev); @@ -4939,7 +4978,7 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) case BC_LEX_KEY_SQRT: { if (BC_PARSE_LEAF(prev, rprn)) - return bc_error("bad expression"); + return bc_error_bad_expression(); s = bc_parse_builtin(p, t, flags, &prev); paren_expr = true; rprn = get_token = bin_last = false; @@ -4951,9 +4990,9 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) case BC_LEX_KEY_READ: { if (BC_PARSE_LEAF(prev, rprn)) - return bc_error("bad expression"); + return bc_error_bad_expression(); else if (flags & BC_PARSE_NOREAD) - s = bc_error("read() call inside of a read() call"); + s = bc_error_nested_read_call(); else s = bc_parse_read(p); @@ -4968,7 +5007,7 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) case BC_LEX_KEY_SCALE: { if (BC_PARSE_LEAF(prev, rprn)) - return bc_error("bad expression"); + return bc_error_bad_expression(); s = bc_parse_scale(p, &prev, flags); paren_expr = true; rprn = get_token = bin_last = false; @@ -4980,7 +5019,7 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) default: { - s = bc_error("bad token"); + s = bc_error_bad_token(); break; } } @@ -4997,7 +5036,7 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) assign = top >= BC_LEX_OP_ASSIGN_POWER && top <= BC_LEX_OP_ASSIGN; if (top == BC_LEX_LPAREN || top == BC_LEX_RPAREN) - return bc_error("bad expression"); + return bc_error_bad_expression(); bc_parse_push(p, BC_PARSE_TOKEN_INST(top)); @@ -5006,12 +5045,12 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) } if (prev == BC_INST_BOOL_NOT || nexprs != 1) - return bc_error("bad expression"); + return bc_error_bad_expression(); for (i = 0; i < next.len; ++i) if (t == next.tokens[i]) goto ok; - return bc_error("bad expression"); + return bc_error_bad_expression(); ok: if (!(flags & BC_PARSE_REL) && nrelops) { @@ -5050,7 +5089,7 @@ static BcStatus dc_parse_register(BcParse *p) s = bc_lex_next(&p->l); if (s) return s; - if (p->l.t.t != BC_LEX_NAME) return bc_error("bad token"); + if (p->l.t.t != BC_LEX_NAME) return bc_error_bad_token(); name = xstrdup(p->l.t.v.v); bc_parse_pushName(p, name); @@ -5158,7 +5197,7 @@ static BcStatus dc_parse_token(BcParse *p, BcLexType t, uint8_t flags) s = bc_lex_next(&p->l); if (s) return s; if (p->l.t.t != BC_LEX_NUMBER) - return bc_error("bad token"); + return bc_error_bad_token(); } bc_parse_number(p, &prev, &p->nbraces); @@ -5172,7 +5211,7 @@ static BcStatus dc_parse_token(BcParse *p, BcLexType t, uint8_t flags) case BC_LEX_KEY_READ: { if (flags & BC_PARSE_NOREAD) - s = bc_error("read() call inside of a read() call"); + s = bc_error_nested_read_call(); else bc_parse_push(p, BC_INST_READ); get_token = true; @@ -5207,7 +5246,7 @@ static BcStatus dc_parse_token(BcParse *p, BcLexType t, uint8_t flags) default: { - s = bc_error("bad token"); + s = bc_error_bad_token(); get_token = true; break; } @@ -5393,7 +5432,7 @@ static BcStatus bc_program_binOpPrep(BcResult **l, BcNum **ln, BcResultType lt, rt; if (!BC_PROG_STACK(&G.prog.results, 2)) - return bc_error("stack has too few elements"); + return bc_error_stack_has_too_few_elements(); *r = bc_vec_item_rev(&G.prog.results, 0); *l = bc_vec_item_rev(&G.prog.results, 1); @@ -5415,9 +5454,9 @@ static BcStatus bc_program_binOpPrep(BcResult **l, BcNum **ln, } if (!BC_PROG_NUM((*l), (*ln)) && (!assign || (*l)->t != BC_RESULT_VAR)) - return bc_error("variable is wrong type"); + return bc_error_variable_is_wrong_type(); if (!assign && !BC_PROG_NUM((*r), (*ln))) - return bc_error("variable is wrong type"); + return bc_error_variable_is_wrong_type(); return s; } @@ -5435,14 +5474,14 @@ static BcStatus bc_program_prep(BcResult **r, BcNum **n) BcStatus s; if (!BC_PROG_STACK(&G.prog.results, 1)) - return bc_error("stack has too few elements"); + return bc_error_stack_has_too_few_elements(); *r = bc_vec_top(&G.prog.results); s = bc_program_num(*r, n, false); if (s) return s; if (!BC_PROG_NUM((*r), (*n))) - return bc_error("variable is wrong type"); + return bc_error_variable_is_wrong_type(); return s; } @@ -5487,7 +5526,7 @@ static BcStatus bc_program_read(void) for (i = 0; i < G.prog.stack.len; ++i) { BcInstPtr *ip_ptr = bc_vec_item(&G.prog.stack, i); if (ip_ptr->func == BC_PROG_READ) - return bc_error("read() call inside of a read() call"); + return bc_error_nested_read_call(); } bc_vec_pop_all(&f->code); @@ -5649,7 +5688,7 @@ static BcStatus bc_program_print(char inst, size_t idx) bool pop = inst != BC_INST_PRINT; if (!BC_PROG_STACK(&G.prog.results, idx + 1)) - return bc_error("stack has too few elements"); + return bc_error_stack_has_too_few_elements(); r = bc_vec_item_rev(&G.prog.results, idx); s = bc_program_num(r, &num, false); @@ -5781,7 +5820,7 @@ static BcStatus bc_program_assignStr(BcResult *r, BcVec *v, if (!push) { if (!BC_PROG_STACK(&G.prog.results, 2)) - return bc_error("stack has too few elements"); + return bc_error_stack_has_too_few_elements(); bc_vec_pop(v); bc_vec_pop(&G.prog.results); } @@ -5803,16 +5842,16 @@ static BcStatus bc_program_copyToVar(char *name, bool var) BcNum *n; if (!BC_PROG_STACK(&G.prog.results, 1)) - return bc_error("stack has too few elements"); + return bc_error_stack_has_too_few_elements(); ptr = bc_vec_top(&G.prog.results); if ((ptr->t == BC_RESULT_ARRAY) != !var) - return bc_error("variable is wrong type"); + return bc_error_variable_is_wrong_type(); v = bc_program_search(name, var); #if ENABLE_DC if (ptr->t == BC_RESULT_STR && !var) - return bc_error("variable is wrong type"); + return bc_error_variable_is_wrong_type(); if (ptr->t == BC_RESULT_STR) return bc_program_assignStr(ptr, v, true); #endif @@ -5858,7 +5897,7 @@ static BcStatus bc_program_assign(char inst) BcVec *v; if (left->t != BC_RESULT_VAR) - return bc_error("variable is wrong type"); + return bc_error_variable_is_wrong_type(); v = bc_program_search(left->d.id.name, true); return bc_program_assignStr(right, v, false); @@ -5952,7 +5991,7 @@ static BcStatus bc_program_pushVar(char *code, size_t *bgn, if (!BC_PROG_STACK(v, 2 - copy)) { free(name); - return bc_error("stack has too few elements"); + return bc_error_stack_has_too_few_elements(); } free(name); @@ -6068,7 +6107,7 @@ static BcStatus bc_program_call(char *code, size_t *idx) return bc_error("undefined function"); } if (nparams != func->nparams) { - return bc_error("function has %u parameters, but called with %u", func->nparams, nparams); + return bc_error_fmt("function has %u parameters, but called with %u", func->nparams, nparams); } ip.len = G.prog.results.len - nparams; @@ -6078,7 +6117,7 @@ static BcStatus bc_program_call(char *code, size_t *idx) arg = bc_vec_top(&G.prog.results); if ((!a->idx) != (arg->t == BC_RESULT_ARRAY) || arg->t == BC_RESULT_STR) - return bc_error("variable is wrong type"); + return bc_error_variable_is_wrong_type(); s = bc_program_copyToVar(a->name, a->idx); if (s) return s; @@ -6114,7 +6153,7 @@ static BcStatus bc_program_return(char inst) BcInstPtr *ip = bc_vec_top(&G.prog.stack); if (!BC_PROG_STACK(&G.prog.results, ip->len + inst == BC_INST_RET)) - return bc_error("stack has too few elements"); + return bc_error_stack_has_too_few_elements(); f = bc_vec_item(&G.prog.fns, ip->func); res.t = BC_RESULT_TEMP; @@ -6177,7 +6216,7 @@ static BcStatus bc_program_builtin(char inst) bool len = inst == BC_INST_LENGTH; if (!BC_PROG_STACK(&G.prog.results, 1)) - return bc_error("stack has too few elements"); + return bc_error_stack_has_too_few_elements(); opnd = bc_vec_top(&G.prog.results); s = bc_program_num(opnd, &num, false); @@ -6185,7 +6224,7 @@ static BcStatus bc_program_builtin(char inst) #if ENABLE_DC if (!BC_PROG_NUM(opnd, num) && !len) - return bc_error("variable is wrong type"); + return bc_error_variable_is_wrong_type(); #endif bc_num_init(&res.d.n, BC_NUM_DEF_SIZE); @@ -6251,7 +6290,7 @@ static BcStatus bc_program_modexp(void) BcNum *n1, *n2, *n3; if (!BC_PROG_STACK(&G.prog.results, 3)) - return bc_error("stack has too few elements"); + return bc_error_stack_has_too_few_elements(); s = bc_program_binOpPrep(&r2, &n2, &r3, &n3, false); if (s) return s; @@ -6259,7 +6298,7 @@ static BcStatus bc_program_modexp(void) s = bc_program_num(r1, &n1, false); if (s) return s; if (!BC_PROG_NUM(r1, n1)) - return bc_error("variable is wrong type"); + return bc_error_variable_is_wrong_type(); // Make sure that the values have their pointers updated, if necessary. if (r1->t == BC_RESULT_VAR || r1->t == BC_RESULT_ARRAY_ELEM) { @@ -6311,7 +6350,7 @@ static BcStatus bc_program_asciify(void) unsigned long val; if (!BC_PROG_STACK(&G.prog.results, 1)) - return bc_error("stack has too few elements"); + return bc_error_stack_has_too_few_elements(); r = bc_vec_top(&G.prog.results); s = bc_program_num(r, &num, false); @@ -6380,7 +6419,7 @@ static BcStatus bc_program_printStream(void) char *str; if (!BC_PROG_STACK(&G.prog.results, 1)) - return bc_error("stack has too few elements"); + return bc_error_stack_has_too_few_elements(); r = bc_vec_top(&G.prog.results); s = bc_program_num(r, &n, false); @@ -6412,7 +6451,7 @@ static BcStatus bc_program_nquit(void) bc_vec_pop(&G.prog.results); if (G.prog.stack.len < val) - return bc_error("stack has too few elements"); + return bc_error_stack_has_too_few_elements(); if (G.prog.stack.len == val) quit(); @@ -6435,7 +6474,7 @@ static BcStatus bc_program_execStr(char *code, size_t *bgn, bool exec; if (!BC_PROG_STACK(&G.prog.results, 1)) - return bc_error("stack has too few elements"); + return bc_error_stack_has_too_few_elements(); r = bc_vec_top(&G.prog.results); @@ -6468,7 +6507,7 @@ static BcStatus bc_program_execStr(char *code, size_t *bgn, if (!exec) goto exit; if (!BC_PROG_STR(n)) { - s = bc_error("variable is wrong type"); + s = bc_error_variable_is_wrong_type(); goto exit; } @@ -6500,7 +6539,7 @@ static BcStatus bc_program_execStr(char *code, size_t *bgn, if (s) goto err; if (prs.l.t.t != BC_LEX_EOF) { - s = bc_error("bad expression"); + s = bc_error_bad_expression(); goto err; } @@ -6723,7 +6762,7 @@ static BcStatus bc_program_exec(void) case BC_INST_POP: { if (!BC_PROG_STACK(&G.prog.results, 1)) - s = bc_error("stack has too few elements"); + s = bc_error_stack_has_too_few_elements(); else bc_vec_pop(&G.prog.results); break; @@ -6836,7 +6875,7 @@ static BcStatus bc_program_exec(void) case BC_INST_DUPLICATE: { if (!BC_PROG_STACK(&G.prog.results, 1)) - return bc_error("stack has too few elements"); + return bc_error_stack_has_too_few_elements(); ptr = bc_vec_top(&G.prog.results); bc_result_copy(&r, ptr); bc_vec_push(&G.prog.results, &r); @@ -6848,7 +6887,7 @@ static BcStatus bc_program_exec(void) BcResult *ptr2; if (!BC_PROG_STACK(&G.prog.results, 2)) - return bc_error("stack has too few elements"); + return bc_error_stack_has_too_few_elements(); ptr = bc_vec_item_rev(&G.prog.results, 0); ptr2 = bc_vec_item_rev(&G.prog.results, 1); @@ -7009,7 +7048,7 @@ static BcStatus bc_vm_file(const char *file) G.prog.file = file; data = bc_read_file(file); - if (!data) return bc_error("file '%s' is not text", file); + if (!data) return bc_error_fmt("file '%s' is not text", file); bc_lex_file(&G.prs.l, file); s = bc_vm_process(data); @@ -7019,7 +7058,7 @@ static BcStatus bc_vm_file(const char *file) ip = bc_vec_item(&G.prog.stack, 0); if (main_func->code.len < ip->idx) - s = bc_error("file '%s' is not executable", file); + s = bc_error_fmt("file '%s' is not executable", file); err: free(data); -- cgit v1.2.3-55-g6feb From 0ad36c46c7a521760e5696ba9d6e9362a1a3777c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 5 Dec 2018 16:21:43 +0100 Subject: bc: do not check for errors when parsing/running internal library function old new delta bc_lib_name 4 - -4 bc_vm_run 1921 1900 -21 ------------------------------------------------------------------------------ (add/remove: 0/1 grow/shrink: 0/1 up/down: 0/-25) Total: -25 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 370 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 186 insertions(+), 184 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 6f2606c79..fd9e31cc5 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -915,185 +915,6 @@ static const BcNumBinaryOp bc_program_ops[] = { static const char bc_program_stdin_name[] = ""; -#if ENABLE_BC -static const char *bc_lib_name = "gen/lib.bc"; - -static const char bc_lib[] = { - "scale=20" -"\n" "define e(x){" -"\n" "auto b,s,n,r,d,i,p,f,v" -"\n" "b=ibase" -"\n" "ibase=A" -"\n" "if(x<0){" -"\n" "n=1" -"\n" "x=-x" -"\n" "}" -"\n" "s=scale" -"\n" "r=6+s+0.44*x" -"\n" "scale=scale(x)+1" -"\n" "while(x>1){" -"\n" "d+=1" -"\n" "x/=2" -"\n" "scale+=1" -"\n" "}" -"\n" "scale=r" -"\n" "r=x+1" -"\n" "p=x" -"\n" "f=v=1" -"\n" "for(i=2;v!=0;++i){" -"\n" "p*=x" -"\n" "f*=i" -"\n" "v=p/f" -"\n" "r+=v" -"\n" "}" -"\n" "while((d--)!=0)r*=r" -"\n" "scale=s" -"\n" "ibase=b" -"\n" "if(n!=0)return(1/r)" -"\n" "return(r/1)" -"\n" "}" -"\n" "define l(x){" -"\n" "auto b,s,r,p,a,q,i,v" -"\n" "b=ibase" -"\n" "ibase=A" -"\n" "if(x<=0){" -"\n" "r=(1-10^scale)/1" -"\n" "ibase=b" -"\n" "return(r)" -"\n" "}" -"\n" "s=scale" -"\n" "scale+=6" -"\n" "p=2" -"\n" "while(x>=2){" -"\n" "p*=2" -"\n" "x=sqrt(x)" -"\n" "}" -"\n" "while(x<=0.5){" -"\n" "p*=2" -"\n" "x=sqrt(x)" -"\n" "}" -"\n" "r=a=(x-1)/(x+1)" -"\n" "q=a*a" -"\n" "v=1" -"\n" "for(i=3;v!=0;i+=2){" -"\n" "a*=q" -"\n" "v=a/i" -"\n" "r+=v" -"\n" "}" -"\n" "r*=p" -"\n" "scale=s" -"\n" "ibase=b" -"\n" "return(r/1)" -"\n" "}" -"\n" "define s(x){" -"\n" "auto b,s,r,n,a,q,i" -"\n" "b=ibase" -"\n" "ibase=A" -"\n" "s=scale" -"\n" "scale=1.1*s+2" -"\n" "a=a(1)" -"\n" "if(x<0){" -"\n" "n=1" -"\n" "x=-x" -"\n" "}" -"\n" "scale=0" -"\n" "q=(x/a+2)/4" -"\n" "x=x-4*q*a" -"\n" "if(q%2!=0)x=-x" -"\n" "scale=s+2" -"\n" "r=a=x" -"\n" "q=-x*x" -"\n" "for(i=3;a!=0;i+=2){" -"\n" "a*=q/(i*(i-1))" -"\n" "r+=a" -"\n" "}" -"\n" "scale=s" -"\n" "ibase=b" -"\n" "if(n!=0)return(-r/1)" -"\n" "return(r/1)" -"\n" "}" -"\n" "define c(x){" -"\n" "auto b,s" -"\n" "b=ibase" -"\n" "ibase=A" -"\n" "s=scale" -"\n" "scale*=1.2" -"\n" "x=s(2*a(1)+x)" -"\n" "scale=s" -"\n" "ibase=b" -"\n" "return(x/1)" -"\n" "}" -"\n" "define a(x){" -"\n" "auto b,s,r,n,a,m,t,f,i,u" -"\n" "b=ibase" -"\n" "ibase=A" -"\n" "n=1" -"\n" "if(x<0){" -"\n" "n=-1" -"\n" "x=-x" -"\n" "}" -"\n" "if(x==1){" -"\n" "if(scale<65){" -"\n" "return(.7853981633974483096156608458198757210492923498437764552437361480/n)" -"\n" "}" -"\n" "}" -"\n" "if(x==.2){" -"\n" "if(scale<65){" -"\n" "return(.1973955598498807583700497651947902934475851037878521015176889402/n)" -"\n" "}" -"\n" "}" -"\n" "s=scale" -"\n" "if(x>.2){" -"\n" "scale+=5" -"\n" "a=a(.2)" -"\n" "}" -"\n" "scale=s+3" -"\n" "while(x>.2){" -"\n" "m+=1" -"\n" "x=(x-.2)/(1+.2*x)" -"\n" "}" -"\n" "r=u=x" -"\n" "f=-x*x" -"\n" "t=1" -"\n" "for(i=3;t!=0;i+=2){" -"\n" "u*=f" -"\n" "t=u/i" -"\n" "r+=t" -"\n" "}" -"\n" "scale=s" -"\n" "ibase=b" -"\n" "return((m*a+r)/n)" -"\n" "}" -"\n" "define j(n,x){" -"\n" "auto b,s,o,a,i,v,f" -"\n" "b=ibase" -"\n" "ibase=A" -"\n" "s=scale" -"\n" "scale=0" -"\n" "n/=1" -"\n" "if(n<0){" -"\n" "n=-n" -"\n" "if(n%2==1)o=1" -"\n" "}" -"\n" "a=1" -"\n" "for(i=2;i<=n;++i)a*=i" -"\n" "scale=1.5*s" -"\n" "a=(x^n)/2^n/a" -"\n" "r=v=1" -"\n" "f=-x*x/4" -"\n" "scale=scale+length(a)-scale(a)" -"\n" "for(i=1;v!=0;++i){" -"\n" "v=v*f/i/(n+i)" -"\n" "r+=v" -"\n" "}" -"\n" "scale=s" -"\n" "ibase=b" -"\n" "if(o!=0)a=-a" -"\n" "return(a*r/1)" -"\n" "}" -}; -#endif // ENABLE_BC - static void fflush_and_check(void) { fflush_all(); @@ -7147,6 +6968,183 @@ static BcStatus bc_vm_stdin(void) return s; } +#if ENABLE_BC +static const char bc_lib[] = { + "scale=20" +"\n" "define e(x){" +"\n" "auto b,s,n,r,d,i,p,f,v" +"\n" "b=ibase" +"\n" "ibase=A" +"\n" "if(x<0){" +"\n" "n=1" +"\n" "x=-x" +"\n" "}" +"\n" "s=scale" +"\n" "r=6+s+0.44*x" +"\n" "scale=scale(x)+1" +"\n" "while(x>1){" +"\n" "d+=1" +"\n" "x/=2" +"\n" "scale+=1" +"\n" "}" +"\n" "scale=r" +"\n" "r=x+1" +"\n" "p=x" +"\n" "f=v=1" +"\n" "for(i=2;v!=0;++i){" +"\n" "p*=x" +"\n" "f*=i" +"\n" "v=p/f" +"\n" "r+=v" +"\n" "}" +"\n" "while((d--)!=0)r*=r" +"\n" "scale=s" +"\n" "ibase=b" +"\n" "if(n!=0)return(1/r)" +"\n" "return(r/1)" +"\n" "}" +"\n" "define l(x){" +"\n" "auto b,s,r,p,a,q,i,v" +"\n" "b=ibase" +"\n" "ibase=A" +"\n" "if(x<=0){" +"\n" "r=(1-10^scale)/1" +"\n" "ibase=b" +"\n" "return(r)" +"\n" "}" +"\n" "s=scale" +"\n" "scale+=6" +"\n" "p=2" +"\n" "while(x>=2){" +"\n" "p*=2" +"\n" "x=sqrt(x)" +"\n" "}" +"\n" "while(x<=0.5){" +"\n" "p*=2" +"\n" "x=sqrt(x)" +"\n" "}" +"\n" "r=a=(x-1)/(x+1)" +"\n" "q=a*a" +"\n" "v=1" +"\n" "for(i=3;v!=0;i+=2){" +"\n" "a*=q" +"\n" "v=a/i" +"\n" "r+=v" +"\n" "}" +"\n" "r*=p" +"\n" "scale=s" +"\n" "ibase=b" +"\n" "return(r/1)" +"\n" "}" +"\n" "define s(x){" +"\n" "auto b,s,r,n,a,q,i" +"\n" "b=ibase" +"\n" "ibase=A" +"\n" "s=scale" +"\n" "scale=1.1*s+2" +"\n" "a=a(1)" +"\n" "if(x<0){" +"\n" "n=1" +"\n" "x=-x" +"\n" "}" +"\n" "scale=0" +"\n" "q=(x/a+2)/4" +"\n" "x=x-4*q*a" +"\n" "if(q%2!=0)x=-x" +"\n" "scale=s+2" +"\n" "r=a=x" +"\n" "q=-x*x" +"\n" "for(i=3;a!=0;i+=2){" +"\n" "a*=q/(i*(i-1))" +"\n" "r+=a" +"\n" "}" +"\n" "scale=s" +"\n" "ibase=b" +"\n" "if(n!=0)return(-r/1)" +"\n" "return(r/1)" +"\n" "}" +"\n" "define c(x){" +"\n" "auto b,s" +"\n" "b=ibase" +"\n" "ibase=A" +"\n" "s=scale" +"\n" "scale*=1.2" +"\n" "x=s(2*a(1)+x)" +"\n" "scale=s" +"\n" "ibase=b" +"\n" "return(x/1)" +"\n" "}" +"\n" "define a(x){" +"\n" "auto b,s,r,n,a,m,t,f,i,u" +"\n" "b=ibase" +"\n" "ibase=A" +"\n" "n=1" +"\n" "if(x<0){" +"\n" "n=-1" +"\n" "x=-x" +"\n" "}" +"\n" "if(x==1){" +"\n" "if(scale<65){" +"\n" "return(.7853981633974483096156608458198757210492923498437764552437361480/n)" +"\n" "}" +"\n" "}" +"\n" "if(x==.2){" +"\n" "if(scale<65){" +"\n" "return(.1973955598498807583700497651947902934475851037878521015176889402/n)" +"\n" "}" +"\n" "}" +"\n" "s=scale" +"\n" "if(x>.2){" +"\n" "scale+=5" +"\n" "a=a(.2)" +"\n" "}" +"\n" "scale=s+3" +"\n" "while(x>.2){" +"\n" "m+=1" +"\n" "x=(x-.2)/(1+.2*x)" +"\n" "}" +"\n" "r=u=x" +"\n" "f=-x*x" +"\n" "t=1" +"\n" "for(i=3;t!=0;i+=2){" +"\n" "u*=f" +"\n" "t=u/i" +"\n" "r+=t" +"\n" "}" +"\n" "scale=s" +"\n" "ibase=b" +"\n" "return((m*a+r)/n)" +"\n" "}" +"\n" "define j(n,x){" +"\n" "auto b,s,o,a,i,v,f" +"\n" "b=ibase" +"\n" "ibase=A" +"\n" "s=scale" +"\n" "scale=0" +"\n" "n/=1" +"\n" "if(n<0){" +"\n" "n=-n" +"\n" "if(n%2==1)o=1" +"\n" "}" +"\n" "a=1" +"\n" "for(i=2;i<=n;++i)a*=i" +"\n" "scale=1.5*s" +"\n" "a=(x^n)/2^n/a" +"\n" "r=v=1" +"\n" "f=-x*x/4" +"\n" "scale=scale+length(a)-scale(a)" +"\n" "for(i=1;v!=0;++i){" +"\n" "v=v*f/i/(n+i)" +"\n" "r+=v" +"\n" "}" +"\n" "scale=s" +"\n" "ibase=b" +"\n" "if(o!=0)a=-a" +"\n" "return(a*r/1)" +"\n" "}" +}; +#endif // ENABLE_BC + static BcStatus bc_vm_exec(void) { BcStatus s = BC_STATUS_SUCCESS; @@ -7155,15 +7153,19 @@ static BcStatus bc_vm_exec(void) #if ENABLE_BC if (option_mask32 & BC_FLAG_L) { - bc_lex_file(&G.prs.l, bc_lib_name); + // We know that internal library is not buggy, + // thus error checking is normally disabled. +# define DEBUG_LIB 0 + bc_lex_file(&G.prs.l, ""); s = bc_parse_text(&G.prs, bc_lib); + if (DEBUG_LIB && s) return s; - while (!s && G.prs.l.t.t != BC_LEX_EOF) + while (G.prs.l.t.t != BC_LEX_EOF) { s = G.prs.parse(&G.prs); - - if (s) return s; + if (DEBUG_LIB && s) return s; + } s = bc_program_exec(); - if (s) return s; + if (DEBUG_LIB && s) return s; } #endif -- cgit v1.2.3-55-g6feb From 0409ad36a11ad51e47813b65a97e6ad68f42d381 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 5 Dec 2018 16:39:22 +0100 Subject: bc: restore printing of script name on errors Examples: On stdin, no file name is available: $ echo 'print "' | busybox bc bc: string end could not be found When the same error is in file: $ busybox bc FILE bc 1.30.0.git Copyright (c) 2018 Gavin D. Howard and contributors Report bugs at: https://github.com/gavinhoward/bc This is free software with ABSOLUTELY NO WARRANTY FILE: string end could not be found ready for more input >>> Line number printing to be added later... function old new delta bc_error_fmt 38 70 +32 bc_posix_error_fmt 60 90 +30 bc_vm_run 1900 1919 +19 bc_program_read 338 355 +17 bc_lex_file 15 12 -3 bc_program_stdin_name 8 - -8 ------------------------------------------------------------------------------ (add/remove: 0/1 grow/shrink: 4/1 up/down: 98/-11) Total: 87 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index fd9e31cc5..171bc8858 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -567,7 +567,6 @@ typedef struct BcLex { const char *buf; size_t i; size_t line; - const char *f; size_t len; bool newline; @@ -913,8 +912,6 @@ static const BcNumBinaryOp bc_program_ops[] = { bc_num_pow, bc_num_mul, bc_num_div, bc_num_mod, bc_num_add, bc_num_sub, }; -static const char bc_program_stdin_name[] = ""; - static void fflush_and_check(void) { fflush_all(); @@ -933,11 +930,18 @@ static void quit(void) static NOINLINE int bc_error_fmt(const char *fmt, ...) { + const char *sv; va_list p; + sv = applet_name; + if (G.prog.file) + applet_name = G.prog.file; + va_start(p, fmt); bb_verror_msg(fmt, p, NULL); va_end(p); + applet_name = sv; + if (!G.ttyin) exit(1); return BC_STATUS_FAILURE; @@ -945,15 +949,21 @@ static NOINLINE int bc_error_fmt(const char *fmt, ...) static NOINLINE int bc_posix_error_fmt(const char *fmt, ...) { + const char *sv; va_list p; // Are non-POSIX constructs totally ok? if (!(option_mask32 & (BC_FLAG_S|BC_FLAG_W))) return BC_STATUS_SUCCESS; // yes + sv = applet_name; + if (G.prog.file) + applet_name = G.prog.file; + va_start(p, fmt); bb_verror_msg(fmt, p, NULL); va_end(p); + applet_name = sv; // Do we treat non-POSIX constructs as errors? if (!(option_mask32 & BC_FLAG_S)) @@ -2860,11 +2870,10 @@ static void bc_lex_free(BcLex *l) bc_vec_free(&l->t.v); } -static void bc_lex_file(BcLex *l, const char *file) +static void bc_lex_file(BcLex *l) { l->line = 1; l->newline = false; - l->f = file; } static BcStatus bc_lex_next(BcLex *l) @@ -5337,6 +5346,7 @@ err: static BcStatus bc_program_read(void) { + const char *sv_file; BcStatus s; BcParse parse; BcVec buf; @@ -5353,11 +5363,14 @@ static BcStatus bc_program_read(void) bc_vec_pop_all(&f->code); bc_char_vec_init(&buf); + sv_file = G.prog.file; + G.prog.file = NULL; + s = bc_read_line(&buf, "read> "); if (s) goto io_err; common_parse_init(&parse, BC_PROG_READ); - bc_lex_file(&parse.l, bc_program_stdin_name); + bc_lex_file(&parse.l); s = bc_parse_text(&parse, buf.v); if (s) goto exec_err; @@ -5380,6 +5393,7 @@ static BcStatus bc_program_read(void) bc_vec_push(&G.prog.stack, &ip); exec_err: + G.prog.file = sv_file; bc_parse_free(&parse); io_err: bc_vec_free(&buf); @@ -6862,16 +6876,18 @@ static BcStatus bc_vm_process(const char *text) static BcStatus bc_vm_file(const char *file) { - BcStatus s; + const char *sv_file; char *data; + BcStatus s; BcFunc *main_func; BcInstPtr *ip; - G.prog.file = file; data = bc_read_file(file); if (!data) return bc_error_fmt("file '%s' is not text", file); - bc_lex_file(&G.prs.l, file); + sv_file = G.prog.file; + G.prog.file = file; + bc_lex_file(&G.prs.l); s = bc_vm_process(data); if (s) goto err; @@ -6882,6 +6898,7 @@ static BcStatus bc_vm_file(const char *file) s = bc_error_fmt("file '%s' is not executable", file); err: + G.prog.file = sv_file; free(data); return s; } @@ -6893,8 +6910,8 @@ static BcStatus bc_vm_stdin(void) size_t len, i, str = 0; bool comment = false; - G.prog.file = bc_program_stdin_name; - bc_lex_file(&G.prs.l, bc_program_stdin_name); + G.prog.file = NULL; + bc_lex_file(&G.prs.l); bc_char_vec_init(&buffer); bc_char_vec_init(&buf); @@ -7156,7 +7173,7 @@ static BcStatus bc_vm_exec(void) // We know that internal library is not buggy, // thus error checking is normally disabled. # define DEBUG_LIB 0 - bc_lex_file(&G.prs.l, ""); + bc_lex_file(&G.prs.l); s = bc_parse_text(&G.prs, bc_lib); if (DEBUG_LIB && s) return s; -- cgit v1.2.3-55-g6feb From 08c033c406e2ef1ef9209b1ea09864928e2158ab Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 5 Dec 2018 16:55:08 +0100 Subject: bc: optimize pushing zero bytes to vectors function old new delta bc_vec_pushZeroByte - 10 +10 bc_vm_run 1919 1917 -2 bc_vec_string 61 59 -2 bc_vec_concat 68 66 -2 bc_parse_create 170 168 -2 bc_lex_number 298 296 -2 dc_lex_token 691 687 -4 bc_read_line 314 303 -11 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 0/7 up/down: 10/-25) Total: -15 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 171bc8858..97adeaa53 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1068,6 +1068,13 @@ static void bc_vec_pushByte(BcVec *v, char data) bc_vec_push(v, &data); } +static void bc_vec_pushZeroByte(BcVec *v) +{ + //bc_vec_pushByte(v, '\0'); + // better: + bc_vec_push(v, &const_int_0); +} + static void bc_vec_pushAt(BcVec *v, const void *data, size_t idx) { if (idx == v->len) @@ -1092,14 +1099,14 @@ static void bc_vec_string(BcVec *v, size_t len, const char *str) memcpy(v->v, str, len); v->len = len; - bc_vec_pushByte(v, '\0'); + bc_vec_pushZeroByte(v); } static void bc_vec_concat(BcVec *v, const char *str) { size_t len; - if (v->len == 0) bc_vec_pushByte(v, '\0'); + if (v->len == 0) bc_vec_pushZeroByte(v); len = v->len + strlen(str); @@ -1173,7 +1180,6 @@ static BcStatus bc_read_line(BcVec *vec, const char *prompt) do { int i; - char c; bad_chars = 0; bc_vec_pop_all(vec); @@ -1222,12 +1228,11 @@ static BcStatus bc_read_line(BcVec *vec, const char *prompt) bc_error_fmt("illegal character 0x%02x", i); bad_chars = 1; } - c = (char) i; - bc_vec_push(vec, &c); + bc_vec_pushByte(vec, (char)i); } while (i != '\n'); } while (bad_chars); - bc_vec_pushByte(vec, '\0'); + bc_vec_pushZeroByte(vec); return BC_STATUS_SUCCESS; } @@ -2833,7 +2838,7 @@ static BcStatus bc_lex_number(BcLex *l, char start) bc_vec_push(&l->t.v, &c); } - bc_vec_pushByte(&l->t.v, '\0'); + bc_vec_pushZeroByte(&l->t.v); l->i += i; return BC_STATUS_SUCCESS; @@ -3307,7 +3312,7 @@ static BcStatus dc_lex_register(BcLex *l) else { bc_vec_pop_all(&l->t.v); bc_vec_pushByte(&l->t.v, l->buf[l->i - 1]); - bc_vec_pushByte(&l->t.v, '\0'); + bc_vec_pushZeroByte(&l->t.v); l->t.t = BC_LEX_NAME; } @@ -3336,7 +3341,7 @@ static BcStatus dc_lex_string(BcLex *l) return bc_error("string end could not be found"); } - bc_vec_pushByte(&l->t.v, '\0'); + bc_vec_pushZeroByte(&l->t.v); if (i - l->i > BC_MAX_STRING) return bc_error("string too long: must be [1, BC_STRING_MAX]"); @@ -3558,7 +3563,7 @@ static void bc_parse_create(BcParse *p, size_t func, bc_vec_init(&p->flags, sizeof(uint8_t), NULL); bc_vec_init(&p->exits, sizeof(BcInstPtr), NULL); bc_vec_init(&p->conds, sizeof(size_t), NULL); - bc_vec_pushByte(&p->flags, 0); + bc_vec_pushZeroByte(&p->flags); bc_vec_init(&p->ops, sizeof(BcLexType), NULL); p->parse = parse; @@ -6915,7 +6920,7 @@ static BcStatus bc_vm_stdin(void) bc_char_vec_init(&buffer); bc_char_vec_init(&buf); - bc_vec_pushByte(&buffer, '\0'); + bc_vec_pushZeroByte(&buffer); // This loop is complex because the vm tries not to send any lines that end // with a backslash to the parser. The reason for that is because the parser -- cgit v1.2.3-55-g6feb From 5318f81fbe5005ec048620b678064a50ba8a8e19 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 5 Dec 2018 17:48:01 +0100 Subject: bc: print error line numbers FILE: print 1 print " $ busybox bc -q FILE bc: FILE:2: string end could not be found ready for more input >>> _ function old new delta bc_verror_msg - 99 +99 bc_lex_file 12 28 +16 bc_lex_next 77 92 +15 dc_lex_token 687 701 +14 bc_lex_token 1237 1251 +14 bc_posix_error_fmt 90 58 -32 bc_error_fmt 70 36 -34 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 4/2 up/down: 158/-66) Total: 92 bytes text data bss dec hex filename 987108 485 7296 994889 f2e49 busybox_old 987210 485 7296 994991 f2eaf busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 97adeaa53..1c1672c00 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -786,6 +786,10 @@ struct globals { BcParse prs; BcProgram prog; + // For error messages. Can be set to current parsed line, + // or [TODO] to current executing line (can be before last parsed one) + unsigned err_line; + BcVec files; char *env_args; @@ -928,19 +932,27 @@ static void quit(void) exit(0); } +static void bc_verror_msg(const char *fmt, va_list p) +{ + const char *sv = sv; /* for compiler */ + if (G.prog.file) { + sv = applet_name; + applet_name = xasprintf("%s: %s:%u", applet_name, G.prog.file, G.err_line); + } + bb_verror_msg(fmt, p, NULL); + if (G.prog.file) { + free((char*)applet_name); + applet_name = sv; + } +} + static NOINLINE int bc_error_fmt(const char *fmt, ...) { - const char *sv; va_list p; - sv = applet_name; - if (G.prog.file) - applet_name = G.prog.file; - va_start(p, fmt); - bb_verror_msg(fmt, p, NULL); + bc_verror_msg(fmt, p); va_end(p); - applet_name = sv; if (!G.ttyin) exit(1); @@ -949,21 +961,15 @@ static NOINLINE int bc_error_fmt(const char *fmt, ...) static NOINLINE int bc_posix_error_fmt(const char *fmt, ...) { - const char *sv; va_list p; // Are non-POSIX constructs totally ok? if (!(option_mask32 & (BC_FLAG_S|BC_FLAG_W))) return BC_STATUS_SUCCESS; // yes - sv = applet_name; - if (G.prog.file) - applet_name = G.prog.file; - va_start(p, fmt); - bb_verror_msg(fmt, p, NULL); + bc_verror_msg(fmt, p); va_end(p); - applet_name = sv; // Do we treat non-POSIX constructs as errors? if (!(option_mask32 & BC_FLAG_S)) @@ -2877,7 +2883,7 @@ static void bc_lex_free(BcLex *l) static void bc_lex_file(BcLex *l) { - l->line = 1; + G.err_line = l->line = 1; l->newline = false; } @@ -2889,6 +2895,7 @@ static BcStatus bc_lex_next(BcLex *l) if (l->t.last == BC_LEX_EOF) return bc_error("end of file"); l->line += l->newline; + G.err_line = l->line; l->t.t = BC_LEX_EOF; l->newline = (l->i == l->len); @@ -2971,6 +2978,7 @@ static BcStatus bc_lex_string(BcLex *l) l->i = i + 1; l->line += nls; + G.err_line = l->line; return BC_STATUS_SUCCESS; } @@ -3011,6 +3019,7 @@ static BcStatus bc_lex_comment(BcLex *l) l->i = i + 1; l->line += nls; + G.err_line = l->line; return BC_STATUS_SUCCESS; } @@ -3347,6 +3356,7 @@ static BcStatus dc_lex_string(BcLex *l) l->i = i; l->line += nls; + G.err_line = l->line; return BC_STATUS_SUCCESS; } -- cgit v1.2.3-55-g6feb From 0064679915169dedca66a4365af7d9be7acc8153 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 5 Dec 2018 18:12:27 +0100 Subject: bc: fix inverted POSIXness test, improve messages, commonalize message strings function old new delta bc_lex_token 1251 1285 +34 bc_POSIX_does_not_allow_bool_ops_this_is_bad - 25 +25 bc_POSIX_does_not_allow_empty_X_expression_in_for - 20 +20 bc_POSIX_does_not_allow - 20 +20 bc_parse_expr 2146 2151 +5 bc_num_ulong 103 92 -11 ------------------------------------------------------------------------------ (add/remove: 3/0 grow/shrink: 2/1 up/down: 104/-11) Total: 93 bytes text data bss dec hex filename 987210 485 7296 994991 f2eaf busybox_old 987084 485 7296 994865 f2e31 busybox_unstripped ^^^^^^^ Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 1c1672c00..ff44293ab 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -992,6 +992,18 @@ static int bc_posix_error(const char *msg) { return bc_posix_error_fmt("%s", msg); } +static int bc_POSIX_does_not_allow(const char *msg) +{ + return bc_posix_error_fmt("%s%s", "POSIX does not allow ", msg); +} +static int bc_POSIX_does_not_allow_bool_ops_this_is_bad(const char *msg) +{ + return bc_posix_error_fmt("%s%s %s", "POSIX does not allow ", "boolean operators; the following is bad:", msg); +} +static int bc_POSIX_does_not_allow_empty_X_expression_in_for(const char *msg) +{ + return bc_posix_error_fmt("%san empty %s expression in a for loop", "POSIX does not allow ", msg); +} static int bc_error_bad_character(char c) { return bc_error_fmt("bad character '%c'", c); @@ -2938,8 +2950,8 @@ static BcStatus bc_lex_identifier(BcLex *l) match: // buf starts with keyword bc_lex_kws[i] l->t.t = BC_LEX_KEY_1st_keyword + i; - if ((1 << i) & POSIX_KWORD_MASK) { - s = bc_posix_error("POSIX does not allow the following keyword:"); // bc_lex_kws[i].name8 + if (!((1 << i) & POSIX_KWORD_MASK)) { + s = bc_posix_error_fmt("%sthe following keyword: '%.8s'", "POSIX does not allow ", bc_lex_kws[i].name8); if (s) return s; } @@ -2952,7 +2964,7 @@ static BcStatus bc_lex_identifier(BcLex *l) if (s) return s; if (l->t.v.len > 2) - s = bc_posix_error("POSIX only allows one character names; the following is bad:"); // buf + s = bc_posix_error_fmt("POSIX only allows one character names; the following is bad: '%s'", buf); return s; } @@ -3055,7 +3067,7 @@ static BcStatus bc_lex_token(BcLex *l) bc_lex_assign(l, BC_LEX_OP_REL_NE, BC_LEX_OP_BOOL_NOT); if (l->t.t == BC_LEX_OP_BOOL_NOT) { - s = bc_posix_error("POSIX does not allow boolean operators; the following is bad:"); // "!" + s = bc_POSIX_does_not_allow_bool_ops_this_is_bad("!"); if (s) return s; } @@ -3070,7 +3082,7 @@ static BcStatus bc_lex_token(BcLex *l) case '#': { - s = bc_posix_error("POSIX does not allow '#' script comments"); + s = bc_POSIX_does_not_allow("'#' script comments"); if (s) return s; bc_lex_lineComment(l); @@ -3089,7 +3101,7 @@ static BcStatus bc_lex_token(BcLex *l) c2 = l->buf[l->i]; if (c2 == '&') { - s = bc_posix_error("POSIX does not allow boolean operators; the following is bad:"); // "&&" + s = bc_POSIX_does_not_allow_bool_ops_this_is_bad("&&"); if (s) return s; ++l->i; @@ -3152,7 +3164,7 @@ static BcStatus bc_lex_token(BcLex *l) s = bc_lex_number(l, c); else { l->t.t = BC_LEX_KEY_LAST; - s = bc_posix_error("POSIX does not allow a period ('.') as a shortcut for the last result"); + s = bc_POSIX_does_not_allow("a period ('.') as a shortcut for the last result"); } break; } @@ -3279,7 +3291,7 @@ static BcStatus bc_lex_token(BcLex *l) c2 = l->buf[l->i]; if (c2 == '|') { - s = bc_posix_error("POSIX does not allow boolean operators; the following is bad:"); // "||" + s = bc_POSIX_does_not_allow_bool_ops_this_is_bad("||"); if (s) return s; ++l->i; @@ -4213,7 +4225,7 @@ static BcStatus bc_parse_for(BcParse *p) if (p->l.t.t != BC_LEX_SCOLON) s = bc_parse_expr(p, 0, bc_parse_next_for); else - s = bc_posix_error("POSIX does not allow an empty init expression in a for loop"); + s = bc_POSIX_does_not_allow_empty_X_expression_in_for("init"); if (s) return s; if (p->l.t.t != BC_LEX_SCOLON) return bc_error_bad_token(); @@ -4230,7 +4242,7 @@ static BcStatus bc_parse_for(BcParse *p) if (p->l.t.t != BC_LEX_SCOLON) s = bc_parse_expr(p, BC_PARSE_REL, bc_parse_next_for); else - s = bc_posix_error("POSIX does not allow an empty condition expression in a for loop"); + s = bc_POSIX_does_not_allow_empty_X_expression_in_for("condition"); if (s) return s; if (p->l.t.t != BC_LEX_SCOLON) return bc_error_bad_token(); @@ -4251,7 +4263,7 @@ static BcStatus bc_parse_for(BcParse *p) if (p->l.t.t != BC_LEX_RPAREN) s = bc_parse_expr(p, 0, bc_parse_next_rel); else - s = bc_posix_error("POSIX does not allow an empty update expression in a for loop"); + s = bc_POSIX_does_not_allow_empty_X_expression_in_for("update"); if (s) return s; @@ -4899,7 +4911,7 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) ok: if (!(flags & BC_PARSE_REL) && nrelops) { - s = bc_posix_error("POSIX does not allow comparison operators outside if or loops"); + s = bc_POSIX_does_not_allow("comparison operators outside if or loops"); if (s) return s; } else if ((flags & BC_PARSE_REL) && nrelops > 1) { -- cgit v1.2.3-55-g6feb From 0d7e46b1de8f11ccff9a5efa5d6d6ea6f5bacabf Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 5 Dec 2018 18:31:19 +0100 Subject: bc: tweak error messages function old new delta bc_lex_token 1285 1299 +14 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index ff44293ab..a78446d04 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -2951,7 +2951,7 @@ static BcStatus bc_lex_identifier(BcLex *l) // buf starts with keyword bc_lex_kws[i] l->t.t = BC_LEX_KEY_1st_keyword + i; if (!((1 << i) & POSIX_KWORD_MASK)) { - s = bc_posix_error_fmt("%sthe following keyword: '%.8s'", "POSIX does not allow ", bc_lex_kws[i].name8); + s = bc_posix_error_fmt("%sthe '%.8s' keyword", "POSIX does not allow ", bc_lex_kws[i].name8); if (s) return s; } @@ -2963,8 +2963,14 @@ static BcStatus bc_lex_identifier(BcLex *l) s = bc_lex_name(l); if (s) return s; - if (l->t.v.len > 2) - s = bc_posix_error_fmt("POSIX only allows one character names; the following is bad: '%s'", buf); + if (l->t.v.len > 2) { + // Prevent this: + // >>> qwe=1 + // bc: POSIX only allows one character names; the following is bad: 'qwe=1 + // ' + unsigned len = strchrnul(buf, '\n') - buf; + s = bc_posix_error_fmt("POSIX only allows one character names; the following is bad: '%.*s'", len, buf); + } return s; } -- cgit v1.2.3-55-g6feb From b692c2faf1e713fe4ec04d34bd6ad77e02dbb5d6 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 5 Dec 2018 18:56:14 +0100 Subject: bc: bc_num_k(): move carry,i,j,len to inner scope This might help compiler function old new delta bc_num_k 957 971 +14 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index a78446d04..ea200ebda 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1639,16 +1639,16 @@ static BcStatus bc_num_k(BcNum *restrict a, BcNum *restrict b, BcNum *restrict c) { BcStatus s; - int carry; - size_t i, j, len, max = BC_MAX(a->len, b->len), max2 = (max + 1) / 2; + size_t max = BC_MAX(a->len, b->len), max2 = (max + 1) / 2; BcNum l1, h1, l2, h2, m2, m1, z0, z1, z2, temp; - bool aone = BC_NUM_ONE(a); + bool aone; if (a->len == 0 || b->len == 0) { bc_num_zero(c); return BC_STATUS_SUCCESS; } - else if (aone || BC_NUM_ONE(b)) { + aone = BC_NUM_ONE(a); + if (aone || BC_NUM_ONE(b)) { bc_num_copy(c, aone ? b : a); return BC_STATUS_SUCCESS; } @@ -1656,13 +1656,17 @@ static BcStatus bc_num_k(BcNum *restrict a, BcNum *restrict b, if (a->len + b->len < BC_NUM_KARATSUBA_LEN || a->len < BC_NUM_KARATSUBA_LEN || b->len < BC_NUM_KARATSUBA_LEN) { + size_t i, j, len; + int carry; + bc_num_expand(c, a->len + b->len + 1); memset(c->num, 0, sizeof(BcDig) * c->cap); - c->len = carry = len = 0; + c->len = len = 0; for (i = 0; i < b->len; ++i) { + carry = 0; for (j = 0; j < a->len; ++j) { int in = (int) c->num[i + j]; in += ((int) a->num[j]) * ((int) b->num[i]) + carry; @@ -1672,7 +1676,6 @@ static BcStatus bc_num_k(BcNum *restrict a, BcNum *restrict b, c->num[i + j] += (BcDig) carry; len = BC_MAX(len, i + j + !!carry); - carry = 0; } c->len = len; -- cgit v1.2.3-55-g6feb From 06fa65bd95455e97d2275ee4d74167f9bfd251c0 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 5 Dec 2018 19:00:58 +0100 Subject: bc: move ^C check fro power calculation to multiplication function old new delta bc_num_k 971 990 +19 bc_num_p 507 478 -29 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/1 up/down: 19/-29) Total: -10 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index ea200ebda..07793e9d4 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1676,6 +1676,10 @@ static BcStatus bc_num_k(BcNum *restrict a, BcNum *restrict b, c->num[i + j] += (BcDig) carry; len = BC_MAX(len, i + j + !!carry); + + // a=2^1000000 + // a*a <- without check below, this will not be interruptible + if (G_interrupt) return BC_STATUS_FAILURE; } c->len = len; @@ -1935,11 +1939,11 @@ static BcStatus bc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) powrdx <<= 1; s = bc_num_mul(©, ©, ©, powrdx); if (s) goto err; - // It is too slow to handle ^C only after entire "2^1000000" completes - if (G_interrupt) { - s = BC_STATUS_FAILURE; - goto err; - } + // Not needed: bc_num_mul() has a check for ^C: + //if (G_interrupt) { + // s = BC_STATUS_FAILURE; + // goto err; + //} } bc_num_copy(c, ©); @@ -1955,11 +1959,11 @@ static BcStatus bc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) s = bc_num_mul(c, ©, c, resrdx); if (s) goto err; } - // It is too slow to handle ^C only after entire "2^1000000" completes - if (G_interrupt) { - s = BC_STATUS_FAILURE; - goto err; - } + // Not needed: bc_num_mul() has a check for ^C: + //if (G_interrupt) { + // s = BC_STATUS_FAILURE; + // goto err; + //} } if (neg) { -- cgit v1.2.3-55-g6feb From b3cb90124bcf1786710c200c00530fd3f213929d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 5 Dec 2018 19:05:32 +0100 Subject: bc: use unsigned division by 10 instead of signed function old new delta bc_num_k 990 988 -2 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 07793e9d4..6dc79118a 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1657,7 +1657,7 @@ static BcStatus bc_num_k(BcNum *restrict a, BcNum *restrict b, a->len < BC_NUM_KARATSUBA_LEN || b->len < BC_NUM_KARATSUBA_LEN) { size_t i, j, len; - int carry; + unsigned carry; bc_num_expand(c, a->len + b->len + 1); @@ -1668,8 +1668,9 @@ static BcStatus bc_num_k(BcNum *restrict a, BcNum *restrict b, carry = 0; for (j = 0; j < a->len; ++j) { - int in = (int) c->num[i + j]; - in += ((int) a->num[j]) * ((int) b->num[i]) + carry; + unsigned in = c->num[i + j]; + in += ((unsigned) a->num[j]) * ((unsigned) b->num[i]) + carry; + // note: compilers prefer _unsigned_ div/const carry = in / 10; c->num[i + j] = (BcDig)(in % 10); } -- cgit v1.2.3-55-g6feb From f381a88234c3fd05177dddceb4da604c7e9462d1 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 5 Dec 2018 19:21:34 +0100 Subject: bc: make division operation interruptible function old new delta bc_num_d 564 584 +20 bc_num_r 230 245 +15 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 35/0) Total: 35 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 6dc79118a..073a113fb 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1840,12 +1840,19 @@ static BcStatus bc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) for (q = 0; (!s && n[len] != 0) || bc_num_compare(n, p, len) >= 0; ++q) bc_num_subArrays(n, p, len); c->num[i] = q; + // a=2^100000 + // scale=40000 + // 1/a <- without check below, this will not be interruptible + if (G_interrupt) { + s = BC_STATUS_FAILURE; + break; + } } bc_num_retireMul(c, scale, a->neg, b->neg); bc_num_free(&cp); - return BC_STATUS_SUCCESS; // can't make void, see bc_num_binary() + return s; } static BcStatus bc_num_r(BcNum *a, BcNum *b, BcNum *restrict c, @@ -1864,7 +1871,8 @@ static BcStatus bc_num_r(BcNum *a, BcNum *b, BcNum *restrict c, } bc_num_init(&temp, d->cap); - bc_num_d(a, b, c, scale); + s = bc_num_d(a, b, c, scale); + if (s) goto err; if (scale != 0) scale = ts; -- cgit v1.2.3-55-g6feb From 6543758b13029509a6b437657eab276045cf7ae0 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 5 Dec 2018 19:37:19 +0100 Subject: bc: code shrink function old new delta bc_parse_operator 181 184 +3 bc_parse_ops 50 25 -25 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/1 up/down: 3/-25) Total: -22 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 073a113fb..9a3bc2743 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -627,11 +627,6 @@ typedef struct BcLex { BC_PARSE_FLAG_LOOP | BC_PARSE_FLAG_LOOP_INNER | BC_PARSE_FLAG_IF | \ BC_PARSE_FLAG_ELSE | BC_PARSE_FLAG_IF_END))) -typedef struct BcOp { - char prec; - bool left; -} BcOp; - typedef struct BcParseNext { uint32_t len; BcLexType tokens[4]; @@ -822,18 +817,22 @@ static const bool bc_parse_exprs[] = { }; // This is an array of data for operators that correspond to token types. -static const BcOp bc_parse_ops[] = { - { 0, false }, { 0, false }, - { 1, false }, - { 2, false }, - { 3, true }, { 3, true }, { 3, true }, - { 4, true }, { 4, true }, - { 6, true }, { 6, true }, { 6, true }, { 6, true }, { 6, true }, { 6, true }, - { 1, false }, - { 7, true }, { 7, true }, - { 5, false }, { 5, false }, { 5, false }, { 5, false }, { 5, false }, - { 5, false }, { 5, false }, +static const uint8_t bc_parse_ops[] = { +#define OP(p,l) ((int)(l) * 0x10 + (p)) + OP(0, false), OP( 0, false ), + OP(1, false), + OP(2, false), + OP(3, true ), OP( 3, true ), OP( 3, true ), + OP(4, true ), OP( 4, true ), + OP(6, true ), OP( 6, true ), OP( 6, true ), OP( 6, true ), OP( 6, true ), OP( 6, true ), + OP(1, false), + OP(7, true ), OP( 7, true ), + OP(5, false), OP( 5, false ), OP( 5, false ), OP( 5, false ), OP( 5, false ), + OP(5, false), OP( 5, false ), +#undef OP }; +#define bc_parse_op_PREC(i) (bc_parse_ops[i] & 0x0f) +#define bc_parse_op_LEFT(i) (bc_parse_ops[i] & 0x10) // These identify what tokens can come after expressions in certain cases. static const BcParseNext bc_parse_next_expr = @@ -3624,15 +3623,15 @@ static BcStatus bc_parse_operator(BcParse *p, BcLexType type, size_t start, { BcStatus s = BC_STATUS_SUCCESS; BcLexType t; - char l, r = bc_parse_ops[type - BC_LEX_OP_INC].prec; - bool left = bc_parse_ops[type - BC_LEX_OP_INC].left; + char l, r = bc_parse_op_PREC(type - BC_LEX_OP_INC); + bool left = bc_parse_op_LEFT(type - BC_LEX_OP_INC); while (p->ops.len > start) { t = BC_PARSE_TOP_OP(p); if (t == BC_LEX_LPAREN) break; - l = bc_parse_ops[t - BC_LEX_OP_INC].prec; + l = bc_parse_op_PREC(t - BC_LEX_OP_INC); if (l >= r && (l != r || !left)) break; bc_parse_push(p, BC_PARSE_TOKEN_INST(t)); -- cgit v1.2.3-55-g6feb From bcb62a7f119173f57104ed353d9718c2f9424049 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 5 Dec 2018 20:17:48 +0100 Subject: bc: code shrink function old new delta bc_parse_expr 2151 2178 +27 bc_parse_exprs 60 - -60 ------------------------------------------------------------------------------ (add/remove: 0/1 grow/shrink: 2/0 up/down: 27/-60) Total: -33 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 54 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 18 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 9a3bc2743..fbe671fd3 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -805,30 +805,48 @@ static void bc_vm_info(void); #if ENABLE_BC -// This is an array that corresponds to token types. An entry is +// This is a bit array that corresponds to token types. An entry is // true if the token is valid in an expression, false otherwise. -static const bool bc_parse_exprs[] = { - false, false, true, true, true, true, true, true, true, true, true, true, - true, true, true, true, true, true, true, true, true, true, true, true, - true, true, true, false, false, true, true, false, false, false, false, - false, false, false, true, true, false, false, false, false, false, false, - false, true, false, true, true, true, true, false, false, true, false, true, - true, false, +enum { + BC_PARSE_EXPRS_BITS = 0 + + ((uint64_t)((0 << 0)+(0 << 1)+(1 << 2)+(1 << 3)+(1 << 4)+(1 << 5)+(1 << 6)+(1 << 7)) << (0*8)) + + ((uint64_t)((1 << 0)+(1 << 1)+(1 << 2)+(1 << 3)+(1 << 4)+(1 << 5)+(1 << 6)+(1 << 7)) << (1*8)) + + ((uint64_t)((1 << 0)+(1 << 1)+(1 << 2)+(1 << 3)+(1 << 4)+(1 << 5)+(1 << 6)+(1 << 7)) << (2*8)) + + ((uint64_t)((1 << 0)+(1 << 1)+(1 << 2)+(0 << 3)+(0 << 4)+(1 << 5)+(1 << 6)+(0 << 7)) << (3*8)) + + ((uint64_t)((0 << 0)+(0 << 1)+(0 << 2)+(0 << 3)+(0 << 4)+(0 << 5)+(1 << 6)+(1 << 7)) << (4*8)) + + ((uint64_t)((0 << 0)+(0 << 1)+(0 << 2)+(0 << 3)+(0 << 4)+(0 << 5)+(0 << 6)+(1 << 7)) << (5*8)) + + ((uint64_t)((0 << 0)+(1 << 1)+(1 << 2)+(1 << 3)+(1 << 4)+(0 << 5)+(0 << 6)+(1 << 7)) << (6*8)) + + ((uint64_t)((0 << 0)+(1 << 1)+(1 << 2)+(0 << 3) ) << (7*8)) }; +static ALWAYS_INLINE long bc_parse_exprs(unsigned i) +{ +#if ULONG_MAX > 0xffffffff + // 64-bit version (will not work correctly for 32-bit longs!) + return BC_PARSE_EXPRS_BITS & (1UL << i); +#else + // 32-bit version + unsigned long m = (uint32_t)BC_PARSE_EXPRS_BITS; + if (i >= 32) { + m = (uint32_t)(BC_PARSE_EXPRS_BITS >> 32); + i &= 31; + } + return m & (1UL << i); +#endif +} // This is an array of data for operators that correspond to token types. static const uint8_t bc_parse_ops[] = { #define OP(p,l) ((int)(l) * 0x10 + (p)) - OP(0, false), OP( 0, false ), - OP(1, false), + OP(0, false), OP( 0, false ), // inc dec + OP(1, false), // neg OP(2, false), - OP(3, true ), OP( 3, true ), OP( 3, true ), - OP(4, true ), OP( 4, true ), - OP(6, true ), OP( 6, true ), OP( 6, true ), OP( 6, true ), OP( 6, true ), OP( 6, true ), - OP(1, false), - OP(7, true ), OP( 7, true ), - OP(5, false), OP( 5, false ), OP( 5, false ), OP( 5, false ), OP( 5, false ), - OP(5, false), OP( 5, false ), + OP(3, true ), OP( 3, true ), OP( 3, true ), // pow mul div + OP(4, true ), OP( 4, true ), // mod + - + OP(6, true ), OP( 6, true ), OP( 6, true ), OP( 6, true ), OP( 6, true ), OP( 6, true ), // == <= >= != < > + OP(1, false), // not + OP(7, true ), OP( 7, true ), // or and + OP(5, false), OP( 5, false ), OP( 5, false ), OP( 5, false ), OP( 5, false ), // ^= *= /= %= += + OP(5, false), OP( 5, false ), // -= = #undef OP }; #define bc_parse_op_PREC(i) (bc_parse_ops[i] & 0x0f) @@ -4708,7 +4726,7 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) paren_expr = rprn = done = get_token = assign = false; bin_last = true; - for (; !G_interrupt && !s && !done && bc_parse_exprs[t]; t = p->l.t.t) { + for (; !G_interrupt && !s && !done && bc_parse_exprs(t); t = p->l.t.t) { switch (t) { case BC_LEX_OP_INC: -- cgit v1.2.3-55-g6feb From 657d6bb26265205556dcf3191f4a7c6ea26e9689 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 5 Dec 2018 20:25:03 +0100 Subject: bc: fix "warning: 's' may be used uninitialized in this function" Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/miscutils/bc.c b/miscutils/bc.c index fbe671fd3..656ecd892 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -6987,6 +6987,7 @@ static BcStatus bc_vm_stdin(void) // with a backslash to the parser. The reason for that is because the parser // treats a backslash+newline combo as whitespace, per the bc spec. In that // case, and for strings and comments, the parser will expect more stuff. + s = BC_STATUS_SUCCESS; while (!G.eof && (s = bc_read_line(&buf, ">>> ")) == BC_STATUS_SUCCESS) { char *string = buf.v; -- cgit v1.2.3-55-g6feb From 452df923f7f5ae47f3076d7da562946af6123ca9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 5 Dec 2018 20:28:26 +0100 Subject: bc: trivial simplification in bc_parse_return() function old new delta bc_parse_stmt 2276 2271 -5 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 656ecd892..b454d4b2b 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -4047,14 +4047,11 @@ static BcStatus bc_parse_return(BcParse *p) else { s = bc_parse_expr(p, 0, bc_parse_next_expr); - if (s && s != BC_STATUS_PARSE_EMPTY_EXP) - return s; - if (s == BC_STATUS_PARSE_EMPTY_EXP) { bc_parse_push(p, BC_INST_RET0); s = bc_lex_next(&p->l); - if (s) return s; } + if (s) return s; if (!paren || p->l.t.last != BC_LEX_RPAREN) { s = bc_posix_error("POSIX requires parentheses around return expressions"); -- cgit v1.2.3-55-g6feb From aad652a69a77401c83546c64fd9ef96bc3c953f1 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 5 Dec 2018 20:33:23 +0100 Subject: bc: remove unused strings text data bss dec hex filename 987088 485 7296 994869 f2e35 busybox_old 987079 485 7296 994860 f2e2c busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index b454d4b2b..0908d7cb9 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -5827,9 +5827,9 @@ static BcStatus bc_program_assign(char inst) static const char *const msg[] = { "bad ibase; must be [2, 16]", //BC_RESULT_IBASE "bad scale; must be [0, BC_SCALE_MAX]", //BC_RESULT_SCALE - "?1", //BC_RESULT_LAST - "?2", //BC_RESULT_CONSTANT - "?3", //BC_RESULT_ONE + NULL, //can't happen //BC_RESULT_LAST + NULL, //can't happen //BC_RESULT_CONSTANT + NULL, //can't happen //BC_RESULT_ONE "bad obase; must be [2, BC_BASE_MAX]", //BC_RESULT_OBASE }; size_t *ptr; -- cgit v1.2.3-55-g6feb From b0e376141067d677c0125be4a6dd3e2c8cb95ed9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 5 Dec 2018 21:03:16 +0100 Subject: bc: reorder functions, delete forward declarations, no code changes Pure block moves of text Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 198 +++++++++++++++++++++++++++------------------------------ 1 file changed, 94 insertions(+), 104 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 0908d7cb9..ef21ab063 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -217,14 +217,6 @@ typedef struct BcNum { typedef BcStatus (*BcNumBinaryOp)(BcNum *, BcNum *, BcNum *, size_t); typedef void (*BcNumDigitOp)(size_t, size_t, bool, size_t *, size_t); -static void bc_num_init(BcNum *n, size_t req); -static void bc_num_expand(BcNum *n, size_t req); -static void bc_num_copy(BcNum *d, BcNum *s); -static void bc_num_free(void *num); - -static BcStatus bc_num_ulong(BcNum *n, unsigned long *result); -static void bc_num_ulong2num(BcNum *n, unsigned long val); - static BcStatus bc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale); static BcStatus bc_num_sub(BcNum *a, BcNum *b, BcNum *c, size_t scale); static BcStatus bc_num_mul(BcNum *a, BcNum *b, BcNum *c, size_t scale); @@ -387,7 +379,6 @@ typedef struct BcInstPtr { size_t len; } BcInstPtr; -static void bc_array_expand(BcVec *a, size_t len); static int bc_id_cmp(const void *e1, const void *e2); // BC_LEX_NEG is not used in lexing; it is only for parsing. @@ -798,11 +789,8 @@ struct globals { #define G_exreg (ENABLE_DC && (option_mask32 & BC_FLAG_X)) #define G_interrupt (ENABLE_FEATURE_BC_SIGNALS ? bb_got_signal : 0) - #define IS_BC (ENABLE_BC && (!ENABLE_DC || applet_name[0] == 'b')) -static void bc_vm_info(void); - #if ENABLE_BC // This is a bit array that corresponds to token types. An entry is @@ -1046,6 +1034,15 @@ static int bc_error_nested_read_call(void) return bc_error("read() call inside of a read() call"); } +static void bc_vm_info(void) +{ + printf("%s "BB_VER"\n" + "Copyright (c) 2018 Gavin D. Howard and contributors\n" + "Report bugs at: https://github.com/gavinhoward/bc\n" + "This is free software with ABSOLUTELY NO WARRANTY\n" + , applet_name); +} + static void bc_vec_grow(BcVec *v, size_t n) { size_t cap = v->cap * 2; @@ -1351,6 +1348,74 @@ static void bc_num_ten(BcNum *n) n->num[1] = 1; } +static void bc_num_init(BcNum *n, size_t req) +{ + req = req >= BC_NUM_DEF_SIZE ? req : BC_NUM_DEF_SIZE; + memset(n, 0, sizeof(BcNum)); + n->num = xmalloc(req); + n->cap = req; +} + +static void bc_num_expand(BcNum *n, size_t req) +{ + req = req >= BC_NUM_DEF_SIZE ? req : BC_NUM_DEF_SIZE; + if (req > n->cap) { + n->num = xrealloc(n->num, req); + n->cap = req; + } +} + +static void bc_num_free(void *num) +{ + free(((BcNum *) num)->num); +} + +static void bc_num_copy(BcNum *d, BcNum *s) +{ + if (d != s) { + bc_num_expand(d, s->cap); + d->len = s->len; + d->neg = s->neg; + d->rdx = s->rdx; + memcpy(d->num, s->num, sizeof(BcDig) * d->len); + } +} + +static BcStatus bc_num_ulong(BcNum *n, unsigned long *result) +{ + size_t i; + unsigned long pow; + + if (n->neg) return bc_error("negative number"); + + for (*result = 0, pow = 1, i = n->rdx; i < n->len; ++i) { + + unsigned long prev = *result, powprev = pow; + + *result += ((unsigned long) n->num[i]) * pow; + pow *= 10; + + if (*result < prev || pow < powprev) + return bc_error("overflow"); + } + + return BC_STATUS_SUCCESS; +} + +static void bc_num_ulong2num(BcNum *n, unsigned long val) +{ + size_t len; + BcDig *ptr; + unsigned long i; + + bc_num_zero(n); + + if (val == 0) return; + + for (len = 1, i = ULONG_MAX; i != 0; i /= 10, ++len) bc_num_expand(n, len); + for (ptr = n->num, i = 0; val; ++i, ++n->len, val /= 10) ptr[i] = val % 10; +} + static void bc_num_subArrays(BcDig *restrict a, BcDig *restrict b, size_t len) { @@ -2343,39 +2408,6 @@ static BcStatus bc_num_stream(BcNum *n, BcNum *base, size_t *nchars, size_t len) } #endif -static void bc_num_init(BcNum *n, size_t req) -{ - req = req >= BC_NUM_DEF_SIZE ? req : BC_NUM_DEF_SIZE; - memset(n, 0, sizeof(BcNum)); - n->num = xmalloc(req); - n->cap = req; -} - -static void bc_num_expand(BcNum *n, size_t req) -{ - req = req >= BC_NUM_DEF_SIZE ? req : BC_NUM_DEF_SIZE; - if (req > n->cap) { - n->num = xrealloc(n->num, req); - n->cap = req; - } -} - -static void bc_num_free(void *num) -{ - free(((BcNum *) num)->num); -} - -static void bc_num_copy(BcNum *d, BcNum *s) -{ - if (d != s) { - bc_num_expand(d, s->cap); - d->len = s->len; - d->neg = s->neg; - d->rdx = s->rdx; - memcpy(d->num, s->num, sizeof(BcDig) * d->len); - } -} - static BcStatus bc_num_parse(BcNum *n, const char *val, BcNum *base, size_t base_t) { @@ -2414,41 +2446,6 @@ static BcStatus bc_num_print(BcNum *n, BcNum *base, size_t base_t, bool newline, return s; } -static BcStatus bc_num_ulong(BcNum *n, unsigned long *result) -{ - size_t i; - unsigned long pow; - - if (n->neg) return bc_error("negative number"); - - for (*result = 0, pow = 1, i = n->rdx; i < n->len; ++i) { - - unsigned long prev = *result, powprev = pow; - - *result += ((unsigned long) n->num[i]) * pow; - pow *= 10; - - if (*result < prev || pow < powprev) - return bc_error("overflow"); - } - - return BC_STATUS_SUCCESS; -} - -static void bc_num_ulong2num(BcNum *n, unsigned long val) -{ - size_t len; - BcDig *ptr; - unsigned long i; - - bc_num_zero(n); - - if (val == 0) return; - - for (len = 1, i = ULONG_MAX; i != 0; i /= 10, ++len) bc_num_expand(n, len); - for (ptr = n->num, i = 0; val; ++i, ++n->len, val /= 10) ptr[i] = val % 10; -} - static BcStatus bc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale) { BcNumBinaryOp op = (!a->neg == !b->neg) ? bc_num_a : bc_num_s; @@ -2712,6 +2709,8 @@ static void bc_func_free(void *func) bc_vec_free(&f->labels); } +static void bc_array_expand(BcVec *a, size_t len); + static void bc_array_init(BcVec *a, bool nums) { if (nums) @@ -2721,21 +2720,6 @@ static void bc_array_init(BcVec *a, bool nums) bc_array_expand(a, 1); } -static void bc_array_copy(BcVec *d, const BcVec *s) -{ - size_t i; - - bc_vec_pop_all(d); - bc_vec_expand(d, s->cap); - d->len = s->len; - - for (i = 0; i < s->len; ++i) { - BcNum *dnum = bc_vec_item(d, i), *snum = bc_vec_item(s, i); - bc_num_init(dnum, snum->len); - bc_num_copy(dnum, snum); - } -} - static void bc_array_expand(BcVec *a, size_t len) { BcResultData data; @@ -2754,6 +2738,21 @@ static void bc_array_expand(BcVec *a, size_t len) } } +static void bc_array_copy(BcVec *d, const BcVec *s) +{ + size_t i; + + bc_vec_pop_all(d); + bc_vec_expand(d, s->cap); + d->len = s->len; + + for (i = 0; i < s->len; ++i) { + BcNum *dnum = bc_vec_item(d, i), *snum = bc_vec_item(s, i); + bc_num_init(dnum, snum->len); + bc_num_copy(dnum, snum); + } +} + static void bc_string_free(void *string) { free(*((char **) string)); @@ -6854,15 +6853,6 @@ static BcStatus bc_program_exec(void) return s; } -static void bc_vm_info(void) -{ - printf("%s "BB_VER"\n" - "Copyright (c) 2018 Gavin D. Howard and contributors\n" - "Report bugs at: https://github.com/gavinhoward/bc\n" - "This is free software with ABSOLUTELY NO WARRANTY\n" - , applet_name); -} - #if ENABLE_BC static void bc_vm_envArgs(void) { -- cgit v1.2.3-55-g6feb From cca79a00647ff05229265192063183677a66a4d6 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 5 Dec 2018 21:15:46 +0100 Subject: bc: reorder functions, delete forward declarations, no code changes - part 2 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 67 +++++++++++++++++++++++----------------------------------- 1 file changed, 27 insertions(+), 40 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index ef21ab063..d2713ceee 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -379,8 +379,6 @@ typedef struct BcInstPtr { size_t len; } BcInstPtr; -static int bc_id_cmp(const void *e1, const void *e2); - // BC_LEX_NEG is not used in lexing; it is only for parsing. typedef enum BcLexType { @@ -656,34 +654,6 @@ typedef struct BcParse { } BcParse; -#if ENABLE_BC - -static BcStatus bc_lex_token(BcLex *l); - -#define BC_PARSE_TOP_OP(p) (*((BcLexType *) bc_vec_top(&(p)->ops))) -#define BC_PARSE_LEAF(p, rparen) \ - (((p) >= BC_INST_NUM && (p) <= BC_INST_SQRT) || (rparen) || \ - (p) == BC_INST_INC_POST || (p) == BC_INST_DEC_POST) - -// We can calculate the conversion between tokens and exprs by subtracting the -// position of the first operator in the lex enum and adding the position of the -// first in the expr enum. Note: This only works for binary operators. -#define BC_PARSE_TOKEN_INST(t) ((char) ((t) -BC_LEX_NEG + BC_INST_NEG)) - -static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next); - -#endif // ENABLE_BC - -#if ENABLE_DC - -#define DC_PARSE_BUF_LEN ((int) (sizeof(uint32_t) * CHAR_BIT)) - -static BcStatus dc_lex_token(BcLex *l); - -static BcStatus dc_parse_expr(BcParse *p, uint8_t flags); - -#endif // ENABLE_DC - typedef struct BcProgram { size_t len; @@ -1165,6 +1135,16 @@ static void bc_vec_free(void *vec) free(v->v); } +static int bc_id_cmp(const void *e1, const void *e2) +{ + return strcmp(((const BcId *) e1)->name, ((const BcId *) e2)->name); +} + +static void bc_id_free(void *id) +{ + free(((BcId *) id)->name); +} + static size_t bc_map_find(const BcVec *v, const void *ptr) { size_t low = 0, high = v->len; @@ -2665,16 +2645,6 @@ err: } #endif // ENABLE_DC -static int bc_id_cmp(const void *e1, const void *e2) -{ - return strcmp(((const BcId *) e1)->name, ((const BcId *) e2)->name); -} - -static void bc_id_free(void *id) -{ - free(((BcId *) id)->name); -} - static BcStatus bc_func_insert(BcFunc *f, char *name, bool var) { BcId a; @@ -3632,8 +3602,20 @@ static void bc_parse_create(BcParse *p, size_t func, } #if ENABLE_BC + +#define BC_PARSE_TOP_OP(p) (*((BcLexType *) bc_vec_top(&(p)->ops))) +#define BC_PARSE_LEAF(p, rparen) \ + (((p) >= BC_INST_NUM && (p) <= BC_INST_SQRT) || (rparen) || \ + (p) == BC_INST_INC_POST || (p) == BC_INST_DEC_POST) + +// We can calculate the conversion between tokens and exprs by subtracting the +// position of the first operator in the lex enum and adding the position of the +// first in the expr enum. Note: This only works for binary operators. +#define BC_PARSE_TOKEN_INST(t) ((char) ((t) -BC_LEX_NEG + BC_INST_NEG)) + static BcStatus bc_parse_else(BcParse *p); static BcStatus bc_parse_stmt(BcParse *p); +static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next); static BcStatus bc_parse_operator(BcParse *p, BcLexType type, size_t start, size_t *nexprs, bool next) @@ -4971,9 +4953,13 @@ static BcStatus bc_parse_expression(BcParse *p, uint8_t flags) { return bc_parse_expr(p, flags, bc_parse_next_read); } + #endif // ENABLE_BC #if ENABLE_DC + +#define DC_PARSE_BUF_LEN ((int) (sizeof(uint32_t) * CHAR_BIT)) + static BcStatus dc_parse_register(BcParse *p) { BcStatus s; @@ -5196,6 +5182,7 @@ static void dc_parse_init(BcParse *p, size_t func) { bc_parse_create(p, func, dc_parse_parse, dc_lex_token); } + #endif // ENABLE_DC static void common_parse_init(BcParse *p, size_t func) -- cgit v1.2.3-55-g6feb From 050b0fe9a7b5a3e4aab1d308637ae6a3bb0a67cb Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 5 Dec 2018 22:40:44 +0100 Subject: bc: do not allow "()" as a valid expression function old new delta bc_parse_expr_empty_ok - 2178 +2178 bc_parse_expr 2178 49 -2129 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 0/1 up/down: 2178/-2129) Total: 49 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index d2713ceee..eb5aff5e2 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -3616,6 +3616,7 @@ static void bc_parse_create(BcParse *p, size_t func, static BcStatus bc_parse_else(BcParse *p); static BcStatus bc_parse_stmt(BcParse *p); static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next); +static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext next); static BcStatus bc_parse_operator(BcParse *p, BcLexType type, size_t start, size_t *nexprs, bool next) @@ -4027,7 +4028,7 @@ static BcStatus bc_parse_return(BcParse *p) bc_parse_push(p, BC_INST_RET0); else { - s = bc_parse_expr(p, 0, bc_parse_next_expr); + s = bc_parse_expr_empty_ok(p, 0, bc_parse_next_expr); if (s == BC_STATUS_PARSE_EMPTY_EXP) { bc_parse_push(p, BC_INST_RET0); s = bc_lex_next(&p->l); @@ -4690,7 +4691,7 @@ static BcStatus bc_parse_parse(BcParse *p) return s; } -static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) +static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext next) { BcStatus s = BC_STATUS_SUCCESS; BcInst prev = BC_INST_PRINT; @@ -4944,6 +4945,16 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) return s; } +static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) +{ + BcStatus s; + + s = bc_parse_expr_empty_ok(p, flags, next); + if (s == BC_STATUS_PARSE_EMPTY_EXP) + return bc_error("empty expression"); + return s; +} + static void bc_parse_init(BcParse *p, size_t func) { bc_parse_create(p, func, bc_parse_parse, bc_lex_token); -- cgit v1.2.3-55-g6feb From e873ff9660a2f02a4b2647b74212e74649726e7d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 6 Dec 2018 00:29:22 +0100 Subject: bc: if FEATURE_CLEAN_UP, clean up allocations on exits Will have exitcode 1 even on "quit" and "halt", is it a problem? Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 43 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index eb5aff5e2..5966953d2 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -754,6 +754,9 @@ struct globals { #define INIT_G() do { \ SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ } while (0) +#define FREE_G() do { \ + FREE_PTR_TO_GLOBALS(); \ +} while (0) #define G_posix (ENABLE_BC && (option_mask32 & BC_FLAG_S)) #define G_warn (ENABLE_BC && (option_mask32 & BC_FLAG_W)) #define G_exreg (ENABLE_DC && (option_mask32 & BC_FLAG_X)) @@ -898,6 +901,16 @@ static void fflush_and_check(void) bb_perror_msg_and_die("output error"); } +#if ENABLE_FEATURE_CLEAN_UP +#define quit_or_return_for_exit() \ +do { \ + G.ttyin = 0; /* do not loop in main loop anymore */ \ + return BC_STATUS_FAILURE; \ +} while (0) +#else +#define quit_or_return_for_exit() quit() +#endif + static void quit(void) NORETURN; static void quit(void) { @@ -929,7 +942,7 @@ static NOINLINE int bc_error_fmt(const char *fmt, ...) bc_verror_msg(fmt, p); va_end(p); - if (!G.ttyin) + if (!ENABLE_FEATURE_CLEAN_UP && !G.ttyin) exit(1); return BC_STATUS_FAILURE; } @@ -949,7 +962,7 @@ static NOINLINE int bc_posix_error_fmt(const char *fmt, ...) // Do we treat non-POSIX constructs as errors? if (!(option_mask32 & BC_FLAG_S)) return BC_STATUS_SUCCESS; // no, it's a warning - if (!G.ttyin) + if (!ENABLE_FEATURE_CLEAN_UP && !G.ttyin) exit(1); return BC_STATUS_FAILURE; } @@ -4645,7 +4658,7 @@ static BcStatus bc_parse_stmt(BcParse *p) // "quit" is a compile-time command. For example, // "if (0 == 1) quit" terminates when parsing the statement, // not when it is executed - quit(); + quit_or_return_for_exit(); } case BC_LEX_KEY_RETURN: @@ -6347,8 +6360,11 @@ static BcStatus bc_program_nquit(void) if (G.prog.stack.len < val) return bc_error_stack_has_too_few_elements(); - if (G.prog.stack.len == val) + if (G.prog.stack.len == val) { + if (ENABLE_FEATURE_CLEAN_UP) + return BC_STATUS_FAILURE; quit(); + } bc_vec_npop(&G.prog.stack, val); @@ -6579,7 +6595,7 @@ static BcStatus bc_program_exec(void) case BC_INST_HALT: { - quit(); + quit_or_return_for_exit(); break; } @@ -6824,7 +6840,7 @@ static BcStatus bc_program_exec(void) case BC_INST_QUIT: { if (G.prog.stack.len <= 2) - quit(); + quit_or_return_for_exit(); bc_vec_npop(&G.prog.stack, 2); break; } @@ -7018,6 +7034,12 @@ static BcStatus bc_vm_stdin(void) bc_vec_concat(&buffer, buf.v); s = bc_vm_process(buffer.v); if (s) { + if (ENABLE_FEATURE_CLEAN_UP && !G.ttyin) { + // Debug config, non-interactive mode: + // return all the way back to main. + // Non-debug builds do not come here, they exit. + break; + } fflush_and_check(); fputs("ready for more input\n", stderr); } @@ -7241,6 +7263,12 @@ static BcStatus bc_vm_exec(void) for (i = 0; !s && i < G.files.len; ++i) s = bc_vm_file(*((char **) bc_vec_item(&G.files, i))); if (s) { + if (ENABLE_FEATURE_CLEAN_UP && !G.ttyin) { + // Debug config, non-interactive mode: + // return all the way back to main. + // Non-debug builds do not come here, they exit. + return s; + } fflush_and_check(); fputs("ready for more input\n", stderr); } @@ -7254,7 +7282,7 @@ static BcStatus bc_vm_exec(void) } #if ENABLE_FEATURE_CLEAN_UP -static void bc_program_free() +static void bc_program_free(void) { bc_num_free(&G.prog.ib); bc_num_free(&G.prog.ob); @@ -7397,6 +7425,7 @@ static BcStatus bc_vm_run(int argc, char *argv[], #if ENABLE_FEATURE_CLEAN_UP bc_vm_free(); + FREE_G(); #endif return st; } -- cgit v1.2.3-55-g6feb From 1ff1c7094403fa96acce46611e7bf9534f2d8404 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 6 Dec 2018 00:46:09 +0100 Subject: bc: make bc_vm_envArgs() NULL-terminate its argv, simplify bc_vm_envLen() function old new delta bc_num_ulong 92 103 +11 static.nullptr - 4 +4 bc_args 120 123 +3 static.bc_args_env_name 4 - -4 dc_main 49 41 -8 bc_main 49 41 -8 bc_vm_run 1917 1883 -34 ------------------------------------------------------------------------------ (add/remove: 1/1 grow/shrink: 2/3 up/down: 18/-54) Total: -36 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 87 +++++++++++++++++++++++++--------------------------------- 1 file changed, 38 insertions(+), 49 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 5966953d2..e9cfecccc 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1284,14 +1284,14 @@ static char* bc_read_file(const char *path) return buf; } -static void bc_args(int argc, char **argv) +static void bc_args(char **argv) { unsigned opts; int i; GETOPT_RESET(); #if ENABLE_FEATURE_BC_LONG_OPTIONS - opts = getopt32long(argv, "xwvsqli", + opts = option_mask32 |= getopt32long(argv, "xwvsqli", "extended-register\0" No_argument "x" "warn\0" No_argument "w" "version\0" No_argument "v" @@ -1301,16 +1301,15 @@ static void bc_args(int argc, char **argv) "interactive\0" No_argument "i" ); #else - opts = getopt32(argv, "xwvsqli"); + opts = option_mask32 |= getopt32(argv, "xwvsqli"); #endif if (getenv("POSIXLY_CORRECT")) option_mask32 |= BC_FLAG_S; +///should be in bc_vm_run() instead?? if (opts & BC_FLAG_V) bc_vm_info(); - // should not be necessary, getopt32() handles this?? - //if (argv[optind] && !strcmp(argv[optind], "--")) ++optind; - for (i = optind; i < argc; ++i) + for (i = optind; argv[i]; ++i) bc_vec_push(&G.files, argv + i); } @@ -6870,10 +6869,11 @@ static BcStatus bc_program_exec(void) #if ENABLE_BC static void bc_vm_envArgs(void) { - static const char* const bc_args_env_name = "BC_ENV_ARGS"; + static char *const nullptr = NULL; BcVec v; - char *env_args = getenv(bc_args_env_name), *buf; + char *env_args = getenv("BC_ENV_ARGS"); + char *buf; if (!env_args) return; @@ -6881,40 +6881,34 @@ static void bc_vm_envArgs(void) buf = G.env_args; bc_vec_init(&v, sizeof(char *), NULL); - bc_vec_push(&v, &bc_args_env_name); + bc_vec_push(&v, &nullptr); - while (*buf != 0) { - if (!isspace(*buf)) { - bc_vec_push(&v, &buf); - while (*buf != 0 && !isspace(*buf)) ++buf; - if (*buf != 0) (*(buf++)) = '\0'; - } - else - ++buf; + while (*(buf = skip_whitespace(buf)) != '\0') { + bc_vec_push(&v, &buf); + buf = skip_non_whitespace(buf); + if (!*buf) + break; + *buf++ = '\0'; } - bc_args((int) v.len, (char **) v.v); + bc_vec_push(&v, &nullptr); + bc_args((char **) v.v); bc_vec_free(&v); } #endif // ENABLE_BC -static size_t bc_vm_envLen(const char *var) +static unsigned bc_vm_envLen(const char *var) { - char *lenv = getenv(var); - size_t i, len = BC_NUM_PRINT_WIDTH; - int num; + char *lenv; + unsigned len; + lenv = getenv(var); + len = BC_NUM_PRINT_WIDTH; if (!lenv) return len; - len = strlen(lenv); - - for (num = 1, i = 0; num && i < len; ++i) num = isdigit(lenv[i]); - if (num) { - len = (size_t) atoi(lenv) - 1; - if (len < 2 || len >= INT32_MAX) len = BC_NUM_PRINT_WIDTH; - } - else + len = bb_strtou(lenv, NULL, 10) - 1; + if (errno || len < 2 || len >= INT_MAX) len = BC_NUM_PRINT_WIDTH; return len; @@ -7314,7 +7308,7 @@ static void bc_vm_free(void) } #endif -static void bc_program_init(size_t line_len) +static void bc_program_init(void) { size_t idx; BcInstPtr ip; @@ -7323,7 +7317,6 @@ static void bc_program_init(size_t line_len) memset(&ip, 0, sizeof(BcInstPtr)); /* G.prog.nchars = G.prog.scale = 0; - already is */ - G.prog.len = line_len; bc_num_init(&G.prog.ib, BC_NUM_DEF_SIZE); bc_num_ten(&G.prog.ib); @@ -7370,17 +7363,12 @@ static void bc_program_init(size_t line_len) bc_vec_push(&G.prog.stack, &ip); } -static void bc_vm_init(const char *env_len) +static void bc_vm_init(void) { - size_t len = bc_vm_envLen(env_len); - bc_vec_init(&G.files, sizeof(char *), NULL); - - if (IS_BC) { + if (IS_BC) bc_vm_envArgs(); - } - - bc_program_init(len); + bc_program_init(); if (IS_BC) { bc_parse_init(&G.prs, BC_PROG_MAIN); } else { @@ -7388,16 +7376,16 @@ static void bc_vm_init(const char *env_len) } } -static BcStatus bc_vm_run(int argc, char *argv[], - const char *env_len) +static BcStatus bc_vm_run(char **argv, const char *env_len) { BcStatus st; - bc_vm_init(env_len); - bc_args(argc, argv); + G.prog.len = bc_vm_envLen(env_len); - G.ttyin = isatty(0); + bc_vm_init(); + bc_args(argv); + G.ttyin = isatty(0); if (G.ttyin) { #if ENABLE_FEATURE_BC_SIGNALS // With SA_RESTART, most system calls will restart @@ -7421,6 +7409,7 @@ static BcStatus bc_vm_run(int argc, char *argv[], if (!(option_mask32 & BC_FLAG_Q)) bc_vm_info(); } + st = bc_vm_exec(); #if ENABLE_FEATURE_CLEAN_UP @@ -7432,23 +7421,23 @@ static BcStatus bc_vm_run(int argc, char *argv[], #if ENABLE_BC int bc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; -int bc_main(int argc, char **argv) +int bc_main(int argc UNUSED_PARAM, char **argv) { INIT_G(); G.sbgn = G.send = '"'; - return bc_vm_run(argc, argv, "BC_LINE_LENGTH"); + return bc_vm_run(argv, "BC_LINE_LENGTH"); } #endif #if ENABLE_DC int dc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; -int dc_main(int argc, char **argv) +int dc_main(int argc UNUSED_PARAM, char **argv) { INIT_G(); G.sbgn = '['; G.send = ']'; - return bc_vm_run(argc, argv, "DC_LINE_LENGTH"); + return bc_vm_run(argv, "DC_LINE_LENGTH"); } #endif -- cgit v1.2.3-55-g6feb From 54214c38db943e7b3541e841f5b7399e36047f70 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 6 Dec 2018 09:07:06 +0100 Subject: bc: fix "bc -v" printing version info twice, and not exiting function old new delta bc_args 123 130 +7 bc_num_binary 150 148 -2 static.nullptr 4 - -4 bc_vm_run 1883 1874 -9 ------------------------------------------------------------------------------ (add/remove: 0/1 grow/shrink: 1/2 up/down: 7/-15) Total: -8 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 94 +++++++++++++++++++++++++++++++--------------------------- 1 file changed, 50 insertions(+), 44 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index e9cfecccc..0943f606d 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1017,15 +1017,6 @@ static int bc_error_nested_read_call(void) return bc_error("read() call inside of a read() call"); } -static void bc_vm_info(void) -{ - printf("%s "BB_VER"\n" - "Copyright (c) 2018 Gavin D. Howard and contributors\n" - "Report bugs at: https://github.com/gavinhoward/bc\n" - "This is free software with ABSOLUTELY NO WARRANTY\n" - , applet_name); -} - static void bc_vec_grow(BcVec *v, size_t n) { size_t cap = v->cap * 2; @@ -1284,35 +1275,6 @@ static char* bc_read_file(const char *path) return buf; } -static void bc_args(char **argv) -{ - unsigned opts; - int i; - - GETOPT_RESET(); -#if ENABLE_FEATURE_BC_LONG_OPTIONS - opts = option_mask32 |= getopt32long(argv, "xwvsqli", - "extended-register\0" No_argument "x" - "warn\0" No_argument "w" - "version\0" No_argument "v" - "standard\0" No_argument "s" - "quiet\0" No_argument "q" - "mathlib\0" No_argument "l" - "interactive\0" No_argument "i" - ); -#else - opts = option_mask32 |= getopt32(argv, "xwvsqli"); -#endif - if (getenv("POSIXLY_CORRECT")) - option_mask32 |= BC_FLAG_S; - -///should be in bc_vm_run() instead?? - if (opts & BC_FLAG_V) bc_vm_info(); - - for (i = optind; argv[i]; ++i) - bc_vec_push(&G.files, argv + i); -} - static void bc_num_setToZero(BcNum *n, size_t scale) { n->len = 0; @@ -6866,14 +6828,53 @@ static BcStatus bc_program_exec(void) return s; } +static void bc_vm_info(void) +{ + printf("%s "BB_VER"\n" + "Copyright (c) 2018 Gavin D. Howard and contributors\n" + "Report bugs at: https://github.com/gavinhoward/bc\n" + "This is free software with ABSOLUTELY NO WARRANTY\n" + , applet_name); +} + +static void bc_args(char **argv) +{ + unsigned opts; + int i; + + GETOPT_RESET(); +#if ENABLE_FEATURE_BC_LONG_OPTIONS + opts = option_mask32 |= getopt32long(argv, "xwvsqli", + "extended-register\0" No_argument "x" + "warn\0" No_argument "w" + "version\0" No_argument "v" + "standard\0" No_argument "s" + "quiet\0" No_argument "q" + "mathlib\0" No_argument "l" + "interactive\0" No_argument "i" + ); +#else + opts = option_mask32 |= getopt32(argv, "xwvsqli"); +#endif + if (getenv("POSIXLY_CORRECT")) + option_mask32 |= BC_FLAG_S; + +///should be in bc_vm_run() instead?? + if (opts & BC_FLAG_V) { + bc_vm_info(); + exit(0); + } + + for (i = optind; argv[i]; ++i) + bc_vec_push(&G.files, argv + i); +} + #if ENABLE_BC static void bc_vm_envArgs(void) { - static char *const nullptr = NULL; - BcVec v; - char *env_args = getenv("BC_ENV_ARGS"); char *buf; + char *env_args = getenv("BC_ENV_ARGS"); if (!env_args) return; @@ -6881,7 +6882,6 @@ static void bc_vm_envArgs(void) buf = G.env_args; bc_vec_init(&v, sizeof(char *), NULL); - bc_vec_push(&v, &nullptr); while (*(buf = skip_whitespace(buf)) != '\0') { bc_vec_push(&v, &buf); @@ -6891,8 +6891,14 @@ static void bc_vm_envArgs(void) *buf++ = '\0'; } - bc_vec_push(&v, &nullptr); - bc_args((char **) v.v); + // NULL terminate, and pass argv[] so that first arg is argv[1] + if (sizeof(int) == sizeof(char*)) { + bc_vec_push(&v, &const_int_0); + } else { + static char *const nullptr = NULL; + bc_vec_push(&v, &nullptr); + } + bc_args(((char **)v.v) - 1); bc_vec_free(&v); } -- cgit v1.2.3-55-g6feb From 1a6a482d19b9226ef764de89283cebdacdce77aa Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 6 Dec 2018 09:20:32 +0100 Subject: bc: if ^C handling is not selected, there is no interactive mode function old new delta packed_usage 33023 33076 +53 bc_num_s 252 246 -6 bc_vm_run 1859 1850 -9 bc_error_fmt 36 20 -16 bc_posix_error_fmt 58 41 -17 bc_read_line 202 168 -34 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/5 up/down: 53/-82) Total: -29 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 0943f606d..ee4f21364 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -116,7 +116,7 @@ //See www.gnu.org/software/bc/manual/bc.html //usage:#define bc_trivial_usage -//usage: "[-sqli] FILE..." +//usage: "[-sqliw] FILE..." //usage: //usage:#define bc_full_usage "\n" //usage: "\nArbitrary precision calculator" @@ -127,6 +127,7 @@ //usage: "\n -q Quiet" //usage: "\n -w Warn if extensions are used" ///////: "\n -v Version" +//usage: "\n$BC_LINE_LENGTH changes output width" //usage: //usage:#define bc_example_usage //usage: "3 + 4.129\n" @@ -734,7 +735,7 @@ static void bc_program_reset(void); #define BC_MAX_VARS ((unsigned long) SIZE_MAX - 1) struct globals { - smallint ttyin; + IF_FEATURE_BC_SIGNALS(smallint ttyin;) smallint eof; char sbgn; char send; @@ -761,7 +762,11 @@ struct globals { #define G_warn (ENABLE_BC && (option_mask32 & BC_FLAG_W)) #define G_exreg (ENABLE_DC && (option_mask32 & BC_FLAG_X)) #define G_interrupt (ENABLE_FEATURE_BC_SIGNALS ? bb_got_signal : 0) - +#if ENABLE_FEATURE_BC_SIGNALS +# define G_ttyin G.ttyin +#else +# define G_ttyin 0 +#endif #define IS_BC (ENABLE_BC && (!ENABLE_DC || applet_name[0] == 'b')) #if ENABLE_BC @@ -904,7 +909,7 @@ static void fflush_and_check(void) #if ENABLE_FEATURE_CLEAN_UP #define quit_or_return_for_exit() \ do { \ - G.ttyin = 0; /* do not loop in main loop anymore */ \ + IF_FEATURE_BC_SIGNALS(G_ttyin = 0;) /* do not loop in main loop anymore */ \ return BC_STATUS_FAILURE; \ } while (0) #else @@ -942,7 +947,7 @@ static NOINLINE int bc_error_fmt(const char *fmt, ...) bc_verror_msg(fmt, p); va_end(p); - if (!ENABLE_FEATURE_CLEAN_UP && !G.ttyin) + if (!ENABLE_FEATURE_CLEAN_UP && !G_ttyin) exit(1); return BC_STATUS_FAILURE; } @@ -962,7 +967,7 @@ static NOINLINE int bc_posix_error_fmt(const char *fmt, ...) // Do we treat non-POSIX constructs as errors? if (!(option_mask32 & BC_FLAG_S)) return BC_STATUS_SUCCESS; // no, it's a warning - if (!ENABLE_FEATURE_CLEAN_UP && !G.ttyin) + if (!ENABLE_FEATURE_CLEAN_UP && !G_ttyin) exit(1); return BC_STATUS_FAILURE; } @@ -1211,7 +1216,7 @@ static BcStatus bc_read_line(BcVec *vec, const char *prompt) , stderr); } #endif - if (G.ttyin && !G_posix) + if (G_ttyin && !G_posix) fputs(prompt, stderr); #if ENABLE_FEATURE_BC_SIGNALS @@ -7034,7 +7039,7 @@ static BcStatus bc_vm_stdin(void) bc_vec_concat(&buffer, buf.v); s = bc_vm_process(buffer.v); if (s) { - if (ENABLE_FEATURE_CLEAN_UP && !G.ttyin) { + if (ENABLE_FEATURE_CLEAN_UP && !G_ttyin) { // Debug config, non-interactive mode: // return all the way back to main. // Non-debug builds do not come here, they exit. @@ -7263,7 +7268,7 @@ static BcStatus bc_vm_exec(void) for (i = 0; !s && i < G.files.len; ++i) s = bc_vm_file(*((char **) bc_vec_item(&G.files, i))); if (s) { - if (ENABLE_FEATURE_CLEAN_UP && !G.ttyin) { + if (ENABLE_FEATURE_CLEAN_UP && !G_ttyin) { // Debug config, non-interactive mode: // return all the way back to main. // Non-debug builds do not come here, they exit. @@ -7391,9 +7396,9 @@ static BcStatus bc_vm_run(char **argv, const char *env_len) bc_vm_init(); bc_args(argv); - G.ttyin = isatty(0); - if (G.ttyin) { + if (isatty(0)) { #if ENABLE_FEATURE_BC_SIGNALS + G_ttyin = 1; // With SA_RESTART, most system calls will restart // (IOW: they won't fail with EINTR). // In particular, this means ^C won't cause -- cgit v1.2.3-55-g6feb From ed849351d11d9f5bb9519baa52e8c1e9d3615ca9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 6 Dec 2018 10:26:13 +0100 Subject: bc: add preparatory indent block, no code changes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 60 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index ee4f21364..90c3bf5d6 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1216,41 +1216,41 @@ static BcStatus bc_read_line(BcVec *vec, const char *prompt) , stderr); } #endif - if (G_ttyin && !G_posix) - fputs(prompt, stderr); + { + if (G_ttyin && !G_posix) + fputs(prompt, stderr); + IF_FEATURE_BC_SIGNALS(errno = 0;) + do { + i = fgetc(stdin); + if (i == EOF) { #if ENABLE_FEATURE_BC_SIGNALS - errno = 0; + // Both conditions appear simultaneously, check both just in case + if (errno == EINTR || bb_got_signal) { + // ^C was pressed + clearerr(stdin); + goto intr; + } #endif - do { - i = fgetc(stdin); - if (i == EOF) { -#if ENABLE_FEATURE_BC_SIGNALS - // Both conditions appear simultaneously, check both just in case - if (errno == EINTR || bb_got_signal) { - // ^C was pressed - clearerr(stdin); - goto intr; + if (ferror(stdin)) + quit(); // this emits error message + G.eof = 1; + // Note: EOF does not append '\n', therefore: + // printf 'print 123\n' | bc - works + // printf 'print 123' | bc - fails (syntax error) + break; } -#endif - if (ferror(stdin)) - quit(); // this emits error message - G.eof = 1; - // Note: EOF does not append '\n', therefore: - // printf 'print 123\n' | bc - works - // printf 'print 123' | bc - fails (syntax error) - break; - } - if ((i < ' ' && i != '\t' && i != '\r' && i != '\n') // also allow '\v' '\f'? - || i > 0x7e - ) { - // Bad chars on this line, ignore entire line - bc_error_fmt("illegal character 0x%02x", i); - bad_chars = 1; - } - bc_vec_pushByte(vec, (char)i); - } while (i != '\n'); + if ((i < ' ' && i != '\t' && i != '\r' && i != '\n') // also allow '\v' '\f'? + || i > 0x7e + ) { + // Bad chars on this line, ignore entire line + bc_error_fmt("illegal character 0x%02x", i); + bad_chars = 1; + } + bc_vec_pushByte(vec, (char)i); + } while (i != '\n'); + } } while (bad_chars); bc_vec_pushZeroByte(vec); -- cgit v1.2.3-55-g6feb From 95f93bdc280f93b6f1c30c64bf10a8be38669578 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 6 Dec 2018 10:29:12 +0100 Subject: bc: hook up line editing with history buffer function old new delta push_input_byte - 65 +65 bc_vm_run 1875 1905 +30 bc_read_line 303 305 +2 bc_num_binary 148 150 +2 bc_num_ulong 103 92 -11 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 3/1 up/down: 99/-11) Total: 88 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 88 +++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 63 insertions(+), 25 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 90c3bf5d6..dc4fa37a4 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -167,6 +167,7 @@ //usage: "64\n" #include "libbb.h" +#include "common_bufsiz.h" typedef enum BcStatus { BC_STATUS_SUCCESS = 0, @@ -750,6 +751,10 @@ struct globals { BcVec files; char *env_args; + +#if ENABLE_FEATURE_EDITING + line_input_t *line_input_state; +#endif } FIX_ALIASING; #define G (*ptr_to_globals) #define INIT_G() do { \ @@ -974,9 +979,9 @@ static NOINLINE int bc_posix_error_fmt(const char *fmt, ...) // We use error functions with "return bc_error(FMT[, PARAMS])" idiom. // This idiom begs for tail-call optimization, but for it to work, -// function must not have calller-cleaned parameters on stack. -// Unfortunately, vararg functions do exactly that on most arches. -// Thus, these shims for the cases when we have no PARAMS: +// function must not have caller-cleaned parameters on stack. +// Unfortunately, vararg function API does exactly that on most arches. +// Thus, use these shims for the cases when we have no vararg PARAMS: static int bc_error(const char *msg) { return bc_error_fmt("%s", msg); @@ -1195,17 +1200,33 @@ static size_t bc_map_index(const BcVec *v, const void *ptr) return bc_id_cmp(ptr, bc_vec_item(v, i)) ? BC_VEC_INVALID_IDX : i; } +static int push_input_byte(BcVec *vec, char c) +{ + if ((c < ' ' && c != '\t' && c != '\r' && c != '\n') // also allow '\v' '\f'? + || c > 0x7e + ) { + // Bad chars on this line, ignore entire line + bc_error_fmt("illegal character 0x%02x", c); + return 1; + } + bc_vec_pushByte(vec, (char)c); + return 0; +} + static BcStatus bc_read_line(BcVec *vec, const char *prompt) { bool bad_chars; + if (G_posix) prompt = ""; + do { - int i; + int c; bad_chars = 0; bc_vec_pop_all(vec); fflush_and_check(); + #if ENABLE_FEATURE_BC_SIGNALS if (bb_got_signal) { // ^C was pressed intr: @@ -1215,23 +1236,42 @@ static BcStatus bc_read_line(BcVec *vec, const char *prompt) : "\ninterrupt (type \"q\" to exit)\n" , stderr); } +# if ENABLE_FEATURE_EDITING + if (G_ttyin) { + int n, i; +# define line_buf bb_common_bufsiz1 + n = read_line_input(G.line_input_state, prompt, line_buf, COMMON_BUFSIZE); + if (n <= 0) { // read errors or EOF, or ^D, or ^C + if (n == 0) // ^C + goto intr; + G.eof = 1; + break; + } + i = 0; + for (;;) { + c = line_buf[i++]; + if (!c) break; + bad_chars |= push_input_byte(vec, c); + } +# undef line_buf + } else +# endif #endif { - if (G_ttyin && !G_posix) + if (G_ttyin) fputs(prompt, stderr); - IF_FEATURE_BC_SIGNALS(errno = 0;) do { - i = fgetc(stdin); - if (i == EOF) { -#if ENABLE_FEATURE_BC_SIGNALS - // Both conditions appear simultaneously, check both just in case - if (errno == EINTR || bb_got_signal) { - // ^C was pressed - clearerr(stdin); - goto intr; - } + c = fgetc(stdin); +#if ENABLE_FEATURE_BC_SIGNALS && !ENABLE_FEATURE_EDITING + // Both conditions appear simultaneously, check both just in case + if (errno == EINTR || bb_got_signal) { + // ^C was pressed + clearerr(stdin); + goto intr; + } #endif + if (c == EOF) { if (ferror(stdin)) quit(); // this emits error message G.eof = 1; @@ -1240,16 +1280,8 @@ static BcStatus bc_read_line(BcVec *vec, const char *prompt) // printf 'print 123' | bc - fails (syntax error) break; } - - if ((i < ' ' && i != '\t' && i != '\r' && i != '\n') // also allow '\v' '\f'? - || i > 0x7e - ) { - // Bad chars on this line, ignore entire line - bc_error_fmt("illegal character 0x%02x", i); - bad_chars = 1; - } - bc_vec_pushByte(vec, (char)i); - } while (i != '\n'); + bad_chars |= push_input_byte(vec, c); + } while (c != '\n'); } } while (bad_chars); @@ -7391,6 +7423,9 @@ static BcStatus bc_vm_run(char **argv, const char *env_len) { BcStatus st; +#if ENABLE_FEATURE_EDITING + G.line_input_state = new_line_input_t(DO_HISTORY); +#endif G.prog.len = bc_vm_envLen(env_len); bc_vm_init(); @@ -7425,6 +7460,9 @@ static BcStatus bc_vm_run(char **argv, const char *env_len) #if ENABLE_FEATURE_CLEAN_UP bc_vm_free(); +# if ENABLE_FEATURE_EDITING + free_line_input_t(G.line_input_state); +# endif FREE_G(); #endif return st; -- cgit v1.2.3-55-g6feb From a6f84e1a35b5d9d15bfb976f76bb5dc340bc995c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 6 Dec 2018 11:10:11 +0100 Subject: bc: reuse common string text data bss dec hex filename 987232 485 7296 995013 f2ec5 busybox_old 987205 485 7296 994986 f2eaa busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index dc4fa37a4..71945ff4a 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -986,9 +986,9 @@ static int bc_error(const char *msg) { return bc_error_fmt("%s", msg); } -static int bc_posix_error(const char *msg) +static int bc_POSIX_requires(const char *msg) { - return bc_posix_error_fmt("%s", msg); + return bc_posix_error_fmt("POSIX requires %s", msg); } static int bc_POSIX_does_not_allow(const char *msg) { @@ -4047,7 +4047,7 @@ static BcStatus bc_parse_return(BcParse *p) if (s) return s; if (!paren || p->l.t.last != BC_LEX_RPAREN) { - s = bc_posix_error("POSIX requires parentheses around return expressions"); + s = bc_POSIX_requires("parentheses around return expressions"); if (s) return s; } @@ -4416,7 +4416,7 @@ static BcStatus bc_parse_func(BcParse *p) if (s) return s; if (p->l.t.t != BC_LEX_LBRACE) - s = bc_posix_error("POSIX requires the left brace be on the same line as the function header"); + s = bc_POSIX_requires("the left brace be on the same line as the function header"); return s; @@ -4944,7 +4944,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext ne if (s) return s; } else if ((flags & BC_PARSE_REL) && nrelops > 1) { - s = bc_posix_error("POSIX requires exactly one comparison operator per condition"); + s = bc_POSIX_requires("exactly one comparison operator per condition"); if (s) return s; } -- cgit v1.2.3-55-g6feb From a68a87cd60c2cb0c0e9170317901d8f70923926a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 6 Dec 2018 11:12:38 +0100 Subject: bc: unbreak FEATURE_CLEAN_UP build Signed-off-by: Denys Vlasenko --- include/libbb.h | 2 +- libbb/lineedit.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/libbb.h b/include/libbb.h index df3c2d3c9..9e0970095 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1786,7 +1786,7 @@ enum { FOR_SHELL = DO_HISTORY | TAB_COMPLETION | USERNAME_COMPLETION, }; line_input_t *new_line_input_t(int flags) FAST_FUNC; -/* So far static: void free_line_input_t(line_input_t *n) FAST_FUNC; */ +void free_line_input_t(line_input_t *n) FAST_FUNC; /* * maxsize must be >= 2. * Returns: diff --git a/libbb/lineedit.c b/libbb/lineedit.c index b1e971f88..b6fcd7af0 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -1382,7 +1382,7 @@ void FAST_FUNC show_history(const line_input_t *st) * than configured MAX_HISTORY lines. */ -static void free_line_input_t(line_input_t *n) +void FAST_FUNC free_line_input_t(line_input_t *n) { int i = n->cnt_history; while (i > 0) -- cgit v1.2.3-55-g6feb From 9ca9ef2d5b4eea4ee79784b226c556ab8b0818de Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 6 Dec 2018 11:31:14 +0100 Subject: dc: re-enable "tiny dc" implementation Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 43 +++++++++++++++++++++++++++++++------------ miscutils/dc.c | 51 +++++---------------------------------------------- 2 files changed, 36 insertions(+), 58 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 71945ff4a..26044afbc 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -94,17 +94,30 @@ //config: Also note that, like the FreeBSD dc, extended registers are not //config: allowed unless the "-x" option is given. //config: +//config:config FEATURE_DC_SMALL +//config: bool "Minimal dc implementation (4.2 kb), not using bc code base" +//config: depends on DC && !BC +//config: default y +//config: +//config:config FEATURE_DC_LIBM +//config: bool "Enable power and exp functions (requires libm)" +//config: default y +//config: depends on FEATURE_DC_SMALL +//config: help +//config: Enable power and exp functions. +//config: NOTE: This will require libm to be present for linking. +//config: //config:config FEATURE_BC_SIGNALS //config: bool "Enable bc/dc signal handling" //config: default y -//config: depends on BC || DC +//config: depends on (BC || DC) && !FEATURE_DC_SMALL //config: help //config: Enable signal handling for bc and dc. //config: //config:config FEATURE_BC_LONG_OPTIONS //config: bool "Enable bc/dc long options" //config: default y -//config: depends on BC || DC +//config: depends on (BC || DC) && !FEATURE_DC_SMALL //config: help //config: Enable long options for bc and dc. @@ -143,16 +156,16 @@ //usage:#define dc_trivial_usage //usage: "EXPRESSION..." //usage: -//usage:#define dc_full_usage "\n\n" -//usage: "Tiny RPN calculator. Operations:\n" -//usage: "+, add, -, sub, *, mul, /, div, %, mod, ^, exp, ~, divmod, |, " -//usage: "modular exponentiation,\n" -//usage: "p - print top of the stack (without popping),\n" -//usage: "f - print entire stack,\n" -//usage: "k - pop the value and set the precision.\n" -//usage: "i - pop the value and set input radix.\n" -//usage: "o - pop the value and set output radix.\n" -//usage: "Examples: 'dc 2 2 add p' -> 4, 'dc 8 8 mul 2 2 + / p' -> 16" +//usage:#define dc_full_usage "\n" +//usage: "\nTiny RPN calculator. Operations:" +//usage: "\n+, add, -, sub, *, mul, /, div, %, mod, ^, exp, ~, divmod, |, " +//usage: "modular exponentiation," +//usage: "\np - print top of the stack (without popping)," +//usage: "\nf - print entire stack," +//usage: "\nk - pop the value and set the precision." +//usage: "\ni - pop the value and set input radix." +//usage: "\no - pop the value and set output radix." +//usage: "\nExamples: 'dc 2 2 add p' -> 4, 'dc 8 8 mul 2 2 + / p' -> 16" //usage: //usage:#define dc_example_usage //usage: "$ dc 2 2 + p\n" @@ -169,6 +182,10 @@ #include "libbb.h" #include "common_bufsiz.h" +#if ENABLE_FEATURE_DC_SMALL +# include "dc.c" +#else + typedef enum BcStatus { BC_STATUS_SUCCESS = 0, BC_STATUS_FAILURE = 1, @@ -7490,3 +7507,5 @@ int dc_main(int argc UNUSED_PARAM, char **argv) return bc_vm_run(argv, "DC_LINE_LENGTH"); } #endif + +#endif // not DC_SMALL diff --git a/miscutils/dc.c b/miscutils/dc.c index d58f97e91..22890147d 100644 --- a/miscutils/dc.c +++ b/miscutils/dc.c @@ -1,52 +1,12 @@ -#if 0 //TODO: use if bc is not selected /* vi: set sw=4 ts=4: */ /* * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ - //config:config DC - //config: bool "dc (4.2 kb)" - //config: default y - //config: help - //config: Dc is a reverse-polish desk calculator which supports unlimited - //config: precision arithmetic. - //config: - //config:config FEATURE_DC_LIBM - //config: bool "Enable power and exp functions (requires libm)" - //config: default y - //config: depends on DC - //config: help - //config: Enable power and exp functions. - //config: NOTE: This will require libm to be present for linking. - - //applet:IF_DC(APPLET(dc, BB_DIR_USR_BIN, BB_SUID_DROP)) - - //kbuild:lib-$(CONFIG_DC) += dc.o - - //usage:#define dc_trivial_usage - //usage: "EXPRESSION..." - //usage: - //usage:#define dc_full_usage "\n\n" - //usage: "Tiny RPN calculator. Operations:\n" - //usage: "+, add, -, sub, *, mul, /, div, %, mod, "IF_FEATURE_DC_LIBM("**, exp, ")"and, or, not, xor,\n" - //usage: "p - print top of the stack (without popping),\n" - //usage: "f - print entire stack,\n" - //usage: "o - pop the value and set output radix (must be 10, 16, 8 or 2).\n" - //usage: "Examples: 'dc 2 2 add p' -> 4, 'dc 8 8 mul 2 2 + / p' -> 16" - //usage: - //usage:#define dc_example_usage - //usage: "$ dc 2 2 + p\n" - //usage: "4\n" - //usage: "$ dc 8 8 \\* 2 2 + / p\n" - //usage: "16\n" - //usage: "$ dc 0 1 and p\n" - //usage: "0\n" - //usage: "$ dc 0 1 or p\n" - //usage: "1\n" - //usage: "$ echo 72 9 div 8 mul p | dc\n" - //usage: "64\n" - -#include "libbb.h" -#include "common_bufsiz.h" + +/* config/applet/usage bits are in bc.c */ + +//#include "libbb.h" +//#include "common_bufsiz.h" #include #if 0 @@ -303,4 +263,3 @@ int dc_main(int argc UNUSED_PARAM, char **argv) } return EXIT_SUCCESS; } -#endif -- cgit v1.2.3-55-g6feb From 23c2e9fcf9a61da814aee986b30efd9c531fb94d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 6 Dec 2018 11:43:17 +0100 Subject: bc: unbreak "BC only" and "DC only" configs Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 26044afbc..ad6831683 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -974,6 +974,7 @@ static NOINLINE int bc_error_fmt(const char *fmt, ...) return BC_STATUS_FAILURE; } +#if ENABLE_BC static NOINLINE int bc_posix_error_fmt(const char *fmt, ...) { va_list p; @@ -993,6 +994,7 @@ static NOINLINE int bc_posix_error_fmt(const char *fmt, ...) exit(1); return BC_STATUS_FAILURE; } +#endif // We use error functions with "return bc_error(FMT[, PARAMS])" idiom. // This idiom begs for tail-call optimization, but for it to work, @@ -1003,6 +1005,7 @@ static int bc_error(const char *msg) { return bc_error_fmt("%s", msg); } +#if ENABLE_BC static int bc_POSIX_requires(const char *msg) { return bc_posix_error_fmt("POSIX requires %s", msg); @@ -1019,6 +1022,7 @@ static int bc_POSIX_does_not_allow_empty_X_expression_in_for(const char *msg) { return bc_posix_error_fmt("%san empty %s expression in a for loop", "POSIX does not allow ", msg); } +#endif static int bc_error_bad_character(char c) { return bc_error_fmt("bad character '%c'", c); @@ -1210,12 +1214,14 @@ static int bc_map_insert(BcVec *v, const void *ptr, size_t *i) return 1; // "was inserted" } +#if ENABLE_BC static size_t bc_map_index(const BcVec *v, const void *ptr) { size_t i = bc_map_find(v, ptr); if (i >= v->len) return BC_VEC_INVALID_IDX; return bc_id_cmp(ptr, bc_vec_item(v, i)) ? BC_VEC_INVALID_IDX : i; } +#endif static int push_input_byte(BcVec *vec, char c) { @@ -2673,6 +2679,7 @@ err: } #endif // ENABLE_DC +#if ENABLE_BC static BcStatus bc_func_insert(BcFunc *f, char *name, bool var) { BcId a; @@ -2690,6 +2697,7 @@ static BcStatus bc_func_insert(BcFunc *f, char *name, bool var) return BC_STATUS_SUCCESS; } +#endif static void bc_func_init(BcFunc *f) { @@ -5227,18 +5235,18 @@ static void dc_parse_init(BcParse *p, size_t func) static void common_parse_init(BcParse *p, size_t func) { if (IS_BC) { - bc_parse_init(p, func); + IF_BC(bc_parse_init(p, func);) } else { - dc_parse_init(p, func); + IF_DC(dc_parse_init(p, func);) } } static BcStatus common_parse_expr(BcParse *p, uint8_t flags) { if (IS_BC) { - return bc_parse_expression(p, flags); + IF_BC(return bc_parse_expression(p, flags);) } else { - return dc_parse_expr(p, flags); + IF_DC(return dc_parse_expr(p, flags);) } } @@ -7427,12 +7435,12 @@ static void bc_vm_init(void) { bc_vec_init(&G.files, sizeof(char *), NULL); if (IS_BC) - bc_vm_envArgs(); + IF_BC(bc_vm_envArgs();) bc_program_init(); if (IS_BC) { - bc_parse_init(&G.prs, BC_PROG_MAIN); + IF_BC(bc_parse_init(&G.prs, BC_PROG_MAIN);) } else { - dc_parse_init(&G.prs, BC_PROG_MAIN); + IF_DC(dc_parse_init(&G.prs, BC_PROG_MAIN);) } } -- cgit v1.2.3-55-g6feb From 4c30406df6d44447a3ae147f3b85c6726bc0f739 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 6 Dec 2018 12:01:17 +0100 Subject: bc: do not needlessly use strcat Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index ad6831683..06b148481 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1148,7 +1148,7 @@ static void bc_vec_concat(BcVec *v, const char *str) len = v->len + strlen(str); if (v->cap < len) bc_vec_grow(v, len - v->len); - strcat(v->v, str); + strcpy(v->v + v->len, str); v->len = len; } -- cgit v1.2.3-55-g6feb From 1ff8862149706b81fec67ae496b3b2c12b6c793f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 6 Dec 2018 12:06:16 +0100 Subject: bc: fix for prev commit Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 06b148481..19e567b88 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1148,7 +1148,7 @@ static void bc_vec_concat(BcVec *v, const char *str) len = v->len + strlen(str); if (v->cap < len) bc_vec_grow(v, len - v->len); - strcpy(v->v + v->len, str); + strcpy(v->v + v->len - 1, str); v->len = len; } -- cgit v1.2.3-55-g6feb From 2fa11b6d35bcb02064df6d518ee660e39a69615c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 6 Dec 2018 12:34:39 +0100 Subject: bc: add comment about BC_NUM_DEF_SIZE Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 19e567b88..eae91e9c5 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -205,9 +205,6 @@ typedef struct BcVec { BcVecFree dtor; } BcVec; -#define bc_vec_pop(v) (bc_vec_npop((v), 1)) -#define bc_vec_top(v) (bc_vec_item_rev((v), 0)) - typedef signed char BcDig; typedef struct BcNum { @@ -218,16 +215,17 @@ typedef struct BcNum { bool neg; } BcNum; -#define BC_NUM_MIN_BASE ((unsigned long) 2) -#define BC_NUM_MAX_IBASE ((unsigned long) 16) -#define BC_NUM_DEF_SIZE (16) -#define BC_NUM_PRINT_WIDTH (69) +#define BC_NUM_MIN_BASE ((unsigned long) 2) +#define BC_NUM_MAX_IBASE ((unsigned long) 16) +// larger value might speed up BIGNUM calculations a bit: +#define BC_NUM_DEF_SIZE (16) +#define BC_NUM_PRINT_WIDTH (69) -#define BC_NUM_KARATSUBA_LEN (32) +#define BC_NUM_KARATSUBA_LEN (32) -#define BC_NUM_NEG(n, neg) ((((ssize_t)(n)) ^ -((ssize_t)(neg))) + (neg)) -#define BC_NUM_ONE(n) ((n)->len == 1 && (n)->rdx == 0 && (n)->num[0] == 1) -#define BC_NUM_INT(n) ((n)->len - (n)->rdx) +#define BC_NUM_NEG(n, neg) ((((ssize_t)(n)) ^ -((ssize_t)(neg))) + (neg)) +#define BC_NUM_ONE(n) ((n)->len == 1 && (n)->rdx == 0 && (n)->num[0] == 1) +#define BC_NUM_INT(n) ((n)->len - (n)->rdx) #define BC_NUM_AREQ(a, b) \ (BC_MAX((a)->rdx, (b)->rdx) + BC_MAX(BC_NUM_INT(a), BC_NUM_INT(b)) + 1) #define BC_NUM_MREQ(a, b, scale) \ @@ -1078,6 +1076,9 @@ static void bc_vec_expand(BcVec *v, size_t req) } } +#define bc_vec_pop(v) (bc_vec_npop((v), 1)) +#define bc_vec_top(v) (bc_vec_item_rev((v), 0)) + static void bc_vec_npop(BcVec *v, size_t n) { if (!v->dtor) -- cgit v1.2.3-55-g6feb From e55a5726001ce23161c4bd0010b842578e7b722c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 6 Dec 2018 12:47:17 +0100 Subject: bc: small simplification in dc_lex_token() Pulling array element into a temporary, taking address of this temporary and copying it? That's much unnecessary work. function old new delta dc_lex_token 701 697 -4 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index eae91e9c5..40430d411 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -588,15 +588,11 @@ typedef struct BcLex { #define BC_PARSE_STREND ((char) UCHAR_MAX) -#define bc_parse_push(p, i) (bc_vec_pushByte(&(p)->func->code, (char) (i))) -#define bc_parse_updateFunc(p, f) \ - ((p)->func = bc_vec_item(&G.prog.fns, ((p)->fidx = (f)))) - -#define BC_PARSE_REL (1 << 0) -#define BC_PARSE_PRINT (1 << 1) +#define BC_PARSE_REL (1 << 0) +#define BC_PARSE_PRINT (1 << 1) #define BC_PARSE_NOCALL (1 << 2) #define BC_PARSE_NOREAD (1 << 3) -#define BC_PARSE_ARRAY (1 << 4) +#define BC_PARSE_ARRAY (1 << 4) #define BC_PARSE_TOP_FLAG_PTR(parse) ((uint8_t *) bc_vec_top(&(parse)->flags)) #define BC_PARSE_TOP_FLAG(parse) (*(BC_PARSE_TOP_FLAG_PTR(parse))) @@ -638,12 +634,6 @@ typedef struct BcParseNext { BcLexType tokens[4]; } BcParseNext; -#define BC_PARSE_NEXT_TOKENS(...) .tokens = { __VA_ARGS__ } -#define BC_PARSE_NEXT(a, ...) \ - { \ - .len = (a), BC_PARSE_NEXT_TOKENS(__VA_ARGS__) \ - } - struct BcParse; struct BcProgram; @@ -716,7 +706,6 @@ typedef struct BcProgram { #define BC_PROG_MAIN (0) #define BC_PROG_READ (1) - #if ENABLE_DC #define BC_PROG_REQ_FUNCS (2) #endif @@ -839,6 +828,11 @@ static const uint8_t bc_parse_ops[] = { #define bc_parse_op_LEFT(i) (bc_parse_ops[i] & 0x10) // These identify what tokens can come after expressions in certain cases. +#define BC_PARSE_NEXT_TOKENS(...) .tokens = { __VA_ARGS__ } +#define BC_PARSE_NEXT(a, ...) \ + { \ + .len = (a), BC_PARSE_NEXT_TOKENS(__VA_ARGS__) \ + } static const BcParseNext bc_parse_next_expr = BC_PARSE_NEXT(4, BC_LEX_NLINE, BC_LEX_SCOLON, BC_LEX_RBRACE, BC_LEX_EOF); static const BcParseNext bc_parse_next_param = @@ -1101,6 +1095,8 @@ static void bc_vec_push(BcVec *v, const void *data) v->len += 1; } +#define bc_parse_push(p, i) bc_vec_pushByte(&(p)->func->code, (char) (i)) + static void bc_vec_pushByte(BcVec *v, char data) { bc_vec_push(v, &data); @@ -3377,7 +3373,7 @@ static BcStatus dc_lex_register(BcLex *l) } else { bc_vec_pop_all(&l->t.v); - bc_vec_pushByte(&l->t.v, l->buf[l->i - 1]); + bc_vec_push(&l->t.v, &l->buf[l->i - 1]); bc_vec_pushZeroByte(&l->t.v); l->t.t = BC_LEX_NAME; } @@ -3587,6 +3583,9 @@ static BcStatus bc_parse_text(BcParse *p, const char *text) return bc_lex_text(&p->l, text); } +#define bc_parse_updateFunc(p, f) \ + ((p)->func = bc_vec_item(&G.prog.fns, ((p)->fidx = (f)))) + // Called when bc/dc_parse_parse() detects a failure, // resets parsing structures. static void bc_parse_reset(BcParse *p) -- cgit v1.2.3-55-g6feb From b6f60863cb9e0b3af3c694c282489e458822002f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 6 Dec 2018 12:54:26 +0100 Subject: bc: move a function to reduce forward declarations Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 38 +++++++++++++++++--------------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 40430d411..6cc9fe2f7 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -716,9 +716,6 @@ typedef struct BcProgram { typedef unsigned long (*BcProgramBuiltIn)(BcNum *); -static void bc_program_addFunc(char *name, size_t *idx); -static void bc_program_reset(void); - #define BC_FLAG_X (1 << 0) #define BC_FLAG_W (1 << 1) #define BC_FLAG_V (1 << 2) @@ -3523,6 +3520,8 @@ static BcStatus dc_lex_token(BcLex *l) } #endif // ENABLE_DC +static void bc_program_addFunc(char *name, size_t *idx); + static void bc_parse_addFunc(BcParse *p, char *name, size_t *idx) { bc_program_addFunc(name, idx); @@ -3583,6 +3582,21 @@ static BcStatus bc_parse_text(BcParse *p, const char *text) return bc_lex_text(&p->l, text); } +// Called when parsing or execution detects a failure, +// resets execution structures. +static void bc_program_reset(void) +{ + BcFunc *f; + BcInstPtr *ip; + + bc_vec_npop(&G.prog.stack, G.prog.stack.len - 1); + bc_vec_pop_all(&G.prog.results); + + f = bc_vec_item(&G.prog.fns, 0); + ip = bc_vec_top(&G.prog.stack); + ip->idx = f->code.len; +} + #define bc_parse_updateFunc(p, f) \ ((p)->func = bc_vec_item(&G.prog.fns, ((p)->fidx = (f)))) @@ -6548,24 +6562,6 @@ static void bc_program_addFunc(char *name, size_t *idx) } } -// Called when parsing or execution detects a failure, -// resets execution structures. -static void bc_program_reset(void) -{ - BcFunc *f; - BcInstPtr *ip; - - bc_vec_npop(&G.prog.stack, G.prog.stack.len - 1); - bc_vec_pop_all(&G.prog.results); - - f = bc_vec_item(&G.prog.fns, 0); - ip = bc_vec_top(&G.prog.stack); - ip->idx = f->code.len; - - // If !tty, no need to check for ^C: we don't have ^C handler, - // we would be killed by a signal and won't reach this place -} - static BcStatus bc_program_exec(void) { BcStatus s = BC_STATUS_SUCCESS; -- cgit v1.2.3-55-g6feb From d00d2f9603d027c30ce21ed42a951bb650a264e9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 6 Dec 2018 12:59:40 +0100 Subject: bc: make keyword POSIXness check more readable Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 56 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 6cc9fe2f7..f936ad6f3 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -508,34 +508,35 @@ typedef enum BcLexType { struct BcLexKeyword { char name8[8]; }; -#define BC_LEX_KW_ENTRY(a, b, c) \ - { .name8 = a /*, .len = b, .posix = c*/ } +#define BC_LEX_KW_ENTRY(a, b) \ + { .name8 = a /*, .posix = b */ } static const struct BcLexKeyword bc_lex_kws[20] = { - BC_LEX_KW_ENTRY("auto" , 4, 1), // 0 - BC_LEX_KW_ENTRY("break" , 5, 1), // 1 - BC_LEX_KW_ENTRY("continue", 8, 0), // 2 note: this one has no terminating NUL - BC_LEX_KW_ENTRY("define" , 6, 1), // 3 - - BC_LEX_KW_ENTRY("else" , 4, 0), // 4 - BC_LEX_KW_ENTRY("for" , 3, 1), // 5 - BC_LEX_KW_ENTRY("halt" , 4, 0), // 6 - BC_LEX_KW_ENTRY("ibase" , 5, 1), // 7 - - BC_LEX_KW_ENTRY("if" , 2, 1), // 8 - BC_LEX_KW_ENTRY("last" , 4, 0), // 9 - BC_LEX_KW_ENTRY("length" , 6, 1), // 10 - BC_LEX_KW_ENTRY("limits" , 6, 0), // 11 - - BC_LEX_KW_ENTRY("obase" , 5, 1), // 12 - BC_LEX_KW_ENTRY("print" , 5, 0), // 13 - BC_LEX_KW_ENTRY("quit" , 4, 1), // 14 - BC_LEX_KW_ENTRY("read" , 4, 0), // 15 - - BC_LEX_KW_ENTRY("return" , 6, 1), // 16 - BC_LEX_KW_ENTRY("scale" , 5, 1), // 17 - BC_LEX_KW_ENTRY("sqrt" , 4, 1), // 18 - BC_LEX_KW_ENTRY("while" , 5, 1), // 19 + BC_LEX_KW_ENTRY("auto" , 1), // 0 + BC_LEX_KW_ENTRY("break" , 1), // 1 + BC_LEX_KW_ENTRY("continue", 0), // 2 note: this one has no terminating NUL + BC_LEX_KW_ENTRY("define" , 1), // 3 + + BC_LEX_KW_ENTRY("else" , 0), // 4 + BC_LEX_KW_ENTRY("for" , 1), // 5 + BC_LEX_KW_ENTRY("halt" , 0), // 6 + BC_LEX_KW_ENTRY("ibase" , 1), // 7 + + BC_LEX_KW_ENTRY("if" , 1), // 8 + BC_LEX_KW_ENTRY("last" , 0), // 9 + BC_LEX_KW_ENTRY("length" , 1), // 10 + BC_LEX_KW_ENTRY("limits" , 0), // 11 + + BC_LEX_KW_ENTRY("obase" , 1), // 12 + BC_LEX_KW_ENTRY("print" , 0), // 13 + BC_LEX_KW_ENTRY("quit" , 1), // 14 + BC_LEX_KW_ENTRY("read" , 0), // 15 + + BC_LEX_KW_ENTRY("return" , 1), // 16 + BC_LEX_KW_ENTRY("scale" , 1), // 17 + BC_LEX_KW_ENTRY("sqrt" , 1), // 18 + BC_LEX_KW_ENTRY("while" , 1), // 19 }; +#undef BC_LEX_KW_ENTRY enum { POSIX_KWORD_MASK = 0 | (1 << 0) @@ -563,6 +564,7 @@ enum { | (1 << 18) | (1 << 19) }; +#define bc_lex_kws_POSIX(i) ((1 << (i)) & POSIX_KWORD_MASK) #endif struct BcLex; @@ -2982,7 +2984,7 @@ static BcStatus bc_lex_identifier(BcLex *l) match: // buf starts with keyword bc_lex_kws[i] l->t.t = BC_LEX_KEY_1st_keyword + i; - if (!((1 << i) & POSIX_KWORD_MASK)) { + if (!bc_lex_kws_POSIX(i)) { s = bc_posix_error_fmt("%sthe '%.8s' keyword", "POSIX does not allow ", bc_lex_kws[i].name8); if (s) return s; } -- cgit v1.2.3-55-g6feb From b23ac51d0cfc04226fa8fcc90edd00808614cb32 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 6 Dec 2018 13:10:56 +0100 Subject: bc: code shrink - convert two macros to functions function old new delta bc_program_printStream - 185 +185 bc_program_pushArray - 147 +147 bc_program_exec 4132 4219 +87 bc_vec_pop - 27 +27 bc_vec_top - 13 +13 bc_num_ulong 92 103 +11 bc_vm_run 1905 1903 -2 bc_vm_process 94 92 -2 bc_program_reset 72 70 -2 bc_program_prep 93 91 -2 bc_program_call 366 364 -2 bc_parse_startBody 47 45 -2 bc_parse_parse 464 462 -2 bc_parse_else 137 135 -2 bc_parse_body 118 116 -2 bc_program_num 1129 1125 -4 bc_parse_text 147 143 -4 bc_program_retire 40 35 -5 bc_program_print 778 773 -5 bc_program_modexp 746 741 -5 bc_program_pushVar 215 208 -7 bc_program_copyToVar 323 316 -7 bc_parse_operator 184 177 -7 bc_parse_noElse 65 56 -9 bc_program_binOpRetire 56 46 -10 bc_parse_stmt 2271 2261 -10 bc_program_execStr 543 528 -15 bc_program_assignStr 161 146 -15 bc_parse_expr_empty_ok 2178 2157 -21 bc_parse_endBody 420 375 -45 bc_program_asciify 464 - -464 ------------------------------------------------------------------------------ (add/remove: 4/1 grow/shrink: 2/24 up/down: 470/-651) Total: -181 bytes text data bss dec hex filename 987227 485 7296 995008 f2ec0 busybox_old 987046 485 7296 994827 f2e0b busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index f936ad6f3..3d53db778 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1069,8 +1069,12 @@ static void bc_vec_expand(BcVec *v, size_t req) } } -#define bc_vec_pop(v) (bc_vec_npop((v), 1)) -#define bc_vec_top(v) (bc_vec_item_rev((v), 0)) +static void bc_vec_pop(BcVec *v) +{ + v->len--; + if (v->dtor) + v->dtor(v->v + (v->size * v->len)); +} static void bc_vec_npop(BcVec *v, size_t n) { @@ -1094,8 +1098,6 @@ static void bc_vec_push(BcVec *v, const void *data) v->len += 1; } -#define bc_parse_push(p, i) bc_vec_pushByte(&(p)->func->code, (char) (i)) - static void bc_vec_pushByte(BcVec *v, char data) { bc_vec_push(v, &data); @@ -1159,6 +1161,11 @@ static void *bc_vec_item_rev(const BcVec *v, size_t idx) return v->v + v->size * (v->len - idx - 1); } +static void *bc_vec_top(const BcVec *v) +{ + return v->v + v->size * (v->len - 1); +} + static void bc_vec_free(void *vec) { BcVec *v = (BcVec *) vec; @@ -3530,6 +3537,8 @@ static void bc_parse_addFunc(BcParse *p, char *name, size_t *idx) p->func = bc_vec_item(&G.prog.fns, p->fidx); } +#define bc_parse_push(p, i) bc_vec_pushByte(&(p)->func->code, (char) (i)) + static void bc_parse_pushName(BcParse *p, char *name) { size_t i = 0, len = strlen(name); -- cgit v1.2.3-55-g6feb From 52c210594cfc78c4d849550890c30a9185f36d9c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 6 Dec 2018 14:10:10 +0100 Subject: fix make_single_applets.sh Signed-off-by: Denys Vlasenko --- make_single_applets.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/make_single_applets.sh b/make_single_applets.sh index aa1ace265..2075cb9a7 100755 --- a/make_single_applets.sh +++ b/make_single_applets.sh @@ -27,6 +27,8 @@ allno="$cfg" for app in $apps; do allno="`echo "$allno" | sed "s/^CONFIG_${app}=y\$/# CONFIG_${app} is not set/"`" done +# remove "busybox" as well +allno="`echo "$allno" | sed "s/^CONFIG_BUSYBOX=y\$/# CONFIG_BUSYBOX is not set/"`" #echo "$allno" >.config_allno trap 'test -f .config.SV && mv .config.SV .config && touch .config' EXIT -- cgit v1.2.3-55-g6feb From 4c9455f967e21d30db0de2e13b6e1115ab8f36ce Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 6 Dec 2018 15:21:39 +0100 Subject: dc: fix "dc does_not_exist" SEGVing Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 3d53db778..0200afca2 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1322,7 +1322,8 @@ static char* bc_read_file(const char *path) size_t size = ((size_t) -1); size_t i; - buf = xmalloc_open_read_close(path, &size); + // Never returns NULL (dies on errors) + buf = xmalloc_xopen_read_close(path, &size); for (i = 0; i < size; ++i) { char c = buf[i]; -- cgit v1.2.3-55-g6feb From 6d0be10aae1fb92879269e4397ae4e7ab037a628 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 6 Dec 2018 18:41:59 +0100 Subject: bc: correctly parse dc options function old new delta bc_vm_init - 821 +821 bc_vm_file - 226 +226 dc_main 41 187 +146 bc_main 41 73 +32 packed_usage 33076 33059 -17 bc_vm_run 1903 701 -1202 ------------------------------------------------------------------------------ (add/remove: 2/0 grow/shrink: 2/2 up/down: 1225/-1219) Total: 6 bytes text data bss dec hex filename 987046 485 7296 994827 f2e0b busybox_old 987037 485 7296 994818 f2e02 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 159 ++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 101 insertions(+), 58 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 0200afca2..3f7da3abc 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -134,12 +134,13 @@ //usage:#define bc_full_usage "\n" //usage: "\nArbitrary precision calculator" //usage: "\n" -//usage: "\n -i Interactive" +///////: "\n -i Interactive" - has no effect for now +//usage: "\n -q Quiet" //usage: "\n -l Load standard math library" //usage: "\n -s Be POSIX compatible" -//usage: "\n -q Quiet" //usage: "\n -w Warn if extensions are used" ///////: "\n -v Version" +//usage: "\n" //usage: "\n$BC_LINE_LENGTH changes output width" //usage: //usage:#define bc_example_usage @@ -154,29 +155,29 @@ //usage: "obase = A\n" //usage: //usage:#define dc_trivial_usage -//usage: "EXPRESSION..." +//usage: "[-eSCRIPT]... [-fFILE]... [FILE]..." //usage: //usage:#define dc_full_usage "\n" //usage: "\nTiny RPN calculator. Operations:" -//usage: "\n+, add, -, sub, *, mul, /, div, %, mod, ^, exp, ~, divmod, |, " +//usage: "\n+, -, *, /, %, ^, exp, ~, divmod, |, " //usage: "modular exponentiation," -//usage: "\np - print top of the stack (without popping)," -//usage: "\nf - print entire stack," -//usage: "\nk - pop the value and set the precision." -//usage: "\ni - pop the value and set input radix." -//usage: "\no - pop the value and set output radix." -//usage: "\nExamples: 'dc 2 2 add p' -> 4, 'dc 8 8 mul 2 2 + / p' -> 16" +//usage: "\np - print top of the stack (without popping)" +//usage: "\nf - print entire stack" +//usage: "\nk - pop the value and set the precision" +//usage: "\ni - pop the value and set input radix" +//usage: "\no - pop the value and set output radix" +//usage: "\nExamples: dc -e'2 2 + p' -> 4, dc -e'8 8 * 2 2 + / p' -> 16" //usage: //usage:#define dc_example_usage -//usage: "$ dc 2 2 + p\n" +//usage: "$ dc -e'2 2 + p'\n" //usage: "4\n" -//usage: "$ dc 8 8 \\* 2 2 + / p\n" +//usage: "$ dc -e'8 8 \\* 2 2 + / p'\n" //usage: "16\n" -//usage: "$ dc 0 1 and p\n" +//usage: "$ dc -e'0 1 & p'\n" //usage: "0\n" -//usage: "$ dc 0 1 or p\n" +//usage: "$ dc -e'0 1 | p'\n" //usage: "1\n" -//usage: "$ echo 72 9 div 8 mul p | dc\n" +//usage: "$ echo '72 9 / 8 * p' | dc\n" //usage: "64\n" #include "libbb.h" @@ -718,13 +719,13 @@ typedef struct BcProgram { typedef unsigned long (*BcProgramBuiltIn)(BcNum *); -#define BC_FLAG_X (1 << 0) -#define BC_FLAG_W (1 << 1) -#define BC_FLAG_V (1 << 2) -#define BC_FLAG_S (1 << 3) -#define BC_FLAG_Q (1 << 4) -#define BC_FLAG_L (1 << 5) -#define BC_FLAG_I (1 << 6) +#define BC_FLAG_W (1 << 0) +#define BC_FLAG_V (1 << 1) +#define BC_FLAG_S (1 << 2) +#define BC_FLAG_Q (1 << 3) +#define BC_FLAG_L (1 << 4) +#define BC_FLAG_I (1 << 5) +#define DC_FLAG_X (1 << 6) #define BC_MAX(a, b) ((a) > (b) ? (a) : (b)) #define BC_MIN(a, b) ((a) < (b) ? (a) : (b)) @@ -768,7 +769,7 @@ struct globals { } while (0) #define G_posix (ENABLE_BC && (option_mask32 & BC_FLAG_S)) #define G_warn (ENABLE_BC && (option_mask32 & BC_FLAG_W)) -#define G_exreg (ENABLE_DC && (option_mask32 & BC_FLAG_X)) +#define G_exreg (ENABLE_DC && (option_mask32 & DC_FLAG_X)) #define G_interrupt (ENABLE_FEATURE_BC_SIGNALS ? bb_got_signal : 0) #if ENABLE_FEATURE_BC_SIGNALS # define G_ttyin G.ttyin @@ -6898,6 +6899,7 @@ static BcStatus bc_program_exec(void) return s; } +#if ENABLE_BC static void bc_vm_info(void) { printf("%s "BB_VER"\n" @@ -6914,8 +6916,7 @@ static void bc_args(char **argv) GETOPT_RESET(); #if ENABLE_FEATURE_BC_LONG_OPTIONS - opts = option_mask32 |= getopt32long(argv, "xwvsqli", - "extended-register\0" No_argument "x" + opts = option_mask32 |= getopt32long(argv, "wvsqli", "warn\0" No_argument "w" "version\0" No_argument "v" "standard\0" No_argument "s" @@ -6924,7 +6925,7 @@ static void bc_args(char **argv) "interactive\0" No_argument "i" ); #else - opts = option_mask32 |= getopt32(argv, "xwvsqli"); + opts = option_mask32 |= getopt32(argv, "wvsqli"); #endif if (getenv("POSIXLY_CORRECT")) option_mask32 |= BC_FLAG_S; @@ -6939,7 +6940,6 @@ static void bc_args(char **argv) bc_vec_push(&G.files, argv + i); } -#if ENABLE_BC static void bc_vm_envArgs(void) { BcVec v; @@ -7308,7 +7308,7 @@ static const char bc_lib[] = { static BcStatus bc_vm_exec(void) { - BcStatus s = BC_STATUS_SUCCESS; + BcStatus s; size_t i; #if ENABLE_BC @@ -7330,21 +7330,24 @@ static BcStatus bc_vm_exec(void) } #endif + s = BC_STATUS_SUCCESS; for (i = 0; !s && i < G.files.len; ++i) s = bc_vm_file(*((char **) bc_vec_item(&G.files, i))); - if (s) { - if (ENABLE_FEATURE_CLEAN_UP && !G_ttyin) { - // Debug config, non-interactive mode: - // return all the way back to main. - // Non-debug builds do not come here, they exit. - return s; - } - fflush_and_check(); - fputs("ready for more input\n", stderr); + if (ENABLE_FEATURE_CLEAN_UP && s && !G_ttyin) { + // Debug config, non-interactive mode: + // return all the way back to main. + // Non-debug builds do not come here, they exit. + return s; } - if (IS_BC || !G.files.len) + if (IS_BC || (option_mask32 & BC_FLAG_I)) { + if (s) { + fflush_and_check(); + fputs("ready for more input\n", stderr); + } s = bc_vm_stdin(); + } + if (!s && !BC_PARSE_CAN_EXEC(&G.prs)) s = bc_vm_process(""); @@ -7439,8 +7442,13 @@ static void bc_program_init(void) bc_vec_push(&G.prog.stack, &ip); } -static void bc_vm_init(void) +static int bc_vm_init(const char *env_len) { +#if ENABLE_FEATURE_EDITING + G.line_input_state = new_line_input_t(DO_HISTORY); +#endif + G.prog.len = bc_vm_envLen(env_len); + bc_vec_init(&G.files, sizeof(char *), NULL); if (IS_BC) IF_BC(bc_vm_envArgs();) @@ -7450,19 +7458,6 @@ static void bc_vm_init(void) } else { IF_DC(dc_parse_init(&G.prs, BC_PROG_MAIN);) } -} - -static BcStatus bc_vm_run(char **argv, const char *env_len) -{ - BcStatus st; - -#if ENABLE_FEATURE_EDITING - G.line_input_state = new_line_input_t(DO_HISTORY); -#endif - G.prog.len = bc_vm_envLen(env_len); - - bc_vm_init(); - bc_args(argv); if (isatty(0)) { #if ENABLE_FEATURE_BC_SIGNALS @@ -7485,12 +7480,14 @@ static BcStatus bc_vm_run(char **argv, const char *env_len) // and exit. //signal_no_SA_RESTART_empty_mask(SIGINT, record_signo); #endif - if (!(option_mask32 & BC_FLAG_Q)) - bc_vm_info(); + return 1; // "tty" } + return 0; // "not a tty" +} - st = bc_vm_exec(); - +static BcStatus bc_vm_run(void) +{ + BcStatus st = bc_vm_exec(); #if ENABLE_FEATURE_CLEAN_UP bc_vm_free(); # if ENABLE_FEATURE_EDITING @@ -7505,10 +7502,19 @@ static BcStatus bc_vm_run(char **argv, const char *env_len) int bc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int bc_main(int argc UNUSED_PARAM, char **argv) { + int is_tty; + INIT_G(); G.sbgn = G.send = '"'; - return bc_vm_run(argv, "BC_LINE_LENGTH"); + is_tty = bc_vm_init("BC_LINE_LENGTH"); + + bc_args(argv); + + if (is_tty && !(option_mask32 & BC_FLAG_Q)) + bc_vm_info(); + + return bc_vm_run(); } #endif @@ -7516,11 +7522,48 @@ int bc_main(int argc UNUSED_PARAM, char **argv) int dc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int dc_main(int argc UNUSED_PARAM, char **argv) { + int noscript; + INIT_G(); G.sbgn = '['; G.send = ']'; + // TODO: dc (GNU bc 1.07.1) 1.4.1 seems to use default width + // 1 char narrower than bc from the same package. Do the same? + bc_vm_init("DC_LINE_LENGTH"); + + // Run -e'SCRIPT' and -fFILE in order of appearance, then handle FILEs + noscript = BC_FLAG_I; + for (;;) { + int n = getopt(argc, argv, "e:f:x"); + if (n <= 0) + break; + switch (n) { + case 'e': + noscript = 0; + n = bc_vm_process(optarg); + if (n) return n; + break; + case 'f': + noscript = 0; + bc_vm_file(optarg); + break; + case 'x': + option_mask32 |= DC_FLAG_X; + break; + default: + bb_show_usage(); + } + } + argv += optind; + + while (*argv) { + noscript = 0; + bc_vec_push(&G.files, argv++); + } + + option_mask32 |= noscript; // set BC_FLAG_I if we need to interpret stdin - return bc_vm_run(argv, "DC_LINE_LENGTH"); + return bc_vm_run(); } #endif -- cgit v1.2.3-55-g6feb From a1331371748fe23ffaec0720f5c5f4f661c37789 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 6 Dec 2018 18:46:42 +0100 Subject: dc: fix testsuite Signed-off-by: Denys Vlasenko --- miscutils/dc.c | 1 + testsuite/dc.tests | 24 ++++++------------------ 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/miscutils/dc.c b/miscutils/dc.c index 22890147d..bca4778bf 100644 --- a/miscutils/dc.c +++ b/miscutils/dc.c @@ -248,6 +248,7 @@ int dc_main(int argc UNUSED_PARAM, char **argv) { INIT_G(); +//TODO: fix this, should take: dc -eSCRIPT -fFILE FILE argv++; if (!argv[0]) { /* take stuff from stdin if no args are given */ diff --git a/testsuite/dc.tests b/testsuite/dc.tests index a5da5372d..d7a332b9c 100755 --- a/testsuite/dc.tests +++ b/testsuite/dc.tests @@ -12,45 +12,33 @@ testing "dc basic syntax (stdin, multiple args)" \ "" "10 20+p" testing "dc basic syntax (argv, single arg)" \ - "dc '10 20+p'" \ + "dc -e'10 20+p'" \ "30\n" \ "" "" testing "dc basic syntax (argv, multiple args)" \ - "dc 10 20+p" \ + "dc -e10 -e20+p" \ "30\n" \ "" "" testing "dc complex with spaces (single arg)" \ - "dc '8 8 * 2 2 + / p'" \ + "dc -e'8 8 * 2 2 + / p'" \ "16\n" \ "" "" testing "dc complex without spaces (single arg)" \ - "dc '8 8*2 2+/p'" \ + "dc -e'8 8*2 2+/p'" \ "16\n" \ "" "" testing "dc complex with spaces (multiple args)" \ - "dc 8 8 \* 2 2 + / p" \ + "dc -e8 -e8 -e\* -e2 -e2 -e+ -e/ -ep" \ "16\n" \ "" "" testing "dc complex without spaces (multiple args)" \ - "dc 8 8\*2 2+/p" \ + "dc -e8 -e8\*2 -e2+/p" \ "16\n" \ "" "" exit $FAILCOUNT - -# we do not support arguments -testing "dc -e " \ - "dc -e '10 2+f'" \ - "12\n" \ - "" "" - -testing "dc -f " \ - "dc -f input" \ - "12\n" \ - "10 2+f" "" - -- cgit v1.2.3-55-g6feb From c7a7ce06b82ef6a4e5f6146046792daf666e3c6d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 6 Dec 2018 23:06:57 +0100 Subject: bc: fix exit codes for FEATURE_CLEAN_UP=y $ echo 0/0 | ./busybox bc; echo $? bc: divide by zero 1 $ echo halt | ./busybox bc; echo $? 0 <------- was 1 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 3f7da3abc..45cdeae7f 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -741,6 +741,7 @@ typedef unsigned long (*BcProgramBuiltIn)(BcNum *); struct globals { IF_FEATURE_BC_SIGNALS(smallint ttyin;) + IF_FEATURE_CLEAN_UP(smallint exiting;) smallint eof; char sbgn; char send; @@ -776,6 +777,11 @@ struct globals { #else # define G_ttyin 0 #endif +#if ENABLE_FEATURE_CLEAN_UP +# define G_exiting G.exiting +#else +# define G_exiting 0 +#endif #define IS_BC (ENABLE_BC && (!ENABLE_DC || applet_name[0] == 'b')) #if ENABLE_BC @@ -921,13 +927,14 @@ static void fflush_and_check(void) } #if ENABLE_FEATURE_CLEAN_UP -#define quit_or_return_for_exit() \ +#define QUIT_OR_RETURN_TO_MAIN \ do { \ IF_FEATURE_BC_SIGNALS(G_ttyin = 0;) /* do not loop in main loop anymore */ \ + G_exiting = 1; \ return BC_STATUS_FAILURE; \ } while (0) #else -#define quit_or_return_for_exit() quit() +#define QUIT_OR_RETURN_TO_MAIN quit() #endif static void quit(void) NORETURN; @@ -4708,7 +4715,7 @@ static BcStatus bc_parse_stmt(BcParse *p) // "quit" is a compile-time command. For example, // "if (0 == 1) quit" terminates when parsing the statement, // not when it is executed - quit_or_return_for_exit(); + QUIT_OR_RETURN_TO_MAIN; } case BC_LEX_KEY_RETURN: @@ -6411,9 +6418,7 @@ static BcStatus bc_program_nquit(void) if (G.prog.stack.len < val) return bc_error_stack_has_too_few_elements(); if (G.prog.stack.len == val) { - if (ENABLE_FEATURE_CLEAN_UP) - return BC_STATUS_FAILURE; - quit(); + QUIT_OR_RETURN_TO_MAIN; } bc_vec_npop(&G.prog.stack, val); @@ -6627,7 +6632,7 @@ static BcStatus bc_program_exec(void) case BC_INST_HALT: { - quit_or_return_for_exit(); + QUIT_OR_RETURN_TO_MAIN; break; } @@ -6872,7 +6877,7 @@ static BcStatus bc_program_exec(void) case BC_INST_QUIT: { if (G.prog.stack.len <= 2) - quit_or_return_for_exit(); + QUIT_OR_RETURN_TO_MAIN; bc_vec_npop(&G.prog.stack, 2); break; } @@ -7489,6 +7494,8 @@ static BcStatus bc_vm_run(void) { BcStatus st = bc_vm_exec(); #if ENABLE_FEATURE_CLEAN_UP + if (G_exiting) // it was actually "halt" or "quit" + st = EXIT_SUCCESS; bc_vm_free(); # if ENABLE_FEATURE_EDITING free_line_input_t(G.line_input_state); -- cgit v1.2.3-55-g6feb From b9c321d6d94fc8bbae5fe657e141cbd9f2397037 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 7 Dec 2018 12:41:42 +0100 Subject: bc: use only G_interrupt as interrupt flag Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 45cdeae7f..0330c43e5 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -771,11 +771,12 @@ struct globals { #define G_posix (ENABLE_BC && (option_mask32 & BC_FLAG_S)) #define G_warn (ENABLE_BC && (option_mask32 & BC_FLAG_W)) #define G_exreg (ENABLE_DC && (option_mask32 & DC_FLAG_X)) -#define G_interrupt (ENABLE_FEATURE_BC_SIGNALS ? bb_got_signal : 0) #if ENABLE_FEATURE_BC_SIGNALS -# define G_ttyin G.ttyin +# define G_interrupt bb_got_signal +# define G_ttyin G.ttyin #else -# define G_ttyin 0 +# define G_interrupt 0 +# define G_ttyin 0 #endif #if ENABLE_FEATURE_CLEAN_UP # define G_exiting G.exiting @@ -1262,9 +1263,9 @@ static BcStatus bc_read_line(BcVec *vec, const char *prompt) fflush_and_check(); #if ENABLE_FEATURE_BC_SIGNALS - if (bb_got_signal) { // ^C was pressed + if (G_interrupt) { // ^C was pressed intr: - bb_got_signal = 0; // resets G_interrupt to zero + G_interrupt = 0; fputs(IS_BC ? "\ninterrupt (type \"quit\" to exit)\n" : "\ninterrupt (type \"q\" to exit)\n" @@ -1299,7 +1300,7 @@ static BcStatus bc_read_line(BcVec *vec, const char *prompt) c = fgetc(stdin); #if ENABLE_FEATURE_BC_SIGNALS && !ENABLE_FEATURE_EDITING // Both conditions appear simultaneously, check both just in case - if (errno == EINTR || bb_got_signal) { + if (errno == EINTR || G_interrupt) { // ^C was pressed clearerr(stdin); goto intr; -- cgit v1.2.3-55-g6feb From 18c6b54f820923549135724fee6cf66c26929b07 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 7 Dec 2018 12:57:32 +0100 Subject: bc: use more compact parsing data structures function old new delta dc_lex_token 697 701 +4 bc_parse_next_rel 20 - -20 bc_parse_next_read 20 - -20 bc_parse_next_print 20 - -20 bc_parse_next_param 20 - -20 bc_parse_next_for 20 - -20 bc_parse_next_expr 20 - -20 bc_parse_next_elem 20 - -20 common_parse_expr 62 40 -22 bc_parse_expr 49 24 -25 dc_lex_regs 52 13 -39 bc_parse_name 581 539 -42 bc_parse_expr_empty_ok 2157 2108 -49 dc_parse_insts 332 83 -249 dc_lex_tokens 364 91 -273 bc_parse_stmt 2261 1868 -393 ------------------------------------------------------------------------------ (add/remove: 0/7 grow/shrink: 1/8 up/down: 4/-1232) Total: -1228 bytes text data bss dec hex filename 987037 485 7296 994818 f2e02 busybox_old 985814 485 7296 993595 f293b busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 62 +++++++++++++++++++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 27 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 0330c43e5..685427e58 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -632,11 +632,6 @@ typedef struct BcLex { BC_PARSE_FLAG_LOOP | BC_PARSE_FLAG_LOOP_INNER | BC_PARSE_FLAG_IF | \ BC_PARSE_FLAG_ELSE | BC_PARSE_FLAG_IF_END))) -typedef struct BcParseNext { - uint32_t len; - BcLexType tokens[4]; -} BcParseNext; - struct BcParse; struct BcProgram; @@ -834,34 +829,40 @@ static const uint8_t bc_parse_ops[] = { #define bc_parse_op_PREC(i) (bc_parse_ops[i] & 0x0f) #define bc_parse_op_LEFT(i) (bc_parse_ops[i] & 0x10) +// Byte array of up to 4 BC_LEX's, packed into 32-bit word +typedef uint32_t BcParseNext; + // These identify what tokens can come after expressions in certain cases. -#define BC_PARSE_NEXT_TOKENS(...) .tokens = { __VA_ARGS__ } -#define BC_PARSE_NEXT(a, ...) \ - { \ - .len = (a), BC_PARSE_NEXT_TOKENS(__VA_ARGS__) \ - } -static const BcParseNext bc_parse_next_expr = - BC_PARSE_NEXT(4, BC_LEX_NLINE, BC_LEX_SCOLON, BC_LEX_RBRACE, BC_LEX_EOF); -static const BcParseNext bc_parse_next_param = - BC_PARSE_NEXT(2, BC_LEX_RPAREN, BC_LEX_COMMA); -static const BcParseNext bc_parse_next_print = - BC_PARSE_NEXT(4, BC_LEX_COMMA, BC_LEX_NLINE, BC_LEX_SCOLON, BC_LEX_EOF); -static const BcParseNext bc_parse_next_rel = BC_PARSE_NEXT(1, BC_LEX_RPAREN); -static const BcParseNext bc_parse_next_elem = BC_PARSE_NEXT(1, BC_LEX_RBRACKET); -static const BcParseNext bc_parse_next_for = BC_PARSE_NEXT(1, BC_LEX_SCOLON); -static const BcParseNext bc_parse_next_read = - BC_PARSE_NEXT(2, BC_LEX_NLINE, BC_LEX_EOF); +enum { +#define BC_PARSE_NEXT4(a,b,c,d) ( (a) | ((b)<<8) | ((c)<<16) | ((((d)|0x80)<<24)) ) +#define BC_PARSE_NEXT2(a,b) BC_PARSE_NEXT4(a,b,0xff,0xff) +#define BC_PARSE_NEXT1(a) BC_PARSE_NEXT4(a,0xff,0xff,0xff) + bc_parse_next_expr = BC_PARSE_NEXT4(BC_LEX_NLINE, BC_LEX_SCOLON, BC_LEX_RBRACE, BC_LEX_EOF), + bc_parse_next_param = BC_PARSE_NEXT2(BC_LEX_RPAREN, BC_LEX_COMMA), + bc_parse_next_print = BC_PARSE_NEXT4(BC_LEX_COMMA, BC_LEX_NLINE, BC_LEX_SCOLON, BC_LEX_EOF), + bc_parse_next_rel = BC_PARSE_NEXT1(BC_LEX_RPAREN), + bc_parse_next_elem = BC_PARSE_NEXT1(BC_LEX_RBRACKET), + bc_parse_next_for = BC_PARSE_NEXT1(BC_LEX_SCOLON), + bc_parse_next_read = BC_PARSE_NEXT2(BC_LEX_NLINE, BC_LEX_EOF), +#undef BC_PARSE_NEXT4 +#undef BC_PARSE_NEXT2 +#undef BC_PARSE_NEXT1 +}; #endif // ENABLE_BC #if ENABLE_DC -static const BcLexType dc_lex_regs[] = { +static const //BcLexType - should be this type, but narrower type saves size: +uint8_t +dc_lex_regs[] = { BC_LEX_OP_REL_EQ, BC_LEX_OP_REL_LE, BC_LEX_OP_REL_GE, BC_LEX_OP_REL_NE, BC_LEX_OP_REL_LT, BC_LEX_OP_REL_GT, BC_LEX_SCOLON, BC_LEX_COLON, BC_LEX_ELSE, BC_LEX_LOAD, BC_LEX_LOAD_POP, BC_LEX_OP_ASSIGN, BC_LEX_STORE_PUSH, }; -static const BcLexType dc_lex_tokens[] = { +static const //BcLexType - should be this type +uint8_t +dc_lex_tokens[] = { BC_LEX_OP_MODULUS, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_LPAREN, BC_LEX_INVALID, BC_LEX_OP_MULTIPLY, BC_LEX_OP_PLUS, BC_LEX_INVALID, BC_LEX_OP_MINUS, BC_LEX_INVALID, BC_LEX_OP_DIVIDE, @@ -889,7 +890,9 @@ static const BcLexType dc_lex_tokens[] = { BC_LEX_INVALID }; -static const BcInst dc_parse_insts[] = { +static const //BcInst - should be this type. Using signed narrow type since BC_INST_INVALID is -1 +int8_t +dc_parse_insts[] = { BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_REL_GE, BC_INST_INVALID, BC_INST_POWER, BC_INST_MULTIPLY, BC_INST_DIVIDE, BC_INST_MODULUS, BC_INST_PLUS, BC_INST_MINUS, @@ -4768,7 +4771,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext ne BcInst prev = BC_INST_PRINT; BcLexType top, t = p->l.t.t; size_t nexprs = 0, ops_bgn = p->ops.len; - uint32_t i, nparens, nrelops; + unsigned nparens, nrelops; bool paren_first, paren_expr, rprn, done, get_token, assign, bin_last; paren_first = p->l.t.t == BC_LEX_LPAREN; @@ -4993,9 +4996,14 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext ne if (prev == BC_INST_BOOL_NOT || nexprs != 1) return bc_error_bad_expression(); - for (i = 0; i < next.len; ++i) - if (t == next.tokens[i]) + // next is BcParseNext, byte array of up to 4 BC_LEX's, packed into 32-bit word + for (;;) { + if (t == (next & 0x7f)) goto ok; + if (next & 0x80) // last element? + break; + next >>= 8; + } return bc_error_bad_expression(); ok: -- cgit v1.2.3-55-g6feb From ffdcebdffe8a2b6261e3eb468d7c19fd0b454a87 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 7 Dec 2018 15:10:05 +0100 Subject: bc: pull temporary into a register function old new delta bc_num_ulong 103 95 -8 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 685427e58..9eafa80e9 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1411,23 +1411,26 @@ static void bc_num_copy(BcNum *d, BcNum *s) } } -static BcStatus bc_num_ulong(BcNum *n, unsigned long *result) +static BcStatus bc_num_ulong(BcNum *n, unsigned long *result_p) { size_t i; - unsigned long pow; + unsigned long pow, result; if (n->neg) return bc_error("negative number"); - for (*result = 0, pow = 1, i = n->rdx; i < n->len; ++i) { + for (result = 0, pow = 1, i = n->rdx; i < n->len; ++i) { - unsigned long prev = *result, powprev = pow; + unsigned long prev = result, powprev = pow; - *result += ((unsigned long) n->num[i]) * pow; + result += ((unsigned long) n->num[i]) * pow; pow *= 10; - if (*result < prev || pow < powprev) + if (result < prev || pow < powprev) return bc_error("overflow"); + prev = result; + powprev = pow; } + *result_p = result; return BC_STATUS_SUCCESS; } @@ -5855,7 +5858,6 @@ static BcStatus bc_program_assign(char inst) BcStatus s; BcResult *left, *right, res; BcNum *l = NULL, *r = NULL; - unsigned long val, max; bool assign = inst == BC_INST_ASSIGN, ib, sc; s = bc_program_binOpPrep(&left, &l, &right, &r, assign); @@ -5909,6 +5911,7 @@ static BcStatus bc_program_assign(char inst) "bad obase; must be [2, BC_BASE_MAX]", //BC_RESULT_OBASE }; size_t *ptr; + unsigned long val, max; s = bc_num_ulong(l, &val); if (s) -- cgit v1.2.3-55-g6feb From 64074a1767f69b186ce58cafb7eb95bc1aa0dda9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 7 Dec 2018 15:50:14 +0100 Subject: bc: do not perform domr limit checks when they can't work (e.g. on 32-bit arches) Also, optimize printing of messages with fixed limit strings by including limits as strings. function old new delta bc_num_ulong 103 95 -8 bc_lex_number 296 281 -15 dc_lex_token 701 684 -17 bc_lex_name 90 73 -17 bc_num_shift 72 54 -18 bc_lex_token 1299 1280 -19 bc_parse_stmt 1868 1768 -100 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/7 up/down: 0/-194) Total: -194 bytes text data bss dec hex filename 985814 485 7296 993595 f293b busybox_old 985526 485 7296 993307 f281b busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 109 ++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 76 insertions(+), 33 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 9eafa80e9..3da03b437 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -725,14 +725,39 @@ typedef unsigned long (*BcProgramBuiltIn)(BcNum *); #define BC_MAX(a, b) ((a) > (b) ? (a) : (b)) #define BC_MIN(a, b) ((a) < (b) ? (a) : (b)) -#define BC_MAX_OBASE ((unsigned) 999) -#define BC_MAX_DIM ((unsigned) INT_MAX) -#define BC_MAX_SCALE ((unsigned) UINT_MAX) -#define BC_MAX_STRING ((unsigned) UINT_MAX - 1) -#define BC_MAX_NAME BC_MAX_STRING -#define BC_MAX_NUM BC_MAX_STRING -#define BC_MAX_EXP ((unsigned long) LONG_MAX) -#define BC_MAX_VARS ((unsigned long) SIZE_MAX - 1) +#define BC_MAX_OBASE ((unsigned) 999) +#define BC_MAX_DIM ((unsigned) INT_MAX) +#define BC_MAX_SCALE ((unsigned) UINT_MAX) +#define BC_MAX_STRING ((unsigned) UINT_MAX - 1) +#define BC_MAX_NUM BC_MAX_STRING +// Unused apart from "limits" message. Just show a "biggish number" there. +//#define BC_MAX_NAME BC_MAX_STRING +//#define BC_MAX_EXP ((unsigned long) LONG_MAX) +//#define BC_MAX_VARS ((unsigned long) SIZE_MAX - 1) +#define BC_MAX_NAME_STR "999999999" +#define BC_MAX_EXP_STR "999999999" +#define BC_MAX_VARS_STR "999999999" + +#define BC_MAX_OBASE_STR "999" + +#if INT_MAX == 2147483647 +# define BC_MAX_DIM_STR "2147483647" +#elif INT_MAX == 9223372036854775807 +# define BC_MAX_DIM_STR "9223372036854775807" +#else +# error Strange INT_MAX +#endif + +#if UINT_MAX == 4294967295 +# define BC_MAX_SCALE_STR "4294967295" +# define BC_MAX_STRING_STR "4294967294" +#elif UINT_MAX == 18446744073709551615 +# define BC_MAX_SCALE_STR "18446744073709551615" +# define BC_MAX_STRING_STR "18446744073709551614" +#else +# error Strange UINT_MAX +#endif +#define BC_MAX_NUM_STR BC_MAX_STRING_STR struct globals { IF_FEATURE_BC_SIGNALS(smallint ttyin;) @@ -1590,8 +1615,12 @@ static void bc_num_split(BcNum *restrict n, size_t idx, BcNum *restrict a, static BcStatus bc_num_shift(BcNum *n, size_t places) { if (places == 0 || n->len == 0) return BC_STATUS_SUCCESS; - if (places + n->len > BC_MAX_NUM) - return bc_error("number too long: must be [1, BC_NUM_MAX]"); + + // This check makes sense only if size_t is (much) larger than BC_MAX_NUM. + if (SIZE_MAX > (BC_MAX_NUM | 0xff)) { + if (places + n->len > BC_MAX_NUM) + return bc_error("number too long: must be [1,"BC_MAX_NUM_STR"]"); + } if (n->rdx >= places) n->rdx -= places; @@ -2891,8 +2920,11 @@ static BcStatus bc_lex_number(BcLex *l, char start) } len = i + !last_pt - bslashes * 2; - if (len > BC_MAX_NUM) - return bc_error("number too long: must be [1, BC_NUM_MAX]"); + // This check makes sense only if size_t is (much) larger than BC_MAX_NUM. + if (SIZE_MAX > (BC_MAX_NUM | 0xff)) { + if (len > BC_MAX_NUM) + return bc_error("number too long: must be [1,"BC_MAX_NUM_STR"]"); + } bc_vec_pop_all(&l->t.v); bc_vec_expand(&l->t.v, len + 1); @@ -2929,8 +2961,11 @@ static BcStatus bc_lex_name(BcLex *l) while ((c >= 'a' && c <= 'z') || isdigit(c) || c == '_') c = buf[++i]; - if (i > BC_MAX_STRING) - return bc_error("name too long: must be [1, BC_NAME_MAX]"); + // This check makes sense only if size_t is (much) larger than BC_MAX_STRING. + if (SIZE_MAX > (BC_MAX_STRING | 0xff)) { + if (i > BC_MAX_STRING) + return bc_error("name too long: must be [1,"BC_MAX_STRING_STR"]"); + } bc_vec_string(&l->t.v, i, buf); // Increment the index. We minus 1 because it has already been incremented. @@ -3047,8 +3082,11 @@ static BcStatus bc_lex_string(BcLex *l) } len = i - l->i; - if (len > BC_MAX_STRING) - return bc_error("string too long: must be [1, BC_STRING_MAX]"); + // This check makes sense only if size_t is (much) larger than BC_MAX_STRING. + if (SIZE_MAX > (BC_MAX_STRING | 0xff)) { + if (len > BC_MAX_STRING) + return bc_error("string too long: must be [1,"BC_MAX_STRING_STR"]"); + } bc_vec_string(&l->t.v, len, l->buf + l->i); l->i = i + 1; @@ -3426,8 +3464,11 @@ static BcStatus dc_lex_string(BcLex *l) } bc_vec_pushZeroByte(&l->t.v); - if (i - l->i > BC_MAX_STRING) - return bc_error("string too long: must be [1, BC_STRING_MAX]"); + // This check makes sense only if size_t is (much) larger than BC_MAX_STRING. + if (SIZE_MAX > (BC_MAX_STRING | 0xff)) { + if (i - l->i > BC_MAX_STRING) + return bc_error("string too long: must be [1,"BC_MAX_STRING_STR"]"); + } l->i = i; l->line += nls; @@ -4700,14 +4741,16 @@ static BcStatus bc_parse_stmt(BcParse *p) // the output is produced at _parse time_. s = bc_lex_next(&p->l); if (s) return s; - printf("BC_BASE_MAX = %u\n", BC_MAX_OBASE); - printf("BC_DIM_MAX = %u\n", BC_MAX_DIM); - printf("BC_SCALE_MAX = %u\n", BC_MAX_SCALE); - printf("BC_STRING_MAX = %u\n", BC_MAX_STRING); - printf("BC_NAME_MAX = %u\n", BC_MAX_NAME); - printf("BC_NUM_MAX = %u\n", BC_MAX_NUM); - printf("MAX Exponent = %lu\n", BC_MAX_EXP); - printf("Number of vars = %lu\n", BC_MAX_VARS); + printf( + "BC_BASE_MAX = "BC_MAX_OBASE_STR "\n" + "BC_DIM_MAX = "BC_MAX_DIM_STR "\n" + "BC_SCALE_MAX = "BC_MAX_SCALE_STR "\n" + "BC_STRING_MAX = "BC_MAX_STRING_STR"\n" + "BC_NAME_MAX = "BC_MAX_NAME_STR "\n" + "BC_NUM_MAX = "BC_MAX_NUM_STR "\n" + "MAX Exponent = "BC_MAX_EXP_STR "\n" + "Number of vars = "BC_MAX_VARS_STR "\n" + ); break; } @@ -5903,12 +5946,12 @@ static BcStatus bc_program_assign(char inst) if (ib || sc || left->t == BC_RESULT_OBASE) { static const char *const msg[] = { - "bad ibase; must be [2, 16]", //BC_RESULT_IBASE - "bad scale; must be [0, BC_SCALE_MAX]", //BC_RESULT_SCALE - NULL, //can't happen //BC_RESULT_LAST - NULL, //can't happen //BC_RESULT_CONSTANT - NULL, //can't happen //BC_RESULT_ONE - "bad obase; must be [2, BC_BASE_MAX]", //BC_RESULT_OBASE + "bad ibase; must be [2,16]", //BC_RESULT_IBASE + "bad scale; must be [0,"BC_MAX_SCALE_STR"]", //BC_RESULT_SCALE + NULL, //can't happen //BC_RESULT_LAST + NULL, //can't happen //BC_RESULT_CONSTANT + NULL, //can't happen //BC_RESULT_ONE + "bad obase; must be [2,"BC_MAX_OBASE_STR"]", //BC_RESULT_OBASE }; size_t *ptr; unsigned long val, max; @@ -6020,7 +6063,7 @@ static BcStatus bc_program_pushArray(char *code, size_t *bgn, if (s) goto err; if (temp > BC_MAX_DIM) { - s = bc_error("array too long; must be [1, BC_DIM_MAX]"); + s = bc_error("array too long; must be [1,"BC_MAX_DIM_STR"]"); goto err; } -- cgit v1.2.3-55-g6feb From 2d615fee3879f7eec6fd51c468ce074cc6e7a47c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 7 Dec 2018 16:22:45 +0100 Subject: bc: convert two macros to functions, unwing one complex max(a,min(b,c)) function old new delta BC_NUM_AREQ - 45 +45 BC_NUM_MREQ - 33 +33 bc_num_rem 104 91 -13 bc_num_divmod 168 155 -13 bc_num_d 584 569 -15 bc_num_mul 80 62 -18 bc_num_mod 80 62 -18 bc_num_div 80 62 -18 bc_num_sub 112 77 -35 bc_num_add 112 77 -35 ------------------------------------------------------------------------------ (add/remove: 2/0 grow/shrink: 0/8 up/down: 78/-165) Total: -87 bytes text data bss dec hex filename 985526 485 7296 993307 f281b busybox_old 985439 485 7296 993220 f27c4 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 3da03b437..2cfe87b1e 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -224,14 +224,6 @@ typedef struct BcNum { #define BC_NUM_KARATSUBA_LEN (32) -#define BC_NUM_NEG(n, neg) ((((ssize_t)(n)) ^ -((ssize_t)(neg))) + (neg)) -#define BC_NUM_ONE(n) ((n)->len == 1 && (n)->rdx == 0 && (n)->num[0] == 1) -#define BC_NUM_INT(n) ((n)->len - (n)->rdx) -#define BC_NUM_AREQ(a, b) \ - (BC_MAX((a)->rdx, (b)->rdx) + BC_MAX(BC_NUM_INT(a), BC_NUM_INT(b)) + 1) -#define BC_NUM_MREQ(a, b, scale) \ - (BC_NUM_INT(a) + BC_NUM_INT(b) + BC_MAX((scale), (a)->rdx + (b)->rdx) + 1) - typedef BcStatus (*BcNumBinaryOp)(BcNum *, BcNum *, BcNum *, size_t); typedef void (*BcNumDigitOp)(size_t, size_t, bool, size_t *, size_t); @@ -1486,6 +1478,20 @@ static void bc_num_subArrays(BcDig *restrict a, BcDig *restrict b, } } +#define BC_NUM_NEG(n, neg) ((((ssize_t)(n)) ^ -((ssize_t)(neg))) + (neg)) +#define BC_NUM_ONE(n) ((n)->len == 1 && (n)->rdx == 0 && (n)->num[0] == 1) +#define BC_NUM_INT(n) ((n)->len - (n)->rdx) +//#define BC_NUM_AREQ(a, b) (BC_MAX((a)->rdx, (b)->rdx) + BC_MAX(BC_NUM_INT(a), BC_NUM_INT(b)) + 1) +static /*ALWAYS_INLINE*/ size_t BC_NUM_AREQ(BcNum *a, BcNum *b) +{ + return BC_MAX(a->rdx, b->rdx) + BC_MAX(BC_NUM_INT(a), BC_NUM_INT(b)) + 1; +} +//#define BC_NUM_MREQ(a, b, scale) (BC_NUM_INT(a) + BC_NUM_INT(b) + BC_MAX((scale), (a)->rdx + (b)->rdx) + 1) +static /*ALWAYS_INLINE*/ size_t BC_NUM_MREQ(BcNum *a, BcNum *b, size_t scale) +{ + return BC_NUM_INT(a) + BC_NUM_INT(b) + BC_MAX(scale, a->rdx + b->rdx) + 1; +} + static ssize_t bc_num_compare(BcDig *restrict a, BcDig *restrict b, size_t len) { size_t i; @@ -2084,7 +2090,12 @@ static BcStatus bc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) bc_num_init(©, a->len); bc_num_copy(©, a); - if (!neg) scale = BC_MIN(a->rdx * pow, BC_MAX(scale, a->rdx)); + if (!neg) { + if (a->rdx > scale) + scale = a->rdx; + if (a->rdx * pow < scale) + scale = a->rdx * pow; + } b->neg = neg; -- cgit v1.2.3-55-g6feb From f522dd94207275ac4a2706c4927a12c37707ff5a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 7 Dec 2018 16:35:43 +0100 Subject: bc: replace G.eof with a special exit code of bc_vm_stdin() function old new delta bc_read_line 305 307 +2 bc_vm_run 701 689 -12 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/1 up/down: 2/-12) Total: -10 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 2cfe87b1e..24e4b6392 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -191,6 +191,7 @@ typedef enum BcStatus { BC_STATUS_SUCCESS = 0, BC_STATUS_FAILURE = 1, BC_STATUS_PARSE_EMPTY_EXP = 2, // bc_parse_expr() uses this + BC_STATUS_EOF = 3, // bc_vm_stdin() uses this } BcStatus; #define BC_VEC_INVALID_IDX ((size_t) -1) @@ -754,7 +755,6 @@ typedef unsigned long (*BcProgramBuiltIn)(BcNum *); struct globals { IF_FEATURE_BC_SIGNALS(smallint ttyin;) IF_FEATURE_CLEAN_UP(smallint exiting;) - smallint eof; char sbgn; char send; @@ -1270,10 +1270,12 @@ static int push_input_byte(BcVec *vec, char c) static BcStatus bc_read_line(BcVec *vec, const char *prompt) { + BcStatus s; bool bad_chars; if (G_posix) prompt = ""; + s = BC_STATUS_SUCCESS; do { int c; @@ -1299,7 +1301,7 @@ static BcStatus bc_read_line(BcVec *vec, const char *prompt) if (n <= 0) { // read errors or EOF, or ^D, or ^C if (n == 0) // ^C goto intr; - G.eof = 1; + s = BC_STATUS_EOF; break; } i = 0; @@ -1329,7 +1331,7 @@ static BcStatus bc_read_line(BcVec *vec, const char *prompt) if (c == EOF) { if (ferror(stdin)) quit(); // this emits error message - G.eof = 1; + s = BC_STATUS_EOF; // Note: EOF does not append '\n', therefore: // printf 'print 123\n' | bc - works // printf 'print 123' | bc - fails (syntax error) @@ -1342,7 +1344,7 @@ static BcStatus bc_read_line(BcVec *vec, const char *prompt) bc_vec_pushZeroByte(vec); - return BC_STATUS_SUCCESS; + return s; } static char* bc_read_file(const char *path) @@ -7129,8 +7131,7 @@ static BcStatus bc_vm_stdin(void) // with a backslash to the parser. The reason for that is because the parser // treats a backslash+newline combo as whitespace, per the bc spec. In that // case, and for strings and comments, the parser will expect more stuff. - s = BC_STATUS_SUCCESS; - while (!G.eof && (s = bc_read_line(&buf, ">>> ")) == BC_STATUS_SUCCESS) { + while ((s = bc_read_line(&buf, ">>> ")) == BC_STATUS_SUCCESS) { char *string = buf.v; @@ -7187,6 +7188,8 @@ static BcStatus bc_vm_stdin(void) bc_vec_pop_all(&buffer); } + if (s == BC_STATUS_EOF) // input EOF (^D) is not an error + s = BC_STATUS_SUCCESS; if (str) { s = bc_error("string end could not be found"); -- cgit v1.2.3-55-g6feb From 9f00a0fdb159432f1d7232253e2180d85e5eca32 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 8 Dec 2018 13:34:43 +0100 Subject: tls: make RIGHTSHIFTX() in AES-GCM faster Signed-off-by: Denys Vlasenko --- networking/tls_aesgcm.c | 63 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 56 insertions(+), 7 deletions(-) diff --git a/networking/tls_aesgcm.c b/networking/tls_aesgcm.c index 688df85fb..008dc9b5d 100644 --- a/networking/tls_aesgcm.c +++ b/networking/tls_aesgcm.c @@ -35,17 +35,66 @@ static ALWAYS_INLINE void FlattenSzInBits(byte* buf, word32 sz) static void RIGHTSHIFTX(byte* x) { - int i; - int carryOut = 0; - int carryIn = 0; - int borrow = x[15] & 0x01; +#define l ((unsigned long*)x) +#if 0 + // Generic byte-at-a-time algorithm + int i; + byte carryIn = (x[15] & 0x01) ? 0xE1 : 0; for (i = 0; i < AES_BLOCK_SIZE; i++) { - carryOut = x[i] & 0x01; - x[i] = (x[i] >> 1) | (carryIn ? 0x80 : 0); + byte carryOut = (x[i] << 7); // zero, or 0x80 + x[i] = (x[i] >> 1) ^ carryIn; + carryIn = carryOut; + } + +#elif BB_BIG_ENDIAN + + // Big-endian can shift-right in larger than byte chunks + // (we use the fact that 'x' is long-aligned) + unsigned long carryIn = (x[15] & 0x01) + ? ((unsigned long)0xE1 << (LONG_BIT-8)) + : 0; +# if ULONG_MAX <= 0xffffffff + int i; + for (i = 0; i < AES_BLOCK_SIZE/sizeof(long); i++) { + unsigned long carryOut = l[i] << (LONG_BIT-1); // zero, or 0x800..00 + l[i] = (l[i] >> 1) ^ carryIn; + carryIn = carryOut; + } +# else + // 64-bit code: need to process only 2 words + unsigned long carryOut = l[0] << (LONG_BIT-1); // zero, or 0x800..00 + l[0] = (l[0] >> 1) ^ carryIn; + l[1] = (l[1] >> 1) ^ carryOut; +# endif + +#else /* LITTLE_ENDIAN */ + + // In order to use word-sized ops, little-endian needs to byteswap. + // On x86, code size increase is ~10 bytes compared to byte-by-byte. + unsigned long carryIn = (x[15] & 0x01) + ? ((unsigned long)0xE1 << (LONG_BIT-8)) + : 0; +# if ULONG_MAX <= 0xffffffff + int i; + for (i = 0; i < AES_BLOCK_SIZE/sizeof(long); i++) { + unsigned long ti = SWAP_BE32(l[i]); + unsigned long carryOut = ti << (LONG_BIT-1); // zero, or 0x800..00 + ti = (ti >> 1) ^ carryIn; + l[i] = SWAP_BE32(ti); carryIn = carryOut; } - if (borrow) x[0] ^= 0xE1; +# else + // 64-bit code: need to process only 2 words + unsigned long tt = SWAP_BE64(l[0]); + unsigned long carryOut = tt << (LONG_BIT-1); // zero, or 0x800..00 + tt = (tt >> 1) ^ carryIn; l[0] = SWAP_BE64(tt); + tt = SWAP_BE64(l[1]); + tt = (tt >> 1) ^ carryOut; l[1] = SWAP_BE64(tt); +# endif + +#endif /* LITTLE_ENDIAN */ +#undef l } static void GMULT(byte* X, byte* Y) -- cgit v1.2.3-55-g6feb From 136fe9bede247d3273f5e82b5e856fa5c15a922c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 8 Dec 2018 13:49:15 +0100 Subject: suppress gcc 8 aliasing warnings function old new delta sigprocmask_SIG_SETMASK - 16 +16 wait_for_child_or_signal 221 213 -8 dowait 432 424 -8 Signed-off-by: Denys Vlasenko --- include/libbb.h | 2 ++ libbb/lineedit.c | 12 +++++++++++- libbb/signals.c | 10 ++++++++++ shell/ash.c | 2 +- shell/hush.c | 2 +- 5 files changed, 25 insertions(+), 3 deletions(-) diff --git a/include/libbb.h b/include/libbb.h index 9e0970095..638c58412 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -544,6 +544,8 @@ void sig_unblock(int sig) FAST_FUNC; int sigaction_set(int sig, const struct sigaction *act) FAST_FUNC; /* SIG_BLOCK/SIG_UNBLOCK all signals: */ int sigprocmask_allsigs(int how) FAST_FUNC; +/* SIG_SETMASK set, and return old set in the same set: */ +int sigprocmask_SIG_SETMASK(sigset_t *set) FAST_FUNC; /* Standard handler which just records signo */ extern smallint bb_got_signal; void record_signo(int signo); /* not FAST_FUNC! */ diff --git a/libbb/lineedit.c b/libbb/lineedit.c index b6fcd7af0..378f0900a 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -2309,6 +2309,16 @@ static int32_t reverse_i_search(int timeout) } #endif +static void sigaction2(int sig, struct sigaction *act) +{ + // Grr... gcc 8.1.1: + // "passing argument 3 to restrict-qualified parameter aliases with argument 2" + // dance around that... + struct sigaction *oact FIX_ALIASING; + oact = act; + sigaction(sig, act, oact); +} + /* maxsize must be >= 2. * Returns: * -1 on read errors or EOF, or on bare Ctrl-D, @@ -2419,7 +2429,7 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman /* Install window resize handler (NB: after *all* init is complete) */ S.SIGWINCH_handler.sa_handler = win_changed; S.SIGWINCH_handler.sa_flags = SA_RESTART; - sigaction(SIGWINCH, &S.SIGWINCH_handler, &S.SIGWINCH_handler); + sigaction2(SIGWINCH, &S.SIGWINCH_handler); #endif read_key_buffer[0] = 0; while (1) { diff --git a/libbb/signals.c b/libbb/signals.c index 3f589321c..5a1544db7 100644 --- a/libbb/signals.c +++ b/libbb/signals.c @@ -31,6 +31,16 @@ int FAST_FUNC sigprocmask_allsigs(int how) return sigprocmask(how, &set, NULL); } +int FAST_FUNC sigprocmask_SIG_SETMASK(sigset_t *set) +{ + // Grr... gcc 8.1.1: + // "passing argument 3 to restrict-qualified parameter aliases with argument 2" + // dance around that... + sigset_t *oset FIX_ALIASING; + oset = set; + return sigprocmask(SIG_SETMASK, set, oset); +} + void FAST_FUNC bb_signals(int sigs, void (*f)(int)) { int sig_no = 0; diff --git a/shell/ash.c b/shell/ash.c index 9ce1d1a76..456aca4f0 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -4217,7 +4217,7 @@ wait_block_or_sig(int *status) /* Children exist, but none are ready. Sleep until interesting signal */ #if 1 sigfillset(&mask); - sigprocmask(SIG_SETMASK, &mask, &mask); + sigprocmask_SIG_SETMASK(&mask); /* mask is updated */ while (!got_sigchld && !pending_sig) sigsuspend(&mask); sigprocmask(SIG_SETMASK, &mask, NULL); diff --git a/shell/hush.c b/shell/hush.c index 90191408d..5953ceb9f 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -11442,7 +11442,7 @@ static int wait_for_child_or_signal(struct pipe *waitfor_pipe, pid_t waitfor_pid * and get stuck in sigsuspend... */ sigfillset(&oldset); /* block all signals, remember old set */ - sigprocmask(SIG_SETMASK, &oldset, &oldset); + sigprocmask_SIG_SETMASK(&oldset); if (!sigisemptyset(&G.pending_set)) { /* Crap! we raced with some signal! */ -- cgit v1.2.3-55-g6feb From b437df1157964ed012f1aeae25b68f6bbaae1787 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 8 Dec 2018 15:35:24 +0100 Subject: inetd: suppress aliasing warning function old new delta sigprocmask2 - 8 +8 wait_for_child_or_signal 213 218 +5 dowait 424 429 +5 block_CHLD_HUP_ALRM 62 59 -3 sigprocmask_SIG_SETMASK 16 - -16 ------------------------------------------------------------------------------ (add/remove: 1/1 grow/shrink: 2/1 up/down: 18/-19) Total: -1 bytes Signed-off-by: Denys Vlasenko --- include/libbb.h | 4 ++-- libbb/signals.c | 4 ++-- networking/inetd.c | 2 +- shell/ash.c | 2 +- shell/hush.c | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/libbb.h b/include/libbb.h index 638c58412..daa96728b 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -544,8 +544,8 @@ void sig_unblock(int sig) FAST_FUNC; int sigaction_set(int sig, const struct sigaction *act) FAST_FUNC; /* SIG_BLOCK/SIG_UNBLOCK all signals: */ int sigprocmask_allsigs(int how) FAST_FUNC; -/* SIG_SETMASK set, and return old set in the same set: */ -int sigprocmask_SIG_SETMASK(sigset_t *set) FAST_FUNC; +/* Return old set in the same set: */ +int sigprocmask2(int how, sigset_t *set) FAST_FUNC; /* Standard handler which just records signo */ extern smallint bb_got_signal; void record_signo(int signo); /* not FAST_FUNC! */ diff --git a/libbb/signals.c b/libbb/signals.c index 5a1544db7..d3d84ef6a 100644 --- a/libbb/signals.c +++ b/libbb/signals.c @@ -31,14 +31,14 @@ int FAST_FUNC sigprocmask_allsigs(int how) return sigprocmask(how, &set, NULL); } -int FAST_FUNC sigprocmask_SIG_SETMASK(sigset_t *set) +int FAST_FUNC sigprocmask2(int how, sigset_t *set) { // Grr... gcc 8.1.1: // "passing argument 3 to restrict-qualified parameter aliases with argument 2" // dance around that... sigset_t *oset FIX_ALIASING; oset = set; - return sigprocmask(SIG_SETMASK, set, oset); + return sigprocmask(how, set, oset); } void FAST_FUNC bb_signals(int sigs, void (*f)(int)) diff --git a/networking/inetd.c b/networking/inetd.c index ca1a97268..8f871ee12 100644 --- a/networking/inetd.c +++ b/networking/inetd.c @@ -488,7 +488,7 @@ static void block_CHLD_HUP_ALRM(sigset_t *m) sigaddset(m, SIGCHLD); sigaddset(m, SIGHUP); sigaddset(m, SIGALRM); - sigprocmask(SIG_BLOCK, m, m); /* old sigmask is stored in m */ + sigprocmask2(SIG_BLOCK, m); /* old sigmask is stored in m */ } static void restore_sigmask(sigset_t *m) diff --git a/shell/ash.c b/shell/ash.c index 456aca4f0..a01c8fa8b 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -4217,7 +4217,7 @@ wait_block_or_sig(int *status) /* Children exist, but none are ready. Sleep until interesting signal */ #if 1 sigfillset(&mask); - sigprocmask_SIG_SETMASK(&mask); /* mask is updated */ + sigprocmask2(SIG_SETMASK, &mask); /* mask is updated */ while (!got_sigchld && !pending_sig) sigsuspend(&mask); sigprocmask(SIG_SETMASK, &mask, NULL); diff --git a/shell/hush.c b/shell/hush.c index 5953ceb9f..2e4a4bcc6 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -11442,7 +11442,7 @@ static int wait_for_child_or_signal(struct pipe *waitfor_pipe, pid_t waitfor_pid * and get stuck in sigsuspend... */ sigfillset(&oldset); /* block all signals, remember old set */ - sigprocmask_SIG_SETMASK(&oldset); + sigprocmask2(SIG_SETMASK, &oldset); if (!sigisemptyset(&G.pending_set)) { /* Crap! we raced with some signal! */ -- cgit v1.2.3-55-g6feb From 51283b8109dc2fdaa3fefc5c5a93b6cda72cddfd Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 8 Dec 2018 15:41:17 +0100 Subject: mdev: suppress aliasing warning Signed-off-by: Denys Vlasenko --- util-linux/mdev.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/util-linux/mdev.c b/util-linux/mdev.c index 4b4eeafba..5ad09e09a 100644 --- a/util-linux/mdev.c +++ b/util-linux/mdev.c @@ -808,6 +808,16 @@ static void make_device(char *device_name, char *path, int operation) } /* for (;;) */ } +static ssize_t readlink2(char *buf, size_t bufsize) +{ + // Grr... gcc 8.1.1: + // "passing argument 2 to restrict-qualified parameter aliases with argument 1" + // dance around that... + char *obuf FIX_ALIASING; + obuf = buf; + return readlink(buf, obuf, bufsize); +} + /* File callback for /sys/ traversal. * We act only on "/sys/.../dev" (pseudo)file */ @@ -831,7 +841,7 @@ static int FAST_FUNC fileAction(const char *fileName, /* Read ".../subsystem" symlink in the same directory where ".../dev" is */ strcpy(subsys, path); strcpy(subsys + len, "/subsystem"); - res = readlink(subsys, subsys, sizeof(subsys)-1); + res = readlink2(subsys, sizeof(subsys)-1); if (res > 0) { subsys[res] = '\0'; free(G.subsystem); -- cgit v1.2.3-55-g6feb From 23427a63fc8f7742210d329b9edd77a6e547d2cd Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 8 Dec 2018 15:45:46 +0100 Subject: lineedit: fix "defined but not used" sigaction2 warning Signed-off-by: Denys Vlasenko --- libbb/lineedit.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 378f0900a..3ed38e54d 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -2309,6 +2309,7 @@ static int32_t reverse_i_search(int timeout) } #endif +#if ENABLE_FEATURE_EDITING_WINCH static void sigaction2(int sig, struct sigaction *act) { // Grr... gcc 8.1.1: @@ -2318,6 +2319,7 @@ static void sigaction2(int sig, struct sigaction *act) oact = act; sigaction(sig, act, oact); } +#endif /* maxsize must be >= 2. * Returns: -- cgit v1.2.3-55-g6feb From d0bc5fdfea72ffac3102c76760f3e55a40a430ea Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 8 Dec 2018 18:59:07 +0100 Subject: dc: fix "small dc" to have standard command line API Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 3 +-- miscutils/dc.c | 70 +++++++++++++++++++++++++++++++++++++++------------------- 2 files changed, 48 insertions(+), 25 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 24e4b6392..e543b2b93 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -159,8 +159,7 @@ //usage: //usage:#define dc_full_usage "\n" //usage: "\nTiny RPN calculator. Operations:" -//usage: "\n+, -, *, /, %, ^, exp, ~, divmod, |, " -//usage: "modular exponentiation," +//usage: "\n+, -, *, /, %, ~, ^, |," //usage: "\np - print top of the stack (without popping)" //usage: "\nf - print entire stack" //usage: "\nk - pop the value and set the precision" diff --git a/miscutils/dc.c b/miscutils/dc.c index bca4778bf..17fdda8fd 100644 --- a/miscutils/dc.c +++ b/miscutils/dc.c @@ -20,7 +20,6 @@ typedef unsigned long long data_t; #define DATA_FMT "ll" #endif - struct globals { unsigned pointer; unsigned base; @@ -36,7 +35,6 @@ enum { STACK_SIZE = (COMMON_BUFSIZE - offsetof(struct globals, stack)) / sizeof( base = 10; \ } while (0) - static void check_under(void) { if (pointer == 0) @@ -184,25 +182,25 @@ struct op { static const struct op operators[] = { #if ENABLE_FEATURE_DC_LIBM - {"**", power}, - {"exp", power}, - {"pow", power}, + {"^", power}, +// {"exp", power}, +// {"pow", power}, #endif {"%", mod}, - {"mod", mod}, +// {"mod", mod}, + // logic ops are not standard, remove? {"and", and}, {"or", or}, {"not", not}, - {"eor", eor}, {"xor", eor}, {"+", add}, - {"add", add}, +// {"add", add}, {"-", sub}, - {"sub", sub}, +// {"sub", sub}, {"*", mul}, - {"mul", mul}, +// {"mul", mul}, {"/", divide}, - {"div", divide}, +// {"div", divide}, {"p", print_no_pop}, {"f", print_stack_no_pop}, {"o", set_output_base}, @@ -243,24 +241,50 @@ static void stack_machine(const char *argument) bb_error_msg_and_die("syntax error at '%s'", argument); } +static void process_file(FILE *fp) +{ + char *line; + while ((line = xmalloc_fgetline(fp)) != NULL) { + stack_machine(line); + free(line); + } +} + int dc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int dc_main(int argc UNUSED_PARAM, char **argv) { + bool script = 0; + INIT_G(); -//TODO: fix this, should take: dc -eSCRIPT -fFILE FILE - argv++; - if (!argv[0]) { - /* take stuff from stdin if no args are given */ - char *line; - while ((line = xmalloc_fgetline(stdin)) != NULL) { - stack_machine(line); - free(line); + /* Run -e'SCRIPT' and -fFILE in order of appearance, then handle FILEs */ + for (;;) { + int n = getopt(argc, argv, "e:f:"); + if (n <= 0) + break; + switch (n) { + case 'e': + script = 1; + stack_machine(optarg); + break; + case 'f': + script = 1; + process_file(xfopen_for_read(optarg)); + break; + default: + bb_show_usage(); } - } else { - do { - stack_machine(*argv); - } while (*++argv); } + argv += optind; + + if (*argv) { + do + process_file(xfopen_for_read(*argv++)); + while (*argv); + } else if (!script) { + /* Take stuff from stdin if no args are given */ + process_file(stdin); + } + return EXIT_SUCCESS; } -- cgit v1.2.3-55-g6feb From 6e7c65fca0cb176592000b249f612e037a1dc7fc Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 8 Dec 2018 19:34:35 +0100 Subject: bc: trim banner, use empty interactive prompts (GNU bc compat) function old new delta bc_vm_run 689 684 -5 bc_program_read 355 350 -5 bc_read_line 307 285 -22 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/3 up/down: 0/-32) Total: -32 bytes text data bss dec hex filename 985409 485 7296 993190 f27a6 busybox_old 985265 485 7296 993046 f2716 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index e543b2b93..cd38bfa42 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -2,9 +2,6 @@ /* * Licensed under GPLv2 or later, see file LICENSE in this source tree. * Copyright (c) 2018 Gavin D. Howard and contributors. - * - * ** Automatically generated from https://github.com/gavinhoward/bc ** - * ** Do not edit unless you know what you are doing. ** */ //config:config BC //config: bool "bc (45 kb; 49 kb when combined with dc)" @@ -97,7 +94,7 @@ //config:config FEATURE_DC_SMALL //config: bool "Minimal dc implementation (4.2 kb), not using bc code base" //config: depends on DC && !BC -//config: default y +//config: default n //config: //config:config FEATURE_DC_LIBM //config: bool "Enable power and exp functions (requires libm)" @@ -155,11 +152,11 @@ //usage: "obase = A\n" //usage: //usage:#define dc_trivial_usage -//usage: "[-eSCRIPT]... [-fFILE]... [FILE]..." +//usage: IF_NOT_FEATURE_DC_SMALL("[-x] ")"[-eSCRIPT]... [-fFILE]... [FILE]..." //usage: //usage:#define dc_full_usage "\n" //usage: "\nTiny RPN calculator. Operations:" -//usage: "\n+, -, *, /, %, ~, ^, |," +//usage: "\n+, -, *, /, %, ~, ^," IF_NOT_FEATURE_DC_SMALL(" |,") //usage: "\np - print top of the stack (without popping)" //usage: "\nf - print entire stack" //usage: "\nk - pop the value and set the precision" @@ -1267,13 +1264,11 @@ static int push_input_byte(BcVec *vec, char c) return 0; } -static BcStatus bc_read_line(BcVec *vec, const char *prompt) +static BcStatus bc_read_line(BcVec *vec) { BcStatus s; bool bad_chars; - if (G_posix) prompt = ""; - s = BC_STATUS_SUCCESS; do { int c; @@ -1296,7 +1291,7 @@ static BcStatus bc_read_line(BcVec *vec, const char *prompt) if (G_ttyin) { int n, i; # define line_buf bb_common_bufsiz1 - n = read_line_input(G.line_input_state, prompt, line_buf, COMMON_BUFSIZE); + n = read_line_input(G.line_input_state, "", line_buf, COMMON_BUFSIZE); if (n <= 0) { // read errors or EOF, or ^D, or ^C if (n == 0) // ^C goto intr; @@ -1314,8 +1309,6 @@ static BcStatus bc_read_line(BcVec *vec, const char *prompt) # endif #endif { - if (G_ttyin) - fputs(prompt, stderr); IF_FEATURE_BC_SIGNALS(errno = 0;) do { c = fgetc(stdin); @@ -5563,7 +5556,7 @@ static BcStatus bc_program_read(void) sv_file = G.prog.file; G.prog.file = NULL; - s = bc_read_line(&buf, "read> "); + s = bc_read_line(&buf); if (s) goto io_err; common_parse_init(&parse, BC_PROG_READ); @@ -6976,8 +6969,6 @@ static void bc_vm_info(void) { printf("%s "BB_VER"\n" "Copyright (c) 2018 Gavin D. Howard and contributors\n" - "Report bugs at: https://github.com/gavinhoward/bc\n" - "This is free software with ABSOLUTELY NO WARRANTY\n" , applet_name); } @@ -7002,7 +6993,6 @@ static void bc_args(char **argv) if (getenv("POSIXLY_CORRECT")) option_mask32 |= BC_FLAG_S; -///should be in bc_vm_run() instead?? if (opts & BC_FLAG_V) { bc_vm_info(); exit(0); @@ -7130,7 +7120,7 @@ static BcStatus bc_vm_stdin(void) // with a backslash to the parser. The reason for that is because the parser // treats a backslash+newline combo as whitespace, per the bc spec. In that // case, and for strings and comments, the parser will expect more stuff. - while ((s = bc_read_line(&buf, ">>> ")) == BC_STATUS_SUCCESS) { + while ((s = bc_read_line(&buf)) == BC_STATUS_SUCCESS) { char *string = buf.v; @@ -7602,8 +7592,18 @@ int dc_main(int argc UNUSED_PARAM, char **argv) INIT_G(); G.sbgn = '['; G.send = ']'; - // TODO: dc (GNU bc 1.07.1) 1.4.1 seems to use default width - // 1 char narrower than bc from the same package. Do the same? + /* + * TODO: dc (GNU bc 1.07.1) 1.4.1 seems to use width + * 1 char wider than bc from the same package. + * Both default width, and xC_LINE_LENGTH=N are wider: + * "DC_LINE_LENGTH=5 dc -e'123456 p'" prints: + * 1234\ + * 56 + * "echo '123456' | BC_LINE_LENGTH=5 bc" prints: + * 123\ + * 456 + * Do the same, or it's a bug? + */ bc_vm_init("DC_LINE_LENGTH"); // Run -e'SCRIPT' and -fFILE in order of appearance, then handle FILEs -- cgit v1.2.3-55-g6feb From 32ec5f170589537ebec40ba334324ecf208009e7 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 8 Dec 2018 21:24:38 +0100 Subject: tls: AES-GCM: in GMULT, avoid memcpy, use one less variable in bit loop function old new delta GMULT 168 159 -9 Signed-off-by: Denys Vlasenko --- networking/tls_aesgcm.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/networking/tls_aesgcm.c b/networking/tls_aesgcm.c index 008dc9b5d..a4663cd79 100644 --- a/networking/tls_aesgcm.c +++ b/networking/tls_aesgcm.c @@ -97,25 +97,25 @@ static void RIGHTSHIFTX(byte* x) #undef l } +// Caller guarantees X is aligned static void GMULT(byte* X, byte* Y) { byte Z[AES_BLOCK_SIZE] ALIGNED_long; - byte V[AES_BLOCK_SIZE] ALIGNED_long; - int i, j; + //byte V[AES_BLOCK_SIZE] ALIGNED_long; + int i; XMEMSET(Z, 0, AES_BLOCK_SIZE); - XMEMCPY(V, X, AES_BLOCK_SIZE); - for (i = 0; i < AES_BLOCK_SIZE; i++) - { - byte y = Y[i]; - for (j = 0; j < 8; j++) - { + //XMEMCPY(V, X, AES_BLOCK_SIZE); + for (i = 0; i < AES_BLOCK_SIZE; i++) { + uint32_t y = 0x800000 | Y[i]; + for (;;) { // for every bit in Y[i], from msb to lsb if (y & 0x80) { - xorbuf_aligned_AES_BLOCK_SIZE(Z, V); + xorbuf_aligned_AES_BLOCK_SIZE(Z, X); // was V, not X } - - RIGHTSHIFTX(V); + RIGHTSHIFTX(X); // was V, not X y = y << 1; + if ((int32_t)y < 0) // if bit 0x80000000 set = if 8 iterations done + break; } } XMEMCPY(X, Z, AES_BLOCK_SIZE); -- cgit v1.2.3-55-g6feb From ac6ed11f8d432206dc0f8c8023df0962bc6b38ba Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 8 Dec 2018 21:39:10 +0100 Subject: bc: remove "ready for more input" message, GNU bc does not print that function old new delta bc_read_line 285 268 -17 bc_vm_run 684 630 -54 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-71) Total: -71 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index cd38bfa42..772696a15 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1282,10 +1282,9 @@ static BcStatus bc_read_line(BcVec *vec) if (G_interrupt) { // ^C was pressed intr: G_interrupt = 0; - fputs(IS_BC - ? "\ninterrupt (type \"quit\" to exit)\n" - : "\ninterrupt (type \"q\" to exit)\n" - , stderr); + // GNU bc says "interrupted execution." + // GNU dc says "Interrupt!" + fputs("\ninterrupted execution\n", stderr); } # if ENABLE_FEATURE_EDITING if (G_ttyin) { @@ -7171,8 +7170,6 @@ static BcStatus bc_vm_stdin(void) // Non-debug builds do not come here, they exit. break; } - fflush_and_check(); - fputs("ready for more input\n", stderr); } bc_vec_pop_all(&buffer); @@ -7403,13 +7400,8 @@ static BcStatus bc_vm_exec(void) return s; } - if (IS_BC || (option_mask32 & BC_FLAG_I)) { - if (s) { - fflush_and_check(); - fputs("ready for more input\n", stderr); - } + if (IS_BC || (option_mask32 & BC_FLAG_I)) s = bc_vm_stdin(); - } if (!s && !BC_PARSE_CAN_EXEC(&G.prs)) s = bc_vm_process(""); -- cgit v1.2.3-55-g6feb From 2a8ad4873407900e51e22b462106261a41cf8941 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 8 Dec 2018 21:56:37 +0100 Subject: bc: do not pass line width in parameters, it's in globals function old new delta bc_num_printNewline 36 47 +11 bc_num_printHex 70 62 -8 bc_num_printDigits 142 132 -10 bc_program_printStream 185 173 -12 bc_program_print 773 754 -19 bc_num_printNum 563 538 -25 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/5 up/down: 11/-74) Total: -63 bytes text data bss dec hex filename 985122 485 7296 992903 f2687 busybox_old 985059 485 7296 992840 f2648 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 57 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 772696a15..a3702756d 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -221,8 +221,9 @@ typedef struct BcNum { #define BC_NUM_KARATSUBA_LEN (32) +typedef void (*BcNumDigitOp)(size_t, size_t, bool, size_t *); + typedef BcStatus (*BcNumBinaryOp)(BcNum *, BcNum *, BcNum *, size_t); -typedef void (*BcNumDigitOp)(size_t, size_t, bool, size_t *, size_t); static BcStatus bc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale); static BcStatus bc_num_sub(BcNum *a, BcNum *b, BcNum *c, size_t scale); @@ -2309,9 +2310,9 @@ int_err: bc_num_free(&temp); } -static void bc_num_printNewline(size_t *nchars, size_t line_len) +static void bc_num_printNewline(size_t *nchars) { - if (*nchars == line_len - 1) { + if (*nchars == G.prog.len - 1) { bb_putchar('\\'); bb_putchar('\n'); *nchars = 0; @@ -2320,30 +2321,30 @@ static void bc_num_printNewline(size_t *nchars, size_t line_len) #if ENABLE_DC static void bc_num_printChar(size_t num, size_t width, bool radix, - size_t *nchars, size_t line_len) + size_t *nchars) { - (void) radix, (void) line_len; + (void) radix; bb_putchar((char) num); *nchars = *nchars + width; } #endif static void bc_num_printDigits(size_t num, size_t width, bool radix, - size_t *nchars, size_t line_len) + size_t *nchars) { size_t exp, pow; - bc_num_printNewline(nchars, line_len); + bc_num_printNewline(nchars); bb_putchar(radix ? '.' : ' '); ++(*nchars); - bc_num_printNewline(nchars, line_len); + bc_num_printNewline(nchars); for (exp = 0, pow = 1; exp < width - 1; ++exp, pow *= 10) continue; for (exp = 0; exp < width; pow /= 10, ++(*nchars), ++exp) { size_t dig; - bc_num_printNewline(nchars, line_len); + bc_num_printNewline(nchars); dig = num / pow; num -= dig * pow; bb_putchar(((char) dig) + '0'); @@ -2351,20 +2352,20 @@ static void bc_num_printDigits(size_t num, size_t width, bool radix, } static void bc_num_printHex(size_t num, size_t width, bool radix, - size_t *nchars, size_t line_len) + size_t *nchars) { if (radix) { - bc_num_printNewline(nchars, line_len); + bc_num_printNewline(nchars); bb_putchar('.'); *nchars += 1; } - bc_num_printNewline(nchars, line_len); + bc_num_printNewline(nchars); bb_putchar(bb_hexdigits_upcase[num]); *nchars = *nchars + width; } -static void bc_num_printDecimal(BcNum *n, size_t *nchars, size_t len) +static void bc_num_printDecimal(BcNum *n, size_t *nchars) { size_t i, rdx = n->rdx - 1; @@ -2372,11 +2373,11 @@ static void bc_num_printDecimal(BcNum *n, size_t *nchars, size_t len) (*nchars) += n->neg; for (i = n->len - 1; i < n->len; --i) - bc_num_printHex((size_t) n->num[i], 1, i == rdx, nchars, len); + bc_num_printHex((size_t) n->num[i], 1, i == rdx, nchars); } static BcStatus bc_num_printNum(BcNum *n, BcNum *base, size_t width, - size_t *nchars, size_t len, BcNumDigitOp print) + size_t *nchars, BcNumDigitOp print) { BcStatus s; BcVec stack; @@ -2386,7 +2387,7 @@ static BcStatus bc_num_printNum(BcNum *n, BcNum *base, size_t width, bool radix; if (n->len == 0) { - print(0, width, false, nchars, len); + print(0, width, false, nchars); return BC_STATUS_SUCCESS; } @@ -2412,7 +2413,7 @@ static BcStatus bc_num_printNum(BcNum *n, BcNum *base, size_t width, for (i = 0; i < stack.len; ++i) { ptr = bc_vec_item_rev(&stack, i); - print(*ptr, width, false, nchars, len); + print(*ptr, width, false, nchars); } if (!n->rdx) goto err; @@ -2425,7 +2426,7 @@ static BcStatus bc_num_printNum(BcNum *n, BcNum *base, size_t width, bc_num_ulong2num(&intp, dig); s = bc_num_sub(&fracp, &intp, &fracp, 0); if (s) goto err; - print(dig, width, radix, nchars, len); + print(dig, width, radix, nchars); s = bc_num_mul(&frac_len, base, &frac_len, 0); if (s) goto err; } @@ -2440,7 +2441,7 @@ err: } static BcStatus bc_num_printBase(BcNum *n, BcNum *base, size_t base_t, - size_t *nchars, size_t line_len) + size_t *nchars) { BcStatus s; size_t width, i; @@ -2461,16 +2462,16 @@ static BcStatus bc_num_printBase(BcNum *n, BcNum *base, size_t base_t, print = bc_num_printDigits; } - s = bc_num_printNum(n, base, width, nchars, line_len, print); + s = bc_num_printNum(n, base, width, nchars, print); n->neg = neg; return s; } #if ENABLE_DC -static BcStatus bc_num_stream(BcNum *n, BcNum *base, size_t *nchars, size_t len) +static BcStatus bc_num_stream(BcNum *n, BcNum *base, size_t *nchars) { - return bc_num_printNum(n, base, 1, nchars, len, bc_num_printChar); + return bc_num_printNum(n, base, 1, nchars, bc_num_printChar); } #endif @@ -2489,20 +2490,20 @@ static BcStatus bc_num_parse(BcNum *n, const char *val, BcNum *base, } static BcStatus bc_num_print(BcNum *n, BcNum *base, size_t base_t, bool newline, - size_t *nchars, size_t line_len) + size_t *nchars) { BcStatus s = BC_STATUS_SUCCESS; - bc_num_printNewline(nchars, line_len); + bc_num_printNewline(nchars); if (n->len == 0) { bb_putchar('0'); ++(*nchars); } else if (base_t == 10) - bc_num_printDecimal(n, nchars, line_len); + bc_num_printDecimal(n, nchars); else - s = bc_num_printBase(n, base, base_t, nchars, line_len); + s = bc_num_printBase(n, base, base_t, nchars); if (newline) { bb_putchar('\n'); @@ -5719,7 +5720,7 @@ static BcStatus bc_program_print(char inst, size_t idx) if (s) return s; if (BC_PROG_NUM(r, num)) { - s = bc_num_print(num, &G.prog.ob, G.prog.ob_t, !pop, &G.prog.nchars, G.prog.len); + s = bc_num_print(num, &G.prog.ob, G.prog.ob_t, !pop, &G.prog.nchars); if (!s) bc_num_copy(&G.prog.last, num); } else { @@ -6450,7 +6451,7 @@ static BcStatus bc_program_printStream(void) if (s) return s; if (BC_PROG_NUM(r, n)) - s = bc_num_stream(n, &G.prog.strmb, &G.prog.nchars, G.prog.len); + s = bc_num_stream(n, &G.prog.strmb, &G.prog.nchars); else { idx = (r->t == BC_RESULT_STR) ? r->d.id.idx : n->rdx; str = *((char **) bc_vec_item(&G.prog.strs, idx)); -- cgit v1.2.3-55-g6feb From 5f1b90b91af1076e6ba63afa7e4d7a3dbf841ce2 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 8 Dec 2018 23:18:06 +0100 Subject: bc: stop propagating pointer to G.prog.nchars deep into printing functions function old new delta bc_num_printHex 62 71 +9 bc_num_printNewline 47 54 +7 bc_num_printDigits 132 136 +4 bc_num_printChar 23 27 +4 bc_program_printStream 173 163 -10 bc_program_print 754 739 -15 bc_num_printNum 538 514 -24 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 4/3 up/down: 24/-49) Total: -25 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 93 ++++++++++++++++++++++++++++------------------------------ 1 file changed, 45 insertions(+), 48 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index a3702756d..4fb6e77ab 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -221,7 +221,7 @@ typedef struct BcNum { #define BC_NUM_KARATSUBA_LEN (32) -typedef void (*BcNumDigitOp)(size_t, size_t, bool, size_t *); +typedef void (*BcNumDigitOp)(size_t, size_t, bool); typedef BcStatus (*BcNumBinaryOp)(BcNum *, BcNum *, BcNum *, size_t); @@ -2310,74 +2310,70 @@ int_err: bc_num_free(&temp); } -static void bc_num_printNewline(size_t *nchars) +static void bc_num_printNewline(void) { - if (*nchars == G.prog.len - 1) { + if (G.prog.nchars == G.prog.len - 1) { bb_putchar('\\'); bb_putchar('\n'); - *nchars = 0; + G.prog.nchars = 0; } } #if ENABLE_DC -static void bc_num_printChar(size_t num, size_t width, bool radix, - size_t *nchars) +static void bc_num_printChar(size_t num, size_t width, bool radix) { (void) radix; bb_putchar((char) num); - *nchars = *nchars + width; + G.prog.nchars += width; } #endif -static void bc_num_printDigits(size_t num, size_t width, bool radix, - size_t *nchars) +static void bc_num_printDigits(size_t num, size_t width, bool radix) { size_t exp, pow; - bc_num_printNewline(nchars); + bc_num_printNewline(); bb_putchar(radix ? '.' : ' '); - ++(*nchars); + ++G.prog.nchars; - bc_num_printNewline(nchars); + bc_num_printNewline(); for (exp = 0, pow = 1; exp < width - 1; ++exp, pow *= 10) continue; - for (exp = 0; exp < width; pow /= 10, ++(*nchars), ++exp) { + for (exp = 0; exp < width; pow /= 10, ++G.prog.nchars, ++exp) { size_t dig; - bc_num_printNewline(nchars); + bc_num_printNewline(); dig = num / pow; num -= dig * pow; bb_putchar(((char) dig) + '0'); } } -static void bc_num_printHex(size_t num, size_t width, bool radix, - size_t *nchars) +static void bc_num_printHex(size_t num, size_t width, bool radix) { if (radix) { - bc_num_printNewline(nchars); + bc_num_printNewline(); bb_putchar('.'); - *nchars += 1; + G.prog.nchars += 1; } - bc_num_printNewline(nchars); + bc_num_printNewline(); bb_putchar(bb_hexdigits_upcase[num]); - *nchars = *nchars + width; + G.prog.nchars += width; } -static void bc_num_printDecimal(BcNum *n, size_t *nchars) +static void bc_num_printDecimal(BcNum *n) { size_t i, rdx = n->rdx - 1; if (n->neg) bb_putchar('-'); - (*nchars) += n->neg; + G.prog.nchars += n->neg; for (i = n->len - 1; i < n->len; --i) - bc_num_printHex((size_t) n->num[i], 1, i == rdx, nchars); + bc_num_printHex((size_t) n->num[i], 1, i == rdx); } -static BcStatus bc_num_printNum(BcNum *n, BcNum *base, size_t width, - size_t *nchars, BcNumDigitOp print) +static BcStatus bc_num_printNum(BcNum *n, BcNum *base, size_t width, BcNumDigitOp print) { BcStatus s; BcVec stack; @@ -2387,7 +2383,7 @@ static BcStatus bc_num_printNum(BcNum *n, BcNum *base, size_t width, bool radix; if (n->len == 0) { - print(0, width, false, nchars); + print(0, width, false); return BC_STATUS_SUCCESS; } @@ -2413,7 +2409,7 @@ static BcStatus bc_num_printNum(BcNum *n, BcNum *base, size_t width, for (i = 0; i < stack.len; ++i) { ptr = bc_vec_item_rev(&stack, i); - print(*ptr, width, false, nchars); + print(*ptr, width, false); } if (!n->rdx) goto err; @@ -2426,7 +2422,7 @@ static BcStatus bc_num_printNum(BcNum *n, BcNum *base, size_t width, bc_num_ulong2num(&intp, dig); s = bc_num_sub(&fracp, &intp, &fracp, 0); if (s) goto err; - print(dig, width, radix, nchars); + print(dig, width, radix); s = bc_num_mul(&frac_len, base, &frac_len, 0); if (s) goto err; } @@ -2440,8 +2436,7 @@ err: return s; } -static BcStatus bc_num_printBase(BcNum *n, BcNum *base, size_t base_t, - size_t *nchars) +static BcStatus bc_num_printBase(BcNum *n, BcNum *base, size_t base_t) { BcStatus s; size_t width, i; @@ -2449,7 +2444,7 @@ static BcStatus bc_num_printBase(BcNum *n, BcNum *base, size_t base_t, bool neg = n->neg; if (neg) bb_putchar('-'); - (*nchars) += neg; + G.prog.nchars += neg; n->neg = false; @@ -2462,16 +2457,16 @@ static BcStatus bc_num_printBase(BcNum *n, BcNum *base, size_t base_t, print = bc_num_printDigits; } - s = bc_num_printNum(n, base, width, nchars, print); + s = bc_num_printNum(n, base, width, print); n->neg = neg; return s; } #if ENABLE_DC -static BcStatus bc_num_stream(BcNum *n, BcNum *base, size_t *nchars) +static BcStatus bc_num_stream(BcNum *n, BcNum *base) { - return bc_num_printNum(n, base, 1, nchars, bc_num_printChar); + return bc_num_printNum(n, base, 1, bc_num_printChar); } #endif @@ -2489,25 +2484,27 @@ static BcStatus bc_num_parse(BcNum *n, const char *val, BcNum *base, return BC_STATUS_SUCCESS; } -static BcStatus bc_num_print(BcNum *n, BcNum *base, size_t base_t, bool newline, - size_t *nchars) +static BcStatus bc_num_print(BcNum *n, bool newline) { + BcNum *base = &G.prog.ob; + size_t base_t = G.prog.ob_t; + BcStatus s = BC_STATUS_SUCCESS; - bc_num_printNewline(nchars); + bc_num_printNewline(); if (n->len == 0) { bb_putchar('0'); - ++(*nchars); + ++G.prog.nchars; } else if (base_t == 10) - bc_num_printDecimal(n, nchars); + bc_num_printDecimal(n); else - s = bc_num_printBase(n, base, base_t, nchars); + s = bc_num_printBase(n, base, base_t); if (newline) { bb_putchar('\n'); - *nchars = 0; + G.prog.nchars = 0; } return s; @@ -5617,7 +5614,7 @@ static char *bc_program_name(char *code, size_t *bgn) return s; } -static void bc_program_printString(const char *str, size_t *nchars) +static void bc_program_printString(const char *str) { size_t i, len = strlen(str); @@ -5628,7 +5625,7 @@ static void bc_program_printString(const char *str, size_t *nchars) } #endif - for (i = 0; i < len; ++i, ++(*nchars)) { + for (i = 0; i < len; ++i, ++G.prog.nchars) { int c = str[i]; @@ -5668,7 +5665,7 @@ static void bc_program_printString(const char *str, size_t *nchars) case 'n': { bb_putchar('\n'); - *nchars = SIZE_MAX; + G.prog.nchars = SIZE_MAX; break; } @@ -5694,7 +5691,7 @@ static void bc_program_printString(const char *str, size_t *nchars) { // Just print the backslash and following character. bb_putchar('\\'); - ++(*nchars); + ++G.prog.nchars; bb_putchar(c); break; } @@ -5720,7 +5717,7 @@ static BcStatus bc_program_print(char inst, size_t idx) if (s) return s; if (BC_PROG_NUM(r, num)) { - s = bc_num_print(num, &G.prog.ob, G.prog.ob_t, !pop, &G.prog.nchars); + s = bc_num_print(num, !pop); if (!s) bc_num_copy(&G.prog.last, num); } else { @@ -5737,7 +5734,7 @@ static BcStatus bc_program_print(char inst, size_t idx) } } else { - bc_program_printString(str, &G.prog.nchars); + bc_program_printString(str); if (inst == BC_INST_PRINT) bb_putchar('\n'); } } @@ -6451,7 +6448,7 @@ static BcStatus bc_program_printStream(void) if (s) return s; if (BC_PROG_NUM(r, n)) - s = bc_num_stream(n, &G.prog.strmb, &G.prog.nchars); + s = bc_num_stream(n, &G.prog.strmb); else { idx = (r->t == BC_RESULT_STR) ? r->d.id.idx : n->rdx; str = *((char **) bc_vec_item(&G.prog.strs, idx)); -- cgit v1.2.3-55-g6feb From ebc41c9d9439feda167e12b27e83f7941246d76c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 8 Dec 2018 23:36:28 +0100 Subject: bc: remove redundant error checks in bc_parse_print() Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 4fb6e77ab..aeb06a97b 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -4097,7 +4097,7 @@ static BcStatus bc_parse_print(BcParse *p) { BcStatus s; BcLexType type; - bool comma = false; + bool comma; s = bc_lex_next(&p->l); if (s) return s; @@ -4107,24 +4107,26 @@ static BcStatus bc_parse_print(BcParse *p) if (type == BC_LEX_SCOLON || type == BC_LEX_NLINE) return bc_error("bad print statement"); - while (!s && type != BC_LEX_SCOLON && type != BC_LEX_NLINE) { + comma = false; + while (type != BC_LEX_SCOLON && type != BC_LEX_NLINE) { - if (type == BC_LEX_STR) + if (type == BC_LEX_STR) { s = bc_parse_string(p, BC_INST_PRINT_POP); - else { + if (s) return s; + } else { s = bc_parse_expr(p, 0, bc_parse_next_print); if (s) return s; bc_parse_push(p, BC_INST_PRINT_POP); } - if (s) return s; - comma = p->l.t.t == BC_LEX_COMMA; - if (comma) s = bc_lex_next(&p->l); + if (comma) { + s = bc_lex_next(&p->l); + if (s) return s; + } type = p->l.t.t; } - if (s) return s; if (comma) return bc_error_bad_token(); return bc_lex_next(&p->l); -- cgit v1.2.3-55-g6feb From 0f37b3286a9a999286606e0ec32cdf2902354099 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 8 Dec 2018 23:48:53 +0100 Subject: bc: eliminate always the same params to bc_num_printBase() function old new delta bc_program_print 739 736 -3 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index aeb06a97b..450c21c60 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -2436,28 +2436,31 @@ err: return s; } -static BcStatus bc_num_printBase(BcNum *n, BcNum *base, size_t base_t) +static BcStatus bc_num_printBase(BcNum *n) { BcStatus s; size_t width, i; BcNumDigitOp print; bool neg = n->neg; - if (neg) bb_putchar('-'); - G.prog.nchars += neg; + if (neg) { + bb_putchar('-'); + G.prog.nchars++; + } n->neg = false; - if (base_t <= BC_NUM_MAX_IBASE) { + if (G.prog.ob_t <= BC_NUM_MAX_IBASE) { width = 1; print = bc_num_printHex; } else { - for (i = base_t - 1, width = 0; i != 0; i /= 10, ++width); + for (i = G.prog.ob_t - 1, width = 0; i != 0; i /= 10, ++width) + continue; print = bc_num_printDigits; } - s = bc_num_printNum(n, base, width, print); + s = bc_num_printNum(n, &G.prog.ob, width, print); n->neg = neg; return s; @@ -2486,9 +2489,6 @@ static BcStatus bc_num_parse(BcNum *n, const char *val, BcNum *base, static BcStatus bc_num_print(BcNum *n, bool newline) { - BcNum *base = &G.prog.ob; - size_t base_t = G.prog.ob_t; - BcStatus s = BC_STATUS_SUCCESS; bc_num_printNewline(); @@ -2497,10 +2497,10 @@ static BcStatus bc_num_print(BcNum *n, bool newline) bb_putchar('0'); ++G.prog.nchars; } - else if (base_t == 10) + else if (G.prog.ob_t == 10) bc_num_printDecimal(n); else - s = bc_num_printBase(n, base, base_t); + s = bc_num_printBase(n); if (newline) { bb_putchar('\n'); -- cgit v1.2.3-55-g6feb From 8fa1e8e6e749cb3103831596fd30706e9364cdfe Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 9 Dec 2018 00:03:57 +0100 Subject: bc: add accessors for G.prog.strs[idx], G.prog.fns[idx] function old new delta bc_program_str - 17 +17 bc_program_func - 17 +17 bc_program_addFunc 209 204 -5 bc_program_reset 70 64 -6 bc_program_printStream 163 157 -6 bc_program_print 736 730 -6 bc_vm_file 226 219 -7 bc_parse_text 143 133 -10 bc_parse_reset 163 153 -10 bc_parse_endBody 375 365 -10 bc_parse_create 168 158 -10 bc_parse_addFunc 41 31 -10 bc_program_call 364 352 -12 bc_program_read 350 335 -15 bc_program_execStr 528 502 -26 bc_program_exec 4219 4179 -40 ------------------------------------------------------------------------------ (add/remove: 2/0 grow/shrink: 0/14 up/down: 34/-173) Total: -139 bytes text data bss dec hex filename 985043 485 7296 992824 f2638 busybox_old 984904 485 7296 992685 f25ad busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 50 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 450c21c60..3f57f4df8 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1182,6 +1182,16 @@ static void *bc_vec_item(const BcVec *v, size_t idx) return v->v + v->size * idx; } +static char** bc_program_str(size_t idx) +{ + return bc_vec_item(&G.prog.strs, idx); +} + +static BcFunc* bc_program_func(size_t idx) +{ + return bc_vec_item(&G.prog.fns, idx); +} + static void *bc_vec_item_rev(const BcVec *v, size_t idx) { return v->v + v->size * (v->len - idx - 1); @@ -3593,7 +3603,7 @@ static void bc_program_addFunc(char *name, size_t *idx); static void bc_parse_addFunc(BcParse *p, char *name, size_t *idx) { bc_program_addFunc(name, idx); - p->func = bc_vec_item(&G.prog.fns, p->fidx); + p->func = bc_program_func(p->fidx); } #define bc_parse_push(p, i) bc_vec_pushByte(&(p)->func->code, (char) (i)) @@ -3639,7 +3649,7 @@ static BcStatus bc_parse_text(BcParse *p, const char *text) { BcStatus s; - p->func = bc_vec_item(&G.prog.fns, p->fidx); + p->func = bc_program_func(p->fidx); if (!text[0] && !BC_PARSE_CAN_EXEC(p)) { p->l.t.t = BC_LEX_INVALID; @@ -3662,13 +3672,13 @@ static void bc_program_reset(void) bc_vec_npop(&G.prog.stack, G.prog.stack.len - 1); bc_vec_pop_all(&G.prog.results); - f = bc_vec_item(&G.prog.fns, 0); + f = bc_program_func(0); ip = bc_vec_top(&G.prog.stack); ip->idx = f->code.len; } #define bc_parse_updateFunc(p, f) \ - ((p)->func = bc_vec_item(&G.prog.fns, ((p)->fidx = (f)))) + ((p)->func = bc_program_func((p)->fidx = (f))) // Called when bc/dc_parse_parse() detects a failure, // resets parsing structures. @@ -5541,7 +5551,7 @@ static BcStatus bc_program_read(void) BcVec buf; BcInstPtr ip; size_t i; - BcFunc *f = bc_vec_item(&G.prog.fns, BC_PROG_READ); + BcFunc *f = bc_program_func(BC_PROG_READ); for (i = 0; i < G.prog.stack.len; ++i) { BcInstPtr *ip_ptr = bc_vec_item(&G.prog.stack, i); @@ -5576,7 +5586,7 @@ static BcStatus bc_program_read(void) ip.len = G.prog.results.len; // Update this pointer, just in case. - f = bc_vec_item(&G.prog.fns, BC_PROG_READ); + f = bc_program_func(BC_PROG_READ); bc_vec_pushByte(&f->code, BC_INST_POP_EXEC); bc_vec_push(&G.prog.stack, &ip); @@ -5725,7 +5735,7 @@ static BcStatus bc_program_print(char inst, size_t idx) else { idx = (r->t == BC_RESULT_STR) ? r->d.id.idx : num->rdx; - str = *((char **) bc_vec_item(&G.prog.strs, idx)); + str = *bc_program_str(idx); if (inst == BC_INST_PRINT_STR) { for (i = 0, len = strlen(str); i < len; ++i) { @@ -6125,7 +6135,7 @@ static BcStatus bc_program_call(char *code, size_t *idx) ip.idx = 0; ip.func = bc_program_index(code, idx); - func = bc_vec_item(&G.prog.fns, ip.func); + func = bc_program_func(ip.func); if (func->code.len == 0) { return bc_error("undefined function"); @@ -6179,7 +6189,7 @@ static BcStatus bc_program_return(char inst) if (!BC_PROG_STACK(&G.prog.results, ip->len + inst == BC_INST_RET)) return bc_error_stack_has_too_few_elements(); - f = bc_vec_item(&G.prog.fns, ip->func); + f = bc_program_func(ip->func); res.t = BC_RESULT_TEMP; if (inst == BC_INST_RET) { @@ -6265,7 +6275,7 @@ static BcStatus bc_program_builtin(char inst) char **str; size_t idx = opnd->t == BC_RESULT_STR ? opnd->d.id.idx : num->rdx; - str = bc_vec_item(&G.prog.strs, idx); + str = bc_program_str(idx); bc_num_ulong2num(&res.d.n, strlen(*str)); } #endif @@ -6397,7 +6407,7 @@ static BcStatus bc_program_asciify(void) } else { idx = (r->t == BC_RESULT_STR) ? r->d.id.idx : num->rdx; - str2 = *((char **) bc_vec_item(&G.prog.strs, idx)); + str2 = *bc_program_str(idx); c = str2[0]; } @@ -6411,7 +6421,7 @@ static BcStatus bc_program_asciify(void) if (idx != len + BC_PROG_REQ_FUNCS) { for (idx = 0; idx < G.prog.strs.len; ++idx) { - if (!strcmp(*((char **) bc_vec_item(&G.prog.strs, idx)), str)) { + if (strcmp(*bc_program_str(idx), str) == 0) { len = idx; break; } @@ -6453,7 +6463,7 @@ static BcStatus bc_program_printStream(void) s = bc_num_stream(n, &G.prog.strmb); else { idx = (r->t == BC_RESULT_STR) ? r->d.id.idx : n->rdx; - str = *((char **) bc_vec_item(&G.prog.strs, idx)); + str = *bc_program_str(idx); printf("%s", str); } @@ -6553,8 +6563,8 @@ static BcStatus bc_program_execStr(char *code, size_t *bgn, fidx = sidx + BC_PROG_REQ_FUNCS; - str = bc_vec_item(&G.prog.strs, sidx); - f = bc_vec_item(&G.prog.fns, fidx); + str = bc_program_str(sidx); + f = bc_program_func(fidx); if (f->code.len == 0) { common_parse_init(&prs, fidx); @@ -6582,7 +6592,7 @@ static BcStatus bc_program_execStr(char *code, size_t *bgn, err: bc_parse_free(&prs); - f = bc_vec_item(&G.prog.fns, fidx); + f = bc_program_func(fidx); bc_vec_pop_all(&f->code); exit: bc_vec_pop(&G.prog.results); @@ -6625,7 +6635,7 @@ static void bc_program_addFunc(char *name, size_t *idx) if (!inserted) { - BcFunc *func = bc_vec_item(&G.prog.fns, entry_ptr->idx); + BcFunc *func = bc_program_func(entry_ptr->idx); // We need to reset these, so the function can be repopulated. func->nparams = 0; @@ -6646,7 +6656,7 @@ static BcStatus bc_program_exec(void) BcResult r, *ptr; BcNum *num; BcInstPtr *ip = bc_vec_top(&G.prog.stack); - BcFunc *func = bc_vec_item(&G.prog.fns, ip->func); + BcFunc *func = bc_program_func(ip->func); char *code = func->code.v; bool cond = false; @@ -6956,7 +6966,7 @@ static BcStatus bc_program_exec(void) // If the stack has changed, pointers may be invalid. ip = bc_vec_top(&G.prog.stack); - func = bc_vec_item(&G.prog.fns, ip->func); + func = bc_program_func(ip->func); code = func->code.v; } @@ -7089,7 +7099,7 @@ static BcStatus bc_vm_file(const char *file) s = bc_vm_process(data); if (s) goto err; - main_func = bc_vec_item(&G.prog.fns, BC_PROG_MAIN); + main_func = bc_program_func(BC_PROG_MAIN); ip = bc_vec_item(&G.prog.stack, 0); if (main_func->code.len < ip->idx) -- cgit v1.2.3-55-g6feb From 927a7d6853da2f528ae13db57fc23c6527549782 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 9 Dec 2018 02:24:14 +0100 Subject: bc: in bc_program_exec(), push two variables into inner scope While at it, delete empty lines. function old new delta bc_program_exec 4179 4152 -27 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 140 ++++++++------------------------------------------------- 1 file changed, 19 insertions(+), 121 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 3f57f4df8..9f44f83f5 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -6651,8 +6651,6 @@ static void bc_program_addFunc(char *name, size_t *idx) static BcStatus bc_program_exec(void) { - BcStatus s = BC_STATUS_SUCCESS; - size_t idx; BcResult r, *ptr; BcNum *num; BcInstPtr *ip = bc_vec_top(&G.prog.stack); @@ -6660,58 +6658,41 @@ static BcStatus bc_program_exec(void) char *code = func->code.v; bool cond = false; - while (!s && ip->idx < func->code.len) { - + while (ip->idx < func->code.len) { + BcStatus s; char inst = code[(ip->idx)++]; switch (inst) { - #if ENABLE_BC case BC_INST_JUMP_ZERO: - { s = bc_program_prep(&ptr, &num); if (s) return s; cond = !bc_num_cmp(num, &G.prog.zero); bc_vec_pop(&G.prog.results); - } - // Fallthrough. - case BC_INST_JUMP: - { + // Fallthrough. + case BC_INST_JUMP: { size_t *addr; - idx = bc_program_index(code, &ip->idx); + size_t idx = bc_program_index(code, &ip->idx); addr = bc_vec_item(&func->labels, idx); if (inst == BC_INST_JUMP || cond) ip->idx = *addr; break; } - case BC_INST_CALL: - { s = bc_program_call(code, &ip->idx); break; - } - case BC_INST_INC_PRE: case BC_INST_DEC_PRE: case BC_INST_INC_POST: case BC_INST_DEC_POST: - { s = bc_program_incdec(inst); break; - } - case BC_INST_HALT: - { QUIT_OR_RETURN_TO_MAIN; break; - } - case BC_INST_RET: case BC_INST_RET0: - { s = bc_program_return(inst); break; - } - case BC_INST_BOOL_OR: case BC_INST_BOOL_AND: #endif // ENABLE_BC @@ -6721,121 +6702,77 @@ static BcStatus bc_program_exec(void) case BC_INST_REL_NE: case BC_INST_REL_LT: case BC_INST_REL_GT: - { s = bc_program_logical(inst); break; - } - case BC_INST_READ: - { s = bc_program_read(); break; - } - case BC_INST_VAR: - { s = bc_program_pushVar(code, &ip->idx, false, false); break; - } - case BC_INST_ARRAY_ELEM: case BC_INST_ARRAY: - { s = bc_program_pushArray(code, &ip->idx, inst); break; - } - case BC_INST_LAST: - { r.t = BC_RESULT_LAST; bc_vec_push(&G.prog.results, &r); break; - } - case BC_INST_IBASE: case BC_INST_SCALE: case BC_INST_OBASE: - { bc_program_pushGlobal(inst); break; - } - case BC_INST_SCALE_FUNC: case BC_INST_LENGTH: case BC_INST_SQRT: - { s = bc_program_builtin(inst); break; - } - case BC_INST_NUM: - { r.t = BC_RESULT_CONSTANT; r.d.id.idx = bc_program_index(code, &ip->idx); bc_vec_push(&G.prog.results, &r); break; - } - case BC_INST_POP: - { if (!BC_PROG_STACK(&G.prog.results, 1)) s = bc_error_stack_has_too_few_elements(); else bc_vec_pop(&G.prog.results); break; - } - case BC_INST_POP_EXEC: - { bc_vec_pop(&G.prog.stack); break; - } - case BC_INST_PRINT: case BC_INST_PRINT_POP: case BC_INST_PRINT_STR: - { s = bc_program_print(inst, 0); break; - } - case BC_INST_STR: - { r.t = BC_RESULT_STR; r.d.id.idx = bc_program_index(code, &ip->idx); bc_vec_push(&G.prog.results, &r); break; - } - case BC_INST_POWER: case BC_INST_MULTIPLY: case BC_INST_DIVIDE: case BC_INST_MODULUS: case BC_INST_PLUS: case BC_INST_MINUS: - { s = bc_program_op(inst); break; - } - case BC_INST_BOOL_NOT: - { s = bc_program_prep(&ptr, &num); if (s) return s; - bc_num_init(&r.d.n, BC_NUM_DEF_SIZE); - (!bc_num_cmp(num, &G.prog.zero) ? bc_num_one : bc_num_zero)(&r.d.n); + if (!bc_num_cmp(num, &G.prog.zero)) + bc_num_one(&r.d.n); + else + bc_num_zero(&r.d.n); bc_program_retire(&r, BC_RESULT_TEMP); - break; - } - case BC_INST_NEG: - { s = bc_program_negate(); break; - } - #if ENABLE_BC case BC_INST_ASSIGN_POWER: case BC_INST_ASSIGN_MULTIPLY: @@ -6845,123 +6782,84 @@ static BcStatus bc_program_exec(void) case BC_INST_ASSIGN_MINUS: #endif case BC_INST_ASSIGN: - { s = bc_program_assign(inst); break; - } #if ENABLE_DC case BC_INST_MODEXP: - { s = bc_program_modexp(); break; - } - case BC_INST_DIVMOD: - { s = bc_program_divmod(); break; - } - case BC_INST_EXECUTE: case BC_INST_EXEC_COND: - { cond = inst == BC_INST_EXEC_COND; s = bc_program_execStr(code, &ip->idx, cond); break; - } - - case BC_INST_PRINT_STACK: - { - for (idx = 0; !s && idx < G.prog.results.len; ++idx) + case BC_INST_PRINT_STACK: { + size_t idx; + for (idx = 0; idx < G.prog.results.len; ++idx) { s = bc_program_print(BC_INST_PRINT, idx); + if (s) break; + } break; } - case BC_INST_CLEAR_STACK: - { bc_vec_pop_all(&G.prog.results); break; - } - case BC_INST_STACK_LEN: - { bc_program_stackLen(); break; - } - case BC_INST_DUPLICATE: - { if (!BC_PROG_STACK(&G.prog.results, 1)) return bc_error_stack_has_too_few_elements(); ptr = bc_vec_top(&G.prog.results); bc_result_copy(&r, ptr); bc_vec_push(&G.prog.results, &r); break; - } - - case BC_INST_SWAP: - { + case BC_INST_SWAP: { BcResult *ptr2; - if (!BC_PROG_STACK(&G.prog.results, 2)) return bc_error_stack_has_too_few_elements(); - ptr = bc_vec_item_rev(&G.prog.results, 0); ptr2 = bc_vec_item_rev(&G.prog.results, 1); memcpy(&r, ptr, sizeof(BcResult)); memcpy(ptr, ptr2, sizeof(BcResult)); memcpy(ptr2, &r, sizeof(BcResult)); - break; } - case BC_INST_ASCIIFY: - { s = bc_program_asciify(); break; - } - case BC_INST_PRINT_STREAM: - { s = bc_program_printStream(); break; - } - case BC_INST_LOAD: - case BC_INST_PUSH_VAR: - { + case BC_INST_PUSH_VAR: { bool copy = inst == BC_INST_LOAD; s = bc_program_pushVar(code, &ip->idx, true, copy); break; } - - case BC_INST_PUSH_TO_VAR: - { + case BC_INST_PUSH_TO_VAR: { char *name = bc_program_name(code, &ip->idx); s = bc_program_copyToVar(name, true); free(name); break; } - case BC_INST_QUIT: - { if (G.prog.stack.len <= 2) QUIT_OR_RETURN_TO_MAIN; bc_vec_npop(&G.prog.stack, 2); break; - } - case BC_INST_NQUIT: - { s = bc_program_nquit(); break; - } #endif // ENABLE_DC } if (s || G_interrupt) { bc_program_reset(); - break; + return s; } // If the stack has changed, pointers may be invalid. @@ -6970,7 +6868,7 @@ static BcStatus bc_program_exec(void) code = func->code.v; } - return s; + return BC_STATUS_SUCCESS; } #if ENABLE_BC -- cgit v1.2.3-55-g6feb From 5ec4b491258be628734f5c8fa315a1df55bffcf7 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 9 Dec 2018 02:54:06 +0100 Subject: bc: in bc_program_execStr(), push two variables into inner scope function old new delta bc_program_execStr 502 496 -6 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 9f44f83f5..0dc3f843c 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -6505,8 +6505,6 @@ static BcStatus bc_program_execStr(char *code, size_t *bgn, BcParse prs; BcInstPtr ip; size_t fidx, sidx; - BcNum *n; - bool exec; if (!BC_PROG_STACK(&G.prog.results, 1)) return bc_error_stack_has_too_few_elements(); @@ -6514,8 +6512,11 @@ static BcStatus bc_program_execStr(char *code, size_t *bgn, r = bc_vec_top(&G.prog.results); if (cond) { - - char *name, *then_name = bc_program_name(code, bgn), *else_name = NULL; + BcNum *n = n; // for compiler + bool exec; + char *name; + char *then_name = bc_program_name(code, bgn); + char *else_name = NULL; if (code[*bgn] == BC_PARSE_STREND) (*bgn) += 1; @@ -6523,10 +6524,8 @@ static BcStatus bc_program_execStr(char *code, size_t *bgn, else_name = bc_program_name(code, bgn); exec = r->d.n.len != 0; - - if (exec) - name = then_name; - else if (else_name != NULL) { + name = then_name; + if (!exec && else_name != NULL) { exec = true; name = else_name; } @@ -6547,17 +6546,15 @@ static BcStatus bc_program_execStr(char *code, size_t *bgn, } sidx = n->rdx; - } - else { - - if (r->t == BC_RESULT_STR) + } else { + if (r->t == BC_RESULT_STR) { sidx = r->d.id.idx; - else if (r->t == BC_RESULT_VAR) { + } else if (r->t == BC_RESULT_VAR) { + BcNum *n; s = bc_program_num(r, &n, false); if (s || !BC_PROG_STR(n)) goto exit; sidx = n->rdx; - } - else + } else goto exit; } -- cgit v1.2.3-55-g6feb From e20e00de341518f2a9d49bde77b9e4876b472a4e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 9 Dec 2018 11:44:20 +0100 Subject: bc: add and use bc_num_init_DEF_SIZE() function old new delta bc_num_init_DEF_SIZE - 10 +10 bc_num_binary 150 148 -2 bc_program_pushVar 208 203 -5 bc_program_modexp 741 736 -5 bc_program_copyToVar 316 311 -5 bc_program_call 352 347 -5 bc_array_expand 88 83 -5 bc_program_num 1125 1115 -10 bc_vm_init 821 786 -35 bc_program_exec 4152 4098 -54 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 0/9 up/down: 10/-126) Total: -116 bytes text data bss dec hex filename 985988 477 7296 993761 f29e1 busybox_old 985872 477 7296 993645 f296d busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 54 +++++++++++++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 0dc3f843c..2e3c4139e 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1407,6 +1407,11 @@ static void bc_num_init(BcNum *n, size_t req) n->cap = req; } +static void bc_num_init_DEF_SIZE(BcNum *n) +{ + bc_num_init(n, BC_NUM_DEF_SIZE); +} + static void bc_num_expand(BcNum *n, size_t req) { req = req >= BC_NUM_DEF_SIZE ? req : BC_NUM_DEF_SIZE; @@ -2260,8 +2265,8 @@ static void bc_num_parseBase(BcNum *n, const char *val, BcNum *base) for (i = 0; zero && i < len; ++i) zero = (val[i] == '.' || val[i] == '0'); if (zero) return; - bc_num_init(&temp, BC_NUM_DEF_SIZE); - bc_num_init(&mult, BC_NUM_DEF_SIZE); + bc_num_init_DEF_SIZE(&temp); + bc_num_init_DEF_SIZE(&mult); for (i = 0; i < len; ++i) { @@ -2584,7 +2589,7 @@ static BcStatus bc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale) bc_num_init(&num1, len); bc_num_init(&num2, len); - bc_num_init(&half, BC_NUM_DEF_SIZE); + bc_num_init_DEF_SIZE(&half); bc_num_one(&half); half.num[0] = 5; @@ -2701,7 +2706,7 @@ static BcStatus bc_num_modexp(BcNum *a, BcNum *b, BcNum *c, BcNum *restrict d) bc_num_expand(d, c->len); bc_num_init(&base, c->len); bc_num_init(&exp, b->len); - bc_num_init(&two, BC_NUM_DEF_SIZE); + bc_num_init_DEF_SIZE(&two); bc_num_init(&temp, b->len); bc_num_one(&two); @@ -2792,7 +2797,7 @@ static void bc_array_expand(BcVec *a, size_t len) if (a->size == sizeof(BcNum) && a->dtor == bc_num_free) { while (len > a->len) { - bc_num_init(&data.n, BC_NUM_DEF_SIZE); + bc_num_init_DEF_SIZE(&data.n); bc_vec_push(a, &data.n); } } @@ -5530,7 +5535,7 @@ static BcStatus bc_program_op(char inst) s = bc_program_binOpPrep(&opd1, &n1, &opd2, &n2, false); if (s) return s; - bc_num_init(&res.d.n, BC_NUM_DEF_SIZE); + bc_num_init_DEF_SIZE(&res.d.n); s = bc_program_ops[inst - BC_INST_POWER](n1, n2, &res.d.n, G.prog.scale); if (s) goto err; @@ -5784,7 +5789,7 @@ static BcStatus bc_program_logical(char inst) s = bc_program_binOpPrep(&opd1, &n1, &opd2, &n2, false); if (s) return s; - bc_num_init(&res.d.n, BC_NUM_DEF_SIZE); + bc_num_init_DEF_SIZE(&res.d.n); if (inst == BC_INST_BOOL_AND) cond = bc_num_cmp(n1, &G.prog.zero) && bc_num_cmp(n2, &G.prog.zero); @@ -5896,7 +5901,7 @@ static BcStatus bc_program_copyToVar(char *name, bool var) v = bc_program_search(name, var); if (var) { - bc_num_init(&r.d.n, BC_NUM_DEF_SIZE); + bc_num_init_DEF_SIZE(&r.d.n); bc_num_copy(&r.d.n, n); } else { @@ -6035,7 +6040,7 @@ static BcStatus bc_program_pushVar(char *code, size_t *bgn, r.t = BC_RESULT_TEMP; - bc_num_init(&r.d.n, BC_NUM_DEF_SIZE); + bc_num_init_DEF_SIZE(&r.d.n); bc_num_copy(&r.d.n, num); } else { @@ -6164,7 +6169,7 @@ static BcStatus bc_program_call(char *code, size_t *idx) v = bc_program_search(a->name, a->idx); if (a->idx) { - bc_num_init(¶m.n, BC_NUM_DEF_SIZE); + bc_num_init_DEF_SIZE(¶m.n); bc_vec_push(v, ¶m.n); } else { @@ -6203,7 +6208,7 @@ static BcStatus bc_program_return(char inst) bc_num_copy(&res.d.n, num); } else { - bc_num_init(&res.d.n, BC_NUM_DEF_SIZE); + bc_num_init_DEF_SIZE(&res.d.n); bc_num_zero(&res.d.n); } @@ -6261,7 +6266,7 @@ static BcStatus bc_program_builtin(char inst) return bc_error_variable_is_wrong_type(); #endif - bc_num_init(&res.d.n, BC_NUM_DEF_SIZE); + bc_num_init_DEF_SIZE(&res.d.n); if (inst == BC_INST_SQRT) s = bc_num_sqrt(num, &res.d.n, G.prog.scale); #if ENABLE_BC @@ -6299,7 +6304,7 @@ static BcStatus bc_program_divmod(void) s = bc_program_binOpPrep(&opd1, &n1, &opd2, &n2, false); if (s) return s; - bc_num_init(&res.d.n, BC_NUM_DEF_SIZE); + bc_num_init_DEF_SIZE(&res.d.n); bc_num_init(&res2.d.n, n2->len); s = bc_num_divmod(n1, n2, &res2.d.n, &res.d.n, G.prog.scale); @@ -6369,7 +6374,7 @@ static void bc_program_stackLen(void) res.t = BC_RESULT_TEMP; - bc_num_init(&res.d.n, BC_NUM_DEF_SIZE); + bc_num_init_DEF_SIZE(&res.d.n); bc_num_ulong2num(&res.d.n, len); bc_vec_push(&G.prog.results, &res); } @@ -6392,7 +6397,7 @@ static BcStatus bc_program_asciify(void) if (BC_PROG_NUM(r, num)) { - bc_num_init(&n, BC_NUM_DEF_SIZE); + bc_num_init_DEF_SIZE(&n); bc_num_copy(&n, num); bc_num_truncate(&n, n.rdx); @@ -6610,7 +6615,7 @@ static void bc_program_pushGlobal(char inst) else val = (unsigned long) G.prog.ob_t; - bc_num_init(&res.d.n, BC_NUM_DEF_SIZE); + bc_num_init_DEF_SIZE(&res.d.n); bc_num_ulong2num(&res.d.n, val); bc_vec_push(&G.prog.results, &res); } @@ -6760,7 +6765,7 @@ static BcStatus bc_program_exec(void) case BC_INST_BOOL_NOT: s = bc_program_prep(&ptr, &num); if (s) return s; - bc_num_init(&r.d.n, BC_NUM_DEF_SIZE); + bc_num_init_DEF_SIZE(&r.d.n); if (!bc_num_cmp(num, &G.prog.zero)) bc_num_one(&r.d.n); else @@ -7356,31 +7361,30 @@ static void bc_program_init(void) memset(&ip, 0, sizeof(BcInstPtr)); /* G.prog.nchars = G.prog.scale = 0; - already is */ - - bc_num_init(&G.prog.ib, BC_NUM_DEF_SIZE); + bc_num_init_DEF_SIZE(&G.prog.ib); bc_num_ten(&G.prog.ib); G.prog.ib_t = 10; - bc_num_init(&G.prog.ob, BC_NUM_DEF_SIZE); + bc_num_init_DEF_SIZE(&G.prog.ob); bc_num_ten(&G.prog.ob); G.prog.ob_t = 10; - bc_num_init(&G.prog.hexb, BC_NUM_DEF_SIZE); + bc_num_init_DEF_SIZE(&G.prog.hexb); bc_num_ten(&G.prog.hexb); G.prog.hexb.num[0] = 6; #if ENABLE_DC - bc_num_init(&G.prog.strmb, BC_NUM_DEF_SIZE); + bc_num_init_DEF_SIZE(&G.prog.strmb); bc_num_ulong2num(&G.prog.strmb, UCHAR_MAX + 1); #endif - bc_num_init(&G.prog.last, BC_NUM_DEF_SIZE); + bc_num_init_DEF_SIZE(&G.prog.last); bc_num_zero(&G.prog.last); - bc_num_init(&G.prog.zero, BC_NUM_DEF_SIZE); + bc_num_init_DEF_SIZE(&G.prog.zero); bc_num_zero(&G.prog.zero); - bc_num_init(&G.prog.one, BC_NUM_DEF_SIZE); + bc_num_init_DEF_SIZE(&G.prog.one); bc_num_one(&G.prog.one); bc_vec_init(&G.prog.fns, sizeof(BcFunc), bc_func_free); -- cgit v1.2.3-55-g6feb From 3129f705fc630cf597abeaa97000f896d2813d52 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 9 Dec 2018 12:04:44 +0100 Subject: bc: no need to "set to zero" BcNum after bc_num_init(), it already is function old new delta bc_num_init 48 49 +1 bc_program_num 1115 1108 -7 bc_program_exec 4098 4081 -17 bc_vm_init 786 768 -18 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/3 up/down: 1/-42) Total: -41 bytes text data bss dec hex filename 985872 477 7296 993645 f296d busybox_old 985831 477 7296 993604 f2944 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 2e3c4139e..71b419d8f 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1399,12 +1399,16 @@ static void bc_num_ten(BcNum *n) n->num[1] = 1; } +// Note: this also sets BcNum to zero static void bc_num_init(BcNum *n, size_t req) { req = req >= BC_NUM_DEF_SIZE ? req : BC_NUM_DEF_SIZE; - memset(n, 0, sizeof(BcNum)); + //memset(n, 0, sizeof(BcNum)); - cleared by assignments below n->num = xmalloc(req); n->cap = req; + n->rdx = 0; + n->len = 0; + n->neg = false; } static void bc_num_init_DEF_SIZE(BcNum *n) @@ -2288,7 +2292,7 @@ static void bc_num_parseBase(BcNum *n, const char *val, BcNum *base) } bc_num_init(&result, base->len); - bc_num_zero(&result); + //bc_num_zero(&result); - already is bc_num_one(&mult); for (i += 1, digits = 0; i < len; ++i, ++digits) { @@ -6209,7 +6213,7 @@ static BcStatus bc_program_return(char inst) } else { bc_num_init_DEF_SIZE(&res.d.n); - bc_num_zero(&res.d.n); + //bc_num_zero(&res.d.n); - already is } // We need to pop arguments as well, so this takes that into account. @@ -6768,8 +6772,7 @@ static BcStatus bc_program_exec(void) bc_num_init_DEF_SIZE(&r.d.n); if (!bc_num_cmp(num, &G.prog.zero)) bc_num_one(&r.d.n); - else - bc_num_zero(&r.d.n); + //else bc_num_zero(&r.d.n); - already is bc_program_retire(&r, BC_RESULT_TEMP); break; case BC_INST_NEG: @@ -7379,10 +7382,10 @@ static void bc_program_init(void) #endif bc_num_init_DEF_SIZE(&G.prog.last); - bc_num_zero(&G.prog.last); + //bc_num_zero(&G.prog.last); - already is bc_num_init_DEF_SIZE(&G.prog.zero); - bc_num_zero(&G.prog.zero); + //bc_num_zero(&G.prog.zero); - already is bc_num_init_DEF_SIZE(&G.prog.one); bc_num_one(&G.prog.one); -- cgit v1.2.3-55-g6feb From 4a024c771992e274f46a8451647dc86f92a90999 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 9 Dec 2018 13:21:54 +0100 Subject: bc: simplify string-tonumber conversion code function old new delta bc_program_num 1108 983 -125 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-125) Total: -125 bytes text data bss dec hex filename 985831 477 7296 993604 f2944 busybox_old 985706 477 7296 993479 f28c7 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 88 ++++++++++++++++++++++++++++------------------------------ 1 file changed, 43 insertions(+), 45 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 71b419d8f..c36486414 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -2199,49 +2199,45 @@ static BcStatus bc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale, static bool bc_num_strValid(const char *val, size_t base) { BcDig b; - bool small, radix = false; - size_t i, len = strlen(val); - - if (!len) return true; - - small = base <= 10; - b = (BcDig)(small ? base + '0' : base - 10 + 'A'); - - for (i = 0; i < len; ++i) { - - BcDig c = val[i]; + bool radix; + b = (BcDig)(base <= 10 ? base + '0' : base - 10 + 'A'); + radix = false; + for (;;) { + BcDig c = *val++; + if (c == '\0') + break; if (c == '.') { - if (radix) return false; - radix = true; continue; } - - if (c < '0' || (small && c >= b) || (c > '9' && (c < 'A' || c >= b))) + if (c < '0' || c >= b || (c > '9' && c < 'A')) return false; } - return true; } +// Note: n is already "bc_num_zero()"ed, +// leading zeroes in "val" are removed static void bc_num_parseDecimal(BcNum *n, const char *val) { size_t len, i; const char *ptr; - bool zero = true; + bool zero; - for (i = 0; val[i] == '0'; ++i); - - val += i; len = strlen(val); - bc_num_zero(n); + if (len == 0) + return; - if (len != 0) { - for (i = 0; zero && i < len; ++i) zero = val[i] == '0' || val[i] == '.'; - bc_num_expand(n, len); + zero = true; + for (i = 0; val[i]; ++i) { + if (val[i] != '0' && val[i] != '.') { + zero = false; + break; + } } + bc_num_expand(n, len); ptr = strchr(val, '.'); @@ -2255,26 +2251,29 @@ static void bc_num_parseDecimal(BcNum *n, const char *val) } } +// Note: n is already "bc_num_zero()"ed, +// leading zeroes in "val" are removed static void bc_num_parseBase(BcNum *n, const char *val, BcNum *base) { BcStatus s; BcNum temp, mult, result; BcDig c = '\0'; - bool zero = true; unsigned long v; - size_t i, digits, len = strlen(val); + size_t i, digits; - bc_num_zero(n); - - for (i = 0; zero && i < len; ++i) zero = (val[i] == '.' || val[i] == '0'); - if (zero) return; + for (i = 0; ; ++i) { + if (val[i] == '\0') + return; + if (val[i] != '.' && val[i] != '0') + break; + } bc_num_init_DEF_SIZE(&temp); bc_num_init_DEF_SIZE(&mult); - for (i = 0; i < len; ++i) { - - c = val[i]; + for (;;) { + c = *val++; + if (c == '\0') goto int_err; if (c == '.') break; v = (unsigned long) (c <= '9' ? c - '0' : c - 'A' + 10); @@ -2286,19 +2285,15 @@ static void bc_num_parseBase(BcNum *n, const char *val, BcNum *base) if (s) goto int_err; } - if (i == len) { - c = val[i]; - if (c == 0) goto int_err; - } - bc_num_init(&result, base->len); //bc_num_zero(&result); - already is bc_num_one(&mult); - for (i += 1, digits = 0; i < len; ++i, ++digits) { - - c = val[i]; - if (c == 0) break; + digits = 0; + for (;;) { + c = *val++; + if (c == '\0') break; + digits++; v = (unsigned long) (c <= '9' ? c - '0' : c - 'A' + 10); @@ -2318,8 +2313,7 @@ static void bc_num_parseBase(BcNum *n, const char *val, BcNum *base) if (n->len != 0) { if (n->rdx < digits) bc_num_extend(n, digits - n->rdx); - } - else + } else bc_num_zero(n); err: @@ -2498,6 +2492,9 @@ static BcStatus bc_num_parse(BcNum *n, const char *val, BcNum *base, if (!bc_num_strValid(val, base_t)) return bc_error("bad number string"); + bc_num_zero(n); + while (*val == '0') val++; + if (base_t == 10) bc_num_parseDecimal(n, val); else @@ -6387,7 +6384,7 @@ static BcStatus bc_program_asciify(void) { BcStatus s; BcResult *r, res; - BcNum *num = NULL, n; + BcNum *num, n; char *str, *str2, c; size_t len = G.prog.strs.len, idx; unsigned long val; @@ -6396,6 +6393,7 @@ static BcStatus bc_program_asciify(void) return bc_error_stack_has_too_few_elements(); r = bc_vec_top(&G.prog.results); + num = NULL; // TODO: is this NULL needed? s = bc_program_num(r, &num, false); if (s) return s; -- cgit v1.2.3-55-g6feb From 218ed1cf5466a37ade2a319e9335fb2c1ff19252 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 9 Dec 2018 13:33:52 +0100 Subject: bc: further simplify string-to-number conversion code function old new delta bc_program_index 66 64 -2 bc_program_num 983 963 -20 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-22) Total: -22 bytes text data bss dec hex filename 985706 477 7296 993479 f28c7 busybox_old 985684 477 7296 993457 f28b1 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index c36486414..ca9506929 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -2246,8 +2246,14 @@ static void bc_num_parseDecimal(BcNum *n, const char *val) n->rdx = (size_t)((val + len) - (ptr + 1)); if (!zero) { - for (i = len - 1; i < len; ++n->len, i -= 1 + (i && val[i - 1] == '.')) + i = len - 1; + for (;;) { n->num[n->len] = val[i] - '0'; + ++n->len; + skip_dot: + if ((ssize_t)--i == (ssize_t)-1) break; + if (val[i] == '.') goto skip_dot; + } } } -- cgit v1.2.3-55-g6feb From 9311e018030314e0c3c625c244b8d63e3ece6ed3 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 10 Dec 2018 11:54:18 +0100 Subject: bc: move str-to-num conversion functions to their only caller, bc_num_parse() Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 266 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 133 insertions(+), 133 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index ca9506929..5b48f84a1 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -2196,139 +2196,6 @@ static BcStatus bc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale, return s; } -static bool bc_num_strValid(const char *val, size_t base) -{ - BcDig b; - bool radix; - - b = (BcDig)(base <= 10 ? base + '0' : base - 10 + 'A'); - radix = false; - for (;;) { - BcDig c = *val++; - if (c == '\0') - break; - if (c == '.') { - if (radix) return false; - radix = true; - continue; - } - if (c < '0' || c >= b || (c > '9' && c < 'A')) - return false; - } - return true; -} - -// Note: n is already "bc_num_zero()"ed, -// leading zeroes in "val" are removed -static void bc_num_parseDecimal(BcNum *n, const char *val) -{ - size_t len, i; - const char *ptr; - bool zero; - - len = strlen(val); - if (len == 0) - return; - - zero = true; - for (i = 0; val[i]; ++i) { - if (val[i] != '0' && val[i] != '.') { - zero = false; - break; - } - } - bc_num_expand(n, len); - - ptr = strchr(val, '.'); - - n->rdx = 0; - if (ptr != NULL) - n->rdx = (size_t)((val + len) - (ptr + 1)); - - if (!zero) { - i = len - 1; - for (;;) { - n->num[n->len] = val[i] - '0'; - ++n->len; - skip_dot: - if ((ssize_t)--i == (ssize_t)-1) break; - if (val[i] == '.') goto skip_dot; - } - } -} - -// Note: n is already "bc_num_zero()"ed, -// leading zeroes in "val" are removed -static void bc_num_parseBase(BcNum *n, const char *val, BcNum *base) -{ - BcStatus s; - BcNum temp, mult, result; - BcDig c = '\0'; - unsigned long v; - size_t i, digits; - - for (i = 0; ; ++i) { - if (val[i] == '\0') - return; - if (val[i] != '.' && val[i] != '0') - break; - } - - bc_num_init_DEF_SIZE(&temp); - bc_num_init_DEF_SIZE(&mult); - - for (;;) { - c = *val++; - if (c == '\0') goto int_err; - if (c == '.') break; - - v = (unsigned long) (c <= '9' ? c - '0' : c - 'A' + 10); - - s = bc_num_mul(n, base, &mult, 0); - if (s) goto int_err; - bc_num_ulong2num(&temp, v); - s = bc_num_add(&mult, &temp, n, 0); - if (s) goto int_err; - } - - bc_num_init(&result, base->len); - //bc_num_zero(&result); - already is - bc_num_one(&mult); - - digits = 0; - for (;;) { - c = *val++; - if (c == '\0') break; - digits++; - - v = (unsigned long) (c <= '9' ? c - '0' : c - 'A' + 10); - - s = bc_num_mul(&result, base, &result, 0); - if (s) goto err; - bc_num_ulong2num(&temp, v); - s = bc_num_add(&result, &temp, &result, 0); - if (s) goto err; - s = bc_num_mul(&mult, base, &mult, 0); - if (s) goto err; - } - - s = bc_num_div(&result, &mult, &result, digits); - if (s) goto err; - s = bc_num_add(n, &result, n, digits); - if (s) goto err; - - if (n->len != 0) { - if (n->rdx < digits) bc_num_extend(n, digits - n->rdx); - } else - bc_num_zero(n); - -err: - bc_num_free(&result); -int_err: - bc_num_free(&mult); - bc_num_free(&temp); -} - static void bc_num_printNewline(void) { if (G.prog.nchars == G.prog.len - 1) { @@ -2492,6 +2359,139 @@ static BcStatus bc_num_stream(BcNum *n, BcNum *base) } #endif +static bool bc_num_strValid(const char *val, size_t base) +{ + BcDig b; + bool radix; + + b = (BcDig)(base <= 10 ? base + '0' : base - 10 + 'A'); + radix = false; + for (;;) { + BcDig c = *val++; + if (c == '\0') + break; + if (c == '.') { + if (radix) return false; + radix = true; + continue; + } + if (c < '0' || c >= b || (c > '9' && c < 'A')) + return false; + } + return true; +} + +// Note: n is already "bc_num_zero()"ed, +// leading zeroes in "val" are removed +static void bc_num_parseDecimal(BcNum *n, const char *val) +{ + size_t len, i; + const char *ptr; + bool zero; + + len = strlen(val); + if (len == 0) + return; + + zero = true; + for (i = 0; val[i]; ++i) { + if (val[i] != '0' && val[i] != '.') { + zero = false; + break; + } + } + bc_num_expand(n, len); + + ptr = strchr(val, '.'); + + n->rdx = 0; + if (ptr != NULL) + n->rdx = (size_t)((val + len) - (ptr + 1)); + + if (!zero) { + i = len - 1; + for (;;) { + n->num[n->len] = val[i] - '0'; + ++n->len; + skip_dot: + if ((ssize_t)--i == (ssize_t)-1) break; + if (val[i] == '.') goto skip_dot; + } + } +} + +// Note: n is already "bc_num_zero()"ed, +// leading zeroes in "val" are removed +static void bc_num_parseBase(BcNum *n, const char *val, BcNum *base) +{ + BcStatus s; + BcNum temp, mult, result; + BcDig c = '\0'; + unsigned long v; + size_t i, digits; + + for (i = 0; ; ++i) { + if (val[i] == '\0') + return; + if (val[i] != '.' && val[i] != '0') + break; + } + + bc_num_init_DEF_SIZE(&temp); + bc_num_init_DEF_SIZE(&mult); + + for (;;) { + c = *val++; + if (c == '\0') goto int_err; + if (c == '.') break; + + v = (unsigned long) (c <= '9' ? c - '0' : c - 'A' + 10); + + s = bc_num_mul(n, base, &mult, 0); + if (s) goto int_err; + bc_num_ulong2num(&temp, v); + s = bc_num_add(&mult, &temp, n, 0); + if (s) goto int_err; + } + + bc_num_init(&result, base->len); + //bc_num_zero(&result); - already is + bc_num_one(&mult); + + digits = 0; + for (;;) { + c = *val++; + if (c == '\0') break; + digits++; + + v = (unsigned long) (c <= '9' ? c - '0' : c - 'A' + 10); + + s = bc_num_mul(&result, base, &result, 0); + if (s) goto err; + bc_num_ulong2num(&temp, v); + s = bc_num_add(&result, &temp, &result, 0); + if (s) goto err; + s = bc_num_mul(&mult, base, &mult, 0); + if (s) goto err; + } + + s = bc_num_div(&result, &mult, &result, digits); + if (s) goto err; + s = bc_num_add(n, &result, n, digits); + if (s) goto err; + + if (n->len != 0) { + if (n->rdx < digits) bc_num_extend(n, digits - n->rdx); + } else + bc_num_zero(n); + +err: + bc_num_free(&result); +int_err: + bc_num_free(&mult); + bc_num_free(&temp); +} + static BcStatus bc_num_parse(BcNum *n, const char *val, BcNum *base, size_t base_t) { -- cgit v1.2.3-55-g6feb From b696d9ec2044a1fd7906c1b2a2a747aff7c3f79f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 10 Dec 2018 12:22:15 +0100 Subject: bc: simplify bc_num_ulong2num() function old new delta bc_num_ulong2num 64 59 -5 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 5b48f84a1..33abe9366 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1467,16 +1467,25 @@ static BcStatus bc_num_ulong(BcNum *n, unsigned long *result_p) static void bc_num_ulong2num(BcNum *n, unsigned long val) { - size_t len; BcDig *ptr; - unsigned long i; bc_num_zero(n); if (val == 0) return; - for (len = 1, i = ULONG_MAX; i != 0; i /= 10, ++len) bc_num_expand(n, len); - for (ptr = n->num, i = 0; val; ++i, ++n->len, val /= 10) ptr[i] = val % 10; + if (ULONG_MAX == 0xffffffffUL) + bc_num_expand(n, 10); // 10 digits: 4294967295 + if (ULONG_MAX == 0xffffffffffffffffUL) + bc_num_expand(n, 20); // 20 digits: 18446744073709551615 + BUILD_BUG_ON(ULONG_MAX > 0xffffffffffffffffUL); + + ptr = n->num; + for (;;) { + n->len++; + *ptr++ = val % 10; + val /= 10; + if (val == 0) break; + } } static void bc_num_subArrays(BcDig *restrict a, BcDig *restrict b, -- cgit v1.2.3-55-g6feb From 44d79d866dc4c9bb0c3bba47612feae78365a046 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 10 Dec 2018 12:33:40 +0100 Subject: bc: simplify bc_program_print() function old new delta bc_program_print 730 713 -17 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 33abe9366..1879581e3 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -5737,15 +5737,14 @@ static BcStatus bc_program_print(char inst, size_t idx) { BcStatus s = BC_STATUS_SUCCESS; BcResult *r; - size_t len, i; - char *str; - BcNum *num = NULL; + BcNum *num; bool pop = inst != BC_INST_PRINT; if (!BC_PROG_STACK(&G.prog.results, idx + 1)) return bc_error_stack_has_too_few_elements(); r = bc_vec_item_rev(&G.prog.results, idx); + num = NULL; // is this NULL necessary? s = bc_program_num(r, &num, false); if (s) return s; @@ -5754,16 +5753,18 @@ static BcStatus bc_program_print(char inst, size_t idx) if (!s) bc_num_copy(&G.prog.last, num); } else { + char *str; idx = (r->t == BC_RESULT_STR) ? r->d.id.idx : num->rdx; str = *bc_program_str(idx); if (inst == BC_INST_PRINT_STR) { - for (i = 0, len = strlen(str); i < len; ++i) { - char c = str[i]; + for (;;) { + char c = *str++; + if (c == '\0') break; bb_putchar(c); - if (c == '\n') G.prog.nchars = SIZE_MAX; ++G.prog.nchars; + if (c == '\n') G.prog.nchars = 0; } } else { -- cgit v1.2.3-55-g6feb From a7f1a3654041ed4b1d4716f71a8396977aca8223 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 10 Dec 2018 12:57:01 +0100 Subject: bc: simplify bc_program_len() function old new delta bc_program_len 42 34 -8 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 1879581e3..afd5c8d0e 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -6254,12 +6254,14 @@ static unsigned long bc_program_scale(BcNum *n) static unsigned long bc_program_len(BcNum *n) { - unsigned long len = n->len; - size_t i; - - if (n->rdx != n->len) return len; - for (i = n->len - 1; i < n->len && n->num[i] == 0; --len, --i); + size_t len = n->len; + if (n->rdx != len) return len; + for (;;) { + if (len == 0) break; + len--; + if (n->num[len] != 0) break; + } return len; } -- cgit v1.2.3-55-g6feb From 8b4cf0dbb08a8a526045051b442e45cb2359b224 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 10 Dec 2018 15:12:58 +0100 Subject: bc: optimize bc_vec_concat() function old new delta bc_vec_concat 71 66 -5 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index afd5c8d0e..71022569e 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1165,13 +1165,14 @@ static void bc_vec_string(BcVec *v, size_t len, const char *str) static void bc_vec_concat(BcVec *v, const char *str) { - size_t len; + size_t len, slen; if (v->len == 0) bc_vec_pushZeroByte(v); - len = v->len + strlen(str); + slen = strlen(str); + len = v->len + slen; - if (v->cap < len) bc_vec_grow(v, len - v->len); + if (v->cap < len) bc_vec_grow(v, slen); strcpy(v->v + v->len - 1, str); v->len = len; -- cgit v1.2.3-55-g6feb From c665c183f15f4246da3d44fba92883ef05fc98af Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 10 Dec 2018 15:15:42 +0100 Subject: bc: 0xffffffffffffffff may be larger than unsigned long Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 71022569e..9774ac45b 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1476,9 +1476,9 @@ static void bc_num_ulong2num(BcNum *n, unsigned long val) if (ULONG_MAX == 0xffffffffUL) bc_num_expand(n, 10); // 10 digits: 4294967295 - if (ULONG_MAX == 0xffffffffffffffffUL) + if (ULONG_MAX == 0xffffffffffffffffULL) bc_num_expand(n, 20); // 20 digits: 18446744073709551615 - BUILD_BUG_ON(ULONG_MAX > 0xffffffffffffffffUL); + BUILD_BUG_ON(ULONG_MAX > 0xffffffffffffffffULL); ptr = n->num; for (;;) { -- cgit v1.2.3-55-g6feb From 5ba55f1f356f3521d2b366d6d7af60c5e05563a8 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 10 Dec 2018 15:37:14 +0100 Subject: bc: make all function pointers FAST_FUNC, on i486 this saves ~400 bytes function old new delta bc_num_rem 91 95 +4 bc_num_inv 53 56 +3 bc_num_d 569 572 +3 bc_num_printDigits 136 137 +1 bc_program_assign 486 485 -1 dc_lex_token 684 682 -2 bc_vec_pop 27 25 -2 bc_vec_npop 55 53 -2 bc_program_read 335 333 -2 bc_program_print 713 711 -2 bc_parse_parse 462 460 -2 bc_lex_token 1280 1278 -2 bc_num_printChar 27 24 -3 bc_num_binary 150 147 -3 dc_parse_parse 59 55 -4 bc_vm_run 630 626 -4 bc_num_printHex 71 67 -4 bc_num_divmod 155 150 -5 bc_vec_free 24 18 -6 bc_string_free 15 9 -6 bc_num_free 15 9 -6 bc_id_free 15 9 -6 bc_parse_free 53 46 -7 bc_program_scale 8 - -8 bc_num_r 245 237 -8 bc_func_free 35 27 -8 bc_result_free 57 46 -11 bc_num_a 454 443 -11 bc_num_sub 77 65 -12 bc_num_add 77 65 -12 bc_program_modexp 736 723 -13 bc_num_s 252 239 -13 bc_num_mul 62 49 -13 bc_num_mod 62 49 -13 bc_num_div 62 49 -13 bc_num_pow 47 31 -16 bc_program_exec 4081 4059 -22 bc_num_printNum 514 489 -25 bc_num_p 478 445 -33 bc_program_len 34 - -34 bc_program_num 963 925 -38 bc_num_k 988 944 -44 ------------------------------------------------------------------------------ (add/remove: 0/2 grow/shrink: 4/36 up/down: 11/-416) Total: -405 bytes text data bss dec hex filename 984536 485 7296 992317 f243d busybox_old 984131 485 7296 991912 f22a8 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 81 ++++++++++++++++++++++++++++------------------------------ 1 file changed, 39 insertions(+), 42 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 9774ac45b..7ed6dd91d 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -193,7 +193,7 @@ typedef enum BcStatus { #define BC_VEC_INVALID_IDX ((size_t) -1) #define BC_VEC_START_CAP (1 << 5) -typedef void (*BcVecFree)(void *); +typedef void (*BcVecFree)(void *) FAST_FUNC; typedef struct BcVec { char *v; @@ -221,16 +221,16 @@ typedef struct BcNum { #define BC_NUM_KARATSUBA_LEN (32) -typedef void (*BcNumDigitOp)(size_t, size_t, bool); +typedef void (*BcNumDigitOp)(size_t, size_t, bool) FAST_FUNC; -typedef BcStatus (*BcNumBinaryOp)(BcNum *, BcNum *, BcNum *, size_t); +typedef BcStatus (*BcNumBinaryOp)(BcNum *, BcNum *, BcNum *, size_t) FAST_FUNC; -static BcStatus bc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale); -static BcStatus bc_num_sub(BcNum *a, BcNum *b, BcNum *c, size_t scale); -static BcStatus bc_num_mul(BcNum *a, BcNum *b, BcNum *c, size_t scale); -static BcStatus bc_num_div(BcNum *a, BcNum *b, BcNum *c, size_t scale); -static BcStatus bc_num_mod(BcNum *a, BcNum *b, BcNum *c, size_t scale); -static BcStatus bc_num_pow(BcNum *a, BcNum *b, BcNum *c, size_t scale); +static BcStatus bc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; +static BcStatus bc_num_sub(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; +static BcStatus bc_num_mul(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; +static BcStatus bc_num_div(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; +static BcStatus bc_num_mod(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; +static BcStatus bc_num_pow(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; static BcStatus bc_num_sqrt(BcNum *a, BcNum *b, size_t scale); static BcStatus bc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d, size_t scale); @@ -559,7 +559,7 @@ enum { #endif struct BcLex; -typedef BcStatus (*BcLexNext)(struct BcLex *); +typedef BcStatus (*BcLexNext)(struct BcLex *) FAST_FUNC; typedef struct BcLex { @@ -626,7 +626,7 @@ struct BcParse; struct BcProgram; -typedef BcStatus (*BcParseParse)(struct BcParse *); +typedef BcStatus (*BcParseParse)(struct BcParse *) FAST_FUNC; typedef struct BcParse { @@ -702,8 +702,6 @@ typedef struct BcProgram { #define BC_PROG_NUM(r, n) \ ((r)->t != BC_RESULT_ARRAY && (r)->t != BC_RESULT_STR && !BC_PROG_STR(n)) -typedef unsigned long (*BcProgramBuiltIn)(BcNum *); - #define BC_FLAG_W (1 << 0) #define BC_FLAG_V (1 << 1) #define BC_FLAG_S (1 << 2) @@ -1203,7 +1201,7 @@ static void *bc_vec_top(const BcVec *v) return v->v + v->size * (v->len - 1); } -static void bc_vec_free(void *vec) +static FAST_FUNC void bc_vec_free(void *vec) { BcVec *v = (BcVec *) vec; bc_vec_pop_all(v); @@ -1215,7 +1213,7 @@ static int bc_id_cmp(const void *e1, const void *e2) return strcmp(((const BcId *) e1)->name, ((const BcId *) e2)->name); } -static void bc_id_free(void *id) +static FAST_FUNC void bc_id_free(void *id) { free(((BcId *) id)->name); } @@ -1426,7 +1424,7 @@ static void bc_num_expand(BcNum *n, size_t req) } } -static void bc_num_free(void *num) +static FAST_FUNC void bc_num_free(void *num) { free(((BcNum *) num)->num); } @@ -1675,7 +1673,7 @@ static BcStatus bc_num_inv(BcNum *a, BcNum *b, size_t scale) return bc_num_div(&one, a, b, scale); } -static BcStatus bc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) +static FAST_FUNC BcStatus bc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) { BcDig *ptr, *ptr_a, *ptr_b, *ptr_c; size_t i, max, min_rdx, min_int, diff, a_int, b_int; @@ -1746,7 +1744,7 @@ static BcStatus bc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) return BC_STATUS_SUCCESS; // can't make void, see bc_num_binary() } -static BcStatus bc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) +static FAST_FUNC BcStatus bc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) { ssize_t cmp; BcNum *minuend, *subtrahend; @@ -1808,7 +1806,7 @@ static BcStatus bc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) return BC_STATUS_SUCCESS; // can't make void, see bc_num_binary() } -static BcStatus bc_num_k(BcNum *restrict a, BcNum *restrict b, +static FAST_FUNC BcStatus bc_num_k(BcNum *restrict a, BcNum *restrict b, BcNum *restrict c) { BcStatus s; @@ -1914,7 +1912,7 @@ err: return s; } -static BcStatus bc_num_m(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) +static FAST_FUNC BcStatus bc_num_m(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) { BcStatus s; BcNum cpa, cpb; @@ -1956,7 +1954,7 @@ err: return s; } -static BcStatus bc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) +static FAST_FUNC BcStatus bc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) { BcStatus s = BC_STATUS_SUCCESS; BcDig *n, *p, q; @@ -2028,7 +2026,7 @@ static BcStatus bc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) return s; } -static BcStatus bc_num_r(BcNum *a, BcNum *b, BcNum *restrict c, +static FAST_FUNC BcStatus bc_num_r(BcNum *a, BcNum *b, BcNum *restrict c, BcNum *restrict d, size_t scale, size_t ts) { BcStatus s; @@ -2065,7 +2063,7 @@ err: return s; } -static BcStatus bc_num_rem(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) +static FAST_FUNC BcStatus bc_num_rem(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) { BcStatus s; BcNum c1; @@ -2078,7 +2076,7 @@ static BcStatus bc_num_rem(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) return s; } -static BcStatus bc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) +static FAST_FUNC BcStatus bc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) { BcStatus s = BC_STATUS_SUCCESS; BcNum copy; @@ -2216,7 +2214,7 @@ static void bc_num_printNewline(void) } #if ENABLE_DC -static void bc_num_printChar(size_t num, size_t width, bool radix) +static FAST_FUNC void bc_num_printChar(size_t num, size_t width, bool radix) { (void) radix; bb_putchar((char) num); @@ -2224,7 +2222,7 @@ static void bc_num_printChar(size_t num, size_t width, bool radix) } #endif -static void bc_num_printDigits(size_t num, size_t width, bool radix) +static FAST_FUNC void bc_num_printDigits(size_t num, size_t width, bool radix) { size_t exp, pow; @@ -2245,7 +2243,7 @@ static void bc_num_printDigits(size_t num, size_t width, bool radix) } } -static void bc_num_printHex(size_t num, size_t width, bool radix) +static FAST_FUNC void bc_num_printHex(size_t num, size_t width, bool radix) { if (radix) { bc_num_printNewline(); @@ -2542,39 +2540,39 @@ static BcStatus bc_num_print(BcNum *n, bool newline) return s; } -static BcStatus bc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale) +static FAST_FUNC BcStatus bc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale) { BcNumBinaryOp op = (!a->neg == !b->neg) ? bc_num_a : bc_num_s; (void) scale; return bc_num_binary(a, b, c, false, op, BC_NUM_AREQ(a, b)); } -static BcStatus bc_num_sub(BcNum *a, BcNum *b, BcNum *c, size_t scale) +static FAST_FUNC BcStatus bc_num_sub(BcNum *a, BcNum *b, BcNum *c, size_t scale) { BcNumBinaryOp op = (!a->neg == !b->neg) ? bc_num_s : bc_num_a; (void) scale; return bc_num_binary(a, b, c, true, op, BC_NUM_AREQ(a, b)); } -static BcStatus bc_num_mul(BcNum *a, BcNum *b, BcNum *c, size_t scale) +static FAST_FUNC BcStatus bc_num_mul(BcNum *a, BcNum *b, BcNum *c, size_t scale) { size_t req = BC_NUM_MREQ(a, b, scale); return bc_num_binary(a, b, c, scale, bc_num_m, req); } -static BcStatus bc_num_div(BcNum *a, BcNum *b, BcNum *c, size_t scale) +static FAST_FUNC BcStatus bc_num_div(BcNum *a, BcNum *b, BcNum *c, size_t scale) { size_t req = BC_NUM_MREQ(a, b, scale); return bc_num_binary(a, b, c, scale, bc_num_d, req); } -static BcStatus bc_num_mod(BcNum *a, BcNum *b, BcNum *c, size_t scale) +static FAST_FUNC BcStatus bc_num_mod(BcNum *a, BcNum *b, BcNum *c, size_t scale) { size_t req = BC_NUM_MREQ(a, b, scale); return bc_num_binary(a, b, c, scale, bc_num_rem, req); } -static BcStatus bc_num_pow(BcNum *a, BcNum *b, BcNum *c, size_t scale) +static FAST_FUNC BcStatus bc_num_pow(BcNum *a, BcNum *b, BcNum *c, size_t scale) { return bc_num_binary(a, b, c, scale, bc_num_p, a->len * b->len + 1); } @@ -2789,7 +2787,7 @@ static void bc_func_init(BcFunc *f) f->nparams = 0; } -static void bc_func_free(void *func) +static FAST_FUNC void bc_func_free(void *func) { BcFunc *f = (BcFunc *) func; bc_vec_free(&f->code); @@ -2841,7 +2839,7 @@ static void bc_array_copy(BcVec *d, const BcVec *s) } } -static void bc_string_free(void *string) +static FAST_FUNC void bc_string_free(void *string) { free(*((char **) string)); } @@ -2883,7 +2881,7 @@ static void bc_result_copy(BcResult *d, BcResult *src) } #endif // ENABLE_DC -static void bc_result_free(void *result) +static FAST_FUNC void bc_result_free(void *result) { BcResult *r = (BcResult *) result; @@ -3171,7 +3169,7 @@ static BcStatus bc_lex_comment(BcLex *l) return BC_STATUS_SUCCESS; } -static BcStatus bc_lex_token(BcLex *l) +static FAST_FUNC BcStatus bc_lex_token(BcLex *l) { BcStatus s = BC_STATUS_SUCCESS; char c = l->buf[l->i++], c2; @@ -3511,7 +3509,7 @@ static BcStatus dc_lex_string(BcLex *l) return BC_STATUS_SUCCESS; } -static BcStatus dc_lex_token(BcLex *l) +static FAST_FUNC BcStatus dc_lex_token(BcLex *l) { BcStatus s = BC_STATUS_SUCCESS; char c = l->buf[l->i++], c2; @@ -4826,7 +4824,7 @@ static BcStatus bc_parse_stmt(BcParse *p) return s; } -static BcStatus bc_parse_parse(BcParse *p) +static FAST_FUNC BcStatus bc_parse_parse(BcParse *p) { BcStatus s; @@ -5333,7 +5331,7 @@ static BcStatus dc_parse_expr(BcParse *p, uint8_t flags) return s; } -static BcStatus dc_parse_parse(BcParse *p) +static FAST_FUNC BcStatus dc_parse_parse(BcParse *p) { BcStatus s; @@ -6305,8 +6303,7 @@ static BcStatus bc_program_builtin(char inst) } #endif else { - BcProgramBuiltIn f = len ? bc_program_len : bc_program_scale; - bc_num_ulong2num(&res.d.n, f(num)); + bc_num_ulong2num(&res.d.n, len ? bc_program_len(num) : bc_program_scale(num)); } bc_program_retire(&res, BC_RESULT_TEMP); -- cgit v1.2.3-55-g6feb From dafbc2cdb8825ed36a25f9a6275d5226f35d3bd3 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 10 Dec 2018 15:38:52 +0100 Subject: bc: simplify bc_num_parseDecimal() further function old new delta bc_program_num 925 912 -13 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 7ed6dd91d..26ab94cbd 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -2395,19 +2395,11 @@ static void bc_num_parseDecimal(BcNum *n, const char *val) { size_t len, i; const char *ptr; - bool zero; len = strlen(val); if (len == 0) return; - zero = true; - for (i = 0; val[i]; ++i) { - if (val[i] != '0' && val[i] != '.') { - zero = false; - break; - } - } bc_num_expand(n, len); ptr = strchr(val, '.'); @@ -2416,16 +2408,21 @@ static void bc_num_parseDecimal(BcNum *n, const char *val) if (ptr != NULL) n->rdx = (size_t)((val + len) - (ptr + 1)); - if (!zero) { - i = len - 1; - for (;;) { - n->num[n->len] = val[i] - '0'; - ++n->len; + for (i = 0; val[i]; ++i) { + if (val[i] != '0' && val[i] != '.') { + // Not entirely zero value - convert it, and exit + i = len - 1; + for (;;) { + n->num[n->len] = val[i] - '0'; + ++n->len; skip_dot: - if ((ssize_t)--i == (ssize_t)-1) break; - if (val[i] == '.') goto skip_dot; + if ((ssize_t)--i == (ssize_t)-1) break; + if (val[i] == '.') goto skip_dot; + } + break; } } + // if this is reached, the value is entirely zero } // Note: n is already "bc_num_zero()"ed, -- cgit v1.2.3-55-g6feb From 71fa5b0a4c3cce55460de2f6d49e3a4a63f1b933 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 10 Dec 2018 16:14:58 +0100 Subject: tls: introduce FEATURE_TLS_SHA1 to make SHA1 code optional When disabled: function old new delta xwrite_encrypted 580 579 -1 prf_hmac_sha256 222 217 -5 hmac_begin 158 149 -9 static.ciphers 32 20 -12 tls_handshake 2115 2095 -20 hmac 87 61 -26 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/6 up/down: 0/-73) Total: -73 bytes Signed-off-by: Denys Vlasenko --- networking/Config.src | 11 +++++++++++ networking/tls.c | 36 ++++++++++++++++++++++++++++++------ 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/networking/Config.src b/networking/Config.src index 2ce5287de..04d644bc9 100644 --- a/networking/Config.src +++ b/networking/Config.src @@ -46,6 +46,17 @@ config VERBOSE_RESOLUTION_ERRORS "can't resolve 'hostname.com'" and want to know more. This may increase size of your executable a bit. +config FEATURE_TLS_SHA1 + bool "In TLS code, support ciphers which use deprecated SHA1" + depends on TLS + default n + help + Selecting this option increases interoperability with very old + servers, but slightly increases code size. + + Most TLS servers support SHA256 today (2018), since SHA1 is + considered possibly insecure (although not yet definitely broken). + INSERT source networking/udhcp/Config.in diff --git a/networking/tls.c b/networking/tls.c index b0eb7b90c..3efb0519d 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -6,6 +6,8 @@ //config:config TLS //config: bool #No description makes it a hidden option //config: default n +//Note: +//Config.src also defines FEATURE_TLS_SHA1 option //kbuild:lib-$(CONFIG_TLS) += tls.o //kbuild:lib-$(CONFIG_TLS) += tls_pstm.o @@ -394,7 +396,7 @@ static void hash_handshake(tls_state_t *tls, const char *fmt, const void *buffer dump_hex(fmt, buffer, len); dbg(" (%u bytes) ", (int)len); len = sha_peek(&tls->hsd->handshake_hash_ctx, h); - if (len == SHA1_OUTSIZE) + if (ENABLE_FEATURE_TLS_SHA1 && len == SHA1_OUTSIZE) dump_hex("sha1:%s\n", h, len); else if (len == SHA256_OUTSIZE) @@ -421,6 +423,11 @@ typedef struct hmac_precomputed { } hmac_precomputed_t; typedef void md5sha_begin_func(md5sha_ctx_t *ctx) FAST_FUNC; +#if !ENABLE_FEATURE_TLS_SHA1 +#define hmac_begin(pre,key,key_size,begin) \ + hmac_begin(pre,key,key_size) +#define begin sha256_begin +#endif static void hmac_begin(hmac_precomputed_t *pre, uint8_t *key, unsigned key_size, md5sha_begin_func *begin) { uint8_t key_xor_ipad[SHA_INSIZE]; @@ -461,6 +468,7 @@ static void hmac_begin(hmac_precomputed_t *pre, uint8_t *key, unsigned key_size, md5sha_hash(&pre->hashed_key_xor_ipad, key_xor_ipad, SHA_INSIZE); md5sha_hash(&pre->hashed_key_xor_opad, key_xor_opad, SHA_INSIZE); } +#undef begin static unsigned hmac_sha_precomputed_v( hmac_precomputed_t *pre, @@ -498,6 +506,10 @@ static unsigned hmac_sha_precomputed(hmac_precomputed_t *pre_init, uint8_t *out, return len; } +#if !ENABLE_FEATURE_TLS_SHA1 +#define hmac(tls,out,key,key_size,...) \ + hmac(out,key,key_size, __VA_ARGS__) +#endif static unsigned hmac(tls_state_t *tls, uint8_t *out, uint8_t *key, unsigned key_size, ...) { hmac_precomputed_t pre; @@ -507,7 +519,7 @@ static unsigned hmac(tls_state_t *tls, uint8_t *out, uint8_t *key, unsigned key_ va_start(va, key_size); hmac_begin(&pre, key, key_size, - (tls->MAC_size == SHA256_OUTSIZE) + (ENABLE_FEATURE_TLS_SHA1 || tls->MAC_size == SHA256_OUTSIZE) ? sha256_begin : sha1_begin ); @@ -1466,15 +1478,17 @@ static ALWAYS_INLINE void fill_handshake_record_hdr(void *buf, unsigned type, un static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) { -#define NUM_CIPHERS (13 + ALLOW_RSA_NULL_SHA256) +#define NUM_CIPHERS (7 + 6 * ENABLE_FEATURE_TLS_SHA1 + ALLOW_RSA_NULL_SHA256) static const uint8_t ciphers[] = { 0x00,(1 + NUM_CIPHERS) * 2, //len16_be 0x00,0xFF, //not a cipher - TLS_EMPTY_RENEGOTIATION_INFO_SCSV /* ^^^^^^ RFC 5746 Renegotiation Indication Extension - some servers will refuse to work with us otherwise */ +#if ENABLE_FEATURE_TLS_SHA1 0xC0,0x09, // 1 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA - ok: wget https://is.gd/ 0xC0,0x0A, // 2 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA - ok: wget https://is.gd/ 0xC0,0x13, // 3 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-SHA 0xC0,0x14, // 4 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA - ok: openssl s_server ... -cipher ECDHE-RSA-AES256-SHA (might fail with older openssl) +#endif 0xC0,0x23, // 5 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 - ok: wget https://is.gd/ // 0xC0,0x24, // TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet 0xC0,0x27, // 6 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-SHA256 @@ -1485,12 +1499,16 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) 0xC0,0x2F, // 8 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-GCM-SHA256 // 0xC0,0x30, // TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 - openssl s_server ... -cipher ECDHE-RSA-AES256-GCM-SHA384: "decryption failed or bad record mac" //possibly these too: +#if ENABLE_FEATURE_TLS_SHA1 // 0xC0,0x35, // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA // 0xC0,0x36, // TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA +#endif // 0xC0,0x37, // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 // 0xC0,0x38, // TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet +#if ENABLE_FEATURE_TLS_SHA1 0x00,0x2F, // 9 TLS_RSA_WITH_AES_128_CBC_SHA - ok: openssl s_server ... -cipher AES128-SHA 0x00,0x35, //10 TLS_RSA_WITH_AES_256_CBC_SHA - ok: openssl s_server ... -cipher AES256-SHA +#endif 0x00,0x3C, //11 TLS_RSA_WITH_AES_128_CBC_SHA256 - ok: openssl s_server ... -cipher AES128-SHA256 0x00,0x3D, //12 TLS_RSA_WITH_AES_256_CBC_SHA256 - ok: openssl s_server ... -cipher AES256-SHA256 0x00,0x9C, //13 TLS_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher AES128-GCM-SHA256 @@ -1669,10 +1687,12 @@ static void get_server_hello(tls_state_t *tls) /* Set up encryption params based on selected cipher */ #if 0 +#if ENABLE_FEATURE_TLS_SHA1 0xC0,0x09, // 1 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA - ok: wget https://is.gd/ 0xC0,0x0A, // 2 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA - ok: wget https://is.gd/ 0xC0,0x13, // 3 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-SHA 0xC0,0x14, // 4 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA - ok: openssl s_server ... -cipher ECDHE-RSA-AES256-SHA (might fail with older openssl) +#endif 0xC0,0x23, // 5 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 - ok: wget https://is.gd/ // 0xC0,0x24, // TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet 0xC0,0x27, // 6 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-SHA256 @@ -1682,12 +1702,16 @@ static void get_server_hello(tls_state_t *tls) 0xC0,0x2F, // 8 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-GCM-SHA256 // 0xC0,0x30, // TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 - openssl s_server ... -cipher ECDHE-RSA-AES256-GCM-SHA384: "decryption failed or bad record mac" //possibly these too: +#if ENABLE_FEATURE_TLS_SHA1 // 0xC0,0x35, // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA // 0xC0,0x36, // TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA +#endif // 0xC0,0x37, // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 // 0xC0,0x38, // TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet +#if ENABLE_FEATURE_TLS_SHA1 0x00,0x2F, // 9 TLS_RSA_WITH_AES_128_CBC_SHA - ok: openssl s_server ... -cipher AES128-SHA 0x00,0x35, //10 TLS_RSA_WITH_AES_256_CBC_SHA - ok: openssl s_server ... -cipher AES256-SHA +#endif 0x00,0x3C, //11 TLS_RSA_WITH_AES_128_CBC_SHA256 - ok: openssl s_server ... -cipher AES128-SHA256 0x00,0x3D, //12 TLS_RSA_WITH_AES_256_CBC_SHA256 - ok: openssl s_server ... -cipher AES256-SHA256 0x00,0x9C, //13 TLS_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher AES128-GCM-SHA256 @@ -1706,7 +1730,7 @@ static void get_server_hello(tls_state_t *tls) /* Odd numbered C0xx use AES128 (even ones use AES256) */ tls->key_size = AES128_KEYSIZE; } - if (cipherid1 <= 0x14) { + if (ENABLE_FEATURE_TLS_SHA1 && cipherid1 <= 0x14) { tls->MAC_size = SHA1_OUTSIZE; } else if (cipherid1 >= 0x2B && cipherid1 <= 0x30) { @@ -1717,13 +1741,13 @@ static void get_server_hello(tls_state_t *tls) } } else { /* All 00xx are RSA */ - if (cipherid1 == 0x2F + if ((ENABLE_FEATURE_TLS_SHA1 && cipherid1 == 0x2F) || cipherid1 == 0x3C || cipherid1 == 0x9C ) { tls->key_size = AES128_KEYSIZE; } - if (cipherid1 <= 0x35) { + if (ENABLE_FEATURE_TLS_SHA1 && cipherid1 <= 0x35) { tls->MAC_size = SHA1_OUTSIZE; } else if (cipherid1 == 0x9C /*|| cipherid1 == 0x9D*/) { -- cgit v1.2.3-55-g6feb From 63bfe0e4c0f3e14dc3a358bbb1ba59a1ade421e0 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 10 Dec 2018 16:43:53 +0100 Subject: tls: if !ENABLE_FEATURE_TLS_SHA1, tls->MAC_size is always SHA256_OUTSIZE for AES-CBC function old new delta tls_xread_record 634 636 +2 xwrite_encrypted 579 580 +1 tls_handshake 2095 2085 -10 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/1 up/down: 3/-10) Total: -7 bytes Signed-off-by: Denys Vlasenko --- networking/tls.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 3efb0519d..be13c6d5e 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -407,6 +407,12 @@ static void hash_handshake(tls_state_t *tls, const char *fmt, const void *buffer #endif } +#if !ENABLE_FEATURE_TLS_SHA1 +# define TLS_MAC_SIZE(tls) SHA256_OUTSIZE +#else +# define TLS_MAC_SIZE(tls) (tls)->MAC_size +#endif + // RFC 2104: // HMAC(key, text) based on a hash H (say, sha256) is: // ipad = [0x36 x INSIZE] @@ -691,7 +697,7 @@ static void xwrite_encrypted_and_hmac_signed(tls_state_t *tls, unsigned size, un /* Calculate MAC signature */ hmac(tls, buf + size, /* result */ - tls->client_write_MAC_key, tls->MAC_size, + tls->client_write_MAC_key, TLS_MAC_SIZE(tls), &tls->write_seq64_be, sizeof(tls->write_seq64_be), xhdr, RECHDR_LEN, buf, size, @@ -699,7 +705,7 @@ static void xwrite_encrypted_and_hmac_signed(tls_state_t *tls, unsigned size, un ); tls->write_seq64_be = SWAP_BE64(1 + SWAP_BE64(tls->write_seq64_be)); - size += tls->MAC_size; + size += TLS_MAC_SIZE(tls); // RFC 5246: // 6.2.3.1. Null or Standard Stream Cipher @@ -784,7 +790,7 @@ static void xwrite_encrypted_and_hmac_signed(tls_state_t *tls, unsigned size, un tls_get_random(buf - AES_BLOCK_SIZE, AES_BLOCK_SIZE); /* IV */ dbg("before crypt: 5 hdr + %u data + %u hash bytes\n", - size - tls->MAC_size, tls->MAC_size); + size - TLS_MAC_SIZE(tls), TLS_MAC_SIZE(tls)); /* Fill IV and padding in outbuf */ // RFC is talking nonsense: @@ -1099,7 +1105,7 @@ static int tls_xread_record(tls_state_t *tls, const char *expected) tls_aesgcm_decrypt(tls, p, sz); dbg("encrypted size:%u\n", sz); } else - if (tls->min_encrypted_len_on_read > tls->MAC_size) { + if (tls->min_encrypted_len_on_read > TLS_MAC_SIZE(tls)) { /* AES+SHA */ uint8_t *p = tls->inbuf + RECHDR_LEN; int padding_len; @@ -1118,7 +1124,7 @@ static int tls_xread_record(tls_state_t *tls, const char *expected) padding_len = p[sz - 1]; dbg("encrypted size:%u type:0x%02x padding_length:0x%02x\n", sz, p[0], padding_len); padding_len++; - sz -= tls->MAC_size + padding_len; /* drop MAC and padding */ + sz -= TLS_MAC_SIZE(tls) + padding_len; /* drop MAC and padding */ } else { /* if nonzero, then it's TLS_RSA_WITH_NULL_SHA256: drop MAC */ /* else: no encryption yet on input, subtract zero = NOP */ @@ -2245,7 +2251,7 @@ void FAST_FUNC tls_handshake(tls_state_t *tls, const char *sni) tls->min_encrypted_len_on_read = tls->MAC_size; } else if (!(tls->flags & ENCRYPTION_AESGCM)) { - unsigned mac_blocks = (unsigned)(tls->MAC_size + AES_BLOCK_SIZE-1) / AES_BLOCK_SIZE; + unsigned mac_blocks = (unsigned)(TLS_MAC_SIZE(tls) + AES_BLOCK_SIZE-1) / AES_BLOCK_SIZE; /* all incoming packets now should be encrypted and have * at least IV + (MAC padded to blocksize): */ -- cgit v1.2.3-55-g6feb From c67ff8a1b04c56b9445a891cb48db7fc0f0f4445 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 10 Dec 2018 18:49:29 +0100 Subject: tls: fix a potential (currently "disabled" by a macro) SHA1-related bug Signed-off-by: Denys Vlasenko --- networking/tls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/networking/tls.c b/networking/tls.c index be13c6d5e..253d687b4 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -525,7 +525,7 @@ static unsigned hmac(tls_state_t *tls, uint8_t *out, uint8_t *key, unsigned key_ va_start(va, key_size); hmac_begin(&pre, key, key_size, - (ENABLE_FEATURE_TLS_SHA1 || tls->MAC_size == SHA256_OUTSIZE) + (!ENABLE_FEATURE_TLS_SHA1 || tls->MAC_size == SHA256_OUTSIZE) ? sha256_begin : sha1_begin ); -- cgit v1.2.3-55-g6feb From 3a4d5a73a876b0922afed095bc9f83dbdf07148e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 10 Dec 2018 19:19:38 +0100 Subject: tls: prepare for ECDH_anon ciphers Signed-off-by: Denys Vlasenko --- networking/tls.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 253d687b4..b90f45e8b 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -525,9 +525,9 @@ static unsigned hmac(tls_state_t *tls, uint8_t *out, uint8_t *key, unsigned key_ va_start(va, key_size); hmac_begin(&pre, key, key_size, - (!ENABLE_FEATURE_TLS_SHA1 || tls->MAC_size == SHA256_OUTSIZE) - ? sha256_begin - : sha1_begin + (ENABLE_FEATURE_TLS_SHA1 && tls->MAC_size == SHA1_OUTSIZE) + ? sha1_begin + : sha256_begin ); len = hmac_sha_precomputed_v(&pre, out, va); @@ -1486,7 +1486,7 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) { #define NUM_CIPHERS (7 + 6 * ENABLE_FEATURE_TLS_SHA1 + ALLOW_RSA_NULL_SHA256) static const uint8_t ciphers[] = { - 0x00,(1 + NUM_CIPHERS) * 2, //len16_be + 0x00,2 + NUM_CIPHERS*2, //len16_be 0x00,0xFF, //not a cipher - TLS_EMPTY_RENEGOTIATION_INFO_SCSV /* ^^^^^^ RFC 5746 Renegotiation Indication Extension - some servers will refuse to work with us otherwise */ #if ENABLE_FEATURE_TLS_SHA1 @@ -1494,6 +1494,8 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) 0xC0,0x0A, // 2 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA - ok: wget https://is.gd/ 0xC0,0x13, // 3 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-SHA 0xC0,0x14, // 4 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA - ok: openssl s_server ... -cipher ECDHE-RSA-AES256-SHA (might fail with older openssl) + // 0xC0,0x18, // TLS_ECDH_anon_WITH_AES_128_CBC_SHA + // 0xC0,0x19, // TLS_ECDH_anon_WITH_AES_256_CBC_SHA #endif 0xC0,0x23, // 5 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 - ok: wget https://is.gd/ // 0xC0,0x24, // TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet @@ -1548,7 +1550,7 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) uint8_t session_id_len; /* uint8_t session_id[]; */ uint8_t cipherid_len16_hi, cipherid_len16_lo; - uint8_t cipherid[(1 + NUM_CIPHERS) * 2]; /* actually variable */ + uint8_t cipherid[2 + NUM_CIPHERS*2]; /* actually variable */ uint8_t comprtypes_len; uint8_t comprtypes[1]; /* actually variable */ /* Extensions (SNI shown): @@ -1596,7 +1598,7 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) memset(record->rand32, 0x11, sizeof(record->rand32)); /* record->session_id_len = 0; - already is */ - BUILD_BUG_ON(sizeof(ciphers) != 2 + (1 + NUM_CIPHERS) * 2 + 2); + BUILD_BUG_ON(sizeof(ciphers) != 2 + 2 + NUM_CIPHERS*2 + 2); memcpy(&record->cipherid_len16_hi, ciphers, sizeof(ciphers)); ptr = (void*)(record + 1); @@ -1698,6 +1700,8 @@ static void get_server_hello(tls_state_t *tls) 0xC0,0x0A, // 2 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA - ok: wget https://is.gd/ 0xC0,0x13, // 3 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-SHA 0xC0,0x14, // 4 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA - ok: openssl s_server ... -cipher ECDHE-RSA-AES256-SHA (might fail with older openssl) + // 0xC0,0x18, // TLS_ECDH_anon_WITH_AES_128_CBC_SHA + // 0xC0,0x19, // TLS_ECDH_anon_WITH_AES_256_CBC_SHA #endif 0xC0,0x23, // 5 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 - ok: wget https://is.gd/ // 0xC0,0x24, // TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet @@ -1705,6 +1709,7 @@ static void get_server_hello(tls_state_t *tls) // 0xC0,0x28, // TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet 0xC0,0x2B, // 7 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - ok: wget https://is.gd/ // 0xC0,0x2C, // TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 - wget https://is.gd/: "TLS error from peer (alert code 20): bad MAC" +//TODO: GCM_SHA384 ciphers can be supported, only need sha384-based PRF? 0xC0,0x2F, // 8 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-GCM-SHA256 // 0xC0,0x30, // TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 - openssl s_server ... -cipher ECDHE-RSA-AES256-GCM-SHA384: "decryption failed or bad record mac" //possibly these too: @@ -1722,7 +1727,9 @@ static void get_server_hello(tls_state_t *tls) 0x00,0x3D, //12 TLS_RSA_WITH_AES_256_CBC_SHA256 - ok: openssl s_server ... -cipher AES256-SHA256 0x00,0x9C, //13 TLS_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher AES128-GCM-SHA256 // 0x00,0x9D, // TLS_RSA_WITH_AES_256_GCM_SHA384 - openssl s_server ... -cipher AES256-GCM-SHA384: "decryption failed or bad record mac" +#if ALLOW_RSA_NULL_SHA256 0x00,0x3B, // TLS_RSA_WITH_NULL_SHA256 +#endif #endif cipherid1 = cipherid[1]; tls->cipher_id = 0x100 * cipherid[0] + cipherid1; @@ -1736,7 +1743,7 @@ static void get_server_hello(tls_state_t *tls) /* Odd numbered C0xx use AES128 (even ones use AES256) */ tls->key_size = AES128_KEYSIZE; } - if (ENABLE_FEATURE_TLS_SHA1 && cipherid1 <= 0x14) { + if (ENABLE_FEATURE_TLS_SHA1 && cipherid1 <= 0x19) { tls->MAC_size = SHA1_OUTSIZE; } else if (cipherid1 >= 0x2B && cipherid1 <= 0x30) { -- cgit v1.2.3-55-g6feb From 86e63cdeca93afae43c7d59a863bedccc3ea0c55 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 10 Dec 2018 19:46:53 +0100 Subject: bc: in non-interactive config, let compiler know that error funcs do not return function old new delta bc_num_s 235 239 +4 bc_lex_next 92 91 -1 dc_parse_register 53 51 -2 dc_parse_parse 46 44 -2 bc_vm_run 624 622 -2 bc_program_assignStr 146 144 -2 bc_parse_else 135 133 -2 bc_parse_body 116 114 -2 bc_num_a 445 443 -2 bc_func_insert 97 95 -2 bc_program_pushVar 203 200 -3 bc_parse_text 133 130 -3 bc_error_bad_character 17 14 -3 bc_error 14 11 -3 bc_program_printStream 157 153 -4 bc_program_prep 91 87 -4 bc_program_copyToVar 311 307 -4 bc_num_ulong 95 90 -5 bc_num_p 445 440 -5 bc_program_print 711 704 -7 bc_parse_endBody 365 358 -7 bc_num_r 237 230 -7 bc_num_d 550 543 -7 dc_lex_token 682 674 -8 bc_program_pushArray 147 139 -8 bc_program_assign 485 475 -10 bc_program_read 333 322 -11 bc_lex_token 1278 1266 -12 bc_parse_stmt 1780 1767 -13 bc_program_modexp 723 707 -16 dc_parse_expr 762 744 -18 bc_program_execStr 496 478 -18 bc_program_call 347 329 -18 bc_vm_file 219 197 -22 bc_program_binOpPrep 311 289 -22 bc_parse_name 539 513 -26 bc_parse_parse 451 423 -28 bc_program_num 912 880 -32 bc_read_line 172 139 -33 bc_program_exec 4048 4010 -38 bc_parse_auto 313 275 -38 bc_parse_expr_empty_ok 2095 2036 -59 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/41 up/down: 4/-509) Total: -505 bytes text data bss dec hex filename 983707 485 7296 991488 f2100 busybox_old 983202 485 7296 990983 f1f07 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 65 +++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 39 insertions(+), 26 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 26ab94cbd..aa478e461 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -976,7 +976,20 @@ static void bc_verror_msg(const char *fmt, va_list p) } } -static NOINLINE int bc_error_fmt(const char *fmt, ...) +#if ENABLE_FEATURE_BC_SIGNALS +# define ERRORFUNC /*nothing*/ +# define ERROR_RETURN(a) a +#else +# if ENABLE_FEATURE_CLEAN_UP +# define ERRORFUNC /*nothing*/ +# define ERROR_RETURN(a) a +# else +# define ERRORFUNC NORETURN +# define ERROR_RETURN(a) /*nothing*/ +# endif +#endif + +static NOINLINE ERRORFUNC int bc_error_fmt(const char *fmt, ...) { va_list p; @@ -986,7 +999,7 @@ static NOINLINE int bc_error_fmt(const char *fmt, ...) if (!ENABLE_FEATURE_CLEAN_UP && !G_ttyin) exit(1); - return BC_STATUS_FAILURE; + ERROR_RETURN(return BC_STATUS_FAILURE;) } #if ENABLE_BC @@ -1016,52 +1029,52 @@ static NOINLINE int bc_posix_error_fmt(const char *fmt, ...) // function must not have caller-cleaned parameters on stack. // Unfortunately, vararg function API does exactly that on most arches. // Thus, use these shims for the cases when we have no vararg PARAMS: -static int bc_error(const char *msg) +static ERRORFUNC int bc_error(const char *msg) { - return bc_error_fmt("%s", msg); + ERROR_RETURN(return) bc_error_fmt("%s", msg); } -#if ENABLE_BC -static int bc_POSIX_requires(const char *msg) +static ERRORFUNC int bc_error_bad_character(char c) { - return bc_posix_error_fmt("POSIX requires %s", msg); + ERROR_RETURN(return) bc_error_fmt("bad character '%c'", c); } -static int bc_POSIX_does_not_allow(const char *msg) +static ERRORFUNC int bc_error_bad_expression(void) { - return bc_posix_error_fmt("%s%s", "POSIX does not allow ", msg); + ERROR_RETURN(return) bc_error("bad expression"); } -static int bc_POSIX_does_not_allow_bool_ops_this_is_bad(const char *msg) +static ERRORFUNC int bc_error_bad_token(void) { - return bc_posix_error_fmt("%s%s %s", "POSIX does not allow ", "boolean operators; the following is bad:", msg); + ERROR_RETURN(return) bc_error("bad token"); } -static int bc_POSIX_does_not_allow_empty_X_expression_in_for(const char *msg) +static ERRORFUNC int bc_error_stack_has_too_few_elements(void) { - return bc_posix_error_fmt("%san empty %s expression in a for loop", "POSIX does not allow ", msg); + ERROR_RETURN(return) bc_error("stack has too few elements"); } -#endif -static int bc_error_bad_character(char c) +static ERRORFUNC int bc_error_variable_is_wrong_type(void) { - return bc_error_fmt("bad character '%c'", c); + ERROR_RETURN(return) bc_error("variable is wrong type"); } -static int bc_error_bad_expression(void) +static ERRORFUNC int bc_error_nested_read_call(void) { - return bc_error("bad expression"); + ERROR_RETURN(return) bc_error("read() call inside of a read() call"); } -static int bc_error_bad_token(void) +#if ENABLE_BC +static int bc_POSIX_requires(const char *msg) { - return bc_error("bad token"); + return bc_posix_error_fmt("POSIX requires %s", msg); } -static int bc_error_stack_has_too_few_elements(void) +static int bc_POSIX_does_not_allow(const char *msg) { - return bc_error("stack has too few elements"); + return bc_posix_error_fmt("%s%s", "POSIX does not allow ", msg); } -static int bc_error_variable_is_wrong_type(void) +static int bc_POSIX_does_not_allow_bool_ops_this_is_bad(const char *msg) { - return bc_error("variable is wrong type"); + return bc_posix_error_fmt("%s%s %s", "POSIX does not allow ", "boolean operators; the following is bad:", msg); } -static int bc_error_nested_read_call(void) +static int bc_POSIX_does_not_allow_empty_X_expression_in_for(const char *msg) { - return bc_error("read() call inside of a read() call"); + return bc_posix_error_fmt("%san empty %s expression in a for loop", "POSIX does not allow ", msg); } +#endif static void bc_vec_grow(BcVec *v, size_t n) { -- cgit v1.2.3-55-g6feb From fa35e598ab3d98037d0db05b257f787ecb4b7a74 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 10 Dec 2018 20:17:24 +0100 Subject: bc: optimize non-interactive config: we know that many functions always succeed function old new delta bc_program_assign 475 471 -4 bc_program_prep 87 81 -6 bc_parse_parse 423 417 -6 bc_num_p 440 434 -6 bc_program_printStream 153 143 -10 bc_program_execStr 478 468 -10 bc_parse_auto 275 265 -10 bc_num_k 925 913 -12 bc_program_copyToVar 307 289 -18 bc_program_binOpPrep 289 271 -18 bc_num_printNum 489 471 -18 bc_num_m 287 269 -18 bc_program_pushArray 139 113 -26 bc_program_modexp 707 677 -30 bc_program_print 704 667 -37 bc_program_exec 4010 3920 -90 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/16 up/down: 0/-319) Total: -319 bytes text data bss dec hex filename 983202 485 7296 990983 f1f07 busybox_old 982883 485 7296 990664 f1dc8 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 60 insertions(+), 13 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index aa478e461..3b9b4d54e 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -977,15 +977,18 @@ static void bc_verror_msg(const char *fmt, va_list p) } #if ENABLE_FEATURE_BC_SIGNALS -# define ERRORFUNC /*nothing*/ -# define ERROR_RETURN(a) a +# define ERRORFUNC /*nothing*/ +# define ERROR_RETURN(a) a +# define ERRORS_ARE_FATAL 0 #else # if ENABLE_FEATURE_CLEAN_UP -# define ERRORFUNC /*nothing*/ -# define ERROR_RETURN(a) a +# define ERRORFUNC /*nothing*/ +# define ERROR_RETURN(a) a +# define ERRORS_ARE_FATAL 0 # else -# define ERRORFUNC NORETURN -# define ERROR_RETURN(a) /*nothing*/ +# define ERRORFUNC NORETURN +# define ERROR_RETURN(a) /*nothing*/ +# define ERRORS_ARE_FATAL 1 # endif #endif @@ -1476,6 +1479,9 @@ static BcStatus bc_num_ulong(BcNum *n, unsigned long *result_p) return BC_STATUS_SUCCESS; } +#if ERRORS_ARE_FATAL +# define bc_num_ulong(...) (bc_num_ulong(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static void bc_num_ulong2num(BcNum *n, unsigned long val) { @@ -1673,6 +1679,9 @@ static BcStatus bc_num_shift(BcNum *n, size_t places) return BC_STATUS_SUCCESS; } +#if ERRORS_ARE_FATAL +# define bc_num_shift(...) (bc_num_shift(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static BcStatus bc_num_inv(BcNum *a, BcNum *b, size_t scale) { @@ -2342,6 +2351,9 @@ err: bc_vec_free(&stack); return s; } +#if ERRORS_ARE_FATAL +# define bc_num_printNum(...) (bc_num_printNum(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static BcStatus bc_num_printBase(BcNum *n) { @@ -2372,6 +2384,9 @@ static BcStatus bc_num_printBase(BcNum *n) return s; } +#if ERRORS_ARE_FATAL +# define bc_num_printBase(...) (bc_num_printBase(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif #if ENABLE_DC static BcStatus bc_num_stream(BcNum *n, BcNum *base) @@ -2526,6 +2541,9 @@ static BcStatus bc_num_parse(BcNum *n, const char *val, BcNum *base, return BC_STATUS_SUCCESS; } +#if ERRORS_ARE_FATAL +# define bc_num_parse(...) (bc_num_parse(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static BcStatus bc_num_print(BcNum *n, bool newline) { @@ -2549,6 +2567,9 @@ static BcStatus bc_num_print(BcNum *n, bool newline) return s; } +#if ERRORS_ARE_FATAL +# define bc_num_print(...) (bc_num_print(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static FAST_FUNC BcStatus bc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale) { @@ -2787,6 +2808,9 @@ static BcStatus bc_func_insert(BcFunc *f, char *name, bool var) return BC_STATUS_SUCCESS; } +#if ERRORS_ARE_FATAL +# define bc_func_insert(...) (bc_func_insert(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif #endif static void bc_func_init(BcFunc *f) @@ -2992,6 +3016,9 @@ static BcStatus bc_lex_number(BcLex *l, char start) return BC_STATUS_SUCCESS; } +#if ERRORS_ARE_FATAL +# define bc_lex_number(...) (bc_lex_number(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static BcStatus bc_lex_name(BcLex *l) { @@ -5410,8 +5437,6 @@ static BcVec* bc_program_search(char *id, bool var) static BcStatus bc_program_num(BcResult *r, BcNum **num, bool hex) { - BcStatus s = BC_STATUS_SUCCESS; - switch (r->t) { case BC_RESULT_STR: @@ -5426,6 +5451,7 @@ static BcStatus bc_program_num(BcResult *r, BcNum **num, bool hex) case BC_RESULT_CONSTANT: { + BcStatus s; char **str = bc_vec_item(&G.prog.consts, r->d.id.idx); size_t base_t, len = strlen(*str); BcNum *base; @@ -5480,8 +5506,11 @@ static BcStatus bc_program_num(BcResult *r, BcNum **num, bool hex) } } - return s; + return BC_STATUS_SUCCESS; } +#if ERRORS_ARE_FATAL +# define bc_program_num(...) (bc_program_num(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static BcStatus bc_program_binOpPrep(BcResult **l, BcNum **ln, BcResult **r, BcNum **rn, bool assign) @@ -5544,6 +5573,9 @@ static BcStatus bc_program_prep(BcResult **r, BcNum **n) return s; } +#if ERRORS_ARE_FATAL +# define bc_program_prep(...) (bc_program_prep(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static void bc_program_retire(BcResult *r, BcResultType t) { @@ -5744,7 +5776,7 @@ static void bc_program_printString(const char *str) static BcStatus bc_program_print(char inst, size_t idx) { - BcStatus s = BC_STATUS_SUCCESS; + BcStatus s; BcResult *r; BcNum *num; bool pop = inst != BC_INST_PRINT; @@ -5786,6 +5818,9 @@ static BcStatus bc_program_print(char inst, size_t idx) return s; } +#if ERRORS_ARE_FATAL +# define bc_program_print(...) (bc_program_print(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static BcStatus bc_program_negate(void) { @@ -5804,6 +5839,9 @@ static BcStatus bc_program_negate(void) return s; } +#if ERRORS_ARE_FATAL +# define bc_program_negate(...) (bc_program_negate(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static BcStatus bc_program_logical(char inst) { @@ -6120,6 +6158,9 @@ err: if (s) free(r.d.id.name); return s; } +#if ERRORS_ARE_FATAL +# define bc_program_pushArray(...) (bc_program_pushArray(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif #if ENABLE_BC static BcStatus bc_program_incdec(char inst) @@ -6153,6 +6194,9 @@ static BcStatus bc_program_incdec(char inst) return s; } +#if ERRORS_ARE_FATAL +# define bc_program_incdec(...) (bc_program_incdec(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static BcStatus bc_program_call(char *code, size_t *idx) { @@ -6444,9 +6488,9 @@ static BcStatus bc_program_asciify(void) c = str2[0]; } - str = xmalloc(2); + str = xzalloc(2); str[0] = c; - str[1] = '\0'; + //str[1] = '\0'; - already is str2 = xstrdup(str); bc_program_addFunc(str2, &idx); @@ -6527,6 +6571,9 @@ static BcStatus bc_program_nquit(void) return s; } +#if ERRORS_ARE_FATAL +# define bc_program_nquit(...) (bc_program_nquit(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static BcStatus bc_program_execStr(char *code, size_t *bgn, bool cond) @@ -6689,7 +6736,7 @@ static BcStatus bc_program_exec(void) bool cond = false; while (ip->idx < func->code.len) { - BcStatus s; + BcStatus s = BC_STATUS_SUCCESS; char inst = code[(ip->idx)++]; switch (inst) { -- cgit v1.2.3-55-g6feb From 88cfea6a818b83a4681b04ad812d3cc047af15b9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 10 Dec 2018 20:26:04 +0100 Subject: bc: stop checking for name length in bc_lex_name() Gigabyte-long names are not a practical concern. function old new delta bc_lex_name 73 69 -4 bc_lex_token 1266 1259 -7 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-11) Total: -11 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 3b9b4d54e..aa0a2c636 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -3020,27 +3020,34 @@ static BcStatus bc_lex_number(BcLex *l, char start) # define bc_lex_number(...) (bc_lex_number(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static BcStatus bc_lex_name(BcLex *l) +static void bc_lex_name(BcLex *l) { - size_t i = 0; - const char *buf = l->buf + l->i - 1; - char c = buf[i]; + size_t i; + const char *buf; l->t.t = BC_LEX_NAME; - while ((c >= 'a' && c <= 'z') || isdigit(c) || c == '_') c = buf[++i]; + i = 0; + buf = l->buf + l->i - 1; + for (;;) { + char c = buf[i]; + if ((c < 'a' || c > 'z') && !isdigit(c) && c != '_') break; + i++; + } +#if 0 // We do not protect against people with gigabyte-long names // This check makes sense only if size_t is (much) larger than BC_MAX_STRING. if (SIZE_MAX > (BC_MAX_STRING | 0xff)) { if (i > BC_MAX_STRING) return bc_error("name too long: must be [1,"BC_MAX_STRING_STR"]"); } +#endif bc_vec_string(&l->t.v, i, buf); // Increment the index. We minus 1 because it has already been incremented. l->i += i - 1; - return BC_STATUS_SUCCESS; + //return BC_STATUS_SUCCESS; } static void bc_lex_init(BcLex *l, BcLexNext next) @@ -3121,8 +3128,7 @@ static BcStatus bc_lex_identifier(BcLex *l) return BC_STATUS_SUCCESS; } - s = bc_lex_name(l); - if (s) return s; + bc_lex_name(l); if (l->t.v.len > 2) { // Prevent this: @@ -3498,7 +3504,7 @@ static BcStatus dc_lex_register(BcLex *l) if (!G_exreg) s = bc_error("extended register"); else - s = bc_lex_name(l); + bc_lex_name(l); } else { bc_vec_pop_all(&l->t.v); @@ -3509,6 +3515,9 @@ static BcStatus dc_lex_register(BcLex *l) return s; } +#if ERRORS_ARE_FATAL +# define dc_lex_register(...) (dc_lex_register(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static BcStatus dc_lex_string(BcLex *l) { @@ -3545,6 +3554,9 @@ static BcStatus dc_lex_string(BcLex *l) return BC_STATUS_SUCCESS; } +#if ERRORS_ARE_FATAL +# define dc_lex_string(...) (dc_lex_string(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static FAST_FUNC BcStatus dc_lex_token(BcLex *l) { -- cgit v1.2.3-55-g6feb From 628bf1bc63aedf696f3de184ddf4cb348828ad66 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 10 Dec 2018 20:41:05 +0100 Subject: bc: more ERRORS_ARE_FATAL annotations function old new delta bc_program_exec 3920 3969 +49 bc_program_call 329 325 -4 bc_vm_run 622 616 -6 bc_program_modexp 677 668 -9 bc_program_assign 471 455 -16 bc_program_pushArray 113 - -113 ------------------------------------------------------------------------------ (add/remove: 0/1 grow/shrink: 1/4 up/down: 49/-148) Total: -99 bytes text data bss dec hex filename 982872 485 7296 990653 f1dbd busybox_old 982773 485 7296 990554 f1d5a busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index aa0a2c636..6dc0f5441 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -2393,6 +2393,9 @@ static BcStatus bc_num_stream(BcNum *n, BcNum *base) { return bc_num_printNum(n, base, 1, bc_num_printChar); } +#if ERRORS_ARE_FATAL +# define bc_num_stream(...) (bc_num_stream(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif #endif static bool bc_num_strValid(const char *val, size_t base) @@ -3211,6 +3214,9 @@ static BcStatus bc_lex_comment(BcLex *l) return BC_STATUS_SUCCESS; } +#if ERRORS_ARE_FATAL +# define bc_lex_comment(...) (bc_lex_comment(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static FAST_FUNC BcStatus bc_lex_token(BcLex *l) { @@ -5560,6 +5566,9 @@ static BcStatus bc_program_binOpPrep(BcResult **l, BcNum **ln, return s; } +#if ERRORS_ARE_FATAL +# define bc_program_binOpPrep(...) (bc_program_binOpPrep(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static void bc_program_binOpRetire(BcResult *r) { @@ -5947,6 +5956,9 @@ static BcStatus bc_program_assignStr(BcResult *r, BcVec *v, return BC_STATUS_SUCCESS; } +#if ERRORS_ARE_FATAL +# define bc_program_assignStr(...) (bc_program_assignStr(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif #endif // ENABLE_DC static BcStatus bc_program_copyToVar(char *name, bool var) @@ -5990,6 +6002,9 @@ static BcStatus bc_program_copyToVar(char *name, bool var) return s; } +#if ERRORS_ARE_FATAL +# define bc_program_copyToVar(...) (bc_program_copyToVar(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static BcStatus bc_program_assign(char inst) { @@ -6212,7 +6227,6 @@ static BcStatus bc_program_incdec(char inst) static BcStatus bc_program_call(char *code, size_t *idx) { - BcStatus s = BC_STATUS_SUCCESS; BcInstPtr ip; size_t i, nparams = bc_program_index(code, idx); BcFunc *func; @@ -6233,6 +6247,7 @@ static BcStatus bc_program_call(char *code, size_t *idx) ip.len = G.prog.results.len - nparams; for (i = 0; i < nparams; ++i) { + BcStatus s; a = bc_vec_item(&func->autos, nparams - 1 - i); arg = bc_vec_top(&G.prog.results); @@ -6264,10 +6279,12 @@ static BcStatus bc_program_call(char *code, size_t *idx) return BC_STATUS_SUCCESS; } +#if ERRORS_ARE_FATAL +# define bc_program_call(...) (bc_program_call(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static BcStatus bc_program_return(char inst) { - BcStatus s; BcResult res; BcFunc *f; size_t i; @@ -6280,7 +6297,7 @@ static BcStatus bc_program_return(char inst) res.t = BC_RESULT_TEMP; if (inst == BC_INST_RET) { - + BcStatus s; BcNum *num; BcResult *operand = bc_vec_top(&G.prog.results); @@ -6296,7 +6313,6 @@ static BcStatus bc_program_return(char inst) // We need to pop arguments as well, so this takes that into account. for (i = 0; i < f->autos.len; ++i) { - BcVec *v; BcId *a = bc_vec_item(&f->autos, i); @@ -6310,6 +6326,9 @@ static BcStatus bc_program_return(char inst) return BC_STATUS_SUCCESS; } +#if ERRORS_ARE_FATAL +# define bc_program_return(...) (bc_program_return(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif #endif // ENABLE_BC static unsigned long bc_program_scale(BcNum *n) @@ -6558,6 +6577,9 @@ static BcStatus bc_program_printStream(void) return s; } +#if ERRORS_ARE_FATAL +# define bc_program_printStream(...) (bc_program_printStream(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static BcStatus bc_program_nquit(void) { @@ -7096,6 +7118,9 @@ err: free(data); return s; } +#if ERRORS_ARE_FATAL +# define bc_vm_file(...) (bc_vm_file(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static BcStatus bc_vm_stdin(void) { -- cgit v1.2.3-55-g6feb From 91cde95916b30d74a9a53127c055403dfce7a838 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 10 Dec 2018 20:56:08 +0100 Subject: bc: it's not clear bc_vm_file() always exits on errors, remove ERRORS_ARE_FATAL Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 6dc0f5441..c756d8cd6 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -7118,9 +7118,6 @@ err: free(data); return s; } -#if ERRORS_ARE_FATAL -# define bc_vm_file(...) (bc_vm_file(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif static BcStatus bc_vm_stdin(void) { @@ -7421,7 +7418,7 @@ static BcStatus bc_vm_exec(void) return s; } - if (IS_BC || (option_mask32 & BC_FLAG_I)) + if (IS_BC || (option_mask32 & BC_FLAG_I)) s = bc_vm_stdin(); if (!s && !BC_PARSE_CAN_EXEC(&G.prs)) -- cgit v1.2.3-55-g6feb From 2930123279c423e5b29639b6992c524571f2add5 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 11 Dec 2018 15:29:32 +0100 Subject: bc: improve "noninteractive" macro machinery so that even "return zero" code is not generated Most affected functions shrink by 2 bytes on x86. function old new delta zbc_program_num - 880 +880 zbc_program_print - 665 +665 zbc_num_printNum - 447 +447 zbc_program_call - 323 +323 zbc_program_copyToVar - 287 +287 zbc_lex_number - 279 +279 zbc_program_binOpPrep - 269 +269 zbc_program_assignStr - 142 +142 zbc_program_printStream - 141 +141 zbc_func_insert - 93 +93 zbc_num_ulong - 88 +88 zbc_program_prep - 79 +79 zbc_num_shift - 53 +53 bc_num_shift 54 - -54 bc_program_prep 81 - -81 bc_num_ulong 90 - -90 bc_func_insert 95 - -95 bc_program_printStream 143 - -143 bc_program_assignStr 144 - -144 bc_program_binOpPrep 271 - -271 bc_lex_number 281 - -281 bc_program_copyToVar 289 - -289 bc_program_call 325 - -325 bc_num_printNum 471 - -471 bc_program_print 667 - -667 bc_program_num 880 - -880 ------------------------------------------------------------------------------ (add/remove: 13/13 grow/shrink: 0/0 up/down: 3746/-3791) Total: -45 bytes text data bss dec hex filename 982779 485 7296 990560 f1d60 busybox_old 982734 485 7296 990515 f1d33 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 395 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 201 insertions(+), 194 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index c756d8cd6..4e5ba804f 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -976,20 +976,29 @@ static void bc_verror_msg(const char *fmt, va_list p) } } -#if ENABLE_FEATURE_BC_SIGNALS +// In configurations where errors abort instead of propagating error +// return code up the call chain, functions returning BC_STATUS +// actually don't return anything, they always succeed and return "void". +// A macro wrapper is provided, which makes this statement work: +// s = zbc_func(...) +// and makes it visible to the compiler that s is always zero, +// allowing compiler to optimize dead code after the statement. +// +// To make code more readable, each such function has a "z" +// ("always returning zero") prefix, i.e. zbc_foo or zdc_foo. +// +#if ENABLE_FEATURE_BC_SIGNALS || ENABLE_FEATURE_CLEAN_UP # define ERRORFUNC /*nothing*/ # define ERROR_RETURN(a) a # define ERRORS_ARE_FATAL 0 +# define BC_STATUS BcStatus +# define RETURN_STATUS(v) return (v) #else -# if ENABLE_FEATURE_CLEAN_UP -# define ERRORFUNC /*nothing*/ -# define ERROR_RETURN(a) a -# define ERRORS_ARE_FATAL 0 -# else -# define ERRORFUNC NORETURN -# define ERROR_RETURN(a) /*nothing*/ -# define ERRORS_ARE_FATAL 1 -# endif +# define ERRORFUNC NORETURN +# define ERROR_RETURN(a) /*nothing*/ +# define ERRORS_ARE_FATAL 1 +# define BC_STATUS void +# define RETURN_STATUS(v) do { ((void)(v)); return; } while (0) #endif static NOINLINE ERRORFUNC int bc_error_fmt(const char *fmt, ...) @@ -1456,12 +1465,12 @@ static void bc_num_copy(BcNum *d, BcNum *s) } } -static BcStatus bc_num_ulong(BcNum *n, unsigned long *result_p) +static BC_STATUS zbc_num_ulong(BcNum *n, unsigned long *result_p) { size_t i; unsigned long pow, result; - if (n->neg) return bc_error("negative number"); + if (n->neg) RETURN_STATUS(bc_error("negative number")); for (result = 0, pow = 1, i = n->rdx; i < n->len; ++i) { @@ -1471,16 +1480,16 @@ static BcStatus bc_num_ulong(BcNum *n, unsigned long *result_p) pow *= 10; if (result < prev || pow < powprev) - return bc_error("overflow"); + RETURN_STATUS(bc_error("overflow")); prev = result; powprev = pow; } *result_p = result; - return BC_STATUS_SUCCESS; + RETURN_STATUS(BC_STATUS_SUCCESS); } #if ERRORS_ARE_FATAL -# define bc_num_ulong(...) (bc_num_ulong(__VA_ARGS__), BC_STATUS_SUCCESS) +# define zbc_num_ulong(...) (zbc_num_ulong(__VA_ARGS__), BC_STATUS_SUCCESS) #endif static void bc_num_ulong2num(BcNum *n, unsigned long val) @@ -1658,14 +1667,14 @@ static void bc_num_split(BcNum *restrict n, size_t idx, BcNum *restrict a, bc_num_clean(b); } -static BcStatus bc_num_shift(BcNum *n, size_t places) +static BC_STATUS zbc_num_shift(BcNum *n, size_t places) { - if (places == 0 || n->len == 0) return BC_STATUS_SUCCESS; + if (places == 0 || n->len == 0) RETURN_STATUS(BC_STATUS_SUCCESS); // This check makes sense only if size_t is (much) larger than BC_MAX_NUM. if (SIZE_MAX > (BC_MAX_NUM | 0xff)) { if (places + n->len > BC_MAX_NUM) - return bc_error("number too long: must be [1,"BC_MAX_NUM_STR"]"); + RETURN_STATUS(bc_error("number too long: must be [1,"BC_MAX_NUM_STR"]")); } if (n->rdx >= places) @@ -1677,10 +1686,10 @@ static BcStatus bc_num_shift(BcNum *n, size_t places) bc_num_clean(n); - return BC_STATUS_SUCCESS; + RETURN_STATUS(BC_STATUS_SUCCESS); } #if ERRORS_ARE_FATAL -# define bc_num_shift(...) (bc_num_shift(__VA_ARGS__), BC_STATUS_SUCCESS) +# define zbc_num_shift(...) (zbc_num_shift(__VA_ARGS__), BC_STATUS_SUCCESS) #endif static BcStatus bc_num_inv(BcNum *a, BcNum *b, size_t scale) @@ -1912,9 +1921,9 @@ static FAST_FUNC BcStatus bc_num_k(BcNum *restrict a, BcNum *restrict b, s = bc_num_sub(&temp, &z2, &z1, 0); if (s) goto err; - s = bc_num_shift(&z0, max2 * 2); + s = zbc_num_shift(&z0, max2 * 2); if (s) goto err; - s = bc_num_shift(&z1, max2); + s = zbc_num_shift(&z1, max2); if (s) goto err; s = bc_num_add(&z0, &z1, &temp, 0); if (s) goto err; @@ -1952,9 +1961,9 @@ static FAST_FUNC BcStatus bc_num_m(BcNum *a, BcNum *b, BcNum *restrict c, size_t bc_num_copy(&cpb, b); cpa.neg = cpb.neg = false; - s = bc_num_shift(&cpa, maxrdx); + s = zbc_num_shift(&cpa, maxrdx); if (s) goto err; - s = bc_num_shift(&cpb, maxrdx); + s = zbc_num_shift(&cpb, maxrdx); if (s) goto err; s = bc_num_k(&cpa, &cpb, c); if (s) goto err; @@ -2127,7 +2136,7 @@ static FAST_FUNC BcStatus bc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t neg = b->neg; b->neg = false; - s = bc_num_ulong(b, &pow); + s = zbc_num_ulong(b, &pow); if (s) return s; bc_num_init(©, a->len); @@ -2289,7 +2298,7 @@ static void bc_num_printDecimal(BcNum *n) bc_num_printHex((size_t) n->num[i], 1, i == rdx); } -static BcStatus bc_num_printNum(BcNum *n, BcNum *base, size_t width, BcNumDigitOp print) +static BC_STATUS zbc_num_printNum(BcNum *n, BcNum *base, size_t width, BcNumDigitOp print) { BcStatus s; BcVec stack; @@ -2300,7 +2309,7 @@ static BcStatus bc_num_printNum(BcNum *n, BcNum *base, size_t width, BcNumDigitO if (n->len == 0) { print(0, width, false); - return BC_STATUS_SUCCESS; + RETURN_STATUS(BC_STATUS_SUCCESS); } bc_vec_init(&stack, sizeof(long), NULL); @@ -2318,7 +2327,7 @@ static BcStatus bc_num_printNum(BcNum *n, BcNum *base, size_t width, BcNumDigitO while (intp.len != 0) { s = bc_num_divmod(&intp, base, &intp, &digit, 0); if (s) goto err; - s = bc_num_ulong(&digit, &dig); + s = zbc_num_ulong(&digit, &dig); if (s) goto err; bc_vec_push(&stack, &dig); } @@ -2333,7 +2342,7 @@ static BcStatus bc_num_printNum(BcNum *n, BcNum *base, size_t width, BcNumDigitO for (radix = true; frac_len.len <= n->rdx; radix = false) { s = bc_num_mul(&fracp, base, &fracp, n->rdx); if (s) goto err; - s = bc_num_ulong(&fracp, &dig); + s = zbc_num_ulong(&fracp, &dig); if (s) goto err; bc_num_ulong2num(&intp, dig); s = bc_num_sub(&fracp, &intp, &fracp, 0); @@ -2349,13 +2358,13 @@ err: bc_num_free(&fracp); bc_num_free(&intp); bc_vec_free(&stack); - return s; + RETURN_STATUS(s); } #if ERRORS_ARE_FATAL -# define bc_num_printNum(...) (bc_num_printNum(__VA_ARGS__), BC_STATUS_SUCCESS) +# define zbc_num_printNum(...) (zbc_num_printNum(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static BcStatus bc_num_printBase(BcNum *n) +static BC_STATUS zbc_num_printBase(BcNum *n) { BcStatus s; size_t width, i; @@ -2379,22 +2388,22 @@ static BcStatus bc_num_printBase(BcNum *n) print = bc_num_printDigits; } - s = bc_num_printNum(n, &G.prog.ob, width, print); + s = zbc_num_printNum(n, &G.prog.ob, width, print); n->neg = neg; - return s; + RETURN_STATUS(s); } #if ERRORS_ARE_FATAL -# define bc_num_printBase(...) (bc_num_printBase(__VA_ARGS__), BC_STATUS_SUCCESS) +# define zbc_num_printBase(...) (zbc_num_printBase(__VA_ARGS__), BC_STATUS_SUCCESS) #endif #if ENABLE_DC -static BcStatus bc_num_stream(BcNum *n, BcNum *base) +static BC_STATUS zbc_num_stream(BcNum *n, BcNum *base) { - return bc_num_printNum(n, base, 1, bc_num_printChar); + RETURN_STATUS(zbc_num_printNum(n, base, 1, bc_num_printChar)); } #if ERRORS_ARE_FATAL -# define bc_num_stream(...) (bc_num_stream(__VA_ARGS__), BC_STATUS_SUCCESS) +# define zbc_num_stream(...) (zbc_num_stream(__VA_ARGS__), BC_STATUS_SUCCESS) #endif #endif @@ -2528,11 +2537,11 @@ int_err: bc_num_free(&temp); } -static BcStatus bc_num_parse(BcNum *n, const char *val, BcNum *base, +static BC_STATUS zbc_num_parse(BcNum *n, const char *val, BcNum *base, size_t base_t) { if (!bc_num_strValid(val, base_t)) - return bc_error("bad number string"); + RETURN_STATUS(bc_error("bad number string")); bc_num_zero(n); while (*val == '0') val++; @@ -2542,13 +2551,13 @@ static BcStatus bc_num_parse(BcNum *n, const char *val, BcNum *base, else bc_num_parseBase(n, val, base); - return BC_STATUS_SUCCESS; + RETURN_STATUS(BC_STATUS_SUCCESS); } #if ERRORS_ARE_FATAL -# define bc_num_parse(...) (bc_num_parse(__VA_ARGS__), BC_STATUS_SUCCESS) +# define zbc_num_parse(...) (zbc_num_parse(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static BcStatus bc_num_print(BcNum *n, bool newline) +static BC_STATUS zbc_num_print(BcNum *n, bool newline) { BcStatus s = BC_STATUS_SUCCESS; @@ -2561,17 +2570,17 @@ static BcStatus bc_num_print(BcNum *n, bool newline) else if (G.prog.ob_t == 10) bc_num_printDecimal(n); else - s = bc_num_printBase(n); + s = zbc_num_printBase(n); if (newline) { bb_putchar('\n'); G.prog.nchars = 0; } - return s; + RETURN_STATUS(s); } #if ERRORS_ARE_FATAL -# define bc_num_print(...) (bc_num_print(__VA_ARGS__), BC_STATUS_SUCCESS) +# define zbc_num_print(...) (zbc_num_print(__VA_ARGS__), BC_STATUS_SUCCESS) #endif static FAST_FUNC BcStatus bc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale) @@ -2794,14 +2803,14 @@ err: #endif // ENABLE_DC #if ENABLE_BC -static BcStatus bc_func_insert(BcFunc *f, char *name, bool var) +static BC_STATUS zbc_func_insert(BcFunc *f, char *name, bool var) { BcId a; size_t i; for (i = 0; i < f->autos.len; ++i) { if (strcmp(name, ((BcId *) bc_vec_item(&f->autos, i))->name) == 0) - return bc_error("function parameter or auto var has the same name as another"); + RETURN_STATUS(bc_error("function parameter or auto var has the same name as another")); } a.idx = var; @@ -2809,10 +2818,10 @@ static BcStatus bc_func_insert(BcFunc *f, char *name, bool var) bc_vec_push(&f->autos, &a); - return BC_STATUS_SUCCESS; + RETURN_STATUS(BC_STATUS_SUCCESS); } #if ERRORS_ARE_FATAL -# define bc_func_insert(...) (bc_func_insert(__VA_ARGS__), BC_STATUS_SUCCESS) +# define zbc_func_insert(...) (zbc_func_insert(__VA_ARGS__), BC_STATUS_SUCCESS) #endif #endif @@ -2963,7 +2972,7 @@ static void bc_lex_whitespace(BcLex *l) for (c = l->buf[l->i]; c != '\n' && isspace(c); c = l->buf[++l->i]); } -static BcStatus bc_lex_number(BcLex *l, char start) +static BC_STATUS zbc_lex_number(BcLex *l, char start) { const char *buf = l->buf + l->i; size_t len, hits = 0, bslashes = 0, i = 0, j; @@ -2992,7 +3001,7 @@ static BcStatus bc_lex_number(BcLex *l, char start) // This check makes sense only if size_t is (much) larger than BC_MAX_NUM. if (SIZE_MAX > (BC_MAX_NUM | 0xff)) { if (len > BC_MAX_NUM) - return bc_error("number too long: must be [1,"BC_MAX_NUM_STR"]"); + RETURN_STATUS(bc_error("number too long: must be [1,"BC_MAX_NUM_STR"]")); } bc_vec_pop_all(&l->t.v); @@ -3017,10 +3026,10 @@ static BcStatus bc_lex_number(BcLex *l, char start) bc_vec_pushZeroByte(&l->t.v); l->i += i; - return BC_STATUS_SUCCESS; + RETURN_STATUS(BC_STATUS_SUCCESS); } #if ERRORS_ARE_FATAL -# define bc_lex_number(...) (bc_lex_number(__VA_ARGS__), BC_STATUS_SUCCESS) +# define zbc_lex_number(...) (zbc_lex_number(__VA_ARGS__), BC_STATUS_SUCCESS) #endif static void bc_lex_name(BcLex *l) @@ -3184,7 +3193,7 @@ static void bc_lex_assign(BcLex *l, BcLexType with, BcLexType without) l->t.t = without; } -static BcStatus bc_lex_comment(BcLex *l) +static BC_STATUS zbc_lex_comment(BcLex *l) { size_t i, nls = 0; const char *buf = l->buf; @@ -3202,7 +3211,7 @@ static BcStatus bc_lex_comment(BcLex *l) } if (c == '\0') { l->i = i; - return bc_error("comment end could not be found"); + RETURN_STATUS(bc_error("comment end could not be found")); } nls += (c == '\n'); i++; @@ -3212,10 +3221,10 @@ static BcStatus bc_lex_comment(BcLex *l) l->line += nls; G.err_line = l->line; - return BC_STATUS_SUCCESS; + RETURN_STATUS(BC_STATUS_SUCCESS); } #if ERRORS_ARE_FATAL -# define bc_lex_comment(...) (bc_lex_comment(__VA_ARGS__), BC_STATUS_SUCCESS) +# define zbc_lex_comment(...) (zbc_lex_comment(__VA_ARGS__), BC_STATUS_SUCCESS) #endif static FAST_FUNC BcStatus bc_lex_token(BcLex *l) @@ -3343,7 +3352,7 @@ static FAST_FUNC BcStatus bc_lex_token(BcLex *l) case '.': { if (isdigit(l->buf[l->i])) - s = bc_lex_number(l, c); + s = zbc_lex_number(l, c); else { l->t.t = BC_LEX_KEY_LAST; s = bc_POSIX_does_not_allow("a period ('.') as a shortcut for the last result"); @@ -3355,7 +3364,7 @@ static FAST_FUNC BcStatus bc_lex_token(BcLex *l) { c2 = l->buf[l->i]; if (c2 == '*') - s = bc_lex_comment(l); + s = zbc_lex_comment(l); else bc_lex_assign(l, BC_LEX_OP_ASSIGN_DIVIDE, BC_LEX_OP_DIVIDE); break; @@ -3378,7 +3387,7 @@ static FAST_FUNC BcStatus bc_lex_token(BcLex *l) case 'E': case 'F': { - s = bc_lex_number(l, c); + s = zbc_lex_number(l, c); break; } @@ -3500,17 +3509,14 @@ static FAST_FUNC BcStatus bc_lex_token(BcLex *l) #endif // ENABLE_BC #if ENABLE_DC -static BcStatus dc_lex_register(BcLex *l) +static BC_STATUS zdc_lex_register(BcLex *l) { - BcStatus s = BC_STATUS_SUCCESS; - if (isspace(l->buf[l->i - 1])) { bc_lex_whitespace(l); ++l->i; if (!G_exreg) - s = bc_error("extended register"); - else - bc_lex_name(l); + RETURN_STATUS(bc_error("extended register")); + bc_lex_name(l); } else { bc_vec_pop_all(&l->t.v); @@ -3519,13 +3525,13 @@ static BcStatus dc_lex_register(BcLex *l) l->t.t = BC_LEX_NAME; } - return s; + RETURN_STATUS(BC_STATUS_SUCCESS); } #if ERRORS_ARE_FATAL -# define dc_lex_register(...) (dc_lex_register(__VA_ARGS__), BC_STATUS_SUCCESS) +# define zdc_lex_register(...) (zdc_lex_register(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static BcStatus dc_lex_string(BcLex *l) +static BC_STATUS zdc_lex_string(BcLex *l) { size_t depth = 1, nls = 0, i = l->i; char c; @@ -3544,24 +3550,24 @@ static BcStatus dc_lex_string(BcLex *l) if (c == '\0') { l->i = i; - return bc_error("string end could not be found"); + RETURN_STATUS(bc_error("string end could not be found")); } bc_vec_pushZeroByte(&l->t.v); // This check makes sense only if size_t is (much) larger than BC_MAX_STRING. if (SIZE_MAX > (BC_MAX_STRING | 0xff)) { if (i - l->i > BC_MAX_STRING) - return bc_error("string too long: must be [1,"BC_MAX_STRING_STR"]"); + RETURN_STATUS(bc_error("string too long: must be [1,"BC_MAX_STRING_STR"]")); } l->i = i; l->line += nls; G.err_line = l->line; - return BC_STATUS_SUCCESS; + RETURN_STATUS(BC_STATUS_SUCCESS); } #if ERRORS_ARE_FATAL -# define dc_lex_string(...) (dc_lex_string(__VA_ARGS__), BC_STATUS_SUCCESS) +# define zdc_lex_string(...) (zdc_lex_string(__VA_ARGS__), BC_STATUS_SUCCESS) #endif static FAST_FUNC BcStatus dc_lex_token(BcLex *l) @@ -3572,7 +3578,7 @@ static FAST_FUNC BcStatus dc_lex_token(BcLex *l) for (i = 0; i < ARRAY_SIZE(dc_lex_regs); ++i) { if (l->t.last == dc_lex_regs[i]) - return dc_lex_register(l); + return zdc_lex_register(l); } if (c >= '%' && c <= '~' && @@ -3628,7 +3634,7 @@ static FAST_FUNC BcStatus dc_lex_token(BcLex *l) case '.': { if (isdigit(l->buf[l->i])) - s = bc_lex_number(l, c); + s = zbc_lex_number(l, c); else s = bc_error_bad_character(c); break; @@ -3651,13 +3657,13 @@ static FAST_FUNC BcStatus dc_lex_token(BcLex *l) case 'E': case 'F': { - s = bc_lex_number(l, c); + s = zbc_lex_number(l, c); break; } case '[': { - s = dc_lex_string(l); + s = zdc_lex_string(l); break; } @@ -4599,7 +4605,7 @@ static BcStatus bc_parse_func(BcParse *p) if (s) goto err; } - s = bc_func_insert(p->func, name, var); + s = zbc_func_insert(p->func, name, var); if (s) goto err; } @@ -4661,7 +4667,7 @@ static BcStatus bc_parse_auto(BcParse *p) if (s) goto err; } - s = bc_func_insert(p->func, name, var); + s = zbc_func_insert(p->func, name, var); if (s) goto err; } @@ -5453,7 +5459,7 @@ static BcVec* bc_program_search(char *id, bool var) return bc_vec_item(v, ptr->idx); } -static BcStatus bc_program_num(BcResult *r, BcNum **num, bool hex) +static BC_STATUS zbc_program_num(BcResult *r, BcNum **num, bool hex) { switch (r->t) { @@ -5479,11 +5485,11 @@ static BcStatus bc_program_num(BcResult *r, BcNum **num, bool hex) hex = hex && len == 1; base = hex ? &G.prog.hexb : &G.prog.ib; base_t = hex ? BC_NUM_MAX_IBASE : G.prog.ib_t; - s = bc_num_parse(&r->d.n, *str, base, base_t); + s = zbc_num_parse(&r->d.n, *str, base, base_t); if (s) { bc_num_free(&r->d.n); - return s; + RETURN_STATUS(s); } *num = &r->d.n; @@ -5524,13 +5530,13 @@ static BcStatus bc_program_num(BcResult *r, BcNum **num, bool hex) } } - return BC_STATUS_SUCCESS; + RETURN_STATUS(BC_STATUS_SUCCESS); } #if ERRORS_ARE_FATAL -# define bc_program_num(...) (bc_program_num(__VA_ARGS__), BC_STATUS_SUCCESS) +# define zbc_program_num(...) (zbc_program_num(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static BcStatus bc_program_binOpPrep(BcResult **l, BcNum **ln, +static BC_STATUS zbc_program_binOpPrep(BcResult **l, BcNum **ln, BcResult **r, BcNum **rn, bool assign) { BcStatus s; @@ -5538,7 +5544,7 @@ static BcStatus bc_program_binOpPrep(BcResult **l, BcNum **ln, BcResultType lt, rt; if (!BC_PROG_STACK(&G.prog.results, 2)) - return bc_error_stack_has_too_few_elements(); + RETURN_STATUS(bc_error_stack_has_too_few_elements()); *r = bc_vec_item_rev(&G.prog.results, 0); *l = bc_vec_item_rev(&G.prog.results, 1); @@ -5547,27 +5553,27 @@ static BcStatus bc_program_binOpPrep(BcResult **l, BcNum **ln, rt = (*r)->t; hex = assign && (lt == BC_RESULT_IBASE || lt == BC_RESULT_OBASE); - s = bc_program_num(*l, ln, false); - if (s) return s; - s = bc_program_num(*r, rn, hex); - if (s) return s; + s = zbc_program_num(*l, ln, false); + if (s) RETURN_STATUS(s); + s = zbc_program_num(*r, rn, hex); + if (s) RETURN_STATUS(s); // We run this again under these conditions in case any vector has been // reallocated out from under the BcNums or arrays we had. if (lt == rt && (lt == BC_RESULT_VAR || lt == BC_RESULT_ARRAY_ELEM)) { - s = bc_program_num(*l, ln, false); - if (s) return s; + s = zbc_program_num(*l, ln, false); + if (s) RETURN_STATUS(s); } if (!BC_PROG_NUM((*l), (*ln)) && (!assign || (*l)->t != BC_RESULT_VAR)) - return bc_error_variable_is_wrong_type(); + RETURN_STATUS(bc_error_variable_is_wrong_type()); if (!assign && !BC_PROG_NUM((*r), (*ln))) - return bc_error_variable_is_wrong_type(); + RETURN_STATUS(bc_error_variable_is_wrong_type()); - return s; + RETURN_STATUS(s); } #if ERRORS_ARE_FATAL -# define bc_program_binOpPrep(...) (bc_program_binOpPrep(__VA_ARGS__), BC_STATUS_SUCCESS) +# define zbc_program_binOpPrep(...) (zbc_program_binOpPrep(__VA_ARGS__), BC_STATUS_SUCCESS) #endif static void bc_program_binOpRetire(BcResult *r) @@ -5578,24 +5584,24 @@ static void bc_program_binOpRetire(BcResult *r) bc_vec_push(&G.prog.results, r); } -static BcStatus bc_program_prep(BcResult **r, BcNum **n) +static BC_STATUS zbc_program_prep(BcResult **r, BcNum **n) { BcStatus s; if (!BC_PROG_STACK(&G.prog.results, 1)) - return bc_error_stack_has_too_few_elements(); + RETURN_STATUS(bc_error_stack_has_too_few_elements()); *r = bc_vec_top(&G.prog.results); - s = bc_program_num(*r, n, false); - if (s) return s; + s = zbc_program_num(*r, n, false); + if (s) RETURN_STATUS(s); if (!BC_PROG_NUM((*r), (*n))) - return bc_error_variable_is_wrong_type(); + RETURN_STATUS(bc_error_variable_is_wrong_type()); - return s; + RETURN_STATUS(s); } #if ERRORS_ARE_FATAL -# define bc_program_prep(...) (bc_program_prep(__VA_ARGS__), BC_STATUS_SUCCESS) +# define zbc_program_prep(...) (zbc_program_prep(__VA_ARGS__), BC_STATUS_SUCCESS) #endif static void bc_program_retire(BcResult *r, BcResultType t) @@ -5611,7 +5617,7 @@ static BcStatus bc_program_op(char inst) BcResult *opd1, *opd2, res; BcNum *n1, *n2 = NULL; - s = bc_program_binOpPrep(&opd1, &n1, &opd2, &n2, false); + s = zbc_program_binOpPrep(&opd1, &n1, &opd2, &n2, false); if (s) return s; bc_num_init_DEF_SIZE(&res.d.n); @@ -5795,7 +5801,7 @@ static void bc_program_printString(const char *str) } } -static BcStatus bc_program_print(char inst, size_t idx) +static BC_STATUS zbc_program_print(char inst, size_t idx) { BcStatus s; BcResult *r; @@ -5803,15 +5809,15 @@ static BcStatus bc_program_print(char inst, size_t idx) bool pop = inst != BC_INST_PRINT; if (!BC_PROG_STACK(&G.prog.results, idx + 1)) - return bc_error_stack_has_too_few_elements(); + RETURN_STATUS(bc_error_stack_has_too_few_elements()); r = bc_vec_item_rev(&G.prog.results, idx); num = NULL; // is this NULL necessary? - s = bc_program_num(r, &num, false); - if (s) return s; + s = zbc_program_num(r, &num, false); + if (s) RETURN_STATUS(s); if (BC_PROG_NUM(r, num)) { - s = bc_num_print(num, !pop); + s = zbc_num_print(num, !pop); if (!s) bc_num_copy(&G.prog.last, num); } else { @@ -5837,20 +5843,20 @@ static BcStatus bc_program_print(char inst, size_t idx) if (!s && pop) bc_vec_pop(&G.prog.results); - return s; + RETURN_STATUS(s); } #if ERRORS_ARE_FATAL -# define bc_program_print(...) (bc_program_print(__VA_ARGS__), BC_STATUS_SUCCESS) +# define zbc_program_print(...) (zbc_program_print(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static BcStatus bc_program_negate(void) +static BC_STATUS zbc_program_negate(void) { BcStatus s; BcResult res, *ptr; BcNum *num = NULL; - s = bc_program_prep(&ptr, &num); - if (s) return s; + s = zbc_program_prep(&ptr, &num); + if (s) RETURN_STATUS(s); bc_num_init(&res.d.n, num->len); bc_num_copy(&res.d.n, num); @@ -5858,10 +5864,10 @@ static BcStatus bc_program_negate(void) bc_program_retire(&res, BC_RESULT_TEMP); - return s; + RETURN_STATUS(s); } #if ERRORS_ARE_FATAL -# define bc_program_negate(...) (bc_program_negate(__VA_ARGS__), BC_STATUS_SUCCESS) +# define zbc_program_negate(...) (zbc_program_negate(__VA_ARGS__), BC_STATUS_SUCCESS) #endif static BcStatus bc_program_logical(char inst) @@ -5872,7 +5878,7 @@ static BcStatus bc_program_logical(char inst) bool cond = 0; ssize_t cmp; - s = bc_program_binOpPrep(&opd1, &n1, &opd2, &n2, false); + s = zbc_program_binOpPrep(&opd1, &n1, &opd2, &n2, false); if (s) return s; bc_num_init_DEF_SIZE(&res.d.n); @@ -5932,7 +5938,7 @@ static BcStatus bc_program_logical(char inst) } #if ENABLE_DC -static BcStatus bc_program_assignStr(BcResult *r, BcVec *v, +static BC_STATUS zbc_program_assignStr(BcResult *r, BcVec *v, bool push) { BcNum n2; @@ -5944,7 +5950,7 @@ static BcStatus bc_program_assignStr(BcResult *r, BcVec *v, if (!push) { if (!BC_PROG_STACK(&G.prog.results, 2)) - return bc_error_stack_has_too_few_elements(); + RETURN_STATUS(bc_error_stack_has_too_few_elements()); bc_vec_pop(v); bc_vec_pop(&G.prog.results); } @@ -5954,14 +5960,14 @@ static BcStatus bc_program_assignStr(BcResult *r, BcVec *v, bc_vec_push(&G.prog.results, &res); bc_vec_push(v, &n2); - return BC_STATUS_SUCCESS; + RETURN_STATUS(BC_STATUS_SUCCESS); } #if ERRORS_ARE_FATAL -# define bc_program_assignStr(...) (bc_program_assignStr(__VA_ARGS__), BC_STATUS_SUCCESS) +# define zbc_program_assignStr(...) (zbc_program_assignStr(__VA_ARGS__), BC_STATUS_SUCCESS) #endif #endif // ENABLE_DC -static BcStatus bc_program_copyToVar(char *name, bool var) +static BC_STATUS zbc_program_copyToVar(char *name, bool var) { BcStatus s; BcResult *ptr, r; @@ -5969,21 +5975,22 @@ static BcStatus bc_program_copyToVar(char *name, bool var) BcNum *n; if (!BC_PROG_STACK(&G.prog.results, 1)) - return bc_error_stack_has_too_few_elements(); + RETURN_STATUS(bc_error_stack_has_too_few_elements()); ptr = bc_vec_top(&G.prog.results); if ((ptr->t == BC_RESULT_ARRAY) != !var) - return bc_error_variable_is_wrong_type(); + RETURN_STATUS(bc_error_variable_is_wrong_type()); v = bc_program_search(name, var); #if ENABLE_DC if (ptr->t == BC_RESULT_STR && !var) - return bc_error_variable_is_wrong_type(); - if (ptr->t == BC_RESULT_STR) return bc_program_assignStr(ptr, v, true); + RETURN_STATUS(bc_error_variable_is_wrong_type()); + if (ptr->t == BC_RESULT_STR) + RETURN_STATUS(zbc_program_assignStr(ptr, v, true)); #endif - s = bc_program_num(ptr, &n, false); - if (s) return s; + s = zbc_program_num(ptr, &n, false); + if (s) RETURN_STATUS(s); // Do this once more to make sure that pointers were not invalidated. v = bc_program_search(name, var); @@ -6000,10 +6007,10 @@ static BcStatus bc_program_copyToVar(char *name, bool var) bc_vec_push(v, &r.d); bc_vec_pop(&G.prog.results); - return s; + RETURN_STATUS(s); } #if ERRORS_ARE_FATAL -# define bc_program_copyToVar(...) (bc_program_copyToVar(__VA_ARGS__), BC_STATUS_SUCCESS) +# define zbc_program_copyToVar(...) (zbc_program_copyToVar(__VA_ARGS__), BC_STATUS_SUCCESS) #endif static BcStatus bc_program_assign(char inst) @@ -6013,7 +6020,7 @@ static BcStatus bc_program_assign(char inst) BcNum *l = NULL, *r = NULL; bool assign = inst == BC_INST_ASSIGN, ib, sc; - s = bc_program_binOpPrep(&left, &l, &right, &r, assign); + s = zbc_program_binOpPrep(&left, &l, &right, &r, assign); if (s) return s; ib = left->t == BC_RESULT_IBASE; @@ -6029,7 +6036,7 @@ static BcStatus bc_program_assign(char inst) return bc_error_variable_is_wrong_type(); v = bc_program_search(left->d.id.name, true); - return bc_program_assignStr(right, v, false); + return zbc_program_assignStr(right, v, false); } #endif @@ -6066,7 +6073,7 @@ static BcStatus bc_program_assign(char inst) size_t *ptr; unsigned long val, max; - s = bc_num_ulong(l, &val); + s = zbc_num_ulong(l, &val); if (s) return s; s = left->t - BC_RESULT_IBASE; @@ -6149,7 +6156,7 @@ static BcStatus bc_program_pushVar(char *code, size_t *bgn, return s; } -static BcStatus bc_program_pushArray(char *code, size_t *bgn, +static BC_STATUS zbc_program_pushArray(char *code, size_t *bgn, char inst) { BcStatus s = BC_STATUS_SUCCESS; @@ -6167,9 +6174,9 @@ static BcStatus bc_program_pushArray(char *code, size_t *bgn, BcResult *operand; unsigned long temp; - s = bc_program_prep(&operand, &num); + s = zbc_program_prep(&operand, &num); if (s) goto err; - s = bc_num_ulong(num, &temp); + s = zbc_num_ulong(num, &temp); if (s) goto err; if (temp > BC_MAX_DIM) { @@ -6183,22 +6190,22 @@ static BcStatus bc_program_pushArray(char *code, size_t *bgn, err: if (s) free(r.d.id.name); - return s; + RETURN_STATUS(s); } #if ERRORS_ARE_FATAL -# define bc_program_pushArray(...) (bc_program_pushArray(__VA_ARGS__), BC_STATUS_SUCCESS) +# define zbc_program_pushArray(...) (zbc_program_pushArray(__VA_ARGS__), BC_STATUS_SUCCESS) #endif #if ENABLE_BC -static BcStatus bc_program_incdec(char inst) +static BC_STATUS zbc_program_incdec(char inst) { BcStatus s; BcResult *ptr, res, copy; BcNum *num = NULL; char inst2 = inst; - s = bc_program_prep(&ptr, &num); - if (s) return s; + s = zbc_program_prep(&ptr, &num); + if (s) RETURN_STATUS(s); if (inst == BC_INST_INC_POST || inst == BC_INST_DEC_POST) { copy.t = BC_RESULT_TEMP; @@ -6219,13 +6226,13 @@ static BcStatus bc_program_incdec(char inst) bc_vec_push(&G.prog.results, ©); } - return s; + RETURN_STATUS(s); } #if ERRORS_ARE_FATAL -# define bc_program_incdec(...) (bc_program_incdec(__VA_ARGS__), BC_STATUS_SUCCESS) +# define zbc_program_incdec(...) (zbc_program_incdec(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static BcStatus bc_program_call(char *code, size_t *idx) +static BC_STATUS zbc_program_call(char *code, size_t *idx) { BcInstPtr ip; size_t i, nparams = bc_program_index(code, idx); @@ -6239,10 +6246,10 @@ static BcStatus bc_program_call(char *code, size_t *idx) func = bc_program_func(ip.func); if (func->code.len == 0) { - return bc_error("undefined function"); + RETURN_STATUS(bc_error("undefined function")); } if (nparams != func->nparams) { - return bc_error_fmt("function has %u parameters, but called with %u", func->nparams, nparams); + RETURN_STATUS(bc_error_fmt("function has %u parameters, but called with %u", func->nparams, nparams)); } ip.len = G.prog.results.len - nparams; @@ -6253,10 +6260,10 @@ static BcStatus bc_program_call(char *code, size_t *idx) arg = bc_vec_top(&G.prog.results); if ((!a->idx) != (arg->t == BC_RESULT_ARRAY) || arg->t == BC_RESULT_STR) - return bc_error_variable_is_wrong_type(); + RETURN_STATUS(bc_error_variable_is_wrong_type()); - s = bc_program_copyToVar(a->name, a->idx); - if (s) return s; + s = zbc_program_copyToVar(a->name, a->idx); + if (s) RETURN_STATUS(s); } for (; i < func->autos.len; ++i) { @@ -6277,13 +6284,13 @@ static BcStatus bc_program_call(char *code, size_t *idx) bc_vec_push(&G.prog.stack, &ip); - return BC_STATUS_SUCCESS; + RETURN_STATUS(BC_STATUS_SUCCESS); } #if ERRORS_ARE_FATAL -# define bc_program_call(...) (bc_program_call(__VA_ARGS__), BC_STATUS_SUCCESS) +# define zbc_program_call(...) (zbc_program_call(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static BcStatus bc_program_return(char inst) +static BC_STATUS zbc_program_return(char inst) { BcResult res; BcFunc *f; @@ -6291,7 +6298,7 @@ static BcStatus bc_program_return(char inst) BcInstPtr *ip = bc_vec_top(&G.prog.stack); if (!BC_PROG_STACK(&G.prog.results, ip->len + inst == BC_INST_RET)) - return bc_error_stack_has_too_few_elements(); + RETURN_STATUS(bc_error_stack_has_too_few_elements()); f = bc_program_func(ip->func); res.t = BC_RESULT_TEMP; @@ -6301,8 +6308,8 @@ static BcStatus bc_program_return(char inst) BcNum *num; BcResult *operand = bc_vec_top(&G.prog.results); - s = bc_program_num(operand, &num, false); - if (s) return s; + s = zbc_program_num(operand, &num, false); + if (s) RETURN_STATUS(s); bc_num_init(&res.d.n, num->len); bc_num_copy(&res.d.n, num); } @@ -6324,10 +6331,10 @@ static BcStatus bc_program_return(char inst) bc_vec_push(&G.prog.results, &res); bc_vec_pop(&G.prog.stack); - return BC_STATUS_SUCCESS; + RETURN_STATUS(BC_STATUS_SUCCESS); } #if ERRORS_ARE_FATAL -# define bc_program_return(...) (bc_program_return(__VA_ARGS__), BC_STATUS_SUCCESS) +# define zbc_program_return(...) (zbc_program_return(__VA_ARGS__), BC_STATUS_SUCCESS) #endif #endif // ENABLE_BC @@ -6361,7 +6368,7 @@ static BcStatus bc_program_builtin(char inst) return bc_error_stack_has_too_few_elements(); opnd = bc_vec_top(&G.prog.results); - s = bc_program_num(opnd, &num, false); + s = zbc_program_num(opnd, &num, false); if (s) return s; #if ENABLE_DC @@ -6403,7 +6410,7 @@ static BcStatus bc_program_divmod(void) BcResult *opd1, *opd2, res, res2; BcNum *n1, *n2 = NULL; - s = bc_program_binOpPrep(&opd1, &n1, &opd2, &n2, false); + s = zbc_program_binOpPrep(&opd1, &n1, &opd2, &n2, false); if (s) return s; bc_num_init_DEF_SIZE(&res.d.n); @@ -6432,11 +6439,11 @@ static BcStatus bc_program_modexp(void) if (!BC_PROG_STACK(&G.prog.results, 3)) return bc_error_stack_has_too_few_elements(); - s = bc_program_binOpPrep(&r2, &n2, &r3, &n3, false); + s = zbc_program_binOpPrep(&r2, &n2, &r3, &n3, false); if (s) return s; r1 = bc_vec_item_rev(&G.prog.results, 2); - s = bc_program_num(r1, &n1, false); + s = zbc_program_num(r1, &n1, false); if (s) return s; if (!BC_PROG_NUM(r1, n1)) return bc_error_variable_is_wrong_type(); @@ -6445,12 +6452,12 @@ static BcStatus bc_program_modexp(void) if (r1->t == BC_RESULT_VAR || r1->t == BC_RESULT_ARRAY_ELEM) { if (r1->t == r2->t) { - s = bc_program_num(r2, &n2, false); + s = zbc_program_num(r2, &n2, false); if (s) return s; } if (r1->t == r3->t) { - s = bc_program_num(r3, &n3, false); + s = zbc_program_num(r3, &n3, false); if (s) return s; } } @@ -6495,7 +6502,7 @@ static BcStatus bc_program_asciify(void) r = bc_vec_top(&G.prog.results); num = NULL; // TODO: is this NULL needed? - s = bc_program_num(r, &num, false); + s = zbc_program_num(r, &num, false); if (s) return s; if (BC_PROG_NUM(r, num)) { @@ -6506,7 +6513,7 @@ static BcStatus bc_program_asciify(void) s = bc_num_mod(&n, &G.prog.strmb, &n, 0); if (s) goto num_err; - s = bc_num_ulong(&n, &val); + s = zbc_num_ulong(&n, &val); if (s) goto num_err; c = (char) val; @@ -6552,7 +6559,7 @@ num_err: return s; } -static BcStatus bc_program_printStream(void) +static BC_STATUS zbc_program_printStream(void) { BcStatus s; BcResult *r; @@ -6561,52 +6568,52 @@ static BcStatus bc_program_printStream(void) char *str; if (!BC_PROG_STACK(&G.prog.results, 1)) - return bc_error_stack_has_too_few_elements(); + RETURN_STATUS(bc_error_stack_has_too_few_elements()); r = bc_vec_top(&G.prog.results); - s = bc_program_num(r, &n, false); - if (s) return s; + s = zbc_program_num(r, &n, false); + if (s) RETURN_STATUS(s); if (BC_PROG_NUM(r, n)) - s = bc_num_stream(n, &G.prog.strmb); + s = zbc_num_stream(n, &G.prog.strmb); else { idx = (r->t == BC_RESULT_STR) ? r->d.id.idx : n->rdx; str = *bc_program_str(idx); printf("%s", str); } - return s; + RETURN_STATUS(s); } #if ERRORS_ARE_FATAL -# define bc_program_printStream(...) (bc_program_printStream(__VA_ARGS__), BC_STATUS_SUCCESS) +# define zbc_program_printStream(...) (zbc_program_printStream(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static BcStatus bc_program_nquit(void) +static BC_STATUS zbc_program_nquit(void) { BcStatus s; BcResult *opnd; BcNum *num = NULL; unsigned long val; - s = bc_program_prep(&opnd, &num); - if (s) return s; - s = bc_num_ulong(num, &val); - if (s) return s; + s = zbc_program_prep(&opnd, &num); + if (s) RETURN_STATUS(s); + s = zbc_num_ulong(num, &val); + if (s) RETURN_STATUS(s); bc_vec_pop(&G.prog.results); if (G.prog.stack.len < val) - return bc_error_stack_has_too_few_elements(); + RETURN_STATUS(bc_error_stack_has_too_few_elements()); if (G.prog.stack.len == val) { QUIT_OR_RETURN_TO_MAIN; } bc_vec_npop(&G.prog.stack, val); - return s; + RETURN_STATUS(s); } #if ERRORS_ARE_FATAL -# define bc_program_nquit(...) (bc_program_nquit(__VA_ARGS__), BC_STATUS_SUCCESS) +# define zbc_program_nquit(...) (zbc_program_nquit(__VA_ARGS__), BC_STATUS_SUCCESS) #endif static BcStatus bc_program_execStr(char *code, size_t *bgn, @@ -6665,7 +6672,7 @@ static BcStatus bc_program_execStr(char *code, size_t *bgn, sidx = r->d.id.idx; } else if (r->t == BC_RESULT_VAR) { BcNum *n; - s = bc_program_num(r, &n, false); + s = zbc_program_num(r, &n, false); if (s || !BC_PROG_STR(n)) goto exit; sidx = n->rdx; } else @@ -6776,7 +6783,7 @@ static BcStatus bc_program_exec(void) switch (inst) { #if ENABLE_BC case BC_INST_JUMP_ZERO: - s = bc_program_prep(&ptr, &num); + s = zbc_program_prep(&ptr, &num); if (s) return s; cond = !bc_num_cmp(num, &G.prog.zero); bc_vec_pop(&G.prog.results); @@ -6789,20 +6796,20 @@ static BcStatus bc_program_exec(void) break; } case BC_INST_CALL: - s = bc_program_call(code, &ip->idx); + s = zbc_program_call(code, &ip->idx); break; case BC_INST_INC_PRE: case BC_INST_DEC_PRE: case BC_INST_INC_POST: case BC_INST_DEC_POST: - s = bc_program_incdec(inst); + s = zbc_program_incdec(inst); break; case BC_INST_HALT: QUIT_OR_RETURN_TO_MAIN; break; case BC_INST_RET: case BC_INST_RET0: - s = bc_program_return(inst); + s = zbc_program_return(inst); break; case BC_INST_BOOL_OR: case BC_INST_BOOL_AND: @@ -6823,7 +6830,7 @@ static BcStatus bc_program_exec(void) break; case BC_INST_ARRAY_ELEM: case BC_INST_ARRAY: - s = bc_program_pushArray(code, &ip->idx, inst); + s = zbc_program_pushArray(code, &ip->idx, inst); break; case BC_INST_LAST: r.t = BC_RESULT_LAST; @@ -6856,7 +6863,7 @@ static BcStatus bc_program_exec(void) case BC_INST_PRINT: case BC_INST_PRINT_POP: case BC_INST_PRINT_STR: - s = bc_program_print(inst, 0); + s = zbc_program_print(inst, 0); break; case BC_INST_STR: r.t = BC_RESULT_STR; @@ -6872,7 +6879,7 @@ static BcStatus bc_program_exec(void) s = bc_program_op(inst); break; case BC_INST_BOOL_NOT: - s = bc_program_prep(&ptr, &num); + s = zbc_program_prep(&ptr, &num); if (s) return s; bc_num_init_DEF_SIZE(&r.d.n); if (!bc_num_cmp(num, &G.prog.zero)) @@ -6881,7 +6888,7 @@ static BcStatus bc_program_exec(void) bc_program_retire(&r, BC_RESULT_TEMP); break; case BC_INST_NEG: - s = bc_program_negate(); + s = zbc_program_negate(); break; #if ENABLE_BC case BC_INST_ASSIGN_POWER: @@ -6909,7 +6916,7 @@ static BcStatus bc_program_exec(void) case BC_INST_PRINT_STACK: { size_t idx; for (idx = 0; idx < G.prog.results.len; ++idx) { - s = bc_program_print(BC_INST_PRINT, idx); + s = zbc_program_print(BC_INST_PRINT, idx); if (s) break; } break; @@ -6942,7 +6949,7 @@ static BcStatus bc_program_exec(void) s = bc_program_asciify(); break; case BC_INST_PRINT_STREAM: - s = bc_program_printStream(); + s = zbc_program_printStream(); break; case BC_INST_LOAD: case BC_INST_PUSH_VAR: { @@ -6952,7 +6959,7 @@ static BcStatus bc_program_exec(void) } case BC_INST_PUSH_TO_VAR: { char *name = bc_program_name(code, &ip->idx); - s = bc_program_copyToVar(name, true); + s = zbc_program_copyToVar(name, true); free(name); break; } @@ -6962,7 +6969,7 @@ static BcStatus bc_program_exec(void) bc_vec_npop(&G.prog.stack, 2); break; case BC_INST_NQUIT: - s = bc_program_nquit(); + s = zbc_program_nquit(); break; #endif // ENABLE_DC } -- cgit v1.2.3-55-g6feb From b402ff844c75bf6e22842d791d261c6f52c6e157 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 11 Dec 2018 15:45:15 +0100 Subject: bc: make bc_program_pushVar "z-function" function old new delta bc_program_pushVar 200 198 -2 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 4e5ba804f..6ab3a4252 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -186,7 +186,7 @@ typedef enum BcStatus { BC_STATUS_SUCCESS = 0, BC_STATUS_FAILURE = 1, - BC_STATUS_PARSE_EMPTY_EXP = 2, // bc_parse_expr() uses this + BC_STATUS_PARSE_EMPTY_EXP = 2, // bc_parse_expr_empty_ok() uses this BC_STATUS_EOF = 3, // bc_vm_stdin() uses this } BcStatus; @@ -1299,6 +1299,7 @@ static int push_input_byte(BcVec *vec, char c) return 0; } +// This is not a "z" function: can also return BC_STATUS_EOF static BcStatus bc_read_line(BcVec *vec) { BcStatus s; @@ -4906,6 +4907,7 @@ static FAST_FUNC BcStatus bc_parse_parse(BcParse *p) return s; } +// This is not a "z" function: can also return BC_STATUS_PARSE_EMPTY_EXP static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext next) { BcStatus s = BC_STATUS_SUCCESS; @@ -6109,10 +6111,9 @@ static BcStatus bc_program_assign(char inst) bc_program_pushVar(code, bgn) // for bc, 'pop' and 'copy' are always false #endif -static BcStatus bc_program_pushVar(char *code, size_t *bgn, +static BC_STATUS bc_program_pushVar(char *code, size_t *bgn, bool pop, bool copy) { - BcStatus s = BC_STATUS_SUCCESS; BcResult r; char *name = bc_program_name(code, bgn); @@ -6128,7 +6129,7 @@ static BcStatus bc_program_pushVar(char *code, size_t *bgn, if (!BC_PROG_STACK(v, 2 - copy)) { free(name); - return bc_error_stack_has_too_few_elements(); + RETURN_STATUS(bc_error_stack_has_too_few_elements()); } free(name); @@ -6153,8 +6154,13 @@ static BcStatus bc_program_pushVar(char *code, size_t *bgn, bc_vec_push(&G.prog.results, &r); - return s; + RETURN_STATUS(BC_STATUS_SUCCESS); } +#if ERRORS_ARE_FATAL +# define zbc_program_pushVar(...) (bc_program_pushVar(__VA_ARGS__), BC_STATUS_SUCCESS) +#else +# define zbc_program_pushVar(...) bc_program_pushVar(__VA_ARGS__) +#endif static BC_STATUS zbc_program_pushArray(char *code, size_t *bgn, char inst) @@ -6826,7 +6832,7 @@ static BcStatus bc_program_exec(void) s = bc_program_read(); break; case BC_INST_VAR: - s = bc_program_pushVar(code, &ip->idx, false, false); + s = zbc_program_pushVar(code, &ip->idx, false, false); break; case BC_INST_ARRAY_ELEM: case BC_INST_ARRAY: @@ -6954,7 +6960,7 @@ static BcStatus bc_program_exec(void) case BC_INST_LOAD: case BC_INST_PUSH_VAR: { bool copy = inst == BC_INST_LOAD; - s = bc_program_pushVar(code, &ip->idx, true, copy); + s = zbc_program_pushVar(code, &ip->idx, true, copy); break; } case BC_INST_PUSH_TO_VAR: { -- cgit v1.2.3-55-g6feb From c355c4a7d620477cc2d7e05b0616976eb2120d17 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 11 Dec 2018 17:36:21 +0100 Subject: bc: code shrink in zbc_lex_number() function old new delta zbc_lex_number 279 190 -89 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 64 +++++++++++++++++++++++++++++++++------------------------- 1 file changed, 36 insertions(+), 28 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 6ab3a4252..5a4c92a1c 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -2976,29 +2976,40 @@ static void bc_lex_whitespace(BcLex *l) static BC_STATUS zbc_lex_number(BcLex *l, char start) { const char *buf = l->buf + l->i; - size_t len, hits = 0, bslashes = 0, i = 0, j; - char c = buf[i]; - bool last_pt, pt = start == '.'; + size_t len, bslashes, i, ccnt; + bool pt; - last_pt = pt; + pt = (start == '.'); l->t.t = BC_LEX_NUMBER; - - while (c != 0 && (isdigit(c) || (c >= 'A' && c <= 'F') || - (c == '.' && !pt) || (c == '\\' && buf[i + 1] == '\n'))) - { - if (c != '\\') { - last_pt = c == '.'; - pt = pt || last_pt; + bslashes = 0; + ccnt = i = 0; + for (;;) { + char c = buf[i]; + if (c == '\0') + break; + if (c == '\\' && buf[i + 1] == '\n') { + i += 2; + bslashes++; + continue; } - else { - ++i; - bslashes += 1; + if (!isdigit(c) && (c < 'A' || c > 'F')) { + if (c != '.') break; + // if '.' was already seen, stop on second one: + if (pt) break; + pt = 1; } - - c = buf[++i]; + // buf[i] is one of "0-9A-F." + i++; + if (c != '.') + ccnt = i; } + //i is buf[i] index of the first not-yet-parsed char + l->i += i; + + //ccnt is the number of chars in the number string, excluding possible + //trailing "." and possible following trailing "\"(s). + len = ccnt - bslashes * 2 + 1; // +1 byte for NUL termination - len = i + !last_pt - bslashes * 2; // This check makes sense only if size_t is (much) larger than BC_MAX_NUM. if (SIZE_MAX > (BC_MAX_NUM | 0xff)) { if (len > BC_MAX_NUM) @@ -3006,26 +3017,23 @@ static BC_STATUS zbc_lex_number(BcLex *l, char start) } bc_vec_pop_all(&l->t.v); - bc_vec_expand(&l->t.v, len + 1); + bc_vec_expand(&l->t.v, 1 + len); bc_vec_push(&l->t.v, &start); - for (buf -= 1, j = 1; j < len + hits * 2; ++j) { - - c = buf[j]; - + while (ccnt != 0) { // If we have hit a backslash, skip it. We don't have // to check for a newline because it's guaranteed. - if (hits < bslashes && c == '\\') { - ++hits; - ++j; + if (*buf == '\\') { + buf += 2; + ccnt -= 2; continue; } - - bc_vec_push(&l->t.v, &c); + bc_vec_push(&l->t.v, buf); + buf++; + ccnt--; } bc_vec_pushZeroByte(&l->t.v); - l->i += i; RETURN_STATUS(BC_STATUS_SUCCESS); } -- cgit v1.2.3-55-g6feb From c2d15dff42d3f8a805d5437bb5063d3131f800c4 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 11 Dec 2018 17:56:09 +0100 Subject: bc: move declarations around, no code changes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 78 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 5a4c92a1c..6fb6c8139 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -221,20 +221,6 @@ typedef struct BcNum { #define BC_NUM_KARATSUBA_LEN (32) -typedef void (*BcNumDigitOp)(size_t, size_t, bool) FAST_FUNC; - -typedef BcStatus (*BcNumBinaryOp)(BcNum *, BcNum *, BcNum *, size_t) FAST_FUNC; - -static BcStatus bc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; -static BcStatus bc_num_sub(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; -static BcStatus bc_num_mul(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; -static BcStatus bc_num_div(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; -static BcStatus bc_num_mod(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; -static BcStatus bc_num_pow(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; -static BcStatus bc_num_sqrt(BcNum *a, BcNum *b, size_t scale); -static BcStatus bc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d, - size_t scale); - typedef enum BcInst { #if ENABLE_BC @@ -931,6 +917,45 @@ dc_parse_insts[] = { }; #endif // ENABLE_DC +// In configurations where errors abort instead of propagating error +// return code up the call chain, functions returning BC_STATUS +// actually don't return anything, they always succeed and return "void". +// A macro wrapper is provided, which makes this statement work: +// s = zbc_func(...) +// and makes it visible to the compiler that s is always zero, +// allowing compiler to optimize dead code after the statement. +// +// To make code more readable, each such function has a "z" +// ("always returning zero") prefix, i.e. zbc_foo or zdc_foo. +// +#if ENABLE_FEATURE_BC_SIGNALS || ENABLE_FEATURE_CLEAN_UP +# define ERRORFUNC /*nothing*/ +# define ERROR_RETURN(a) a +# define ERRORS_ARE_FATAL 0 +# define BC_STATUS BcStatus +# define RETURN_STATUS(v) return (v) +#else +# define ERRORFUNC NORETURN +# define ERROR_RETURN(a) /*nothing*/ +# define ERRORS_ARE_FATAL 1 +# define BC_STATUS void +# define RETURN_STATUS(v) do { ((void)(v)); return; } while (0) +#endif + +typedef void (*BcNumDigitOp)(size_t, size_t, bool) FAST_FUNC; + +typedef BcStatus (*BcNumBinaryOp)(BcNum *, BcNum *, BcNum *, size_t) FAST_FUNC; + +static BcStatus bc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; +static BcStatus bc_num_sub(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; +static BcStatus bc_num_mul(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; +static BcStatus bc_num_div(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; +static BcStatus bc_num_mod(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; +static BcStatus bc_num_pow(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; +static BcStatus bc_num_sqrt(BcNum *a, BcNum *b, size_t scale); +static BcStatus bc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d, + size_t scale); + static const BcNumBinaryOp bc_program_ops[] = { bc_num_pow, bc_num_mul, bc_num_div, bc_num_mod, bc_num_add, bc_num_sub, }; @@ -976,31 +1001,6 @@ static void bc_verror_msg(const char *fmt, va_list p) } } -// In configurations where errors abort instead of propagating error -// return code up the call chain, functions returning BC_STATUS -// actually don't return anything, they always succeed and return "void". -// A macro wrapper is provided, which makes this statement work: -// s = zbc_func(...) -// and makes it visible to the compiler that s is always zero, -// allowing compiler to optimize dead code after the statement. -// -// To make code more readable, each such function has a "z" -// ("always returning zero") prefix, i.e. zbc_foo or zdc_foo. -// -#if ENABLE_FEATURE_BC_SIGNALS || ENABLE_FEATURE_CLEAN_UP -# define ERRORFUNC /*nothing*/ -# define ERROR_RETURN(a) a -# define ERRORS_ARE_FATAL 0 -# define BC_STATUS BcStatus -# define RETURN_STATUS(v) return (v) -#else -# define ERRORFUNC NORETURN -# define ERROR_RETURN(a) /*nothing*/ -# define ERRORS_ARE_FATAL 1 -# define BC_STATUS void -# define RETURN_STATUS(v) do { ((void)(v)); return; } while (0) -#endif - static NOINLINE ERRORFUNC int bc_error_fmt(const char *fmt, ...) { va_list p; -- cgit v1.2.3-55-g6feb From 1aeacefbb33f2590c875c9a3704e485a4a643898 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 11 Dec 2018 19:12:13 +0100 Subject: bc: rename arithmetic calc functions to "z" functions, no code changes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 177 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 88 insertions(+), 89 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 6fb6c8139..3ab0bf3b7 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -946,18 +946,17 @@ typedef void (*BcNumDigitOp)(size_t, size_t, bool) FAST_FUNC; typedef BcStatus (*BcNumBinaryOp)(BcNum *, BcNum *, BcNum *, size_t) FAST_FUNC; -static BcStatus bc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; -static BcStatus bc_num_sub(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; -static BcStatus bc_num_mul(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; -static BcStatus bc_num_div(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; -static BcStatus bc_num_mod(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; -static BcStatus bc_num_pow(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; -static BcStatus bc_num_sqrt(BcNum *a, BcNum *b, size_t scale); -static BcStatus bc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d, +static BcStatus zbc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; +static BcStatus zbc_num_sub(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; +static BcStatus zbc_num_mul(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; +static BcStatus zbc_num_div(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; +static BcStatus zbc_num_mod(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; +static BcStatus zbc_num_pow(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; +static BcStatus zbc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d, size_t scale); -static const BcNumBinaryOp bc_program_ops[] = { - bc_num_pow, bc_num_mul, bc_num_div, bc_num_mod, bc_num_add, bc_num_sub, +static const BcNumBinaryOp zbc_program_ops[] = { + zbc_num_pow, zbc_num_mul, zbc_num_div, zbc_num_mod, zbc_num_add, zbc_num_sub, }; static void fflush_and_check(void) @@ -1693,7 +1692,7 @@ static BC_STATUS zbc_num_shift(BcNum *n, size_t places) # define zbc_num_shift(...) (zbc_num_shift(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static BcStatus bc_num_inv(BcNum *a, BcNum *b, size_t scale) +static BcStatus zbc_num_inv(BcNum *a, BcNum *b, size_t scale) { BcNum one; BcDig num[2]; @@ -1702,10 +1701,10 @@ static BcStatus bc_num_inv(BcNum *a, BcNum *b, size_t scale) one.num = num; bc_num_one(&one); - return bc_num_div(&one, a, b, scale); + return zbc_num_div(&one, a, b, scale); } -static FAST_FUNC BcStatus bc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) +static FAST_FUNC BcStatus zbc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) { BcDig *ptr, *ptr_a, *ptr_b, *ptr_c; size_t i, max, min_rdx, min_int, diff, a_int, b_int; @@ -1773,10 +1772,10 @@ static FAST_FUNC BcStatus bc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_t if (carry != 0) c->num[c->len++] = (BcDig) carry; - return BC_STATUS_SUCCESS; // can't make void, see bc_num_binary() + return BC_STATUS_SUCCESS; // can't make void, see zbc_num_binary() } -static FAST_FUNC BcStatus bc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) +static FAST_FUNC BcStatus zbc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) { ssize_t cmp; BcNum *minuend, *subtrahend; @@ -1835,10 +1834,10 @@ static FAST_FUNC BcStatus bc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size_t bc_num_clean(c); - return BC_STATUS_SUCCESS; // can't make void, see bc_num_binary() + return BC_STATUS_SUCCESS; // can't make void, see zbc_num_binary() } -static FAST_FUNC BcStatus bc_num_k(BcNum *restrict a, BcNum *restrict b, +static FAST_FUNC BcStatus zbc_num_k(BcNum *restrict a, BcNum *restrict b, BcNum *restrict c) { BcStatus s; @@ -1905,30 +1904,30 @@ static FAST_FUNC BcStatus bc_num_k(BcNum *restrict a, BcNum *restrict b, bc_num_split(a, max2, &l1, &h1); bc_num_split(b, max2, &l2, &h2); - s = bc_num_add(&h1, &l1, &m1, 0); + s = zbc_num_add(&h1, &l1, &m1, 0); if (s) goto err; - s = bc_num_add(&h2, &l2, &m2, 0); + s = zbc_num_add(&h2, &l2, &m2, 0); if (s) goto err; - s = bc_num_k(&h1, &h2, &z0); + s = zbc_num_k(&h1, &h2, &z0); if (s) goto err; - s = bc_num_k(&m1, &m2, &z1); + s = zbc_num_k(&m1, &m2, &z1); if (s) goto err; - s = bc_num_k(&l1, &l2, &z2); + s = zbc_num_k(&l1, &l2, &z2); if (s) goto err; - s = bc_num_sub(&z1, &z0, &temp, 0); + s = zbc_num_sub(&z1, &z0, &temp, 0); if (s) goto err; - s = bc_num_sub(&temp, &z2, &z1, 0); + s = zbc_num_sub(&temp, &z2, &z1, 0); if (s) goto err; s = zbc_num_shift(&z0, max2 * 2); if (s) goto err; s = zbc_num_shift(&z1, max2); if (s) goto err; - s = bc_num_add(&z0, &z1, &temp, 0); + s = zbc_num_add(&z0, &z1, &temp, 0); if (s) goto err; - s = bc_num_add(&temp, &z2, c, 0); + s = zbc_num_add(&temp, &z2, c, 0); err: bc_num_free(&temp); @@ -1944,7 +1943,7 @@ err: return s; } -static FAST_FUNC BcStatus bc_num_m(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) +static FAST_FUNC BcStatus zbc_num_m(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) { BcStatus s; BcNum cpa, cpb; @@ -1966,7 +1965,7 @@ static FAST_FUNC BcStatus bc_num_m(BcNum *a, BcNum *b, BcNum *restrict c, size_t if (s) goto err; s = zbc_num_shift(&cpb, maxrdx); if (s) goto err; - s = bc_num_k(&cpa, &cpb, c); + s = zbc_num_k(&cpa, &cpb, c); if (s) goto err; maxrdx += scale; @@ -1986,7 +1985,7 @@ err: return s; } -static FAST_FUNC BcStatus bc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) +static FAST_FUNC BcStatus zbc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) { BcStatus s = BC_STATUS_SUCCESS; BcDig *n, *p, q; @@ -2058,7 +2057,7 @@ static FAST_FUNC BcStatus bc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_t return s; } -static FAST_FUNC BcStatus bc_num_r(BcNum *a, BcNum *b, BcNum *restrict c, +static FAST_FUNC BcStatus zbc_num_r(BcNum *a, BcNum *b, BcNum *restrict c, BcNum *restrict d, size_t scale, size_t ts) { BcStatus s; @@ -2074,14 +2073,14 @@ static FAST_FUNC BcStatus bc_num_r(BcNum *a, BcNum *b, BcNum *restrict c, } bc_num_init(&temp, d->cap); - s = bc_num_d(a, b, c, scale); + s = zbc_num_d(a, b, c, scale); if (s) goto err; if (scale != 0) scale = ts; - s = bc_num_m(c, b, &temp, scale); + s = zbc_num_m(c, b, &temp, scale); if (s) goto err; - s = bc_num_sub(a, &temp, d, scale); + s = zbc_num_sub(a, &temp, d, scale); if (s) goto err; if (ts > d->rdx && d->len) bc_num_extend(d, ts - d->rdx); @@ -2095,20 +2094,20 @@ err: return s; } -static FAST_FUNC BcStatus bc_num_rem(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) +static FAST_FUNC BcStatus zbc_num_rem(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) { BcStatus s; BcNum c1; size_t ts = BC_MAX(scale + b->rdx, a->rdx), len = BC_NUM_MREQ(a, b, ts); bc_num_init(&c1, len); - s = bc_num_r(a, b, &c1, c, scale, ts); + s = zbc_num_r(a, b, &c1, c, scale, ts); bc_num_free(&c1); return s; } -static FAST_FUNC BcStatus bc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) +static FAST_FUNC BcStatus zbc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) { BcStatus s = BC_STATUS_SUCCESS; BcNum copy; @@ -2130,7 +2129,7 @@ static FAST_FUNC BcStatus bc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t if (!b->neg) bc_num_copy(c, a); else - s = bc_num_inv(a, c, scale); + s = zbc_num_inv(a, c, scale); return s; } @@ -2154,9 +2153,9 @@ static FAST_FUNC BcStatus bc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t for (powrdx = a->rdx; !(pow & 1); pow >>= 1) { powrdx <<= 1; - s = bc_num_mul(©, ©, ©, powrdx); + s = zbc_num_mul(©, ©, ©, powrdx); if (s) goto err; - // Not needed: bc_num_mul() has a check for ^C: + // Not needed: zbc_num_mul() has a check for ^C: //if (G_interrupt) { // s = BC_STATUS_FAILURE; // goto err; @@ -2168,15 +2167,15 @@ static FAST_FUNC BcStatus bc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t for (resrdx = powrdx, pow >>= 1; pow != 0; pow >>= 1) { powrdx <<= 1; - s = bc_num_mul(©, ©, ©, powrdx); + s = zbc_num_mul(©, ©, ©, powrdx); if (s) goto err; if (pow & 1) { resrdx += powrdx; - s = bc_num_mul(c, ©, c, resrdx); + s = zbc_num_mul(c, ©, c, resrdx); if (s) goto err; } - // Not needed: bc_num_mul() has a check for ^C: + // Not needed: zbc_num_mul() has a check for ^C: //if (G_interrupt) { // s = BC_STATUS_FAILURE; // goto err; @@ -2184,7 +2183,7 @@ static FAST_FUNC BcStatus bc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t } if (neg) { - s = bc_num_inv(c, c, scale); + s = zbc_num_inv(c, c, scale); if (s) goto err; } @@ -2199,7 +2198,7 @@ err: return s; } -static BcStatus bc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale, +static BcStatus zbc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale, BcNumBinaryOp op, size_t req) { BcStatus s; @@ -2322,11 +2321,11 @@ static BC_STATUS zbc_num_printNum(BcNum *n, BcNum *base, size_t width, BcNumDigi bc_num_one(&frac_len); bc_num_truncate(&intp, intp.rdx); - s = bc_num_sub(n, &intp, &fracp, 0); + s = zbc_num_sub(n, &intp, &fracp, 0); if (s) goto err; while (intp.len != 0) { - s = bc_num_divmod(&intp, base, &intp, &digit, 0); + s = zbc_num_divmod(&intp, base, &intp, &digit, 0); if (s) goto err; s = zbc_num_ulong(&digit, &dig); if (s) goto err; @@ -2341,15 +2340,15 @@ static BC_STATUS zbc_num_printNum(BcNum *n, BcNum *base, size_t width, BcNumDigi if (!n->rdx) goto err; for (radix = true; frac_len.len <= n->rdx; radix = false) { - s = bc_num_mul(&fracp, base, &fracp, n->rdx); + s = zbc_num_mul(&fracp, base, &fracp, n->rdx); if (s) goto err; s = zbc_num_ulong(&fracp, &dig); if (s) goto err; bc_num_ulong2num(&intp, dig); - s = bc_num_sub(&fracp, &intp, &fracp, 0); + s = zbc_num_sub(&fracp, &intp, &fracp, 0); if (s) goto err; print(dig, width, radix); - s = bc_num_mul(&frac_len, base, &frac_len, 0); + s = zbc_num_mul(&frac_len, base, &frac_len, 0); if (s) goto err; } @@ -2493,10 +2492,10 @@ static void bc_num_parseBase(BcNum *n, const char *val, BcNum *base) v = (unsigned long) (c <= '9' ? c - '0' : c - 'A' + 10); - s = bc_num_mul(n, base, &mult, 0); + s = zbc_num_mul(n, base, &mult, 0); if (s) goto int_err; bc_num_ulong2num(&temp, v); - s = bc_num_add(&mult, &temp, n, 0); + s = zbc_num_add(&mult, &temp, n, 0); if (s) goto int_err; } @@ -2512,18 +2511,18 @@ static void bc_num_parseBase(BcNum *n, const char *val, BcNum *base) v = (unsigned long) (c <= '9' ? c - '0' : c - 'A' + 10); - s = bc_num_mul(&result, base, &result, 0); + s = zbc_num_mul(&result, base, &result, 0); if (s) goto err; bc_num_ulong2num(&temp, v); - s = bc_num_add(&result, &temp, &result, 0); + s = zbc_num_add(&result, &temp, &result, 0); if (s) goto err; - s = bc_num_mul(&mult, base, &mult, 0); + s = zbc_num_mul(&mult, base, &mult, 0); if (s) goto err; } - s = bc_num_div(&result, &mult, &result, digits); + s = zbc_num_div(&result, &mult, &result, digits); if (s) goto err; - s = bc_num_add(n, &result, n, digits); + s = zbc_num_add(n, &result, n, digits); if (s) goto err; if (n->len != 0) { @@ -2584,44 +2583,44 @@ static BC_STATUS zbc_num_print(BcNum *n, bool newline) # define zbc_num_print(...) (zbc_num_print(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static FAST_FUNC BcStatus bc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale) +static FAST_FUNC BcStatus zbc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale) { - BcNumBinaryOp op = (!a->neg == !b->neg) ? bc_num_a : bc_num_s; + BcNumBinaryOp op = (!a->neg == !b->neg) ? zbc_num_a : zbc_num_s; (void) scale; - return bc_num_binary(a, b, c, false, op, BC_NUM_AREQ(a, b)); + return zbc_num_binary(a, b, c, false, op, BC_NUM_AREQ(a, b)); } -static FAST_FUNC BcStatus bc_num_sub(BcNum *a, BcNum *b, BcNum *c, size_t scale) +static FAST_FUNC BcStatus zbc_num_sub(BcNum *a, BcNum *b, BcNum *c, size_t scale) { - BcNumBinaryOp op = (!a->neg == !b->neg) ? bc_num_s : bc_num_a; + BcNumBinaryOp op = (!a->neg == !b->neg) ? zbc_num_s : zbc_num_a; (void) scale; - return bc_num_binary(a, b, c, true, op, BC_NUM_AREQ(a, b)); + return zbc_num_binary(a, b, c, true, op, BC_NUM_AREQ(a, b)); } -static FAST_FUNC BcStatus bc_num_mul(BcNum *a, BcNum *b, BcNum *c, size_t scale) +static FAST_FUNC BcStatus zbc_num_mul(BcNum *a, BcNum *b, BcNum *c, size_t scale) { size_t req = BC_NUM_MREQ(a, b, scale); - return bc_num_binary(a, b, c, scale, bc_num_m, req); + return zbc_num_binary(a, b, c, scale, zbc_num_m, req); } -static FAST_FUNC BcStatus bc_num_div(BcNum *a, BcNum *b, BcNum *c, size_t scale) +static FAST_FUNC BcStatus zbc_num_div(BcNum *a, BcNum *b, BcNum *c, size_t scale) { size_t req = BC_NUM_MREQ(a, b, scale); - return bc_num_binary(a, b, c, scale, bc_num_d, req); + return zbc_num_binary(a, b, c, scale, zbc_num_d, req); } -static FAST_FUNC BcStatus bc_num_mod(BcNum *a, BcNum *b, BcNum *c, size_t scale) +static FAST_FUNC BcStatus zbc_num_mod(BcNum *a, BcNum *b, BcNum *c, size_t scale) { size_t req = BC_NUM_MREQ(a, b, scale); - return bc_num_binary(a, b, c, scale, bc_num_rem, req); + return zbc_num_binary(a, b, c, scale, zbc_num_rem, req); } -static FAST_FUNC BcStatus bc_num_pow(BcNum *a, BcNum *b, BcNum *c, size_t scale) +static FAST_FUNC BcStatus zbc_num_pow(BcNum *a, BcNum *b, BcNum *c, size_t scale) { - return bc_num_binary(a, b, c, scale, bc_num_p, a->len * b->len + 1); + return zbc_num_binary(a, b, c, scale, zbc_num_p, a->len * b->len + 1); } -static BcStatus bc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale) +static BcStatus zbc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale) { BcStatus s; BcNum num1, num2, half, f, fprime, *x0, *x1, *temp; @@ -2684,11 +2683,11 @@ static BcStatus bc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale) while (cmp != 0 || digs < len) { - s = bc_num_div(a, x0, &f, resrdx); + s = zbc_num_div(a, x0, &f, resrdx); if (s) goto err; - s = bc_num_add(x0, &f, &fprime, resrdx); + s = zbc_num_add(x0, &f, &fprime, resrdx); if (s) goto err; - s = bc_num_mul(&fprime, &half, x1, resrdx); + s = zbc_num_mul(&fprime, &half, x1, resrdx); if (s) goto err; cmp = bc_num_cmp(x1, x0); @@ -2723,7 +2722,7 @@ err: return s; } -static BcStatus bc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d, +static BcStatus zbc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d, size_t scale) { BcStatus s; @@ -2742,7 +2741,7 @@ static BcStatus bc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d, bc_num_expand(c, len); } - s = bc_num_r(ptr_a, b, c, d, scale, ts); + s = zbc_num_r(ptr_a, b, c, d, scale, ts); if (init) bc_num_free(&num2); @@ -2750,7 +2749,7 @@ static BcStatus bc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d, } #if ENABLE_DC -static BcStatus bc_num_modexp(BcNum *a, BcNum *b, BcNum *c, BcNum *restrict d) +static BcStatus zbc_num_modexp(BcNum *a, BcNum *b, BcNum *c, BcNum *restrict d) { BcStatus s; BcNum base, exp, two, temp; @@ -2772,25 +2771,25 @@ static BcStatus bc_num_modexp(BcNum *a, BcNum *b, BcNum *c, BcNum *restrict d) two.num[0] = 2; bc_num_one(d); - s = bc_num_rem(a, c, &base, 0); + s = zbc_num_rem(a, c, &base, 0); if (s) goto err; bc_num_copy(&exp, b); while (exp.len != 0) { - s = bc_num_divmod(&exp, &two, &exp, &temp, 0); + s = zbc_num_divmod(&exp, &two, &exp, &temp, 0); if (s) goto err; if (BC_NUM_ONE(&temp)) { - s = bc_num_mul(d, &base, &temp, 0); + s = zbc_num_mul(d, &base, &temp, 0); if (s) goto err; - s = bc_num_rem(&temp, c, d, 0); + s = zbc_num_rem(&temp, c, d, 0); if (s) goto err; } - s = bc_num_mul(&base, &base, &temp, 0); + s = zbc_num_mul(&base, &base, &temp, 0); if (s) goto err; - s = bc_num_rem(&temp, c, &base, 0); + s = zbc_num_rem(&temp, c, &base, 0); if (s) goto err; } @@ -5631,7 +5630,7 @@ static BcStatus bc_program_op(char inst) if (s) return s; bc_num_init_DEF_SIZE(&res.d.n); - s = bc_program_ops[inst - BC_INST_POWER](n1, n2, &res.d.n, G.prog.scale); + s = zbc_program_ops[inst - BC_INST_POWER](n1, n2, &res.d.n, G.prog.scale); if (s) goto err; bc_program_binOpRetire(&res); @@ -6064,7 +6063,7 @@ static BcStatus bc_program_assign(char inst) if (assign) bc_num_copy(l, r); else - s = bc_program_ops[inst - BC_INST_ASSIGN_POWER](l, r, l, G.prog.scale); + s = zbc_program_ops[inst - BC_INST_ASSIGN_POWER](l, r, l, G.prog.scale); if (s) return s; #else @@ -6392,7 +6391,7 @@ static BcStatus bc_program_builtin(char inst) bc_num_init_DEF_SIZE(&res.d.n); - if (inst == BC_INST_SQRT) s = bc_num_sqrt(num, &res.d.n, G.prog.scale); + if (inst == BC_INST_SQRT) s = zbc_num_sqrt(num, &res.d.n, G.prog.scale); #if ENABLE_BC else if (len != 0 && opnd->t == BC_RESULT_ARRAY) { bc_num_ulong2num(&res.d.n, (unsigned long) ((BcVec *) num)->len); @@ -6430,7 +6429,7 @@ static BcStatus bc_program_divmod(void) bc_num_init_DEF_SIZE(&res.d.n); bc_num_init(&res2.d.n, n2->len); - s = bc_num_divmod(n1, n2, &res2.d.n, &res.d.n, G.prog.scale); + s = zbc_num_divmod(n1, n2, &res2.d.n, &res.d.n, G.prog.scale); if (s) goto err; bc_program_binOpRetire(&res2); @@ -6477,7 +6476,7 @@ static BcStatus bc_program_modexp(void) } bc_num_init(&res.d.n, n3->len); - s = bc_num_modexp(n1, n2, n3, &res.d.n); + s = zbc_num_modexp(n1, n2, n3, &res.d.n); if (s) goto err; bc_vec_pop(&G.prog.results); @@ -6525,7 +6524,7 @@ static BcStatus bc_program_asciify(void) bc_num_copy(&n, num); bc_num_truncate(&n, n.rdx); - s = bc_num_mod(&n, &G.prog.strmb, &n, 0); + s = zbc_num_mod(&n, &G.prog.strmb, &n, 0); if (s) goto num_err; s = zbc_num_ulong(&n, &val); if (s) goto num_err; -- cgit v1.2.3-55-g6feb From 7f4daa4f5842b26c5f3e233819e583573eeebaf6 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 11 Dec 2018 19:04:44 +0100 Subject: bc: convert arithmetic calc functions to "z" logic In order for magic macros to work, a bit of reordering was necessary. function old new delta zbc_program_modexp - 558 +558 zbc_program_assign - 448 +448 zbc_program_pushArray - 111 +111 zbc_num_s 239 237 -2 zbc_num_d 543 541 -2 zbc_num_binary 145 143 -2 zbc_num_a 443 441 -2 zbc_num_rem 95 91 -4 zbc_num_divmod 150 146 -4 zbc_num_m 269 257 -12 zbc_num_r 230 208 -22 zbc_num_printNum 447 417 -30 bc_program_exec 3960 3928 -32 zbc_num_p 434 399 -35 zbc_program_num 880 840 -40 zbc_num_k 913 852 -61 zbc_program_printStream 141 - -141 bc_program_assign 455 - -455 bc_program_modexp 668 - -668 ------------------------------------------------------------------------------ (add/remove: 3/3 grow/shrink: 0/13 up/down: 1117/-1512) Total: -395 bytes text data bss dec hex filename 982632 485 7296 990413 f1ccd busybox_old 982237 485 7296 990018 f1b42 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 779 +++++++++++++++++++++++++++++++-------------------------- 1 file changed, 424 insertions(+), 355 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 3ab0bf3b7..5ede8598d 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -929,35 +929,94 @@ dc_parse_insts[] = { // ("always returning zero") prefix, i.e. zbc_foo or zdc_foo. // #if ENABLE_FEATURE_BC_SIGNALS || ENABLE_FEATURE_CLEAN_UP +# define ERRORS_ARE_FATAL 0 # define ERRORFUNC /*nothing*/ # define ERROR_RETURN(a) a -# define ERRORS_ARE_FATAL 0 # define BC_STATUS BcStatus # define RETURN_STATUS(v) return (v) #else +# define ERRORS_ARE_FATAL 1 # define ERRORFUNC NORETURN # define ERROR_RETURN(a) /*nothing*/ -# define ERRORS_ARE_FATAL 1 # define BC_STATUS void # define RETURN_STATUS(v) do { ((void)(v)); return; } while (0) #endif +#define BC_NUM_NEG(n, neg) ((((ssize_t)(n)) ^ -((ssize_t)(neg))) + (neg)) +#define BC_NUM_ONE(n) ((n)->len == 1 && (n)->rdx == 0 && (n)->num[0] == 1) +#define BC_NUM_INT(n) ((n)->len - (n)->rdx) +//#define BC_NUM_AREQ(a, b) (BC_MAX((a)->rdx, (b)->rdx) + BC_MAX(BC_NUM_INT(a), BC_NUM_INT(b)) + 1) +static /*ALWAYS_INLINE*/ size_t BC_NUM_AREQ(BcNum *a, BcNum *b) +{ + return BC_MAX(a->rdx, b->rdx) + BC_MAX(BC_NUM_INT(a), BC_NUM_INT(b)) + 1; +} +//#define BC_NUM_MREQ(a, b, scale) (BC_NUM_INT(a) + BC_NUM_INT(b) + BC_MAX((scale), (a)->rdx + (b)->rdx) + 1) +static /*ALWAYS_INLINE*/ size_t BC_NUM_MREQ(BcNum *a, BcNum *b, size_t scale) +{ + return BC_NUM_INT(a) + BC_NUM_INT(b) + BC_MAX(scale, a->rdx + b->rdx) + 1; +} + typedef void (*BcNumDigitOp)(size_t, size_t, bool) FAST_FUNC; -typedef BcStatus (*BcNumBinaryOp)(BcNum *, BcNum *, BcNum *, size_t) FAST_FUNC; +typedef BC_STATUS (*BcNumBinaryOp)(BcNum *, BcNum *, BcNum *, size_t) FAST_FUNC; -static BcStatus zbc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; -static BcStatus zbc_num_sub(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; -static BcStatus zbc_num_mul(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; -static BcStatus zbc_num_div(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; -static BcStatus zbc_num_mod(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; -static BcStatus zbc_num_pow(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC; -static BcStatus zbc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d, - size_t scale); +static BC_STATUS zbc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale, + BcNumBinaryOp op, size_t req); +static FAST_FUNC BC_STATUS zbc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale); +static FAST_FUNC BC_STATUS zbc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale); +static FAST_FUNC BC_STATUS zbc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale); +static FAST_FUNC BC_STATUS zbc_num_m(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale); +static FAST_FUNC BC_STATUS zbc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale); +static FAST_FUNC BC_STATUS zbc_num_rem(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale); + +static FAST_FUNC BC_STATUS zbc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale) +{ + BcNumBinaryOp op = (!a->neg == !b->neg) ? zbc_num_a : zbc_num_s; + (void) scale; + RETURN_STATUS(zbc_num_binary(a, b, c, false, op, BC_NUM_AREQ(a, b))); +} + +static FAST_FUNC BC_STATUS zbc_num_sub(BcNum *a, BcNum *b, BcNum *c, size_t scale) +{ + BcNumBinaryOp op = (!a->neg == !b->neg) ? zbc_num_s : zbc_num_a; + (void) scale; + RETURN_STATUS(zbc_num_binary(a, b, c, true, op, BC_NUM_AREQ(a, b))); +} + +static FAST_FUNC BC_STATUS zbc_num_mul(BcNum *a, BcNum *b, BcNum *c, size_t scale) +{ + size_t req = BC_NUM_MREQ(a, b, scale); + RETURN_STATUS(zbc_num_binary(a, b, c, scale, zbc_num_m, req)); +} + +static FAST_FUNC BC_STATUS zbc_num_div(BcNum *a, BcNum *b, BcNum *c, size_t scale) +{ + size_t req = BC_NUM_MREQ(a, b, scale); + RETURN_STATUS(zbc_num_binary(a, b, c, scale, zbc_num_d, req)); +} + +static FAST_FUNC BC_STATUS zbc_num_mod(BcNum *a, BcNum *b, BcNum *c, size_t scale) +{ + size_t req = BC_NUM_MREQ(a, b, scale); + RETURN_STATUS(zbc_num_binary(a, b, c, scale, zbc_num_rem, req)); +} + +static FAST_FUNC BC_STATUS zbc_num_pow(BcNum *a, BcNum *b, BcNum *c, size_t scale) +{ + RETURN_STATUS(zbc_num_binary(a, b, c, scale, zbc_num_p, a->len * b->len + 1)); +} static const BcNumBinaryOp zbc_program_ops[] = { zbc_num_pow, zbc_num_mul, zbc_num_div, zbc_num_mod, zbc_num_add, zbc_num_sub, }; +#if ERRORS_ARE_FATAL +# define zbc_num_add(...) (zbc_num_add(__VA_ARGS__), BC_STATUS_SUCCESS) +# define zbc_num_sub(...) (zbc_num_sub(__VA_ARGS__), BC_STATUS_SUCCESS) +# define zbc_num_mul(...) (zbc_num_mul(__VA_ARGS__), BC_STATUS_SUCCESS) +# define zbc_num_div(...) (zbc_num_div(__VA_ARGS__), BC_STATUS_SUCCESS) +# define zbc_num_mod(...) (zbc_num_mod(__VA_ARGS__), BC_STATUS_SUCCESS) +# define zbc_num_pow(...) (zbc_num_pow(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static void fflush_and_check(void) { @@ -1527,20 +1586,6 @@ static void bc_num_subArrays(BcDig *restrict a, BcDig *restrict b, } } -#define BC_NUM_NEG(n, neg) ((((ssize_t)(n)) ^ -((ssize_t)(neg))) + (neg)) -#define BC_NUM_ONE(n) ((n)->len == 1 && (n)->rdx == 0 && (n)->num[0] == 1) -#define BC_NUM_INT(n) ((n)->len - (n)->rdx) -//#define BC_NUM_AREQ(a, b) (BC_MAX((a)->rdx, (b)->rdx) + BC_MAX(BC_NUM_INT(a), BC_NUM_INT(b)) + 1) -static /*ALWAYS_INLINE*/ size_t BC_NUM_AREQ(BcNum *a, BcNum *b) -{ - return BC_MAX(a->rdx, b->rdx) + BC_MAX(BC_NUM_INT(a), BC_NUM_INT(b)) + 1; -} -//#define BC_NUM_MREQ(a, b, scale) (BC_NUM_INT(a) + BC_NUM_INT(b) + BC_MAX((scale), (a)->rdx + (b)->rdx) + 1) -static /*ALWAYS_INLINE*/ size_t BC_NUM_MREQ(BcNum *a, BcNum *b, size_t scale) -{ - return BC_NUM_INT(a) + BC_NUM_INT(b) + BC_MAX(scale, a->rdx + b->rdx) + 1; -} - static ssize_t bc_num_compare(BcDig *restrict a, BcDig *restrict b, size_t len) { size_t i; @@ -1692,7 +1737,7 @@ static BC_STATUS zbc_num_shift(BcNum *n, size_t places) # define zbc_num_shift(...) (zbc_num_shift(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static BcStatus zbc_num_inv(BcNum *a, BcNum *b, size_t scale) +static BC_STATUS zbc_num_inv(BcNum *a, BcNum *b, size_t scale) { BcNum one; BcDig num[2]; @@ -1701,10 +1746,13 @@ static BcStatus zbc_num_inv(BcNum *a, BcNum *b, size_t scale) one.num = num; bc_num_one(&one); - return zbc_num_div(&one, a, b, scale); + RETURN_STATUS(zbc_num_div(&one, a, b, scale)); } +#if ERRORS_ARE_FATAL +# define zbc_num_inv(...) (zbc_num_inv(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif -static FAST_FUNC BcStatus zbc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) +static FAST_FUNC BC_STATUS zbc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) { BcDig *ptr, *ptr_a, *ptr_b, *ptr_c; size_t i, max, min_rdx, min_int, diff, a_int, b_int; @@ -1716,11 +1764,11 @@ static FAST_FUNC BcStatus zbc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_ if (a->len == 0) { bc_num_copy(c, b); if (sub && c->len) c->neg = !c->neg; - return BC_STATUS_SUCCESS; + RETURN_STATUS(BC_STATUS_SUCCESS); } - else if (b->len == 0) { + if (b->len == 0) { bc_num_copy(c, a); - return BC_STATUS_SUCCESS; + RETURN_STATUS(BC_STATUS_SUCCESS); } c->neg = a->neg; @@ -1772,10 +1820,10 @@ static FAST_FUNC BcStatus zbc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_ if (carry != 0) c->num[c->len++] = (BcDig) carry; - return BC_STATUS_SUCCESS; // can't make void, see zbc_num_binary() + RETURN_STATUS(BC_STATUS_SUCCESS); // can't make void, see zbc_num_binary() } -static FAST_FUNC BcStatus zbc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) +static FAST_FUNC BC_STATUS zbc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) { ssize_t cmp; BcNum *minuend, *subtrahend; @@ -1788,11 +1836,11 @@ static FAST_FUNC BcStatus zbc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size_ if (a->len == 0) { bc_num_copy(c, b); if (sub && c->len) c->neg = !c->neg; - return BC_STATUS_SUCCESS; + RETURN_STATUS(BC_STATUS_SUCCESS); } - else if (b->len == 0) { + if (b->len == 0) { bc_num_copy(c, a); - return BC_STATUS_SUCCESS; + RETURN_STATUS(BC_STATUS_SUCCESS); } aneg = a->neg; @@ -1806,9 +1854,9 @@ static FAST_FUNC BcStatus zbc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size_ if (cmp == 0) { bc_num_setToZero(c, BC_MAX(a->rdx, b->rdx)); - return BC_STATUS_SUCCESS; + RETURN_STATUS(BC_STATUS_SUCCESS); } - else if (cmp > 0) { + if (cmp > 0) { neg = a->neg; minuend = a; subtrahend = b; @@ -1834,11 +1882,14 @@ static FAST_FUNC BcStatus zbc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size_ bc_num_clean(c); - return BC_STATUS_SUCCESS; // can't make void, see zbc_num_binary() + RETURN_STATUS(BC_STATUS_SUCCESS); // can't make void, see zbc_num_binary() } -static FAST_FUNC BcStatus zbc_num_k(BcNum *restrict a, BcNum *restrict b, +static FAST_FUNC BC_STATUS zbc_num_k(BcNum *restrict a, BcNum *restrict b, BcNum *restrict c) +#if ERRORS_ARE_FATAL +# define zbc_num_k(...) (zbc_num_k(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif { BcStatus s; size_t max = BC_MAX(a->len, b->len), max2 = (max + 1) / 2; @@ -1847,12 +1898,12 @@ static FAST_FUNC BcStatus zbc_num_k(BcNum *restrict a, BcNum *restrict b, if (a->len == 0 || b->len == 0) { bc_num_zero(c); - return BC_STATUS_SUCCESS; + RETURN_STATUS(BC_STATUS_SUCCESS); } aone = BC_NUM_ONE(a); if (aone || BC_NUM_ONE(b)) { bc_num_copy(c, aone ? b : a); - return BC_STATUS_SUCCESS; + RETURN_STATUS(BC_STATUS_SUCCESS); } if (a->len + b->len < BC_NUM_KARATSUBA_LEN || @@ -1880,14 +1931,16 @@ static FAST_FUNC BcStatus zbc_num_k(BcNum *restrict a, BcNum *restrict b, c->num[i + j] += (BcDig) carry; len = BC_MAX(len, i + j + !!carry); +#if ENABLE_FEATURE_BC_SIGNALS // a=2^1000000 // a*a <- without check below, this will not be interruptible if (G_interrupt) return BC_STATUS_FAILURE; +#endif } c->len = len; - return BC_STATUS_SUCCESS; + RETURN_STATUS(BC_STATUS_SUCCESS); } bc_num_init(&l1, max); @@ -1940,10 +1993,10 @@ err: bc_num_free(&l2); bc_num_free(&h1); bc_num_free(&l1); - return s; + RETURN_STATUS(s); } -static FAST_FUNC BcStatus zbc_num_m(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) +static FAST_FUNC BC_STATUS zbc_num_m(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) { BcStatus s; BcNum cpa, cpb; @@ -1982,10 +2035,13 @@ static FAST_FUNC BcStatus zbc_num_m(BcNum *a, BcNum *b, BcNum *restrict c, size_ err: bc_num_free(&cpb); bc_num_free(&cpa); - return s; + RETURN_STATUS(s); } +#if ERRORS_ARE_FATAL +# define zbc_num_m(...) (zbc_num_m(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif -static FAST_FUNC BcStatus zbc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) +static FAST_FUNC BC_STATUS zbc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) { BcStatus s = BC_STATUS_SUCCESS; BcDig *n, *p, q; @@ -1994,15 +2050,15 @@ static FAST_FUNC BcStatus zbc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_ bool zero = true; if (b->len == 0) - return bc_error("divide by zero"); - else if (a->len == 0) { + RETURN_STATUS(bc_error("divide by zero")); + if (a->len == 0) { bc_num_setToZero(c, scale); - return BC_STATUS_SUCCESS; + RETURN_STATUS(BC_STATUS_SUCCESS); } - else if (BC_NUM_ONE(b)) { + if (BC_NUM_ONE(b)) { bc_num_copy(c, a); bc_num_retireMul(c, scale, a->neg, b->neg); - return BC_STATUS_SUCCESS; + RETURN_STATUS(BC_STATUS_SUCCESS); } bc_num_init(&cp, BC_NUM_MREQ(a, b, scale)); @@ -2042,6 +2098,7 @@ static FAST_FUNC BcStatus zbc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_ for (q = 0; (!s && n[len] != 0) || bc_num_compare(n, p, len) >= 0; ++q) bc_num_subArrays(n, p, len); c->num[i] = q; +#if ENABLE_FEATURE_BC_SIGNALS // a=2^100000 // scale=40000 // 1/a <- without check below, this will not be interruptible @@ -2049,15 +2106,19 @@ static FAST_FUNC BcStatus zbc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_ s = BC_STATUS_FAILURE; break; } +#endif } bc_num_retireMul(c, scale, a->neg, b->neg); bc_num_free(&cp); - return s; + RETURN_STATUS(s); } +#if ERRORS_ARE_FATAL +# define zbc_num_d(...) (zbc_num_d(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif -static FAST_FUNC BcStatus zbc_num_r(BcNum *a, BcNum *b, BcNum *restrict c, +static FAST_FUNC BC_STATUS zbc_num_r(BcNum *a, BcNum *b, BcNum *restrict c, BcNum *restrict d, size_t scale, size_t ts) { BcStatus s; @@ -2065,11 +2126,11 @@ static FAST_FUNC BcStatus zbc_num_r(BcNum *a, BcNum *b, BcNum *restrict c, bool neg; if (b->len == 0) - return bc_error("divide by zero"); + RETURN_STATUS(bc_error("divide by zero")); if (a->len == 0) { bc_num_setToZero(d, ts); - return BC_STATUS_SUCCESS; + RETURN_STATUS(BC_STATUS_SUCCESS); } bc_num_init(&temp, d->cap); @@ -2091,10 +2152,13 @@ static FAST_FUNC BcStatus zbc_num_r(BcNum *a, BcNum *b, BcNum *restrict c, err: bc_num_free(&temp); - return s; + RETURN_STATUS(s); } +#if ERRORS_ARE_FATAL +# define zbc_num_r(...) (zbc_num_r(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif -static FAST_FUNC BcStatus zbc_num_rem(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) +static FAST_FUNC BC_STATUS zbc_num_rem(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) { BcStatus s; BcNum c1; @@ -2104,10 +2168,13 @@ static FAST_FUNC BcStatus zbc_num_rem(BcNum *a, BcNum *b, BcNum *restrict c, siz s = zbc_num_r(a, b, &c1, c, scale, ts); bc_num_free(&c1); - return s; + RETURN_STATUS(s); } +#if ERRORS_ARE_FATAL +# define zbc_num_rem(...) (zbc_num_rem(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif -static FAST_FUNC BcStatus zbc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) +static FAST_FUNC BC_STATUS zbc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) { BcStatus s = BC_STATUS_SUCCESS; BcNum copy; @@ -2115,29 +2182,29 @@ static FAST_FUNC BcStatus zbc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_ size_t i, powrdx, resrdx; bool neg, zero; - if (b->rdx) return bc_error("non integer number"); + if (b->rdx) RETURN_STATUS(bc_error("non integer number")); if (b->len == 0) { bc_num_one(c); - return BC_STATUS_SUCCESS; + RETURN_STATUS(BC_STATUS_SUCCESS); } - else if (a->len == 0) { + if (a->len == 0) { bc_num_setToZero(c, scale); - return BC_STATUS_SUCCESS; + RETURN_STATUS(BC_STATUS_SUCCESS); } - else if (BC_NUM_ONE(b)) { + if (BC_NUM_ONE(b)) { if (!b->neg) bc_num_copy(c, a); else s = zbc_num_inv(a, c, scale); - return s; + RETURN_STATUS(s); } neg = b->neg; b->neg = false; s = zbc_num_ulong(b, &pow); - if (s) return s; + if (s) RETURN_STATUS(s); bc_num_init(©, a->len); bc_num_copy(©, a); @@ -2195,10 +2262,13 @@ static FAST_FUNC BcStatus zbc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_ err: bc_num_free(©); - return s; + RETURN_STATUS(s); } +#if ERRORS_ARE_FATAL +# define zbc_num_p(...) (zbc_num_p(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif -static BcStatus zbc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale, +static BC_STATUS zbc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale, BcNumBinaryOp op, size_t req) { BcStatus s; @@ -2228,183 +2298,19 @@ static BcStatus zbc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale, else bc_num_expand(c, req); +#if !ERRORS_ARE_FATAL s = op(ptr_a, ptr_b, c, scale); - - if (init) bc_num_free(&num2); - - return s; -} - -static void bc_num_printNewline(void) -{ - if (G.prog.nchars == G.prog.len - 1) { - bb_putchar('\\'); - bb_putchar('\n'); - G.prog.nchars = 0; - } -} - -#if ENABLE_DC -static FAST_FUNC void bc_num_printChar(size_t num, size_t width, bool radix) -{ - (void) radix; - bb_putchar((char) num); - G.prog.nchars += width; -} -#endif - -static FAST_FUNC void bc_num_printDigits(size_t num, size_t width, bool radix) -{ - size_t exp, pow; - - bc_num_printNewline(); - bb_putchar(radix ? '.' : ' '); - ++G.prog.nchars; - - bc_num_printNewline(); - for (exp = 0, pow = 1; exp < width - 1; ++exp, pow *= 10) - continue; - - for (exp = 0; exp < width; pow /= 10, ++G.prog.nchars, ++exp) { - size_t dig; - bc_num_printNewline(); - dig = num / pow; - num -= dig * pow; - bb_putchar(((char) dig) + '0'); - } -} - -static FAST_FUNC void bc_num_printHex(size_t num, size_t width, bool radix) -{ - if (radix) { - bc_num_printNewline(); - bb_putchar('.'); - G.prog.nchars += 1; - } - - bc_num_printNewline(); - bb_putchar(bb_hexdigits_upcase[num]); - G.prog.nchars += width; -} - -static void bc_num_printDecimal(BcNum *n) -{ - size_t i, rdx = n->rdx - 1; - - if (n->neg) bb_putchar('-'); - G.prog.nchars += n->neg; - - for (i = n->len - 1; i < n->len; --i) - bc_num_printHex((size_t) n->num[i], 1, i == rdx); -} - -static BC_STATUS zbc_num_printNum(BcNum *n, BcNum *base, size_t width, BcNumDigitOp print) -{ - BcStatus s; - BcVec stack; - BcNum intp, fracp, digit, frac_len; - unsigned long dig, *ptr; - size_t i; - bool radix; - - if (n->len == 0) { - print(0, width, false); - RETURN_STATUS(BC_STATUS_SUCCESS); - } - - bc_vec_init(&stack, sizeof(long), NULL); - bc_num_init(&intp, n->len); - bc_num_init(&fracp, n->rdx); - bc_num_init(&digit, width); - bc_num_init(&frac_len, BC_NUM_INT(n)); - bc_num_copy(&intp, n); - bc_num_one(&frac_len); - - bc_num_truncate(&intp, intp.rdx); - s = zbc_num_sub(n, &intp, &fracp, 0); - if (s) goto err; - - while (intp.len != 0) { - s = zbc_num_divmod(&intp, base, &intp, &digit, 0); - if (s) goto err; - s = zbc_num_ulong(&digit, &dig); - if (s) goto err; - bc_vec_push(&stack, &dig); - } - - for (i = 0; i < stack.len; ++i) { - ptr = bc_vec_item_rev(&stack, i); - print(*ptr, width, false); - } - - if (!n->rdx) goto err; - - for (radix = true; frac_len.len <= n->rdx; radix = false) { - s = zbc_num_mul(&fracp, base, &fracp, n->rdx); - if (s) goto err; - s = zbc_num_ulong(&fracp, &dig); - if (s) goto err; - bc_num_ulong2num(&intp, dig); - s = zbc_num_sub(&fracp, &intp, &fracp, 0); - if (s) goto err; - print(dig, width, radix); - s = zbc_num_mul(&frac_len, base, &frac_len, 0); - if (s) goto err; - } - -err: - bc_num_free(&frac_len); - bc_num_free(&digit); - bc_num_free(&fracp); - bc_num_free(&intp); - bc_vec_free(&stack); - RETURN_STATUS(s); -} -#if ERRORS_ARE_FATAL -# define zbc_num_printNum(...) (zbc_num_printNum(__VA_ARGS__), BC_STATUS_SUCCESS) +#else + op(ptr_a, ptr_b, c, scale); + s = BC_STATUS_SUCCESS; #endif -static BC_STATUS zbc_num_printBase(BcNum *n) -{ - BcStatus s; - size_t width, i; - BcNumDigitOp print; - bool neg = n->neg; - - if (neg) { - bb_putchar('-'); - G.prog.nchars++; - } - - n->neg = false; - - if (G.prog.ob_t <= BC_NUM_MAX_IBASE) { - width = 1; - print = bc_num_printHex; - } - else { - for (i = G.prog.ob_t - 1, width = 0; i != 0; i /= 10, ++width) - continue; - print = bc_num_printDigits; - } - - s = zbc_num_printNum(n, &G.prog.ob, width, print); - n->neg = neg; + if (init) bc_num_free(&num2); RETURN_STATUS(s); } #if ERRORS_ARE_FATAL -# define zbc_num_printBase(...) (zbc_num_printBase(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif - -#if ENABLE_DC -static BC_STATUS zbc_num_stream(BcNum *n, BcNum *base) -{ - RETURN_STATUS(zbc_num_printNum(n, base, 1, bc_num_printChar)); -} -#if ERRORS_ARE_FATAL -# define zbc_num_stream(...) (zbc_num_stream(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +# define zbc_num_binary(...) (zbc_num_binary(__VA_ARGS__), BC_STATUS_SUCCESS) #endif static bool bc_num_strValid(const char *val, size_t base) @@ -2557,70 +2463,7 @@ static BC_STATUS zbc_num_parse(BcNum *n, const char *val, BcNum *base, # define zbc_num_parse(...) (zbc_num_parse(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static BC_STATUS zbc_num_print(BcNum *n, bool newline) -{ - BcStatus s = BC_STATUS_SUCCESS; - - bc_num_printNewline(); - - if (n->len == 0) { - bb_putchar('0'); - ++G.prog.nchars; - } - else if (G.prog.ob_t == 10) - bc_num_printDecimal(n); - else - s = zbc_num_printBase(n); - - if (newline) { - bb_putchar('\n'); - G.prog.nchars = 0; - } - - RETURN_STATUS(s); -} -#if ERRORS_ARE_FATAL -# define zbc_num_print(...) (zbc_num_print(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif - -static FAST_FUNC BcStatus zbc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale) -{ - BcNumBinaryOp op = (!a->neg == !b->neg) ? zbc_num_a : zbc_num_s; - (void) scale; - return zbc_num_binary(a, b, c, false, op, BC_NUM_AREQ(a, b)); -} - -static FAST_FUNC BcStatus zbc_num_sub(BcNum *a, BcNum *b, BcNum *c, size_t scale) -{ - BcNumBinaryOp op = (!a->neg == !b->neg) ? zbc_num_s : zbc_num_a; - (void) scale; - return zbc_num_binary(a, b, c, true, op, BC_NUM_AREQ(a, b)); -} - -static FAST_FUNC BcStatus zbc_num_mul(BcNum *a, BcNum *b, BcNum *c, size_t scale) -{ - size_t req = BC_NUM_MREQ(a, b, scale); - return zbc_num_binary(a, b, c, scale, zbc_num_m, req); -} - -static FAST_FUNC BcStatus zbc_num_div(BcNum *a, BcNum *b, BcNum *c, size_t scale) -{ - size_t req = BC_NUM_MREQ(a, b, scale); - return zbc_num_binary(a, b, c, scale, zbc_num_d, req); -} - -static FAST_FUNC BcStatus zbc_num_mod(BcNum *a, BcNum *b, BcNum *c, size_t scale) -{ - size_t req = BC_NUM_MREQ(a, b, scale); - return zbc_num_binary(a, b, c, scale, zbc_num_rem, req); -} - -static FAST_FUNC BcStatus zbc_num_pow(BcNum *a, BcNum *b, BcNum *c, size_t scale) -{ - return zbc_num_binary(a, b, c, scale, zbc_num_p, a->len * b->len + 1); -} - -static BcStatus zbc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale) +static BC_STATUS zbc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale) { BcStatus s; BcNum num1, num2, half, f, fprime, *x0, *x1, *temp; @@ -2632,14 +2475,14 @@ static BcStatus zbc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale) if (a->len == 0) { bc_num_setToZero(b, scale); - return BC_STATUS_SUCCESS; + RETURN_STATUS(BC_STATUS_SUCCESS); } else if (a->neg) - return bc_error("negative number"); + RETURN_STATUS(bc_error("negative number")); else if (BC_NUM_ONE(a)) { bc_num_one(b); bc_num_extend(b, scale); - return BC_STATUS_SUCCESS; + RETURN_STATUS(BC_STATUS_SUCCESS); } scale = BC_MAX(scale, a->rdx) + 1; @@ -2719,10 +2562,13 @@ err: bc_num_free(&half); bc_num_free(&num2); bc_num_free(&num1); - return s; + RETURN_STATUS(s); } +#if ERRORS_ARE_FATAL +# define zbc_num_sqrt(...) (zbc_num_sqrt(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif -static BcStatus zbc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d, +static BC_STATUS zbc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d, size_t scale) { BcStatus s; @@ -2745,21 +2591,24 @@ static BcStatus zbc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d, if (init) bc_num_free(&num2); - return s; + RETURN_STATUS(s); } +#if ERRORS_ARE_FATAL +# define zbc_num_divmod(...) (zbc_num_divmod(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif #if ENABLE_DC -static BcStatus zbc_num_modexp(BcNum *a, BcNum *b, BcNum *c, BcNum *restrict d) +static BC_STATUS zbc_num_modexp(BcNum *a, BcNum *b, BcNum *c, BcNum *restrict d) { BcStatus s; BcNum base, exp, two, temp; if (c->len == 0) - return bc_error("divide by zero"); + RETURN_STATUS(bc_error("divide by zero")); if (a->rdx || b->rdx || c->rdx) - return bc_error("non integer number"); + RETURN_STATUS(bc_error("non integer number")); if (b->neg) - return bc_error("negative number"); + RETURN_STATUS(bc_error("negative number")); bc_num_expand(d, c->len); bc_num_init(&base, c->len); @@ -2798,8 +2647,11 @@ err: bc_num_free(&two); bc_num_free(&exp); bc_num_free(&base); - return s; + RETURN_STATUS(s); } +#if ERRORS_ARE_FATAL +# define zbc_num_modexp(...) (zbc_num_modexp(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif #endif // ENABLE_DC #if ENABLE_BC @@ -5630,7 +5482,11 @@ static BcStatus bc_program_op(char inst) if (s) return s; bc_num_init_DEF_SIZE(&res.d.n); - s = zbc_program_ops[inst - BC_INST_POWER](n1, n2, &res.d.n, G.prog.scale); + s = BC_STATUS_SUCCESS; +#if !ERRORS_ARE_FATAL + s = +#endif + zbc_program_ops[inst - BC_INST_POWER](n1, n2, &res.d.n, G.prog.scale); if (s) goto err; bc_program_binOpRetire(&res); @@ -5810,6 +5666,204 @@ static void bc_program_printString(const char *str) } } +static void bc_num_printNewline(void) +{ + if (G.prog.nchars == G.prog.len - 1) { + bb_putchar('\\'); + bb_putchar('\n'); + G.prog.nchars = 0; + } +} + +#if ENABLE_DC +static FAST_FUNC void bc_num_printChar(size_t num, size_t width, bool radix) +{ + (void) radix; + bb_putchar((char) num); + G.prog.nchars += width; +} +#endif + +static FAST_FUNC void bc_num_printDigits(size_t num, size_t width, bool radix) +{ + size_t exp, pow; + + bc_num_printNewline(); + bb_putchar(radix ? '.' : ' '); + ++G.prog.nchars; + + bc_num_printNewline(); + for (exp = 0, pow = 1; exp < width - 1; ++exp, pow *= 10) + continue; + + for (exp = 0; exp < width; pow /= 10, ++G.prog.nchars, ++exp) { + size_t dig; + bc_num_printNewline(); + dig = num / pow; + num -= dig * pow; + bb_putchar(((char) dig) + '0'); + } +} + +static FAST_FUNC void bc_num_printHex(size_t num, size_t width, bool radix) +{ + if (radix) { + bc_num_printNewline(); + bb_putchar('.'); + G.prog.nchars += 1; + } + + bc_num_printNewline(); + bb_putchar(bb_hexdigits_upcase[num]); + G.prog.nchars += width; +} + +static void bc_num_printDecimal(BcNum *n) +{ + size_t i, rdx = n->rdx - 1; + + if (n->neg) bb_putchar('-'); + G.prog.nchars += n->neg; + + for (i = n->len - 1; i < n->len; --i) + bc_num_printHex((size_t) n->num[i], 1, i == rdx); +} + +static BC_STATUS zbc_num_printNum(BcNum *n, BcNum *base, size_t width, BcNumDigitOp print) +{ + BcStatus s; + BcVec stack; + BcNum intp, fracp, digit, frac_len; + unsigned long dig, *ptr; + size_t i; + bool radix; + + if (n->len == 0) { + print(0, width, false); + RETURN_STATUS(BC_STATUS_SUCCESS); + } + + bc_vec_init(&stack, sizeof(long), NULL); + bc_num_init(&intp, n->len); + bc_num_init(&fracp, n->rdx); + bc_num_init(&digit, width); + bc_num_init(&frac_len, BC_NUM_INT(n)); + bc_num_copy(&intp, n); + bc_num_one(&frac_len); + + bc_num_truncate(&intp, intp.rdx); + s = zbc_num_sub(n, &intp, &fracp, 0); + if (s) goto err; + + while (intp.len != 0) { + s = zbc_num_divmod(&intp, base, &intp, &digit, 0); + if (s) goto err; + s = zbc_num_ulong(&digit, &dig); + if (s) goto err; + bc_vec_push(&stack, &dig); + } + + for (i = 0; i < stack.len; ++i) { + ptr = bc_vec_item_rev(&stack, i); + print(*ptr, width, false); + } + + if (!n->rdx) goto err; + + for (radix = true; frac_len.len <= n->rdx; radix = false) { + s = zbc_num_mul(&fracp, base, &fracp, n->rdx); + if (s) goto err; + s = zbc_num_ulong(&fracp, &dig); + if (s) goto err; + bc_num_ulong2num(&intp, dig); + s = zbc_num_sub(&fracp, &intp, &fracp, 0); + if (s) goto err; + print(dig, width, radix); + s = zbc_num_mul(&frac_len, base, &frac_len, 0); + if (s) goto err; + } + +err: + bc_num_free(&frac_len); + bc_num_free(&digit); + bc_num_free(&fracp); + bc_num_free(&intp); + bc_vec_free(&stack); + RETURN_STATUS(s); +} +#if ERRORS_ARE_FATAL +# define zbc_num_printNum(...) (zbc_num_printNum(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif + +static BC_STATUS zbc_num_printBase(BcNum *n) +{ + BcStatus s; + size_t width, i; + BcNumDigitOp print; + bool neg = n->neg; + + if (neg) { + bb_putchar('-'); + G.prog.nchars++; + } + + n->neg = false; + + if (G.prog.ob_t <= BC_NUM_MAX_IBASE) { + width = 1; + print = bc_num_printHex; + } + else { + for (i = G.prog.ob_t - 1, width = 0; i != 0; i /= 10, ++width) + continue; + print = bc_num_printDigits; + } + + s = zbc_num_printNum(n, &G.prog.ob, width, print); + n->neg = neg; + + RETURN_STATUS(s); +} +#if ERRORS_ARE_FATAL +# define zbc_num_printBase(...) (zbc_num_printBase(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif + +#if ENABLE_DC +static BC_STATUS zbc_num_stream(BcNum *n, BcNum *base) +{ + RETURN_STATUS(zbc_num_printNum(n, base, 1, bc_num_printChar)); +} +#if ERRORS_ARE_FATAL +# define zbc_num_stream(...) (zbc_num_stream(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif +#endif + +static BC_STATUS zbc_num_print(BcNum *n, bool newline) +{ + BcStatus s = BC_STATUS_SUCCESS; + + bc_num_printNewline(); + + if (n->len == 0) { + bb_putchar('0'); + ++G.prog.nchars; + } + else if (G.prog.ob_t == 10) + bc_num_printDecimal(n); + else + s = zbc_num_printBase(n); + + if (newline) { + bb_putchar('\n'); + G.prog.nchars = 0; + } + + RETURN_STATUS(s); +} +#if ERRORS_ARE_FATAL +# define zbc_num_print(...) (zbc_num_print(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif + static BC_STATUS zbc_program_print(char inst, size_t idx) { BcStatus s; @@ -6022,7 +6076,7 @@ static BC_STATUS zbc_program_copyToVar(char *name, bool var) # define zbc_program_copyToVar(...) (zbc_program_copyToVar(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static BcStatus bc_program_assign(char inst) +static BC_STATUS zbc_program_assign(char inst) { BcStatus s; BcResult *left, *right, res; @@ -6030,7 +6084,7 @@ static BcStatus bc_program_assign(char inst) bool assign = inst == BC_INST_ASSIGN, ib, sc; s = zbc_program_binOpPrep(&left, &l, &right, &r, assign); - if (s) return s; + if (s) RETURN_STATUS(s); ib = left->t == BC_RESULT_IBASE; sc = left->t == BC_RESULT_SCALE; @@ -6042,30 +6096,34 @@ static BcStatus bc_program_assign(char inst) BcVec *v; if (left->t != BC_RESULT_VAR) - return bc_error_variable_is_wrong_type(); + RETURN_STATUS(bc_error_variable_is_wrong_type()); v = bc_program_search(left->d.id.name, true); - return zbc_program_assignStr(right, v, false); + RETURN_STATUS(zbc_program_assignStr(right, v, false)); } #endif if (left->t == BC_RESULT_CONSTANT || left->t == BC_RESULT_TEMP) - return bc_error("bad assignment:" + RETURN_STATUS(("bad assignment:" " left side must be scale," " ibase, obase, last, var," " or array element" - ); + )); #if ENABLE_BC if (inst == BC_INST_ASSIGN_DIVIDE && !bc_num_cmp(r, &G.prog.zero)) - return bc_error("divide by zero"); + RETURN_STATUS(bc_error("divide by zero")); if (assign) bc_num_copy(l, r); - else - s = zbc_program_ops[inst - BC_INST_ASSIGN_POWER](l, r, l, G.prog.scale); - - if (s) return s; + else { + s = BC_STATUS_SUCCESS; +#if !ERRORS_ARE_FATAL + s = +#endif + zbc_program_ops[inst - BC_INST_ASSIGN_POWER](l, r, l, G.prog.scale); + } + if (s) RETURN_STATUS(s); #else bc_num_copy(l, r); #endif @@ -6083,8 +6141,7 @@ static BcStatus bc_program_assign(char inst) unsigned long val, max; s = zbc_num_ulong(l, &val); - if (s) - return s; + if (s) RETURN_STATUS(s); s = left->t - BC_RESULT_IBASE; if (sc) { max = BC_MAX_SCALE; @@ -6092,13 +6149,13 @@ static BcStatus bc_program_assign(char inst) } else { if (val < BC_NUM_MIN_BASE) - return bc_error(msg[s]); + RETURN_STATUS(bc_error(msg[s])); max = ib ? BC_NUM_MAX_IBASE : BC_MAX_OBASE; ptr = ib ? &G.prog.ib_t : &G.prog.ob_t; } if (val > max) - return bc_error(msg[s]); + RETURN_STATUS(bc_error(msg[s])); if (!sc) bc_num_copy(ib ? &G.prog.ib : &G.prog.ob, l); @@ -6110,8 +6167,11 @@ static BcStatus bc_program_assign(char inst) bc_num_copy(&res.d.n, l); bc_program_binOpRetire(&res); - return s; + RETURN_STATUS(s); } +#if ERRORS_ARE_FATAL +# define zbc_program_assign(...) (zbc_program_assign(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif #if !ENABLE_DC #define bc_program_pushVar(code, bgn, pop, copy) \ @@ -6232,7 +6292,8 @@ static BC_STATUS zbc_program_incdec(char inst) BC_INST_ASSIGN_MINUS; bc_vec_push(&G.prog.results, &res); - bc_program_assign(inst); + s = zbc_program_assign(inst); + if (s) RETURN_STATUS(s); if (inst2 == BC_INST_INC_POST || inst2 == BC_INST_DEC_POST) { bc_vec_pop(&G.prog.results); @@ -6369,7 +6430,7 @@ static unsigned long bc_program_len(BcNum *n) return len; } -static BcStatus bc_program_builtin(char inst) +static BC_STATUS zbc_program_builtin(char inst) { BcStatus s; BcResult *opnd; @@ -6378,15 +6439,15 @@ static BcStatus bc_program_builtin(char inst) bool len = inst == BC_INST_LENGTH; if (!BC_PROG_STACK(&G.prog.results, 1)) - return bc_error_stack_has_too_few_elements(); + RETURN_STATUS(bc_error_stack_has_too_few_elements()); opnd = bc_vec_top(&G.prog.results); s = zbc_program_num(opnd, &num, false); - if (s) return s; + if (s) RETURN_STATUS(s); #if ENABLE_DC if (!BC_PROG_NUM(opnd, num) && !len) - return bc_error_variable_is_wrong_type(); + RETURN_STATUS(bc_error_variable_is_wrong_type()); #endif bc_num_init_DEF_SIZE(&res.d.n); @@ -6399,7 +6460,6 @@ static BcStatus bc_program_builtin(char inst) #endif #if ENABLE_DC else if (len != 0 && !BC_PROG_NUM(opnd, num)) { - char **str; size_t idx = opnd->t == BC_RESULT_STR ? opnd->d.id.idx : num->rdx; @@ -6413,18 +6473,21 @@ static BcStatus bc_program_builtin(char inst) bc_program_retire(&res, BC_RESULT_TEMP); - return s; + RETURN_STATUS(s); } +#if ERRORS_ARE_FATAL +# define zbc_program_builtin(...) (zbc_program_builtin(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif #if ENABLE_DC -static BcStatus bc_program_divmod(void) +static BC_STATUS zbc_program_divmod(void) { BcStatus s; BcResult *opd1, *opd2, res, res2; BcNum *n1, *n2 = NULL; s = zbc_program_binOpPrep(&opd1, &n1, &opd2, &n2, false); - if (s) return s; + if (s) RETURN_STATUS(s); bc_num_init_DEF_SIZE(&res.d.n); bc_num_init(&res2.d.n, n2->len); @@ -6436,42 +6499,45 @@ static BcStatus bc_program_divmod(void) res.t = BC_RESULT_TEMP; bc_vec_push(&G.prog.results, &res); - return s; + RETURN_STATUS(s); err: bc_num_free(&res2.d.n); bc_num_free(&res.d.n); - return s; + RETURN_STATUS(s); } +#if ERRORS_ARE_FATAL +# define zbc_program_divmod(...) (zbc_program_divmod(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif -static BcStatus bc_program_modexp(void) +static BC_STATUS zbc_program_modexp(void) { BcStatus s; BcResult *r1, *r2, *r3, res; BcNum *n1, *n2, *n3; if (!BC_PROG_STACK(&G.prog.results, 3)) - return bc_error_stack_has_too_few_elements(); + RETURN_STATUS(bc_error_stack_has_too_few_elements()); s = zbc_program_binOpPrep(&r2, &n2, &r3, &n3, false); - if (s) return s; + if (s) RETURN_STATUS(s); r1 = bc_vec_item_rev(&G.prog.results, 2); s = zbc_program_num(r1, &n1, false); - if (s) return s; + if (s) RETURN_STATUS(s); if (!BC_PROG_NUM(r1, n1)) - return bc_error_variable_is_wrong_type(); + RETURN_STATUS(bc_error_variable_is_wrong_type()); // Make sure that the values have their pointers updated, if necessary. if (r1->t == BC_RESULT_VAR || r1->t == BC_RESULT_ARRAY_ELEM) { if (r1->t == r2->t) { s = zbc_program_num(r2, &n2, false); - if (s) return s; + if (s) RETURN_STATUS(s); } if (r1->t == r3->t) { s = zbc_program_num(r3, &n3, false); - if (s) return s; + if (s) RETURN_STATUS(s); } } @@ -6482,12 +6548,15 @@ static BcStatus bc_program_modexp(void) bc_vec_pop(&G.prog.results); bc_program_binOpRetire(&res); - return s; + RETURN_STATUS(s); err: bc_num_free(&res.d.n); - return s; + RETURN_STATUS(s); } +#if ERRORS_ARE_FATAL +# define zbc_program_modexp(...) (zbc_program_modexp(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static void bc_program_stackLen(void) { @@ -6857,7 +6926,7 @@ static BcStatus bc_program_exec(void) case BC_INST_SCALE_FUNC: case BC_INST_LENGTH: case BC_INST_SQRT: - s = bc_program_builtin(inst); + s = zbc_program_builtin(inst); break; case BC_INST_NUM: r.t = BC_RESULT_CONSTANT; @@ -6912,14 +6981,14 @@ static BcStatus bc_program_exec(void) case BC_INST_ASSIGN_MINUS: #endif case BC_INST_ASSIGN: - s = bc_program_assign(inst); + s = zbc_program_assign(inst); break; #if ENABLE_DC case BC_INST_MODEXP: - s = bc_program_modexp(); + s = zbc_program_modexp(); break; case BC_INST_DIVMOD: - s = bc_program_divmod(); + s = zbc_program_divmod(); break; case BC_INST_EXECUTE: case BC_INST_EXEC_COND: -- cgit v1.2.3-55-g6feb From 09d8df84ee908b940a31822c3480f36f817e4f09 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 11 Dec 2018 19:29:35 +0100 Subject: bc: do not use "(cond ? f1 : f2)(params)" idiom, it messes up static function optimizations With direct calls, GCC no longer thinks that we take addresses of the functions, and can use "more optimal" internal ABI for _all_ calls to these functions, not only at this callsite. On i486, regparm is used, and: function old new delta zbc_num_inv 56 57 +1 zbc_num_k 852 851 -1 zbc_program_modexp 558 556 -2 zbc_num_d 541 539 -2 bc_num_ulong2num 59 57 -2 zbc_program_num 840 836 -4 bc_num_zero 11 7 -4 bc_num_one 28 24 -4 bc_program_exec 3928 3918 -10 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/8 up/down: 1/-29) Total: -28 bytes text data bss dec hex filename 982237 485 7296 990018 f1b42 busybox_old 982209 485 7296 989990 f1b26 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 60 ++++++++++++++++++++-------------------------------------- 1 file changed, 21 insertions(+), 39 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 5ede8598d..e7f48fcea 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -5943,6 +5943,7 @@ static BcStatus bc_program_logical(char inst) s = zbc_program_binOpPrep(&opd1, &n1, &opd2, &n2, false); if (s) return s; + bc_num_init_DEF_SIZE(&res.d.n); if (inst == BC_INST_BOOL_AND) @@ -5950,50 +5951,31 @@ static BcStatus bc_program_logical(char inst) else if (inst == BC_INST_BOOL_OR) cond = bc_num_cmp(n1, &G.prog.zero) || bc_num_cmp(n2, &G.prog.zero); else { - cmp = bc_num_cmp(n1, n2); - switch (inst) { - - case BC_INST_REL_EQ: - { - cond = cmp == 0; - break; - } - - case BC_INST_REL_LE: - { - cond = cmp <= 0; - break; - } - - case BC_INST_REL_GE: - { - cond = cmp >= 0; - break; - } - - case BC_INST_REL_NE: - { - cond = cmp != 0; - break; - } - - case BC_INST_REL_LT: - { - cond = cmp < 0; - break; - } - - case BC_INST_REL_GT: - { - cond = cmp > 0; - break; - } + case BC_INST_REL_EQ: + cond = cmp == 0; + break; + case BC_INST_REL_LE: + cond = cmp <= 0; + break; + case BC_INST_REL_GE: + cond = cmp >= 0; + break; + case BC_INST_REL_NE: + cond = cmp != 0; + break; + case BC_INST_REL_LT: + cond = cmp < 0; + break; + case BC_INST_REL_GT: + cond = cmp > 0; + break; } } - (cond ? bc_num_one : bc_num_zero)(&res.d.n); + if (cond) bc_num_one(&res.d.n); + //else bc_num_zero(&res.d.n); - already is bc_program_binOpRetire(&res); -- cgit v1.2.3-55-g6feb From 728e7c9ecb1b64473412fe45caf1623e22a9204b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 11 Dec 2018 19:37:00 +0100 Subject: bc: convert bc_program_logical to "z" function Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index e7f48fcea..acc0b6073 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -5933,7 +5933,7 @@ static BC_STATUS zbc_program_negate(void) # define zbc_program_negate(...) (zbc_program_negate(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static BcStatus bc_program_logical(char inst) +static BC_STATUS zbc_program_logical(char inst) { BcStatus s; BcResult *opd1, *opd2, res; @@ -5942,7 +5942,7 @@ static BcStatus bc_program_logical(char inst) ssize_t cmp; s = zbc_program_binOpPrep(&opd1, &n1, &opd2, &n2, false); - if (s) return s; + if (s) RETURN_STATUS(s); bc_num_init_DEF_SIZE(&res.d.n); @@ -5979,8 +5979,11 @@ static BcStatus bc_program_logical(char inst) bc_program_binOpRetire(&res); - return s; + RETURN_STATUS(s); } +#if ERRORS_ARE_FATAL +# define zbc_program_logical(...) (zbc_program_logical(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif #if ENABLE_DC static BC_STATUS zbc_program_assignStr(BcResult *r, BcVec *v, @@ -6884,7 +6887,7 @@ static BcStatus bc_program_exec(void) case BC_INST_REL_NE: case BC_INST_REL_LT: case BC_INST_REL_GT: - s = bc_program_logical(inst); + s = zbc_program_logical(inst); break; case BC_INST_READ: s = bc_program_read(); -- cgit v1.2.3-55-g6feb From 259137d0f0600150cd783c796e4011164c44a7f0 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 11 Dec 2018 19:42:05 +0100 Subject: bc: convert zbc_program_op to "z" function, fix a thinko in prev commits function old new delta zbc_program_assign 448 447 -1 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index acc0b6073..be118d81d 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -5472,14 +5472,14 @@ static void bc_program_retire(BcResult *r, BcResultType t) bc_vec_push(&G.prog.results, r); } -static BcStatus bc_program_op(char inst) +static BC_STATUS zbc_program_op(char inst) { BcStatus s; BcResult *opd1, *opd2, res; BcNum *n1, *n2 = NULL; s = zbc_program_binOpPrep(&opd1, &n1, &opd2, &n2, false); - if (s) return s; + if (s) RETURN_STATUS(s); bc_num_init_DEF_SIZE(&res.d.n); s = BC_STATUS_SUCCESS; @@ -5490,12 +5490,15 @@ static BcStatus bc_program_op(char inst) if (s) goto err; bc_program_binOpRetire(&res); - return s; + RETURN_STATUS(s); err: bc_num_free(&res.d.n); - return s; + RETURN_STATUS(s); } +#if ERRORS_ARE_FATAL +# define zbc_program_op(...) (zbc_program_op(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static BcStatus bc_program_read(void) { @@ -6089,7 +6092,7 @@ static BC_STATUS zbc_program_assign(char inst) #endif if (left->t == BC_RESULT_CONSTANT || left->t == BC_RESULT_TEMP) - RETURN_STATUS(("bad assignment:" + RETURN_STATUS(bc_error("bad assignment:" " left side must be scale," " ibase, obase, last, var," " or array element" @@ -6943,7 +6946,7 @@ static BcStatus bc_program_exec(void) case BC_INST_MODULUS: case BC_INST_PLUS: case BC_INST_MINUS: - s = bc_program_op(inst); + s = zbc_program_op(inst); break; case BC_INST_BOOL_NOT: s = zbc_program_prep(&ptr, &num); -- cgit v1.2.3-55-g6feb From 9f657e0f7deae5e27f95d783f52f897f42eafa57 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 11 Dec 2018 19:52:25 +0100 Subject: bc: shrink bc_program_printString function old new delta zbc_program_print 665 642 -23 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 110 ++++++++++++++++++++------------------------------------- 1 file changed, 39 insertions(+), 71 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index be118d81d..5f1baf431 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -5585,87 +5585,55 @@ static char *bc_program_name(char *code, size_t *bgn) static void bc_program_printString(const char *str) { - size_t i, len = strlen(str); - #if ENABLE_DC - if (len == 0) { + // Huh? Example when this happens? + if (!str[0]) { bb_putchar('\0'); return; } #endif - - for (i = 0; i < len; ++i, ++G.prog.nchars) { - - int c = str[i]; - - if (c != '\\' || i == len - 1) + while (*str) { + int c = *str++; + if (c != '\\' || !*str) bb_putchar(c); else { - - c = str[++i]; - + c = *str++; switch (c) { - - case 'a': - { - bb_putchar('\a'); - break; - } - - case 'b': - { - bb_putchar('\b'); - break; - } - - case '\\': - case 'e': - { - bb_putchar('\\'); - break; - } - - case 'f': - { - bb_putchar('\f'); - break; - } - - case 'n': - { - bb_putchar('\n'); - G.prog.nchars = SIZE_MAX; - break; - } - - case 'r': - { - bb_putchar('\r'); - break; - } - - case 'q': - { - bb_putchar('"'); - break; - } - - case 't': - { - bb_putchar('\t'); - break; - } - - default: - { - // Just print the backslash and following character. - bb_putchar('\\'); - ++G.prog.nchars; - bb_putchar(c); - break; - } + case 'a': + bb_putchar('\a'); + break; + case 'b': + bb_putchar('\b'); + break; + case '\\': + case 'e': + bb_putchar('\\'); + break; + case 'f': + bb_putchar('\f'); + break; + case 'n': + bb_putchar('\n'); + G.prog.nchars = SIZE_MAX; + break; + case 'r': + bb_putchar('\r'); + break; + case 'q': + bb_putchar('"'); + break; + case 't': + bb_putchar('\t'); + break; + default: + // Just print the backslash and following character. + bb_putchar('\\'); + ++G.prog.nchars; + bb_putchar(c); + break; } } + ++G.prog.nchars; } } -- cgit v1.2.3-55-g6feb From c008a73762ebe4ce0dc8bc7741a887d394b6fb6f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 11 Dec 2018 20:57:53 +0100 Subject: bc: convert bc_program_asciify to "z" function Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 5f1baf431..9f05cad0c 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -6526,7 +6526,7 @@ static void bc_program_stackLen(void) bc_vec_push(&G.prog.results, &res); } -static BcStatus bc_program_asciify(void) +static BC_STATUS zbc_program_asciify(void) { BcStatus s; BcResult *r, res; @@ -6536,12 +6536,12 @@ static BcStatus bc_program_asciify(void) unsigned long val; if (!BC_PROG_STACK(&G.prog.results, 1)) - return bc_error_stack_has_too_few_elements(); + RETURN_STATUS(bc_error_stack_has_too_few_elements()); r = bc_vec_top(&G.prog.results); num = NULL; // TODO: is this NULL needed? s = zbc_program_num(r, &num, false); - if (s) return s; + if (s) RETURN_STATUS(s); if (BC_PROG_NUM(r, num)) { @@ -6572,7 +6572,6 @@ static BcStatus bc_program_asciify(void) bc_program_addFunc(str2, &idx); if (idx != len + BC_PROG_REQ_FUNCS) { - for (idx = 0; idx < G.prog.strs.len; ++idx) { if (strcmp(*bc_program_str(idx), str) == 0) { len = idx; @@ -6590,12 +6589,15 @@ static BcStatus bc_program_asciify(void) bc_vec_pop(&G.prog.results); bc_vec_push(&G.prog.results, &res); - return BC_STATUS_SUCCESS; + RETURN_STATUS(BC_STATUS_SUCCESS); num_err: bc_num_free(&n); - return s; + RETURN_STATUS(s); } +#if ERRORS_ARE_FATAL +# define zbc_program_asciify(...) (zbc_program_asciify(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static BC_STATUS zbc_program_printStream(void) { @@ -6984,7 +6986,7 @@ static BcStatus bc_program_exec(void) break; } case BC_INST_ASCIIFY: - s = bc_program_asciify(); + s = zbc_program_asciify(); break; case BC_INST_PRINT_STREAM: s = zbc_program_printStream(); -- cgit v1.2.3-55-g6feb From 2c6f563216da4fd38626b59cbd01774bbc0e2a71 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 11 Dec 2018 21:21:14 +0100 Subject: bc: tweak comment Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 9f05cad0c..143bb64b1 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -5586,8 +5586,9 @@ static char *bc_program_name(char *code, size_t *bgn) static void bc_program_printString(const char *str) { #if ENABLE_DC - // Huh? Example when this happens? if (!str[0]) { + // Example: echo '[]ap' | dc + // should print two bytes: 0x00, 0x0A bb_putchar('\0'); return; } -- cgit v1.2.3-55-g6feb From 4dd3652c2fa782ac25a0cb59df060275e6384908 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 11 Dec 2018 22:26:38 +0100 Subject: bc: fix EOF handling in bc_program_read() $ bc -q read() 2^D^D2 ^ prints the result of read()'ed expression function old new delta zbc_program_print 629 642 +13 bc_program_read 322 312 -10 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/1 up/down: 13/-10) Total: 3 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 143bb64b1..32e002913 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1358,6 +1358,8 @@ static int push_input_byte(BcVec *vec, char c) } // This is not a "z" function: can also return BC_STATUS_EOF +// Can return success (0) or BC_STATUS_EOF. +// Exits with error message if read error is detected. static BcStatus bc_read_line(BcVec *vec) { BcStatus s; @@ -5523,7 +5525,7 @@ static BcStatus bc_program_read(void) G.prog.file = NULL; s = bc_read_line(&buf); - if (s) goto io_err; + //if (s) goto io_err; - wrong, nonzero return means EOF, not error common_parse_init(&parse, BC_PROG_READ); bc_lex_file(&parse.l); @@ -5549,9 +5551,9 @@ static BcStatus bc_program_read(void) bc_vec_push(&G.prog.stack, &ip); exec_err: - G.prog.file = sv_file; bc_parse_free(&parse); -io_err: +//io_err: + G.prog.file = sv_file; bc_vec_free(&buf); return s; } @@ -7171,8 +7173,8 @@ static BcStatus bc_vm_stdin(void) { BcStatus s; BcVec buf, buffer; - size_t len, i, str = 0; - bool comment = false; + size_t str; + bool comment; G.prog.file = NULL; bc_lex_file(&G.prs.l); @@ -7185,12 +7187,13 @@ static BcStatus bc_vm_stdin(void) // with a backslash to the parser. The reason for that is because the parser // treats a backslash+newline combo as whitespace, per the bc spec. In that // case, and for strings and comments, the parser will expect more stuff. + comment = false; + str = 0; while ((s = bc_read_line(&buf)) == BC_STATUS_SUCCESS) { - + size_t len; char *string = buf.v; len = buf.len - 1; - if (len == 1) { if (str && buf.v[0] == G.send) str -= 1; @@ -7198,9 +7201,8 @@ static BcStatus bc_vm_stdin(void) str += 1; } else if (len > 1 || comment) { - + size_t i; for (i = 0; i < len; ++i) { - bool notend = len > i + 1; char c = string[i]; -- cgit v1.2.3-55-g6feb From f0f069b08f8e22a7da580ae2c19425bfb1313297 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 11 Dec 2018 23:22:52 +0100 Subject: bc: use common_parse_init() in bc_vm_init() function old new delta common_parse_init 26 45 +19 dc_parse_init 17 - -17 bc_parse_init 17 - -17 bc_vm_init 744 725 -19 ------------------------------------------------------------------------------ (add/remove: 0/2 grow/shrink: 1/1 up/down: 19/-53) Total: -34 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 32e002913..e3e8198b7 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -7575,11 +7575,7 @@ static int bc_vm_init(const char *env_len) if (IS_BC) IF_BC(bc_vm_envArgs();) bc_program_init(); - if (IS_BC) { - IF_BC(bc_parse_init(&G.prs, BC_PROG_MAIN);) - } else { - IF_DC(dc_parse_init(&G.prs, BC_PROG_MAIN);) - } + common_parse_init(&G.prs, BC_PROG_MAIN); if (isatty(0)) { #if ENABLE_FEATURE_BC_SIGNALS -- cgit v1.2.3-55-g6feb From 12b9eaf787146d8706a343d87f19902e6892be86 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 11 Dec 2018 23:50:14 +0100 Subject: bc: in non-interactive config, POSIX error functions never return nonzero function old new delta bc_parse_expr_empty_ok 2036 2032 -4 bc_parse_stmt 1767 1753 -14 bc_lex_token 1259 1228 -31 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/3 up/down: 0/-49) Total: -49 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 151 ++++++--------------------------------------------------- 1 file changed, 16 insertions(+), 135 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index e3e8198b7..70db2ce3d 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -2994,7 +2994,7 @@ static BcStatus bc_lex_identifier(BcLex *l) l->t.t = BC_LEX_KEY_1st_keyword + i; if (!bc_lex_kws_POSIX(i)) { s = bc_posix_error_fmt("%sthe '%.8s' keyword", "POSIX does not allow ", bc_lex_kws[i].name8); - if (s) return s; + ERROR_RETURN(if (s) return s;) } // We minus 1 because the index has already been incremented. @@ -3096,123 +3096,75 @@ static FAST_FUNC BcStatus bc_lex_token(BcLex *l) // This is the workhorse of the lexer. switch (c) { - case '\0': case '\n': - { l->newline = true; l->t.t = !c ? BC_LEX_EOF : BC_LEX_NLINE; break; - } - case '\t': case '\v': case '\f': case '\r': case ' ': - { bc_lex_whitespace(l); break; - } - case '!': - { bc_lex_assign(l, BC_LEX_OP_REL_NE, BC_LEX_OP_BOOL_NOT); - if (l->t.t == BC_LEX_OP_BOOL_NOT) { s = bc_POSIX_does_not_allow_bool_ops_this_is_bad("!"); - if (s) return s; + ERROR_RETURN(if (s) return s;) } - break; - } - case '"': - { s = bc_lex_string(l); break; - } - case '#': - { s = bc_POSIX_does_not_allow("'#' script comments"); - if (s) return s; - + ERROR_RETURN(if (s) return s;) bc_lex_lineComment(l); - break; - } - case '%': - { bc_lex_assign(l, BC_LEX_OP_ASSIGN_MODULUS, BC_LEX_OP_MODULUS); break; - } - case '&': - { c2 = l->buf[l->i]; if (c2 == '&') { - s = bc_POSIX_does_not_allow_bool_ops_this_is_bad("&&"); - if (s) return s; - + ERROR_RETURN(if (s) return s;) ++l->i; l->t.t = BC_LEX_OP_BOOL_AND; - } - else { + } else { l->t.t = BC_LEX_INVALID; s = bc_error_bad_character('&'); } - break; - } - case '(': case ')': - { l->t.t = (BcLexType)(c - '(' + BC_LEX_LPAREN); break; - } - case '*': - { bc_lex_assign(l, BC_LEX_OP_ASSIGN_MULTIPLY, BC_LEX_OP_MULTIPLY); break; - } - case '+': - { c2 = l->buf[l->i]; if (c2 == '+') { ++l->i; l->t.t = BC_LEX_OP_INC; - } - else + } else bc_lex_assign(l, BC_LEX_OP_ASSIGN_PLUS, BC_LEX_OP_PLUS); break; - } - case ',': - { l->t.t = BC_LEX_COMMA; break; - } - case '-': - { c2 = l->buf[l->i]; if (c2 == '-') { ++l->i; l->t.t = BC_LEX_OP_DEC; - } - else + } else bc_lex_assign(l, BC_LEX_OP_ASSIGN_MINUS, BC_LEX_OP_MINUS); break; - } - case '.': - { if (isdigit(l->buf[l->i])) s = zbc_lex_number(l, c); else { @@ -3220,18 +3172,13 @@ static FAST_FUNC BcStatus bc_lex_token(BcLex *l) s = bc_POSIX_does_not_allow("a period ('.') as a shortcut for the last result"); } break; - } - case '/': - { c2 = l->buf[l->i]; if (c2 == '*') s = zbc_lex_comment(l); else bc_lex_assign(l, BC_LEX_OP_ASSIGN_DIVIDE, BC_LEX_OP_DIVIDE); break; - } - case '0': case '1': case '2': @@ -3248,59 +3195,34 @@ static FAST_FUNC BcStatus bc_lex_token(BcLex *l) case 'D': case 'E': case 'F': - { s = zbc_lex_number(l, c); break; - } - case ';': - { l->t.t = BC_LEX_SCOLON; break; - } - case '<': - { bc_lex_assign(l, BC_LEX_OP_REL_LE, BC_LEX_OP_REL_LT); break; - } - case '=': - { bc_lex_assign(l, BC_LEX_OP_REL_EQ, BC_LEX_OP_ASSIGN); break; - } - case '>': - { bc_lex_assign(l, BC_LEX_OP_REL_GE, BC_LEX_OP_REL_GT); break; - } - case '[': case ']': - { l->t.t = (BcLexType)(c - '[' + BC_LEX_LBRACKET); break; - } - case '\\': - { if (l->buf[l->i] == '\n') { l->t.t = BC_LEX_WHITESPACE; ++l->i; - } - else + } else s = bc_error_bad_character(c); break; - } - case '^': - { bc_lex_assign(l, BC_LEX_OP_ASSIGN_POWER, BC_LEX_OP_POWER); break; - } - case 'a': case 'b': case 'c': @@ -3327,43 +3249,28 @@ static FAST_FUNC BcStatus bc_lex_token(BcLex *l) case 'x': case 'y': case 'z': - { s = bc_lex_identifier(l); break; - } - case '{': case '}': - { l->t.t = (BcLexType)(c - '{' + BC_LEX_LBRACE); break; - } - case '|': - { c2 = l->buf[l->i]; - if (c2 == '|') { s = bc_POSIX_does_not_allow_bool_ops_this_is_bad("||"); - if (s) return s; - + ERROR_RETURN(if (s) return s;) ++l->i; l->t.t = BC_LEX_OP_BOOL_OR; - } - else { + } else { l->t.t = BC_LEX_INVALID; s = bc_error_bad_character(c); } - break; - } - default: - { l->t.t = BC_LEX_INVALID; s = bc_error_bad_character(c); break; - } } return s; @@ -3443,37 +3350,28 @@ static FAST_FUNC BcStatus dc_lex_token(BcLex *l) return zdc_lex_register(l); } - if (c >= '%' && c <= '~' && - (l->t.t = dc_lex_tokens[(c - '%')]) != BC_LEX_INVALID) - { + if (c >= '%' && c <= '~' + && (l->t.t = dc_lex_tokens[(c - '%')]) != BC_LEX_INVALID + ) { return s; } // This is the workhorse of the lexer. switch (c) { - case '\0': - { l->t.t = BC_LEX_EOF; break; - } - case '\n': case '\t': case '\v': case '\f': case '\r': case ' ': - { l->newline = (c == '\n'); bc_lex_whitespace(l); break; - } - case '!': - { c2 = l->buf[l->i]; - if (c2 == '=') l->t.t = BC_LEX_OP_REL_NE; else if (c2 == '<') @@ -3482,26 +3380,17 @@ static FAST_FUNC BcStatus dc_lex_token(BcLex *l) l->t.t = BC_LEX_OP_REL_GE; else return bc_error_bad_character(c); - ++l->i; break; - } - case '#': - { bc_lex_lineComment(l); break; - } - case '.': - { if (isdigit(l->buf[l->i])) s = zbc_lex_number(l, c); else s = bc_error_bad_character(c); break; - } - case '0': case '1': case '2': @@ -3518,23 +3407,15 @@ static FAST_FUNC BcStatus dc_lex_token(BcLex *l) case 'D': case 'E': case 'F': - { s = zbc_lex_number(l, c); break; - } - case '[': - { s = zdc_lex_string(l); break; - } - default: - { l->t.t = BC_LEX_INVALID; s = bc_error_bad_character(c); break; - } } return s; @@ -4112,7 +3993,7 @@ static BcStatus bc_parse_return(BcParse *p) if (!paren || p->l.t.last != BC_LEX_RPAREN) { s = bc_POSIX_requires("parentheses around return expressions"); - if (s) return s; + ERROR_RETURN(if (s) return s;) } bc_parse_push(p, BC_INST_RET); @@ -5013,11 +4894,11 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext ne if (!(flags & BC_PARSE_REL) && nrelops) { s = bc_POSIX_does_not_allow("comparison operators outside if or loops"); - if (s) return s; + ERROR_RETURN(if (s) return s;) } else if ((flags & BC_PARSE_REL) && nrelops > 1) { s = bc_POSIX_requires("exactly one comparison operator per condition"); - if (s) return s; + ERROR_RETURN(if (s) return s;) } if (flags & BC_PARSE_PRINT) { -- cgit v1.2.3-55-g6feb From 69171dc466ab94daf14e7560efe92c5050b0c1b1 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 12 Dec 2018 00:29:24 +0100 Subject: bc: simplify nested read() check function old new delta bc_vm_run 622 624 +2 dc_main 186 187 +1 bc_main 72 73 +1 bc_program_read 312 277 -35 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 3/1 up/down: 4/-35) Total: -31 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 70db2ce3d..791275c8c 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -736,6 +736,7 @@ typedef struct BcProgram { struct globals { IF_FEATURE_BC_SIGNALS(smallint ttyin;) IF_FEATURE_CLEAN_UP(smallint exiting;) + smallint in_read; char sbgn; char send; @@ -5390,20 +5391,18 @@ static BcStatus bc_program_read(void) BcParse parse; BcVec buf; BcInstPtr ip; - size_t i; - BcFunc *f = bc_program_func(BC_PROG_READ); + BcFunc *f; - for (i = 0; i < G.prog.stack.len; ++i) { - BcInstPtr *ip_ptr = bc_vec_item(&G.prog.stack, i); - if (ip_ptr->func == BC_PROG_READ) - return bc_error_nested_read_call(); - } + if (G.in_read) + return bc_error_nested_read_call(); + f = bc_program_func(BC_PROG_READ); bc_vec_pop_all(&f->code); bc_char_vec_init(&buf); sv_file = G.prog.file; G.prog.file = NULL; + G.in_read = 1; s = bc_read_line(&buf); //if (s) goto io_err; - wrong, nonzero return means EOF, not error @@ -5434,6 +5433,7 @@ static BcStatus bc_program_read(void) exec_err: bc_parse_free(&parse); //io_err: + G.in_read = 0; G.prog.file = sv_file; bc_vec_free(&buf); return s; -- cgit v1.2.3-55-g6feb From 16494f557fd742ca484943407888fb8a349c01ee Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 12 Dec 2018 00:50:23 +0100 Subject: bc: simplify zbc_program_logical() function old new delta bc_program_exec 3918 3876 -42 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-42) Total: -42 bytes text data bss dec hex filename 982061 485 7296 989842 f1a92 busybox_old 982019 485 7296 989800 f1a68 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 791275c8c..8426998d0 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -5793,8 +5793,7 @@ static BC_STATUS zbc_program_logical(char inst) BcStatus s; BcResult *opd1, *opd2, res; BcNum *n1, *n2; - bool cond = 0; - ssize_t cmp; + ssize_t cond; s = zbc_program_binOpPrep(&opd1, &n1, &opd2, &n2, false); if (s) RETURN_STATUS(s); @@ -5806,25 +5805,25 @@ static BC_STATUS zbc_program_logical(char inst) else if (inst == BC_INST_BOOL_OR) cond = bc_num_cmp(n1, &G.prog.zero) || bc_num_cmp(n2, &G.prog.zero); else { - cmp = bc_num_cmp(n1, n2); + cond = bc_num_cmp(n1, n2); switch (inst) { case BC_INST_REL_EQ: - cond = cmp == 0; + cond = (cond == 0); break; case BC_INST_REL_LE: - cond = cmp <= 0; + cond = (cond <= 0); break; case BC_INST_REL_GE: - cond = cmp >= 0; - break; - case BC_INST_REL_NE: - cond = cmp != 0; + cond = (cond >= 0); break; case BC_INST_REL_LT: - cond = cmp < 0; + cond = (cond < 0); break; case BC_INST_REL_GT: - cond = cmp > 0; + cond = (cond > 0); + break; + default: // = case BC_INST_REL_NE: + //cond = (cond != 0); - not needed break; } } -- cgit v1.2.3-55-g6feb From 251fbb57be45a8c4835f90f7126fa9fd27176373 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 12 Dec 2018 11:51:32 +0100 Subject: bc: code shrink in bc_num_cmp() function old new delta bc_num_cmp 275 231 -44 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 8426998d0..8f326d20e 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1601,46 +1601,44 @@ static ssize_t bc_num_cmp(BcNum *a, BcNum *b) { size_t i, min, a_int, b_int, diff; BcDig *max_num, *min_num; - bool a_max, neg = false; + bool a_max, neg; ssize_t cmp; if (a == b) return 0; if (a->len == 0) return BC_NUM_NEG(!!b->len, !b->neg); if (b->len == 0) return BC_NUM_NEG(1, a->neg); - if (a->neg) { - if (b->neg) - neg = true; - else - return -1; - } - else if (b->neg) - return 1; + + if (a->neg != b->neg) // signs of a and b differ + // +a,-b = a>b = 1 or -a,+b = aneg - (int)a->neg; + neg = a->neg; // 1 if both negative, 0 if both positive a_int = BC_NUM_INT(a); b_int = BC_NUM_INT(b); a_int -= b_int; - a_max = (a->rdx > b->rdx); if (a_int != 0) return (ssize_t) a_int; + a_max = (a->rdx > b->rdx); if (a_max) { min = b->rdx; diff = a->rdx - b->rdx; max_num = a->num + diff; min_num = b->num; - } - else { + // neg = (a_max == neg); - NOP (maps 1->1 and 0->0) + } else { min = a->rdx; diff = b->rdx - a->rdx; max_num = b->num + diff; min_num = a->num; + neg = !neg; // same as "neg = (a_max == neg)" } cmp = bc_num_compare(max_num, min_num, b_int + min); - if (cmp != 0) return BC_NUM_NEG(cmp, (!a_max) != neg); + if (cmp != 0) return BC_NUM_NEG(cmp, neg); for (max_num -= diff, i = diff - 1; i < diff; --i) { - if (max_num[i]) return BC_NUM_NEG(1, (!a_max) != neg); + if (max_num[i]) return BC_NUM_NEG(1, neg); } return 0; -- cgit v1.2.3-55-g6feb From 9a34e89289d760fbe41aa79c684159f3c9f60645 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 12 Dec 2018 13:58:55 +0100 Subject: bc: partially convert lexer functions to "z" convention function old new delta bc_lex_token 1228 - -1228 zbc_lex_token - 1193 +1193 dc_lex_token 674 - -674 zdc_lex_token - 672 +672 bc_parse_operator 177 - -177 zbc_parse_operator - 175 +175 bc_parse_else 133 - -133 zbc_parse_else - 133 +133 bc_lex_next 91 - -91 zbc_lex_next - 81 +81 dc_parse_expr 744 748 +4 bc_parse_string 100 102 +2 bc_parse_body 114 116 +2 dc_parse_mem 116 115 -1 bc_parse_text 130 129 -1 dc_parse_register 51 43 -8 bc_parse_endBody 358 338 -20 bc_parse_name 513 451 -62 bc_parse_auto 265 201 -64 bc_parse_expr_empty_ok 2032 1955 -77 bc_parse_parse 417 321 -96 bc_parse_stmt 1753 1598 -155 ------------------------------------------------------------------------------ (add/remove: 5/5 grow/shrink: 3/9 up/down: 2262/-2787) Total: -525 bytes text data bss dec hex filename 981975 485 7296 989756 f1a3c busybox_old 981450 485 7296 989231 f182f busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 266 ++++++++++++++++++++++++++++++++------------------------- 1 file changed, 148 insertions(+), 118 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 8f326d20e..eae5063a8 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -544,8 +544,14 @@ enum { #define bc_lex_kws_POSIX(i) ((1 << (i)) & POSIX_KWORD_MASK) #endif +#if ENABLE_FEATURE_BC_SIGNALS || ENABLE_FEATURE_CLEAN_UP +# define BC_STATUS BcStatus +#else +# define BC_STATUS void +#endif + struct BcLex; -typedef BcStatus (*BcLexNext)(struct BcLex *) FAST_FUNC; +typedef BC_STATUS (*BcLexNext)(struct BcLex *) FAST_FUNC; typedef struct BcLex { @@ -933,13 +939,13 @@ dc_parse_insts[] = { # define ERRORS_ARE_FATAL 0 # define ERRORFUNC /*nothing*/ # define ERROR_RETURN(a) a -# define BC_STATUS BcStatus +//moved up: # define BC_STATUS BcStatus # define RETURN_STATUS(v) return (v) #else # define ERRORS_ARE_FATAL 1 # define ERRORFUNC NORETURN # define ERROR_RETURN(a) /*nothing*/ -# define BC_STATUS void +//moved up: # define BC_STATUS void # define RETURN_STATUS(v) do { ((void)(v)); return; } while (0) #endif @@ -2940,40 +2946,48 @@ static void bc_lex_file(BcLex *l) l->newline = false; } -static BcStatus bc_lex_next(BcLex *l) +static BC_STATUS zbc_lex_next(BcLex *l) { BcStatus s; l->t.last = l->t.t; - if (l->t.last == BC_LEX_EOF) return bc_error("end of file"); + if (l->t.last == BC_LEX_EOF) RETURN_STATUS(bc_error("end of file")); l->line += l->newline; G.err_line = l->line; l->t.t = BC_LEX_EOF; l->newline = (l->i == l->len); - if (l->newline) return BC_STATUS_SUCCESS; + if (l->newline) RETURN_STATUS(BC_STATUS_SUCCESS); // Loop until failure or we don't have whitespace. This // is so the parser doesn't get inundated with whitespace. + s = BC_STATUS_SUCCESS; do { - s = l->next(l); +//TODO: replace pointer with if(IS_BC) + ERROR_RETURN(s =) l->next(l); } while (!s && l->t.t == BC_LEX_WHITESPACE); - return s; + RETURN_STATUS(s); } +#if ERRORS_ARE_FATAL +# define zbc_lex_next(...) (zbc_lex_next(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif -static BcStatus bc_lex_text(BcLex *l, const char *text) +static BC_STATUS zbc_lex_text(BcLex *l, const char *text) { l->buf = text; l->i = 0; l->len = strlen(text); l->t.t = l->t.last = BC_LEX_INVALID; - return bc_lex_next(l); + RETURN_STATUS(zbc_lex_next(l)); } +#if ERRORS_ARE_FATAL +# define zbc_lex_text(...) (zbc_lex_text(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif #if ENABLE_BC -static BcStatus bc_lex_identifier(BcLex *l) +static BC_STATUS zbc_lex_identifier(BcLex *l) { BcStatus s; unsigned i; @@ -2993,12 +3007,12 @@ static BcStatus bc_lex_identifier(BcLex *l) l->t.t = BC_LEX_KEY_1st_keyword + i; if (!bc_lex_kws_POSIX(i)) { s = bc_posix_error_fmt("%sthe '%.8s' keyword", "POSIX does not allow ", bc_lex_kws[i].name8); - ERROR_RETURN(if (s) return s;) + ERROR_RETURN(if (s) RETURN_STATUS(s);) } // We minus 1 because the index has already been incremented. l->i += j - 1; - return BC_STATUS_SUCCESS; + RETURN_STATUS(BC_STATUS_SUCCESS); } bc_lex_name(l); @@ -3012,8 +3026,11 @@ static BcStatus bc_lex_identifier(BcLex *l) s = bc_posix_error_fmt("POSIX only allows one character names; the following is bad: '%.*s'", len, buf); } - return s; + RETURN_STATUS(s); } +#if ERRORS_ARE_FATAL +# define zbc_lex_identifier(...) (zbc_lex_identifier(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static BcStatus bc_lex_string(BcLex *l) { @@ -3088,7 +3105,7 @@ static BC_STATUS zbc_lex_comment(BcLex *l) # define zbc_lex_comment(...) (zbc_lex_comment(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static FAST_FUNC BcStatus bc_lex_token(BcLex *l) +static FAST_FUNC BC_STATUS zbc_lex_token(BcLex *l) { BcStatus s = BC_STATUS_SUCCESS; char c = l->buf[l->i++], c2; @@ -3111,7 +3128,7 @@ static FAST_FUNC BcStatus bc_lex_token(BcLex *l) bc_lex_assign(l, BC_LEX_OP_REL_NE, BC_LEX_OP_BOOL_NOT); if (l->t.t == BC_LEX_OP_BOOL_NOT) { s = bc_POSIX_does_not_allow_bool_ops_this_is_bad("!"); - ERROR_RETURN(if (s) return s;) + ERROR_RETURN(if (s) RETURN_STATUS(s);) } break; case '"': @@ -3119,7 +3136,7 @@ static FAST_FUNC BcStatus bc_lex_token(BcLex *l) break; case '#': s = bc_POSIX_does_not_allow("'#' script comments"); - ERROR_RETURN(if (s) return s;) + ERROR_RETURN(if (s) RETURN_STATUS(s);) bc_lex_lineComment(l); break; case '%': @@ -3129,7 +3146,7 @@ static FAST_FUNC BcStatus bc_lex_token(BcLex *l) c2 = l->buf[l->i]; if (c2 == '&') { s = bc_POSIX_does_not_allow_bool_ops_this_is_bad("&&"); - ERROR_RETURN(if (s) return s;) + ERROR_RETURN(if (s) RETURN_STATUS(s);) ++l->i; l->t.t = BC_LEX_OP_BOOL_AND; } else { @@ -3248,7 +3265,7 @@ static FAST_FUNC BcStatus bc_lex_token(BcLex *l) case 'x': case 'y': case 'z': - s = bc_lex_identifier(l); + s = zbc_lex_identifier(l); break; case '{': case '}': @@ -3258,7 +3275,7 @@ static FAST_FUNC BcStatus bc_lex_token(BcLex *l) c2 = l->buf[l->i]; if (c2 == '|') { s = bc_POSIX_does_not_allow_bool_ops_this_is_bad("||"); - ERROR_RETURN(if (s) return s;) + ERROR_RETURN(if (s) RETURN_STATUS(s);) ++l->i; l->t.t = BC_LEX_OP_BOOL_OR; } else { @@ -3272,7 +3289,7 @@ static FAST_FUNC BcStatus bc_lex_token(BcLex *l) break; } - return s; + RETURN_STATUS(s); } #endif // ENABLE_BC @@ -3338,7 +3355,7 @@ static BC_STATUS zdc_lex_string(BcLex *l) # define zdc_lex_string(...) (zdc_lex_string(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static FAST_FUNC BcStatus dc_lex_token(BcLex *l) +static FAST_FUNC BC_STATUS zdc_lex_token(BcLex *l) { BcStatus s = BC_STATUS_SUCCESS; char c = l->buf[l->i++], c2; @@ -3346,13 +3363,13 @@ static FAST_FUNC BcStatus dc_lex_token(BcLex *l) for (i = 0; i < ARRAY_SIZE(dc_lex_regs); ++i) { if (l->t.last == dc_lex_regs[i]) - return zdc_lex_register(l); + RETURN_STATUS(zdc_lex_register(l)); } if (c >= '%' && c <= '~' && (l->t.t = dc_lex_tokens[(c - '%')]) != BC_LEX_INVALID ) { - return s; + RETURN_STATUS(s); } // This is the workhorse of the lexer. @@ -3378,7 +3395,7 @@ static FAST_FUNC BcStatus dc_lex_token(BcLex *l) else if (c2 == '>') l->t.t = BC_LEX_OP_REL_GE; else - return bc_error_bad_character(c); + RETURN_STATUS(bc_error_bad_character(c)); ++l->i; break; case '#': @@ -3417,7 +3434,7 @@ static FAST_FUNC BcStatus dc_lex_token(BcLex *l) break; } - return s; + RETURN_STATUS(s); } #endif // ENABLE_DC @@ -3482,7 +3499,7 @@ static BcStatus bc_parse_text(BcParse *p, const char *text) return bc_error("file is not executable"); } - return bc_lex_text(&p->l, text); + return zbc_lex_text(&p->l, text); } // Called when parsing or execution detects a failure, @@ -3566,12 +3583,12 @@ static void bc_parse_create(BcParse *p, size_t func, // first in the expr enum. Note: This only works for binary operators. #define BC_PARSE_TOKEN_INST(t) ((char) ((t) -BC_LEX_NEG + BC_INST_NEG)) -static BcStatus bc_parse_else(BcParse *p); +static BC_STATUS zbc_parse_else(BcParse *p); static BcStatus bc_parse_stmt(BcParse *p); static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next); static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext next); -static BcStatus bc_parse_operator(BcParse *p, BcLexType type, size_t start, +static BC_STATUS zbc_parse_operator(BcParse *p, BcLexType type, size_t start, size_t *nexprs, bool next) { BcStatus s = BC_STATUS_SUCCESS; @@ -3593,35 +3610,40 @@ static BcStatus bc_parse_operator(BcParse *p, BcLexType type, size_t start, } bc_vec_push(&p->ops, &type); - if (next) s = bc_lex_next(&p->l); + if (next) s = zbc_lex_next(&p->l); - return s; + RETURN_STATUS(s); } +#if ERRORS_ARE_FATAL +# define zbc_parse_operator(...) (zbc_parse_operator(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif -static BcStatus bc_parse_rightParen(BcParse *p, size_t ops_bgn, size_t *nexs) +static BC_STATUS zbc_parse_rightParen(BcParse *p, size_t ops_bgn, size_t *nexs) { BcLexType top; if (p->ops.len <= ops_bgn) - return bc_error_bad_expression(); + RETURN_STATUS(bc_error_bad_expression()); top = BC_PARSE_TOP_OP(p); while (top != BC_LEX_LPAREN) { - bc_parse_push(p, BC_PARSE_TOKEN_INST(top)); bc_vec_pop(&p->ops); *nexs -= top != BC_LEX_OP_BOOL_NOT && top != BC_LEX_NEG; if (p->ops.len <= ops_bgn) - return bc_error_bad_expression(); + RETURN_STATUS(bc_error_bad_expression()); top = BC_PARSE_TOP_OP(p); } bc_vec_pop(&p->ops); - return bc_lex_next(&p->l); + RETURN_STATUS(zbc_lex_next(&p->l)); } +#if ERRORS_ARE_FATAL +# define zbc_parse_rightParen(...) (zbc_parse_rightParen(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static BcStatus bc_parse_params(BcParse *p, uint8_t flags) { @@ -3629,7 +3651,7 @@ static BcStatus bc_parse_params(BcParse *p, uint8_t flags) bool comma = false; size_t nparams; - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) return s; for (nparams = 0; p->l.t.t != BC_LEX_RPAREN; ++nparams) { @@ -3640,7 +3662,7 @@ static BcStatus bc_parse_params(BcParse *p, uint8_t flags) comma = p->l.t.t == BC_LEX_COMMA; if (comma) { - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) return s; } } @@ -3682,7 +3704,7 @@ static BcStatus bc_parse_call(BcParse *p, char *name, uint8_t flags) entry_ptr = bc_vec_item(&G.prog.fn_map, idx); bc_parse_pushIndex(p, entry_ptr->idx); - return bc_lex_next(&p->l); + return zbc_lex_next(&p->l); err: free(name); @@ -3695,12 +3717,12 @@ static BcStatus bc_parse_name(BcParse *p, BcInst *type, uint8_t flags) char *name; name = xstrdup(p->l.t.v.v); - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) goto err; if (p->l.t.t == BC_LEX_LBRACKET) { - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) goto err; if (p->l.t.t == BC_LEX_RBRACKET) { @@ -3721,7 +3743,7 @@ static BcStatus bc_parse_name(BcParse *p, BcInst *type, uint8_t flags) if (s) goto err; } - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) goto err; bc_parse_push(p, *type); bc_parse_pushName(p, name); @@ -3753,17 +3775,17 @@ static BcStatus bc_parse_read(BcParse *p) { BcStatus s; - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) return s; if (p->l.t.t != BC_LEX_LPAREN) return bc_error_bad_token(); - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) return s; if (p->l.t.t != BC_LEX_RPAREN) return bc_error_bad_token(); bc_parse_push(p, BC_INST_READ); - return bc_lex_next(&p->l); + return zbc_lex_next(&p->l); } static BcStatus bc_parse_builtin(BcParse *p, BcLexType type, uint8_t flags, @@ -3771,13 +3793,13 @@ static BcStatus bc_parse_builtin(BcParse *p, BcLexType type, uint8_t flags, { BcStatus s; - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) return s; if (p->l.t.t != BC_LEX_LPAREN) return bc_error_bad_token(); flags = (flags & ~(BC_PARSE_PRINT | BC_PARSE_REL)) | BC_PARSE_ARRAY; - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) return s; s = bc_parse_expr(p, flags, bc_parse_next_rel); @@ -3788,14 +3810,14 @@ static BcStatus bc_parse_builtin(BcParse *p, BcLexType type, uint8_t flags, *prev = (type == BC_LEX_KEY_LENGTH) ? BC_INST_LENGTH : BC_INST_SQRT; bc_parse_push(p, *prev); - return bc_lex_next(&p->l); + return zbc_lex_next(&p->l); } static BcStatus bc_parse_scale(BcParse *p, BcInst *type, uint8_t flags) { BcStatus s; - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) return s; if (p->l.t.t != BC_LEX_LPAREN) { @@ -3807,7 +3829,7 @@ static BcStatus bc_parse_scale(BcParse *p, BcInst *type, uint8_t flags) *type = BC_INST_SCALE_FUNC; flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL); - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) return s; s = bc_parse_expr(p, flags, bc_parse_next_rel); @@ -3815,7 +3837,7 @@ static BcStatus bc_parse_scale(BcParse *p, BcInst *type, uint8_t flags) if (p->l.t.t != BC_LEX_RPAREN) return bc_error_bad_token(); bc_parse_push(p, BC_INST_SCALE_FUNC); - return bc_lex_next(&p->l); + return zbc_lex_next(&p->l); } static BcStatus bc_parse_incdec(BcParse *p, BcInst *prev, bool *paren_expr, @@ -3832,14 +3854,14 @@ static BcStatus bc_parse_incdec(BcParse *p, BcInst *prev, bool *paren_expr, { *prev = inst = BC_INST_INC_POST + (p->l.t.t != BC_LEX_OP_INC); bc_parse_push(p, inst); - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); } else { *prev = inst = BC_INST_INC_PRE + (p->l.t.t != BC_LEX_OP_INC); *paren_expr = true; - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) return s; type = p->l.t.t; @@ -3860,13 +3882,13 @@ static BcStatus bc_parse_incdec(BcParse *p, BcInst *prev, bool *paren_expr, case BC_LEX_KEY_OBASE: { bc_parse_push(p, type - BC_LEX_KEY_IBASE + BC_INST_IBASE); - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); break; } case BC_LEX_KEY_SCALE: { - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) return s; if (p->l.t.t == BC_LEX_LPAREN) s = bc_error_bad_token(); @@ -3895,7 +3917,7 @@ static BcStatus bc_parse_minus(BcParse *p, BcInst *prev, size_t ops_bgn, BcLexType type; BcInst etype = *prev; - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) return s; type = rparen || etype == BC_INST_INC_POST || etype == BC_INST_DEC_POST || @@ -3909,7 +3931,7 @@ static BcStatus bc_parse_minus(BcParse *p, BcInst *prev, size_t ops_bgn, if (type != BC_LEX_OP_MINUS) bc_vec_push(&p->ops, &type); else - s = bc_parse_operator(p, type, ops_bgn, nexprs, false); + s = zbc_parse_operator(p, type, ops_bgn, nexprs, false); return s; } @@ -3923,7 +3945,7 @@ static BcStatus bc_parse_string(BcParse *p, char inst) bc_vec_push(&G.prog.strs, &str); bc_parse_push(p, inst); - return bc_lex_next(&p->l); + return zbc_lex_next(&p->l); } static BcStatus bc_parse_print(BcParse *p) @@ -3932,7 +3954,7 @@ static BcStatus bc_parse_print(BcParse *p) BcLexType type; bool comma; - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) return s; type = p->l.t.t; @@ -3954,7 +3976,7 @@ static BcStatus bc_parse_print(BcParse *p) comma = p->l.t.t == BC_LEX_COMMA; if (comma) { - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) return s; } type = p->l.t.t; @@ -3962,7 +3984,7 @@ static BcStatus bc_parse_print(BcParse *p) if (comma) return bc_error_bad_token(); - return bc_lex_next(&p->l); + return zbc_lex_next(&p->l); } static BcStatus bc_parse_return(BcParse *p) @@ -3973,7 +3995,7 @@ static BcStatus bc_parse_return(BcParse *p) if (!BC_PARSE_FUNC(p)) return bc_error_bad_token(); - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) return s; t = p->l.t.t; @@ -3986,7 +4008,7 @@ static BcStatus bc_parse_return(BcParse *p) s = bc_parse_expr_empty_ok(p, 0, bc_parse_next_expr); if (s == BC_STATUS_PARSE_EMPTY_EXP) { bc_parse_push(p, BC_INST_RET0); - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); } if (s) return s; @@ -4013,7 +4035,7 @@ static BcStatus bc_parse_endBody(BcParse *p, bool brace) if (p->l.t.t == BC_LEX_RBRACE) { if (!p->nbraces) return bc_error_bad_token(); --p->nbraces; - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) return s; } else @@ -4025,7 +4047,7 @@ static BcStatus bc_parse_endBody(BcParse *p, bool brace) uint8_t *flag_ptr; while (p->l.t.t == BC_LEX_NLINE) { - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) return s; } @@ -4034,7 +4056,8 @@ static BcStatus bc_parse_endBody(BcParse *p, bool brace) flag_ptr = BC_PARSE_TOP_FLAG_PTR(p); *flag_ptr = (*flag_ptr | BC_PARSE_FLAG_IF_END); - if (p->l.t.t == BC_LEX_KEY_ELSE) s = bc_parse_else(p); + if (p->l.t.t == BC_LEX_KEY_ELSE) + ERROR_RETURN(s =) zbc_parse_else(p); } else if (BC_PARSE_ELSE(p)) { @@ -4101,17 +4124,17 @@ static BcStatus bc_parse_if(BcParse *p) BcStatus s; BcInstPtr ip; - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) return s; if (p->l.t.t != BC_LEX_LPAREN) return bc_error_bad_token(); - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) return s; s = bc_parse_expr(p, BC_PARSE_REL, bc_parse_next_rel); if (s) return s; if (p->l.t.t != BC_LEX_RPAREN) return bc_error_bad_token(); - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) return s; bc_parse_push(p, BC_INST_JUMP_ZERO); @@ -4126,11 +4149,11 @@ static BcStatus bc_parse_if(BcParse *p) return BC_STATUS_SUCCESS; } -static BcStatus bc_parse_else(BcParse *p) +static BC_STATUS zbc_parse_else(BcParse *p) { BcInstPtr ip; - if (!BC_PARSE_IF_END(p)) return bc_error_bad_token(); + if (!BC_PARSE_IF_END(p)) RETURN_STATUS(bc_error_bad_token()); ip.idx = p->func->labels.len; ip.func = ip.len = 0; @@ -4144,18 +4167,21 @@ static BcStatus bc_parse_else(BcParse *p) bc_vec_push(&p->func->labels, &ip.idx); bc_parse_startBody(p, BC_PARSE_FLAG_ELSE); - return bc_lex_next(&p->l); + RETURN_STATUS(zbc_lex_next(&p->l)); } +#if ERRORS_ARE_FATAL +# define zbc_parse_else(...) (zbc_parse_else(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static BcStatus bc_parse_while(BcParse *p) { BcStatus s; BcInstPtr ip; - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) return s; if (p->l.t.t != BC_LEX_LPAREN) return bc_error_bad_token(); - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) return s; ip.idx = p->func->labels.len; @@ -4173,7 +4199,7 @@ static BcStatus bc_parse_while(BcParse *p) s = bc_parse_expr(p, BC_PARSE_REL, bc_parse_next_rel); if (s) return s; if (p->l.t.t != BC_LEX_RPAREN) return bc_error_bad_token(); - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) return s; bc_parse_push(p, BC_INST_JUMP_ZERO); @@ -4189,10 +4215,10 @@ static BcStatus bc_parse_for(BcParse *p) BcInstPtr ip; size_t cond_idx, exit_idx, body_idx, update_idx; - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) return s; if (p->l.t.t != BC_LEX_LPAREN) return bc_error_bad_token(); - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) return s; if (p->l.t.t != BC_LEX_SCOLON) @@ -4202,7 +4228,7 @@ static BcStatus bc_parse_for(BcParse *p) if (s) return s; if (p->l.t.t != BC_LEX_SCOLON) return bc_error_bad_token(); - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) return s; cond_idx = p->func->labels.len; @@ -4220,7 +4246,7 @@ static BcStatus bc_parse_for(BcParse *p) if (s) return s; if (p->l.t.t != BC_LEX_SCOLON) return bc_error_bad_token(); - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) return s; bc_parse_push(p, BC_INST_JUMP_ZERO); @@ -4251,7 +4277,8 @@ static BcStatus bc_parse_for(BcParse *p) bc_vec_push(&p->exits, &ip); bc_vec_push(&p->func->labels, &ip.idx); - bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); + if (s) return s; bc_parse_startBody(p, BC_PARSE_FLAG_LOOP | BC_PARSE_FLAG_LOOP_INNER); return BC_STATUS_SUCCESS; @@ -4283,13 +4310,13 @@ static BcStatus bc_parse_loopExit(BcParse *p, BcLexType type) bc_parse_push(p, BC_INST_JUMP); bc_parse_pushIndex(p, i); - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) return s; if (p->l.t.t != BC_LEX_SCOLON && p->l.t.t != BC_LEX_NLINE) return bc_error_bad_token(); - return bc_lex_next(&p->l); + return zbc_lex_next(&p->l); } static BcStatus bc_parse_func(BcParse *p) @@ -4299,7 +4326,7 @@ static BcStatus bc_parse_func(BcParse *p) uint8_t flags; char *name; - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) return s; if (p->l.t.t != BC_LEX_NAME) return bc_error("bad function definition"); @@ -4307,11 +4334,11 @@ static BcStatus bc_parse_func(BcParse *p) name = xstrdup(p->l.t.v.v); bc_parse_addFunc(p, name, &p->fidx); - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) return s; if (p->l.t.t != BC_LEX_LPAREN) return bc_error("bad function definition"); - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) return s; while (p->l.t.t != BC_LEX_RPAREN) { @@ -4322,14 +4349,14 @@ static BcStatus bc_parse_func(BcParse *p) ++p->func->nparams; name = xstrdup(p->l.t.v.v); - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) goto err; var = p->l.t.t != BC_LEX_LBRACKET; if (!var) { - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) goto err; if (p->l.t.t != BC_LEX_RBRACKET) { @@ -4337,13 +4364,13 @@ static BcStatus bc_parse_func(BcParse *p) goto err; } - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) goto err; } comma = p->l.t.t == BC_LEX_COMMA; if (comma) { - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) goto err; } @@ -4356,7 +4383,7 @@ static BcStatus bc_parse_func(BcParse *p) flags = BC_PARSE_FLAG_FUNC | BC_PARSE_FLAG_FUNC_INNER | BC_PARSE_FLAG_BODY; bc_parse_startBody(p, flags); - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) return s; if (p->l.t.t != BC_LEX_LBRACE) @@ -4376,7 +4403,7 @@ static BcStatus bc_parse_auto(BcParse *p) char *name; if (!p->auto_part) return bc_error_bad_token(); - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) return s; p->auto_part = comma = false; @@ -4385,13 +4412,13 @@ static BcStatus bc_parse_auto(BcParse *p) while (p->l.t.t == BC_LEX_NAME) { name = xstrdup(p->l.t.v.v); - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) goto err; var = p->l.t.t != BC_LEX_LBRACKET; if (!var) { - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) goto err; if (p->l.t.t != BC_LEX_RBRACKET) { @@ -4399,13 +4426,13 @@ static BcStatus bc_parse_auto(BcParse *p) goto err; } - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) goto err; } comma = p->l.t.t == BC_LEX_COMMA; if (comma) { - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) goto err; } @@ -4419,7 +4446,7 @@ static BcStatus bc_parse_auto(BcParse *p) if (p->l.t.t != BC_LEX_NLINE && p->l.t.t != BC_LEX_SCOLON) return bc_error_bad_token(); - return bc_lex_next(&p->l); + return zbc_lex_next(&p->l); err: free(name); @@ -4443,7 +4470,7 @@ static BcStatus bc_parse_body(BcParse *p, bool brace) if (s) return s; } - if (p->l.t.t == BC_LEX_NLINE) s = bc_lex_next(&p->l); + if (p->l.t.t == BC_LEX_NLINE) s = zbc_lex_next(&p->l); } else { s = bc_parse_stmt(p); @@ -4461,7 +4488,7 @@ static BcStatus bc_parse_stmt(BcParse *p) case BC_LEX_NLINE: { - return bc_lex_next(&p->l); + return zbc_lex_next(&p->l); } case BC_LEX_KEY_ELSE: @@ -4475,7 +4502,7 @@ static BcStatus bc_parse_stmt(BcParse *p) if (!BC_PARSE_BODY(p)) return bc_error_bad_token(); ++p->nbraces; - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) return s; return bc_parse_body(p, true); @@ -4524,13 +4551,13 @@ static BcStatus bc_parse_stmt(BcParse *p) case BC_LEX_KEY_ELSE: { - s = bc_parse_else(p); + s = zbc_parse_else(p); break; } case BC_LEX_SCOLON: { - while (!s && p->l.t.t == BC_LEX_SCOLON) s = bc_lex_next(&p->l); + while (!s && p->l.t.t == BC_LEX_SCOLON) s = zbc_lex_next(&p->l); break; } @@ -4562,7 +4589,7 @@ static BcStatus bc_parse_stmt(BcParse *p) case BC_LEX_KEY_HALT: { bc_parse_push(p, BC_INST_HALT); - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); break; } @@ -4576,7 +4603,7 @@ static BcStatus bc_parse_stmt(BcParse *p) { // "limits" is a compile-time command, // the output is produced at _parse time_. - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) return s; printf( "BC_BASE_MAX = "BC_MAX_OBASE_STR "\n" @@ -4726,7 +4753,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext ne nrelops += t >= BC_LEX_OP_REL_EQ && t <= BC_LEX_OP_REL_GT; prev = BC_PARSE_TOKEN_INST(t); - s = bc_parse_operator(p, t, ops_bgn, &nexprs, true); + s = zbc_parse_operator(p, t, ops_bgn, &nexprs, true); rprn = get_token = false; bin_last = t != BC_LEX_OP_BOOL_NOT; @@ -4763,7 +4790,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext ne paren_expr = rprn = true; get_token = bin_last = false; - s = bc_parse_rightParen(p, ops_bgn, &nexprs); + s = zbc_parse_rightParen(p, ops_bgn, &nexprs); break; } @@ -4857,7 +4884,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext ne } } - if (!s && get_token) s = bc_lex_next(&p->l); + if (!s && get_token) s = zbc_lex_next(&p->l); } if (s) return s; @@ -4920,7 +4947,7 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) static void bc_parse_init(BcParse *p, size_t func) { - bc_parse_create(p, func, bc_parse_parse, bc_lex_token); + bc_parse_create(p, func, bc_parse_parse, zbc_lex_token); } static BcStatus bc_parse_expression(BcParse *p, uint8_t flags) @@ -4939,7 +4966,7 @@ static BcStatus dc_parse_register(BcParse *p) BcStatus s; char *name; - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) return s; if (p->l.t.t != BC_LEX_NAME) return bc_error_bad_token(); @@ -4949,7 +4976,7 @@ static BcStatus dc_parse_register(BcParse *p) return s; } -static BcStatus dc_parse_string(BcParse *p) +static BC_STATUS zdc_parse_string(BcParse *p) { char *str, *name, b[DC_PARSE_BUF_LEN + 1]; size_t idx, len = G.prog.strs.len; @@ -4963,8 +4990,11 @@ static BcStatus dc_parse_string(BcParse *p) bc_vec_push(&G.prog.strs, &str); bc_parse_addFunc(p, name, &idx); - return bc_lex_next(&p->l); + RETURN_STATUS(zbc_lex_next(&p->l)); } +#if ERRORS_ARE_FATAL +# define zdc_parse_string(...) (zdc_parse_string(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static BcStatus dc_parse_mem(BcParse *p, uint8_t inst, bool name, bool store) { @@ -4982,7 +5012,7 @@ static BcStatus dc_parse_mem(BcParse *p, uint8_t inst, bool name, bool store) bc_parse_push(p, BC_INST_POP); } - return bc_lex_next(&p->l); + return zbc_lex_next(&p->l); } static BcStatus dc_parse_cond(BcParse *p, uint8_t inst) @@ -4995,13 +5025,13 @@ static BcStatus dc_parse_cond(BcParse *p, uint8_t inst) s = dc_parse_register(p); if (s) return s; - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) return s; if (p->l.t.t == BC_LEX_ELSE) { s = dc_parse_register(p); if (s) return s; - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); } else bc_parse_push(p, BC_PARSE_STREND); @@ -5038,7 +5068,7 @@ static BcStatus dc_parse_token(BcParse *p, BcLexType t, uint8_t flags) case BC_LEX_STR: { - s = dc_parse_string(p); + s = zdc_parse_string(p); break; } @@ -5046,7 +5076,7 @@ static BcStatus dc_parse_token(BcParse *p, BcLexType t, uint8_t flags) case BC_LEX_NUMBER: { if (t == BC_LEX_NEG) { - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); if (s) return s; if (p->l.t.t != BC_LEX_NUMBER) return bc_error_bad_token(); @@ -5104,7 +5134,7 @@ static BcStatus dc_parse_token(BcParse *p, BcLexType t, uint8_t flags) } } - if (!s && get_token) s = bc_lex_next(&p->l); + if (!s && get_token) s = zbc_lex_next(&p->l); return s; } @@ -5123,7 +5153,7 @@ static BcStatus dc_parse_expr(BcParse *p, uint8_t flags) if (inst != BC_INST_INVALID) { bc_parse_push(p, inst); - s = bc_lex_next(&p->l); + s = zbc_lex_next(&p->l); } else s = dc_parse_token(p, t, flags); @@ -5154,7 +5184,7 @@ static FAST_FUNC BcStatus dc_parse_parse(BcParse *p) static void dc_parse_init(BcParse *p, size_t func) { - bc_parse_create(p, func, dc_parse_parse, dc_lex_token); + bc_parse_create(p, func, dc_parse_parse, zdc_lex_token); } #endif // ENABLE_DC -- cgit v1.2.3-55-g6feb From 8cd468f60431931aa1aa88d3083dd2920e2cd7f2 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 12 Dec 2018 14:54:38 +0100 Subject: bc: convert more of lexer functions to "z" convention function old new delta dc_parse_expr 748 - -748 zdc_parse_expr - 688 +688 bc_parse_endBody 338 - -338 zbc_parse_endBody - 343 +343 bc_parse_auto 201 - -201 zbc_parse_auto - 198 +198 dc_parse_mem 115 - -115 zdc_parse_mem - 108 +108 bc_parse_body 116 - -116 zbc_parse_body - 108 +108 bc_parse_string 102 - -102 zbc_parse_string - 100 +100 dc_parse_register 43 - -43 zdc_parse_register - 40 +40 common_parse_expr 40 43 +3 bc_parse_parse 321 476 +155 bc_parse_stmt 1598 1594 -4 dc_parse_parse 44 26 -18 bc_parse_reset 153 - -153 ------------------------------------------------------------------------------ (add/remove: 7/8 grow/shrink: 2/2 up/down: 1743/-1838) Total: -95 bytes text data bss dec hex filename 981450 485 7296 989231 f182f busybox_old 981355 485 7296 989136 f17d0 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 274 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 137 insertions(+), 137 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index eae5063a8..3815b7f09 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -3771,22 +3771,25 @@ err: return s; } -static BcStatus bc_parse_read(BcParse *p) +static BC_STATUS zbc_parse_read(BcParse *p) { BcStatus s; s = zbc_lex_next(&p->l); - if (s) return s; - if (p->l.t.t != BC_LEX_LPAREN) return bc_error_bad_token(); + if (s) RETURN_STATUS(s); + if (p->l.t.t != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); s = zbc_lex_next(&p->l); - if (s) return s; - if (p->l.t.t != BC_LEX_RPAREN) return bc_error_bad_token(); + if (s) RETURN_STATUS(s); + if (p->l.t.t != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); bc_parse_push(p, BC_INST_READ); - return zbc_lex_next(&p->l); + RETURN_STATUS(zbc_lex_next(&p->l)); } +#if ERRORS_ARE_FATAL +# define zbc_parse_read(...) (zbc_parse_read(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static BcStatus bc_parse_builtin(BcParse *p, BcLexType type, uint8_t flags, BcInst *prev) @@ -3910,7 +3913,7 @@ static BcStatus bc_parse_incdec(BcParse *p, BcInst *prev, bool *paren_expr, return s; } -static BcStatus bc_parse_minus(BcParse *p, BcInst *prev, size_t ops_bgn, +static BC_STATUS zbc_parse_minus(BcParse *p, BcInst *prev, size_t ops_bgn, bool rparen, size_t *nexprs) { BcStatus s; @@ -3918,7 +3921,7 @@ static BcStatus bc_parse_minus(BcParse *p, BcInst *prev, size_t ops_bgn, BcInst etype = *prev; s = zbc_lex_next(&p->l); - if (s) return s; + if (s) RETURN_STATUS(s); type = rparen || etype == BC_INST_INC_POST || etype == BC_INST_DEC_POST || (etype >= BC_INST_NUM && etype <= BC_INST_SQRT) ? @@ -3933,10 +3936,13 @@ static BcStatus bc_parse_minus(BcParse *p, BcInst *prev, size_t ops_bgn, else s = zbc_parse_operator(p, type, ops_bgn, nexprs, false); - return s; + RETURN_STATUS(s); } +#if ERRORS_ARE_FATAL +# define zbc_parse_minus(...) (zbc_parse_minus(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif -static BcStatus bc_parse_string(BcParse *p, char inst) +static BC_STATUS zbc_parse_string(BcParse *p, char inst) { char *str = xstrdup(p->l.t.v.v); @@ -3945,8 +3951,11 @@ static BcStatus bc_parse_string(BcParse *p, char inst) bc_vec_push(&G.prog.strs, &str); bc_parse_push(p, inst); - return zbc_lex_next(&p->l); + RETURN_STATUS(zbc_lex_next(&p->l)); } +#if ERRORS_ARE_FATAL +# define zbc_parse_string(...) (zbc_parse_string(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static BcStatus bc_parse_print(BcParse *p) { @@ -3966,7 +3975,7 @@ static BcStatus bc_parse_print(BcParse *p) while (type != BC_LEX_SCOLON && type != BC_LEX_NLINE) { if (type == BC_LEX_STR) { - s = bc_parse_string(p, BC_INST_PRINT_POP); + s = zbc_parse_string(p, BC_INST_PRINT_POP); if (s) return s; } else { s = bc_parse_expr(p, 0, bc_parse_next_print); @@ -4023,32 +4032,29 @@ static BcStatus bc_parse_return(BcParse *p) return s; } -static BcStatus bc_parse_endBody(BcParse *p, bool brace) +static BC_STATUS zbc_parse_endBody(BcParse *p, bool brace) { BcStatus s = BC_STATUS_SUCCESS; if (p->flags.len <= 1 || (brace && p->nbraces == 0)) - return bc_error_bad_token(); + RETURN_STATUS(bc_error_bad_token()); if (brace) { - - if (p->l.t.t == BC_LEX_RBRACE) { - if (!p->nbraces) return bc_error_bad_token(); - --p->nbraces; - s = zbc_lex_next(&p->l); - if (s) return s; - } - else - return bc_error_bad_token(); + if (p->l.t.t != BC_LEX_RBRACE) + RETURN_STATUS(bc_error_bad_token()); + if (!p->nbraces) + RETURN_STATUS(bc_error_bad_token()); + --p->nbraces; + s = zbc_lex_next(&p->l); + if (s) RETURN_STATUS(s); } if (BC_PARSE_IF(p)) { - uint8_t *flag_ptr; while (p->l.t.t == BC_LEX_NLINE) { s = zbc_lex_next(&p->l); - if (s) return s; + if (s) RETURN_STATUS(s); } bc_vec_pop(&p->flags); @@ -4060,7 +4066,6 @@ static BcStatus bc_parse_endBody(BcParse *p, bool brace) ERROR_RETURN(s =) zbc_parse_else(p); } else if (BC_PARSE_ELSE(p)) { - BcInstPtr *ip; size_t *label; @@ -4078,7 +4083,6 @@ static BcStatus bc_parse_endBody(BcParse *p, bool brace) bc_vec_pop(&p->flags); } else { - BcInstPtr *ip = bc_vec_top(&p->exits); size_t *label = bc_vec_top(&p->conds); @@ -4093,8 +4097,11 @@ static BcStatus bc_parse_endBody(BcParse *p, bool brace) bc_vec_pop(&p->conds); } - return s; + RETURN_STATUS(s); } +#if ERRORS_ARE_FATAL +# define zbc_parse_endBody(...) (zbc_parse_endBody(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static void bc_parse_startBody(BcParse *p, uint8_t flags) { @@ -4284,23 +4291,24 @@ static BcStatus bc_parse_for(BcParse *p) return BC_STATUS_SUCCESS; } -static BcStatus bc_parse_loopExit(BcParse *p, BcLexType type) +static BC_STATUS zbc_parse_loopExit(BcParse *p, BcLexType type) { BcStatus s; size_t i; BcInstPtr *ip; - if (!BC_PARSE_LOOP(p)) return bc_error_bad_token(); + if (!BC_PARSE_LOOP(p)) RETURN_STATUS(bc_error_bad_token()); if (type == BC_LEX_KEY_BREAK) { - - if (p->exits.len == 0) return bc_error_bad_token(); + if (p->exits.len == 0) RETURN_STATUS(bc_error_bad_token()); i = p->exits.len - 1; ip = bc_vec_item(&p->exits, i); - while (!ip->func && i < p->exits.len) ip = bc_vec_item(&p->exits, i--); - if (i >= p->exits.len && !ip->func) return bc_error_bad_token(); + while (!ip->func && i < p->exits.len) + ip = bc_vec_item(&p->exits, i--); + if (i >= p->exits.len && !ip->func) + RETURN_STATUS(bc_error_bad_token()); i = ip->idx; } @@ -4311,15 +4319,18 @@ static BcStatus bc_parse_loopExit(BcParse *p, BcLexType type) bc_parse_pushIndex(p, i); s = zbc_lex_next(&p->l); - if (s) return s; + if (s) RETURN_STATUS(s); if (p->l.t.t != BC_LEX_SCOLON && p->l.t.t != BC_LEX_NLINE) - return bc_error_bad_token(); + RETURN_STATUS(bc_error_bad_token()); - return zbc_lex_next(&p->l); + RETURN_STATUS(zbc_lex_next(&p->l)); } +#if ERRORS_ARE_FATAL +# define zbc_parse_loopExit(...) (zbc_parse_loopExit(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif -static BcStatus bc_parse_func(BcParse *p) +static BC_STATUS zbc_parse_func(BcParse *p) { BcStatus s; bool var, comma = false; @@ -4327,24 +4338,23 @@ static BcStatus bc_parse_func(BcParse *p) char *name; s = zbc_lex_next(&p->l); - if (s) return s; + if (s) RETURN_STATUS(s); if (p->l.t.t != BC_LEX_NAME) - return bc_error("bad function definition"); + RETURN_STATUS(bc_error("bad function definition")); name = xstrdup(p->l.t.v.v); bc_parse_addFunc(p, name, &p->fidx); s = zbc_lex_next(&p->l); - if (s) return s; + if (s) RETURN_STATUS(s); if (p->l.t.t != BC_LEX_LPAREN) - return bc_error("bad function definition"); + RETURN_STATUS(bc_error("bad function definition")); s = zbc_lex_next(&p->l); - if (s) return s; + if (s) RETURN_STATUS(s); while (p->l.t.t != BC_LEX_RPAREN) { - if (p->l.t.t != BC_LEX_NAME) - return bc_error("bad function definition"); + RETURN_STATUS(bc_error("bad function definition")); ++p->func->nparams; @@ -4355,7 +4365,6 @@ static BcStatus bc_parse_func(BcParse *p) var = p->l.t.t != BC_LEX_LBRACKET; if (!var) { - s = zbc_lex_next(&p->l); if (s) goto err; @@ -4378,46 +4387,48 @@ static BcStatus bc_parse_func(BcParse *p) if (s) goto err; } - if (comma) return bc_error("bad function definition"); + if (comma) RETURN_STATUS(bc_error("bad function definition")); flags = BC_PARSE_FLAG_FUNC | BC_PARSE_FLAG_FUNC_INNER | BC_PARSE_FLAG_BODY; bc_parse_startBody(p, flags); s = zbc_lex_next(&p->l); - if (s) return s; + if (s) RETURN_STATUS(s); if (p->l.t.t != BC_LEX_LBRACE) s = bc_POSIX_requires("the left brace be on the same line as the function header"); - return s; + RETURN_STATUS(s); err: free(name); - return s; + RETURN_STATUS(s); } +#if ERRORS_ARE_FATAL +# define zbc_parse_func(...) (zbc_parse_func(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif -static BcStatus bc_parse_auto(BcParse *p) +static BC_STATUS zbc_parse_auto(BcParse *p) { BcStatus s; bool comma, var, one; char *name; - if (!p->auto_part) return bc_error_bad_token(); + if (!p->auto_part) RETURN_STATUS(bc_error_bad_token()); + s = zbc_lex_next(&p->l); - if (s) return s; + if (s) RETURN_STATUS(s); p->auto_part = comma = false; one = p->l.t.t == BC_LEX_NAME; while (p->l.t.t == BC_LEX_NAME) { - name = xstrdup(p->l.t.v.v); s = zbc_lex_next(&p->l); if (s) goto err; var = p->l.t.t != BC_LEX_LBRACKET; if (!var) { - s = zbc_lex_next(&p->l); if (s) goto err; @@ -4440,20 +4451,23 @@ static BcStatus bc_parse_auto(BcParse *p) if (s) goto err; } - if (comma) return bc_error("bad function definition"); - if (!one) return bc_error("no auto variable found"); + if (comma) RETURN_STATUS(bc_error("bad function definition")); + if (!one) RETURN_STATUS(bc_error("no auto variable found")); if (p->l.t.t != BC_LEX_NLINE && p->l.t.t != BC_LEX_SCOLON) - return bc_error_bad_token(); + RETURN_STATUS(bc_error_bad_token()); - return zbc_lex_next(&p->l); + RETURN_STATUS(zbc_lex_next(&p->l)); err: free(name); - return s; + RETURN_STATUS(s); } +#if ERRORS_ARE_FATAL +# define zbc_parse_auto(...) (zbc_parse_auto(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif -static BcStatus bc_parse_body(BcParse *p, bool brace) +static BC_STATUS zbc_parse_body(BcParse *p, bool brace) { BcStatus s = BC_STATUS_SUCCESS; uint8_t *flag_ptr = bc_vec_top(&p->flags); @@ -4461,24 +4475,27 @@ static BcStatus bc_parse_body(BcParse *p, bool brace) *flag_ptr &= ~(BC_PARSE_FLAG_BODY); if (*flag_ptr & BC_PARSE_FLAG_FUNC_INNER) { + if (!brace) RETURN_STATUS(bc_error_bad_token()); - if (!brace) return bc_error_bad_token(); p->auto_part = p->l.t.t != BC_LEX_KEY_AUTO; if (!p->auto_part) { - s = bc_parse_auto(p); - if (s) return s; + s = zbc_parse_auto(p); + if (s) RETURN_STATUS(s); } if (p->l.t.t == BC_LEX_NLINE) s = zbc_lex_next(&p->l); } else { s = bc_parse_stmt(p); - if (!s && !brace) s = bc_parse_endBody(p, false); + if (!s && !brace) s = zbc_parse_endBody(p, false); } - return s; + RETURN_STATUS(s); } +#if ERRORS_ARE_FATAL +# define zbc_parse_body(...) (zbc_parse_body(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static BcStatus bc_parse_stmt(BcParse *p) { @@ -4505,12 +4522,12 @@ static BcStatus bc_parse_stmt(BcParse *p) s = zbc_lex_next(&p->l); if (s) return s; - return bc_parse_body(p, true); + return zbc_parse_body(p, true); } case BC_LEX_KEY_AUTO: { - return bc_parse_auto(p); + return zbc_parse_auto(p); } default: @@ -4522,7 +4539,7 @@ static BcStatus bc_parse_stmt(BcParse *p) return BC_STATUS_SUCCESS; } else if (BC_PARSE_BODY(p)) - return bc_parse_body(p, false); + return zbc_parse_body(p, false); break; } @@ -4563,20 +4580,20 @@ static BcStatus bc_parse_stmt(BcParse *p) case BC_LEX_RBRACE: { - s = bc_parse_endBody(p, true); + s = zbc_parse_endBody(p, true); break; } case BC_LEX_STR: { - s = bc_parse_string(p, BC_INST_PRINT_STR); + s = zbc_parse_string(p, BC_INST_PRINT_STR); break; } case BC_LEX_KEY_BREAK: case BC_LEX_KEY_CONTINUE: { - s = bc_parse_loopExit(p, p->l.t.t); + s = zbc_parse_loopExit(p, p->l.t.t); break; } @@ -4662,7 +4679,7 @@ static FAST_FUNC BcStatus bc_parse_parse(BcParse *p) s = p->flags.len > 0 ? bc_error("block end could not be found") : bc_error("end of file"); else if (p->l.t.t == BC_LEX_KEY_DEFINE) { if (!BC_PARSE_CAN_EXEC(p)) return bc_error_bad_token(); - s = bc_parse_func(p); + s = zbc_parse_func(p); } else s = bc_parse_stmt(p); @@ -4703,7 +4720,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext ne case BC_LEX_OP_MINUS: { - s = bc_parse_minus(p, &prev, ops_bgn, rprn, &nexprs); + s = zbc_parse_minus(p, &prev, ops_bgn, rprn, &nexprs); rprn = get_token = false; bin_last = prev == BC_INST_MINUS; break; @@ -4854,7 +4871,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext ne else if (flags & BC_PARSE_NOREAD) s = bc_error_nested_read_call(); else - s = bc_parse_read(p); + s = zbc_parse_read(p); paren_expr = true; rprn = get_token = bin_last = false; @@ -4961,20 +4978,23 @@ static BcStatus bc_parse_expression(BcParse *p, uint8_t flags) #define DC_PARSE_BUF_LEN ((int) (sizeof(uint32_t) * CHAR_BIT)) -static BcStatus dc_parse_register(BcParse *p) +static BC_STATUS zdc_parse_register(BcParse *p) { BcStatus s; char *name; s = zbc_lex_next(&p->l); - if (s) return s; - if (p->l.t.t != BC_LEX_NAME) return bc_error_bad_token(); + if (s) RETURN_STATUS(s); + if (p->l.t.t != BC_LEX_NAME) RETURN_STATUS(bc_error_bad_token()); name = xstrdup(p->l.t.v.v); bc_parse_pushName(p, name); - return s; + RETURN_STATUS(s); } +#if ERRORS_ARE_FATAL +# define zdc_parse_register(...) (zdc_parse_register(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static BC_STATUS zdc_parse_string(BcParse *p) { @@ -4996,14 +5016,14 @@ static BC_STATUS zdc_parse_string(BcParse *p) # define zdc_parse_string(...) (zdc_parse_string(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static BcStatus dc_parse_mem(BcParse *p, uint8_t inst, bool name, bool store) +static BC_STATUS zdc_parse_mem(BcParse *p, uint8_t inst, bool name, bool store) { BcStatus s; bc_parse_push(p, inst); if (name) { - s = dc_parse_register(p); - if (s) return s; + s = zdc_parse_register(p); + if (s) RETURN_STATUS(s); } if (store) { @@ -5012,34 +5032,40 @@ static BcStatus dc_parse_mem(BcParse *p, uint8_t inst, bool name, bool store) bc_parse_push(p, BC_INST_POP); } - return zbc_lex_next(&p->l); + RETURN_STATUS(zbc_lex_next(&p->l)); } +#if ERRORS_ARE_FATAL +# define zdc_parse_mem(...) (zdc_parse_mem(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif -static BcStatus dc_parse_cond(BcParse *p, uint8_t inst) +static BC_STATUS zdc_parse_cond(BcParse *p, uint8_t inst) { BcStatus s; bc_parse_push(p, inst); bc_parse_push(p, BC_INST_EXEC_COND); - s = dc_parse_register(p); - if (s) return s; + s = zdc_parse_register(p); + if (s) RETURN_STATUS(s); s = zbc_lex_next(&p->l); - if (s) return s; + if (s) RETURN_STATUS(s); if (p->l.t.t == BC_LEX_ELSE) { - s = dc_parse_register(p); - if (s) return s; + s = zdc_parse_register(p); + if (s) RETURN_STATUS(s); s = zbc_lex_next(&p->l); } else bc_parse_push(p, BC_PARSE_STREND); - return s; + RETURN_STATUS(s); } +#if ERRORS_ARE_FATAL +# define zdc_parse_cond(...) (zdc_parse_cond(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif -static BcStatus dc_parse_token(BcParse *p, BcLexType t, uint8_t flags) +static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t, uint8_t flags) { BcStatus s = BC_STATUS_SUCCESS; BcInst prev; @@ -5047,99 +5073,72 @@ static BcStatus dc_parse_token(BcParse *p, BcLexType t, uint8_t flags) bool assign, get_token = false; switch (t) { - case BC_LEX_OP_REL_EQ: case BC_LEX_OP_REL_LE: case BC_LEX_OP_REL_GE: case BC_LEX_OP_REL_NE: case BC_LEX_OP_REL_LT: case BC_LEX_OP_REL_GT: - { - s = dc_parse_cond(p, t - BC_LEX_OP_REL_EQ + BC_INST_REL_EQ); + s = zdc_parse_cond(p, t - BC_LEX_OP_REL_EQ + BC_INST_REL_EQ); break; - } - case BC_LEX_SCOLON: case BC_LEX_COLON: - { - s = dc_parse_mem(p, BC_INST_ARRAY_ELEM, true, t == BC_LEX_COLON); + s = zdc_parse_mem(p, BC_INST_ARRAY_ELEM, true, t == BC_LEX_COLON); break; - } - case BC_LEX_STR: - { s = zdc_parse_string(p); break; - } - case BC_LEX_NEG: case BC_LEX_NUMBER: - { if (t == BC_LEX_NEG) { s = zbc_lex_next(&p->l); - if (s) return s; + if (s) RETURN_STATUS(s); if (p->l.t.t != BC_LEX_NUMBER) - return bc_error_bad_token(); + RETURN_STATUS(bc_error_bad_token()); } - bc_parse_number(p, &prev, &p->nbraces); - if (t == BC_LEX_NEG) bc_parse_push(p, BC_INST_NEG); get_token = true; - break; - } - case BC_LEX_KEY_READ: - { if (flags & BC_PARSE_NOREAD) s = bc_error_nested_read_call(); else bc_parse_push(p, BC_INST_READ); get_token = true; break; - } - case BC_LEX_OP_ASSIGN: case BC_LEX_STORE_PUSH: - { assign = t == BC_LEX_OP_ASSIGN; inst = assign ? BC_INST_VAR : BC_INST_PUSH_TO_VAR; - s = dc_parse_mem(p, inst, true, assign); + s = zdc_parse_mem(p, inst, true, assign); break; - } - case BC_LEX_LOAD: case BC_LEX_LOAD_POP: - { inst = t == BC_LEX_LOAD_POP ? BC_INST_PUSH_VAR : BC_INST_LOAD; - s = dc_parse_mem(p, inst, true, false); + s = zdc_parse_mem(p, inst, true, false); break; - } - case BC_LEX_STORE_IBASE: case BC_LEX_STORE_SCALE: case BC_LEX_STORE_OBASE: - { inst = t - BC_LEX_STORE_IBASE + BC_INST_IBASE; - s = dc_parse_mem(p, inst, false, true); + s = zdc_parse_mem(p, inst, false, true); break; - } - default: - { s = bc_error_bad_token(); get_token = true; break; - } } if (!s && get_token) s = zbc_lex_next(&p->l); - return s; + RETURN_STATUS(s); } +#if ERRORS_ARE_FATAL +# define zdc_parse_token(...) (zdc_parse_token(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif -static BcStatus dc_parse_expr(BcParse *p, uint8_t flags) +static BC_STATUS zdc_parse_expr(BcParse *p, uint8_t flags) { BcStatus s = BC_STATUS_SUCCESS; BcInst inst; @@ -5148,22 +5147,23 @@ static BcStatus dc_parse_expr(BcParse *p, uint8_t flags) if (flags & BC_PARSE_NOCALL) p->nbraces = G.prog.results.len; for (t = p->l.t.t; !s && t != BC_LEX_EOF; t = p->l.t.t) { - inst = dc_parse_insts[t]; if (inst != BC_INST_INVALID) { bc_parse_push(p, inst); s = zbc_lex_next(&p->l); - } - else - s = dc_parse_token(p, t, flags); + } else + s = zdc_parse_token(p, t, flags); } if (!s && p->l.t.t == BC_LEX_EOF && (flags & BC_PARSE_NOCALL)) bc_parse_push(p, BC_INST_POP_EXEC); - return s; + RETURN_STATUS(s); } +#if ERRORS_ARE_FATAL +# define zdc_parse_expr(...) (zdc_parse_expr(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static FAST_FUNC BcStatus dc_parse_parse(BcParse *p) { @@ -5172,7 +5172,7 @@ static FAST_FUNC BcStatus dc_parse_parse(BcParse *p) if (p->l.t.t == BC_LEX_EOF) s = bc_error("end of file"); else - s = dc_parse_expr(p, 0); + s = zdc_parse_expr(p, 0); if (s || G_interrupt) { bc_parse_reset(p); @@ -5203,7 +5203,7 @@ static BcStatus common_parse_expr(BcParse *p, uint8_t flags) if (IS_BC) { IF_BC(return bc_parse_expression(p, flags);) } else { - IF_DC(return dc_parse_expr(p, flags);) + IF_DC(return zdc_parse_expr(p, flags);) } } -- cgit v1.2.3-55-g6feb From ae0faf91d0b3ece70c7d29ab2711c3c044ae7148 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 12 Dec 2018 15:19:54 +0100 Subject: bc: convert even more of lexer functions to "z" convention function old new delta bc_parse_stmt 1594 - -1594 zbc_parse_stmt - 1540 +1540 common_parse_expr 43 - -43 zcommon_parse_expr - 40 +40 bc_parse_expr 24 - -24 zbc_parse_expr - 24 +24 zbc_parse_body 108 104 -4 bc_program_read 277 271 -6 bc_program_execStr 468 460 -8 bc_parse_expr_empty_ok 1955 1939 -16 bc_parse_name 451 416 -35 bc_parse_parse 476 305 -171 ------------------------------------------------------------------------------ (add/remove: 3/3 grow/shrink: 0/6 up/down: 1604/-1901) Total: -297 bytes text data bss dec hex filename 981355 485 7296 989136 f17d0 busybox_old 981058 485 7296 988839 f16a7 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 269 ++++++++++++++++++++++++++------------------------------- 1 file changed, 121 insertions(+), 148 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 3815b7f09..f942d42ac 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -3584,9 +3584,14 @@ static void bc_parse_create(BcParse *p, size_t func, #define BC_PARSE_TOKEN_INST(t) ((char) ((t) -BC_LEX_NEG + BC_INST_NEG)) static BC_STATUS zbc_parse_else(BcParse *p); -static BcStatus bc_parse_stmt(BcParse *p); -static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next); +static BC_STATUS zbc_parse_stmt(BcParse *p); +static BC_STATUS zbc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next); static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext next); +#if ERRORS_ARE_FATAL +# define zbc_parse_else(...) (zbc_parse_else(__VA_ARGS__), BC_STATUS_SUCCESS) +# define zbc_parse_stmt(...) (zbc_parse_stmt(__VA_ARGS__), BC_STATUS_SUCCESS) +# define zbc_parse_expr(...) (zbc_parse_expr(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static BC_STATUS zbc_parse_operator(BcParse *p, BcLexType type, size_t start, size_t *nexprs, bool next) @@ -3657,7 +3662,7 @@ static BcStatus bc_parse_params(BcParse *p, uint8_t flags) for (nparams = 0; p->l.t.t != BC_LEX_RPAREN; ++nparams) { flags = (flags & ~(BC_PARSE_PRINT | BC_PARSE_REL)) | BC_PARSE_ARRAY; - s = bc_parse_expr(p, flags, bc_parse_next_param); + s = zbc_parse_expr(p, flags, bc_parse_next_param); if (s) return s; comma = p->l.t.t == BC_LEX_COMMA; @@ -3739,7 +3744,7 @@ static BcStatus bc_parse_name(BcParse *p, BcInst *type, uint8_t flags) *type = BC_INST_ARRAY_ELEM; flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL); - s = bc_parse_expr(p, flags, bc_parse_next_elem); + s = zbc_parse_expr(p, flags, bc_parse_next_elem); if (s) goto err; } @@ -3805,7 +3810,7 @@ static BcStatus bc_parse_builtin(BcParse *p, BcLexType type, uint8_t flags, s = zbc_lex_next(&p->l); if (s) return s; - s = bc_parse_expr(p, flags, bc_parse_next_rel); + s = zbc_parse_expr(p, flags, bc_parse_next_rel); if (s) return s; if (p->l.t.t != BC_LEX_RPAREN) return bc_error_bad_token(); @@ -3835,7 +3840,7 @@ static BcStatus bc_parse_scale(BcParse *p, BcInst *type, uint8_t flags) s = zbc_lex_next(&p->l); if (s) return s; - s = bc_parse_expr(p, flags, bc_parse_next_rel); + s = zbc_parse_expr(p, flags, bc_parse_next_rel); if (s) return s; if (p->l.t.t != BC_LEX_RPAREN) return bc_error_bad_token(); bc_parse_push(p, BC_INST_SCALE_FUNC); @@ -3957,55 +3962,57 @@ static BC_STATUS zbc_parse_string(BcParse *p, char inst) # define zbc_parse_string(...) (zbc_parse_string(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static BcStatus bc_parse_print(BcParse *p) +static BC_STATUS zbc_parse_print(BcParse *p) { BcStatus s; BcLexType type; bool comma; s = zbc_lex_next(&p->l); - if (s) return s; + if (s) RETURN_STATUS(s); type = p->l.t.t; if (type == BC_LEX_SCOLON || type == BC_LEX_NLINE) - return bc_error("bad print statement"); + RETURN_STATUS(bc_error("bad print statement")); comma = false; while (type != BC_LEX_SCOLON && type != BC_LEX_NLINE) { - if (type == BC_LEX_STR) { s = zbc_parse_string(p, BC_INST_PRINT_POP); - if (s) return s; + if (s) RETURN_STATUS(s); } else { - s = bc_parse_expr(p, 0, bc_parse_next_print); - if (s) return s; + s = zbc_parse_expr(p, 0, bc_parse_next_print); + if (s) RETURN_STATUS(s); bc_parse_push(p, BC_INST_PRINT_POP); } comma = p->l.t.t == BC_LEX_COMMA; if (comma) { s = zbc_lex_next(&p->l); - if (s) return s; + if (s) RETURN_STATUS(s); } type = p->l.t.t; } - if (comma) return bc_error_bad_token(); + if (comma) RETURN_STATUS(bc_error_bad_token()); - return zbc_lex_next(&p->l); + RETURN_STATUS(zbc_lex_next(&p->l)); } +#if ERRORS_ARE_FATAL +# define zbc_parse_print(...) (zbc_parse_print(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif -static BcStatus bc_parse_return(BcParse *p) +static BC_STATUS zbc_parse_return(BcParse *p) { BcStatus s; BcLexType t; bool paren; - if (!BC_PARSE_FUNC(p)) return bc_error_bad_token(); + if (!BC_PARSE_FUNC(p)) RETURN_STATUS(bc_error_bad_token()); s = zbc_lex_next(&p->l); - if (s) return s; + if (s) RETURN_STATUS(s); t = p->l.t.t; paren = t == BC_LEX_LPAREN; @@ -4013,24 +4020,26 @@ static BcStatus bc_parse_return(BcParse *p) if (t == BC_LEX_NLINE || t == BC_LEX_SCOLON) bc_parse_push(p, BC_INST_RET0); else { - s = bc_parse_expr_empty_ok(p, 0, bc_parse_next_expr); if (s == BC_STATUS_PARSE_EMPTY_EXP) { bc_parse_push(p, BC_INST_RET0); s = zbc_lex_next(&p->l); } - if (s) return s; + if (s) RETURN_STATUS(s); if (!paren || p->l.t.last != BC_LEX_RPAREN) { s = bc_POSIX_requires("parentheses around return expressions"); - ERROR_RETURN(if (s) return s;) + ERROR_RETURN(if (s) RETURN_STATUS(s);) } bc_parse_push(p, BC_INST_RET); } - return s; + RETURN_STATUS(s); } +#if ERRORS_ARE_FATAL +# define zbc_parse_return(...) (zbc_parse_return(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static BC_STATUS zbc_parse_endBody(BcParse *p, bool brace) { @@ -4063,7 +4072,7 @@ static BC_STATUS zbc_parse_endBody(BcParse *p, bool brace) *flag_ptr = (*flag_ptr | BC_PARSE_FLAG_IF_END); if (p->l.t.t == BC_LEX_KEY_ELSE) - ERROR_RETURN(s =) zbc_parse_else(p); + s = zbc_parse_else(p); } else if (BC_PARSE_ELSE(p)) { BcInstPtr *ip; @@ -4126,23 +4135,23 @@ static void bc_parse_noElse(BcParse *p) bc_vec_pop(&p->exits); } -static BcStatus bc_parse_if(BcParse *p) +static BC_STATUS zbc_parse_if(BcParse *p) { BcStatus s; BcInstPtr ip; s = zbc_lex_next(&p->l); - if (s) return s; - if (p->l.t.t != BC_LEX_LPAREN) return bc_error_bad_token(); + if (s) RETURN_STATUS(s); + if (p->l.t.t != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); s = zbc_lex_next(&p->l); - if (s) return s; - s = bc_parse_expr(p, BC_PARSE_REL, bc_parse_next_rel); - if (s) return s; - if (p->l.t.t != BC_LEX_RPAREN) return bc_error_bad_token(); + if (s) RETURN_STATUS(s); + s = zbc_parse_expr(p, BC_PARSE_REL, bc_parse_next_rel); + if (s) RETURN_STATUS(s); + if (p->l.t.t != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); s = zbc_lex_next(&p->l); - if (s) return s; + if (s) RETURN_STATUS(s); bc_parse_push(p, BC_INST_JUMP_ZERO); ip.idx = p->func->labels.len; @@ -4153,9 +4162,13 @@ static BcStatus bc_parse_if(BcParse *p) bc_vec_push(&p->func->labels, &ip.idx); bc_parse_startBody(p, BC_PARSE_FLAG_IF); - return BC_STATUS_SUCCESS; + RETURN_STATUS(BC_STATUS_SUCCESS); } +#if ERRORS_ARE_FATAL +# define zbc_parse_if(...) (zbc_parse_if(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif +#undef zbc_parse_else static BC_STATUS zbc_parse_else(BcParse *p) { BcInstPtr ip; @@ -4180,16 +4193,16 @@ static BC_STATUS zbc_parse_else(BcParse *p) # define zbc_parse_else(...) (zbc_parse_else(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static BcStatus bc_parse_while(BcParse *p) +static BC_STATUS zbc_parse_while(BcParse *p) { BcStatus s; BcInstPtr ip; s = zbc_lex_next(&p->l); - if (s) return s; - if (p->l.t.t != BC_LEX_LPAREN) return bc_error_bad_token(); + if (s) RETURN_STATUS(s); + if (p->l.t.t != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); s = zbc_lex_next(&p->l); - if (s) return s; + if (s) RETURN_STATUS(s); ip.idx = p->func->labels.len; @@ -4203,40 +4216,43 @@ static BcStatus bc_parse_while(BcParse *p) bc_vec_push(&p->exits, &ip); bc_vec_push(&p->func->labels, &ip.idx); - s = bc_parse_expr(p, BC_PARSE_REL, bc_parse_next_rel); - if (s) return s; - if (p->l.t.t != BC_LEX_RPAREN) return bc_error_bad_token(); + s = zbc_parse_expr(p, BC_PARSE_REL, bc_parse_next_rel); + if (s) RETURN_STATUS(s); + if (p->l.t.t != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); s = zbc_lex_next(&p->l); - if (s) return s; + if (s) RETURN_STATUS(s); bc_parse_push(p, BC_INST_JUMP_ZERO); bc_parse_pushIndex(p, ip.idx); bc_parse_startBody(p, BC_PARSE_FLAG_LOOP | BC_PARSE_FLAG_LOOP_INNER); - return BC_STATUS_SUCCESS; + RETURN_STATUS(BC_STATUS_SUCCESS); } +#if ERRORS_ARE_FATAL +# define zbc_parse_while(...) (zbc_parse_while(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif -static BcStatus bc_parse_for(BcParse *p) +static BC_STATUS zbc_parse_for(BcParse *p) { BcStatus s; BcInstPtr ip; size_t cond_idx, exit_idx, body_idx, update_idx; s = zbc_lex_next(&p->l); - if (s) return s; - if (p->l.t.t != BC_LEX_LPAREN) return bc_error_bad_token(); + if (s) RETURN_STATUS(s); + if (p->l.t.t != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); s = zbc_lex_next(&p->l); - if (s) return s; + if (s) RETURN_STATUS(s); if (p->l.t.t != BC_LEX_SCOLON) - s = bc_parse_expr(p, 0, bc_parse_next_for); + s = zbc_parse_expr(p, 0, bc_parse_next_for); else s = bc_POSIX_does_not_allow_empty_X_expression_in_for("init"); - if (s) return s; - if (p->l.t.t != BC_LEX_SCOLON) return bc_error_bad_token(); + if (s) RETURN_STATUS(s); + if (p->l.t.t != BC_LEX_SCOLON) RETURN_STATUS(bc_error_bad_token()); s = zbc_lex_next(&p->l); - if (s) return s; + if (s) RETURN_STATUS(s); cond_idx = p->func->labels.len; update_idx = cond_idx + 1; @@ -4246,15 +4262,15 @@ static BcStatus bc_parse_for(BcParse *p) bc_vec_push(&p->func->labels, &p->func->code.len); if (p->l.t.t != BC_LEX_SCOLON) - s = bc_parse_expr(p, BC_PARSE_REL, bc_parse_next_for); + s = zbc_parse_expr(p, BC_PARSE_REL, bc_parse_next_for); else s = bc_POSIX_does_not_allow_empty_X_expression_in_for("condition"); - if (s) return s; - if (p->l.t.t != BC_LEX_SCOLON) return bc_error_bad_token(); + if (s) RETURN_STATUS(s); + if (p->l.t.t != BC_LEX_SCOLON) RETURN_STATUS(bc_error_bad_token()); s = zbc_lex_next(&p->l); - if (s) return s; + if (s) RETURN_STATUS(s); bc_parse_push(p, BC_INST_JUMP_ZERO); bc_parse_pushIndex(p, exit_idx); @@ -4267,13 +4283,13 @@ static BcStatus bc_parse_for(BcParse *p) bc_vec_push(&p->func->labels, &p->func->code.len); if (p->l.t.t != BC_LEX_RPAREN) - s = bc_parse_expr(p, 0, bc_parse_next_rel); + s = zbc_parse_expr(p, 0, bc_parse_next_rel); else s = bc_POSIX_does_not_allow_empty_X_expression_in_for("update"); - if (s) return s; + if (s) RETURN_STATUS(s); - if (p->l.t.t != BC_LEX_RPAREN) return bc_error_bad_token(); + if (p->l.t.t != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); bc_parse_push(p, BC_INST_JUMP); bc_parse_pushIndex(p, cond_idx); bc_vec_push(&p->func->labels, &p->func->code.len); @@ -4285,11 +4301,14 @@ static BcStatus bc_parse_for(BcParse *p) bc_vec_push(&p->exits, &ip); bc_vec_push(&p->func->labels, &ip.idx); s = zbc_lex_next(&p->l); - if (s) return s; + if (s) RETURN_STATUS(s); bc_parse_startBody(p, BC_PARSE_FLAG_LOOP | BC_PARSE_FLAG_LOOP_INNER); - return BC_STATUS_SUCCESS; + RETURN_STATUS(BC_STATUS_SUCCESS); } +#if ERRORS_ARE_FATAL +# define zbc_parse_for(...) (zbc_parse_for(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static BC_STATUS zbc_parse_loopExit(BcParse *p, BcLexType type) { @@ -4487,7 +4506,7 @@ static BC_STATUS zbc_parse_body(BcParse *p, bool brace) if (p->l.t.t == BC_LEX_NLINE) s = zbc_lex_next(&p->l); } else { - s = bc_parse_stmt(p); + s = zbc_parse_stmt(p); if (!s && !brace) s = zbc_parse_endBody(p, false); } @@ -4497,56 +4516,41 @@ static BC_STATUS zbc_parse_body(BcParse *p, bool brace) # define zbc_parse_body(...) (zbc_parse_body(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static BcStatus bc_parse_stmt(BcParse *p) +#undef zbc_parse_stmt +static BC_STATUS zbc_parse_stmt(BcParse *p) { BcStatus s = BC_STATUS_SUCCESS; switch (p->l.t.t) { - case BC_LEX_NLINE: - { - return zbc_lex_next(&p->l); - } + RETURN_STATUS(zbc_lex_next(&p->l)); case BC_LEX_KEY_ELSE: - { p->auto_part = false; break; - } case BC_LEX_LBRACE: - { - if (!BC_PARSE_BODY(p)) return bc_error_bad_token(); - + if (!BC_PARSE_BODY(p)) RETURN_STATUS(bc_error_bad_token()); ++p->nbraces; s = zbc_lex_next(&p->l); - if (s) return s; - - return zbc_parse_body(p, true); - } + if (s) RETURN_STATUS(s); + RETURN_STATUS(zbc_parse_body(p, true)); case BC_LEX_KEY_AUTO: - { - return zbc_parse_auto(p); - } + RETURN_STATUS(zbc_parse_auto(p)); default: - { p->auto_part = false; - if (BC_PARSE_IF_END(p)) { bc_parse_noElse(p); - return BC_STATUS_SUCCESS; + RETURN_STATUS(BC_STATUS_SUCCESS); } - else if (BC_PARSE_BODY(p)) - return zbc_parse_body(p, false); - + if (BC_PARSE_BODY(p)) + RETURN_STATUS(zbc_parse_body(p, false)); break; - } } switch (p->l.t.t) { - case BC_LEX_OP_INC: case BC_LEX_OP_DEC: case BC_LEX_OP_MINUS: @@ -4561,67 +4565,39 @@ static BcStatus bc_parse_stmt(BcParse *p) case BC_LEX_KEY_READ: case BC_LEX_KEY_SCALE: case BC_LEX_KEY_SQRT: - { - s = bc_parse_expr(p, BC_PARSE_PRINT, bc_parse_next_expr); + s = zbc_parse_expr(p, BC_PARSE_PRINT, bc_parse_next_expr); break; - } - case BC_LEX_KEY_ELSE: - { s = zbc_parse_else(p); break; - } - case BC_LEX_SCOLON: - { while (!s && p->l.t.t == BC_LEX_SCOLON) s = zbc_lex_next(&p->l); break; - } - case BC_LEX_RBRACE: - { s = zbc_parse_endBody(p, true); break; - } - case BC_LEX_STR: - { s = zbc_parse_string(p, BC_INST_PRINT_STR); break; - } - case BC_LEX_KEY_BREAK: case BC_LEX_KEY_CONTINUE: - { s = zbc_parse_loopExit(p, p->l.t.t); break; - } - case BC_LEX_KEY_FOR: - { - s = bc_parse_for(p); + s = zbc_parse_for(p); break; - } - case BC_LEX_KEY_HALT: - { bc_parse_push(p, BC_INST_HALT); s = zbc_lex_next(&p->l); break; - } - case BC_LEX_KEY_IF: - { - s = bc_parse_if(p); + s = zbc_parse_if(p); break; - } - case BC_LEX_KEY_LIMITS: - { // "limits" is a compile-time command, // the output is produced at _parse time_. s = zbc_lex_next(&p->l); - if (s) return s; + if (s) RETURN_STATUS(s); printf( "BC_BASE_MAX = "BC_MAX_OBASE_STR "\n" "BC_DIM_MAX = "BC_MAX_DIM_STR "\n" @@ -4633,43 +4609,30 @@ static BcStatus bc_parse_stmt(BcParse *p) "Number of vars = "BC_MAX_VARS_STR "\n" ); break; - } - case BC_LEX_KEY_PRINT: - { - s = bc_parse_print(p); + s = zbc_parse_print(p); break; - } - case BC_LEX_KEY_QUIT: - { // "quit" is a compile-time command. For example, // "if (0 == 1) quit" terminates when parsing the statement, // not when it is executed QUIT_OR_RETURN_TO_MAIN; - } - case BC_LEX_KEY_RETURN: - { - s = bc_parse_return(p); + s = zbc_parse_return(p); break; - } - case BC_LEX_KEY_WHILE: - { - s = bc_parse_while(p); + s = zbc_parse_while(p); break; - } - default: - { s = bc_error_bad_token(); break; - } } - return s; + RETURN_STATUS(s); } +#if ERRORS_ARE_FATAL +# define zbc_parse_stmt(...) (zbc_parse_stmt(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static FAST_FUNC BcStatus bc_parse_parse(BcParse *p) { @@ -4682,7 +4645,7 @@ static FAST_FUNC BcStatus bc_parse_parse(BcParse *p) s = zbc_parse_func(p); } else - s = bc_parse_stmt(p); + s = zbc_parse_stmt(p); if (s || G_interrupt) { bc_parse_reset(p); @@ -4952,25 +4915,32 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext ne return s; } -static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) +#undef zbc_parse_expr +static BC_STATUS zbc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) { BcStatus s; s = bc_parse_expr_empty_ok(p, flags, next); if (s == BC_STATUS_PARSE_EMPTY_EXP) - return bc_error("empty expression"); - return s; + RETURN_STATUS(bc_error("empty expression")); + RETURN_STATUS(s); } +#if ERRORS_ARE_FATAL +# define zbc_parse_expr(...) (zbc_parse_expr(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static void bc_parse_init(BcParse *p, size_t func) { bc_parse_create(p, func, bc_parse_parse, zbc_lex_token); } -static BcStatus bc_parse_expression(BcParse *p, uint8_t flags) +static BC_STATUS zbc_parse_expression(BcParse *p, uint8_t flags) { - return bc_parse_expr(p, flags, bc_parse_next_read); + RETURN_STATUS(zbc_parse_expr(p, flags, bc_parse_next_read)); } +#if ERRORS_ARE_FATAL +# define zbc_parse_expression(...) (zbc_parse_expression(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif #endif // ENABLE_BC @@ -5198,14 +5168,17 @@ static void common_parse_init(BcParse *p, size_t func) } } -static BcStatus common_parse_expr(BcParse *p, uint8_t flags) +static BC_STATUS zcommon_parse_expr(BcParse *p, uint8_t flags) { if (IS_BC) { - IF_BC(return bc_parse_expression(p, flags);) + IF_BC(RETURN_STATUS(zbc_parse_expression(p, flags));) } else { - IF_DC(return zdc_parse_expr(p, flags);) + IF_DC(RETURN_STATUS(zdc_parse_expr(p, flags));) } } +#if ERRORS_ARE_FATAL +# define zcommon_parse_expr(...) (zcommon_parse_expr(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static BcVec* bc_program_search(char *id, bool var) { @@ -5440,7 +5413,7 @@ static BcStatus bc_program_read(void) s = bc_parse_text(&parse, buf.v); if (s) goto exec_err; - s = common_parse_expr(&parse, BC_PARSE_NOREAD); + s = zcommon_parse_expr(&parse, BC_PARSE_NOREAD); if (s) goto exec_err; if (parse.l.t.t != BC_LEX_NLINE && parse.l.t.t != BC_LEX_EOF) { @@ -6639,7 +6612,7 @@ static BcStatus bc_program_execStr(char *code, size_t *bgn, common_parse_init(&prs, fidx); s = bc_parse_text(&prs, *str); if (s) goto err; - s = common_parse_expr(&prs, BC_PARSE_NOCALL); + s = zcommon_parse_expr(&prs, BC_PARSE_NOCALL); if (s) goto err; if (prs.l.t.t != BC_LEX_EOF) { -- cgit v1.2.3-55-g6feb From 26819db9a3f029c1abaaf596fe1889315a203122 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 12 Dec 2018 16:08:46 +0100 Subject: bc: convert even more of lexer functions to "z" convention function old new delta bc_parse_name 416 - -416 zbc_parse_name - 414 +414 bc_parse_parse 305 - -305 zbc_parse_parse - 311 +311 bc_program_read 271 - -271 zbc_program_read - 261 +261 bc_parse_text 129 - -129 zbc_parse_text - 122 +122 dc_parse_parse 26 - -26 zdc_parse_parse - 23 +23 bc_program_index 66 64 -2 bc_vm_process 92 74 -18 bc_program_execStr 460 429 -31 bc_parse_expr_empty_ok 1939 1882 -57 ------------------------------------------------------------------------------ (add/remove: 5/5 grow/shrink: 0/4 up/down: 1131/-1255) Total: -124 bytes text data bss dec hex filename 981058 485 7296 988839 f16a7 busybox_old 980934 485 7296 988715 f162b busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 226 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 114 insertions(+), 112 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index f942d42ac..73c801c44 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -618,7 +618,7 @@ struct BcParse; struct BcProgram; -typedef BcStatus (*BcParseParse)(struct BcParse *) FAST_FUNC; +typedef BC_STATUS (*BcParseParse)(struct BcParse *) FAST_FUNC; typedef struct BcParse { @@ -1364,8 +1364,8 @@ static int push_input_byte(BcVec *vec, char c) return 0; } -// This is not a "z" function: can also return BC_STATUS_EOF -// Can return success (0) or BC_STATUS_EOF. +// This is not a "z" function: +// can return success (0) or BC_STATUS_EOF. // Exits with error message if read error is detected. static BcStatus bc_read_line(BcVec *vec) { @@ -2305,12 +2305,8 @@ static BC_STATUS zbc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale, else bc_num_expand(c, req); -#if !ERRORS_ARE_FATAL - s = op(ptr_a, ptr_b, c, scale); -#else - op(ptr_a, ptr_b, c, scale); s = BC_STATUS_SUCCESS; -#endif + ERROR_RETURN(s =) op(ptr_a, ptr_b, c, scale); if (init) bc_num_free(&num2); @@ -3032,25 +3028,26 @@ static BC_STATUS zbc_lex_identifier(BcLex *l) # define zbc_lex_identifier(...) (zbc_lex_identifier(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static BcStatus bc_lex_string(BcLex *l) +static BC_STATUS zbc_lex_string(BcLex *l) { size_t len, nls = 0, i = l->i; char c; l->t.t = BC_LEX_STR; - for (c = l->buf[i]; c != 0 && c != '"'; c = l->buf[++i]) nls += (c == '\n'); + for (c = l->buf[i]; c != 0 && c != '"'; c = l->buf[++i]) + nls += (c == '\n'); if (c == '\0') { l->i = i; - return bc_error("string end could not be found"); + RETURN_STATUS(bc_error("string end could not be found")); } len = i - l->i; // This check makes sense only if size_t is (much) larger than BC_MAX_STRING. if (SIZE_MAX > (BC_MAX_STRING | 0xff)) { if (len > BC_MAX_STRING) - return bc_error("string too long: must be [1,"BC_MAX_STRING_STR"]"); + RETURN_STATUS(("string too long: must be [1,"BC_MAX_STRING_STR"]")); } bc_vec_string(&l->t.v, len, l->buf + l->i); @@ -3058,8 +3055,11 @@ static BcStatus bc_lex_string(BcLex *l) l->line += nls; G.err_line = l->line; - return BC_STATUS_SUCCESS; + RETURN_STATUS(BC_STATUS_SUCCESS); } +#if ERRORS_ARE_FATAL +# define zbc_lex_string(...) (zbc_lex_string(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static void bc_lex_assign(BcLex *l, BcLexType with, BcLexType without) { @@ -3132,7 +3132,7 @@ static FAST_FUNC BC_STATUS zbc_lex_token(BcLex *l) } break; case '"': - s = bc_lex_string(l); + s = zbc_lex_string(l); break; case '#': s = bc_POSIX_does_not_allow("'#' script comments"); @@ -3462,6 +3462,7 @@ static void bc_parse_pushIndex(BcParse *p, size_t idx) { unsigned char amt, i, nums[sizeof(size_t)]; +///oh boy for (amt = 0; idx; ++amt) { nums[amt] = (char) idx; idx = (idx & ((unsigned long) ~(UCHAR_MAX))) >> sizeof(char) * CHAR_BIT; @@ -3485,7 +3486,7 @@ static void bc_parse_number(BcParse *p, BcInst *prev, size_t *nexs) (*prev) = BC_INST_NUM; } -static BcStatus bc_parse_text(BcParse *p, const char *text) +static BC_STATUS zbc_parse_text(BcParse *p, const char *text) { BcStatus s; @@ -3493,14 +3494,18 @@ static BcStatus bc_parse_text(BcParse *p, const char *text) if (!text[0] && !BC_PARSE_CAN_EXEC(p)) { p->l.t.t = BC_LEX_INVALID; - s = p->parse(p); - if (s) return s; + s = BC_STATUS_SUCCESS; + ERROR_RETURN(s =) p->parse(p); + if (s) RETURN_STATUS(s); if (!BC_PARSE_CAN_EXEC(p)) - return bc_error("file is not executable"); + RETURN_STATUS(bc_error("file is not executable")); } - return zbc_lex_text(&p->l, text); + RETURN_STATUS(zbc_lex_text(&p->l, text)); } +#if ERRORS_ARE_FATAL +# define zbc_parse_text(...) (zbc_parse_text(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif // Called when parsing or execution detects a failure, // resets execution structures. @@ -3520,7 +3525,7 @@ static void bc_program_reset(void) #define bc_parse_updateFunc(p, f) \ ((p)->func = bc_program_func((p)->fidx = (f))) -// Called when bc/dc_parse_parse() detects a failure, +// Called when zbc/zdc_parse_parse() detects a failure, // resets parsing structures. static void bc_parse_reset(BcParse *p) { @@ -3650,36 +3655,38 @@ static BC_STATUS zbc_parse_rightParen(BcParse *p, size_t ops_bgn, size_t *nexs) # define zbc_parse_rightParen(...) (zbc_parse_rightParen(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static BcStatus bc_parse_params(BcParse *p, uint8_t flags) +static BC_STATUS zbc_parse_params(BcParse *p, uint8_t flags) { BcStatus s; bool comma = false; size_t nparams; s = zbc_lex_next(&p->l); - if (s) return s; + if (s) RETURN_STATUS(s); for (nparams = 0; p->l.t.t != BC_LEX_RPAREN; ++nparams) { - flags = (flags & ~(BC_PARSE_PRINT | BC_PARSE_REL)) | BC_PARSE_ARRAY; s = zbc_parse_expr(p, flags, bc_parse_next_param); - if (s) return s; + if (s) RETURN_STATUS(s); comma = p->l.t.t == BC_LEX_COMMA; if (comma) { s = zbc_lex_next(&p->l); - if (s) return s; + if (s) RETURN_STATUS(s); } } - if (comma) return bc_error_bad_token(); + if (comma) RETURN_STATUS(bc_error_bad_token()); bc_parse_push(p, BC_INST_CALL); bc_parse_pushIndex(p, nparams); - return BC_STATUS_SUCCESS; + RETURN_STATUS(BC_STATUS_SUCCESS); } +#if ERRORS_ARE_FATAL +# define zbc_parse_params(...) (zbc_parse_params(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif -static BcStatus bc_parse_call(BcParse *p, char *name, uint8_t flags) +static BC_STATUS zbc_parse_call(BcParse *p, char *name, uint8_t flags) { BcStatus s; BcId entry, *entry_ptr; @@ -3687,7 +3694,7 @@ static BcStatus bc_parse_call(BcParse *p, char *name, uint8_t flags) entry.name = name; - s = bc_parse_params(p, flags); + s = zbc_parse_params(p, flags); if (s) goto err; if (p->l.t.t != BC_LEX_RPAREN) { @@ -3702,21 +3709,23 @@ static BcStatus bc_parse_call(BcParse *p, char *name, uint8_t flags) bc_parse_addFunc(p, name, &idx); idx = bc_map_index(&G.prog.fn_map, &entry); free(entry.name); - } - else + } else free(name); entry_ptr = bc_vec_item(&G.prog.fn_map, idx); bc_parse_pushIndex(p, entry_ptr->idx); - return zbc_lex_next(&p->l); + RETURN_STATUS(zbc_lex_next(&p->l)); err: free(name); - return s; + RETURN_STATUS(s); } +#if ERRORS_ARE_FATAL +# define zbc_parse_call(...) (zbc_parse_call(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif -static BcStatus bc_parse_name(BcParse *p, BcInst *type, uint8_t flags) +static BC_STATUS zbc_parse_name(BcParse *p, BcInst *type, uint8_t flags) { BcStatus s; char *name; @@ -3726,55 +3735,48 @@ static BcStatus bc_parse_name(BcParse *p, BcInst *type, uint8_t flags) if (s) goto err; if (p->l.t.t == BC_LEX_LBRACKET) { - s = zbc_lex_next(&p->l); if (s) goto err; if (p->l.t.t == BC_LEX_RBRACKET) { - if (!(flags & BC_PARSE_ARRAY)) { s = bc_error_bad_expression(); goto err; } - *type = BC_INST_ARRAY; - } - else { - + } else { *type = BC_INST_ARRAY_ELEM; - flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL); s = zbc_parse_expr(p, flags, bc_parse_next_elem); if (s) goto err; } - s = zbc_lex_next(&p->l); if (s) goto err; bc_parse_push(p, *type); bc_parse_pushName(p, name); } else if (p->l.t.t == BC_LEX_LPAREN) { - if (flags & BC_PARSE_NOCALL) { s = bc_error_bad_token(); goto err; } - *type = BC_INST_CALL; - s = bc_parse_call(p, name, flags); - } - else { + s = zbc_parse_call(p, name, flags); + } else { *type = BC_INST_VAR; bc_parse_push(p, BC_INST_VAR); bc_parse_pushName(p, name); } - return s; + RETURN_STATUS(s); err: free(name); - return s; + RETURN_STATUS(s); } +#if ERRORS_ARE_FATAL +# define zbc_parse_name(...) (zbc_parse_name(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static BC_STATUS zbc_parse_read(BcParse *p) { @@ -3796,59 +3798,66 @@ static BC_STATUS zbc_parse_read(BcParse *p) # define zbc_parse_read(...) (zbc_parse_read(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static BcStatus bc_parse_builtin(BcParse *p, BcLexType type, uint8_t flags, +static BC_STATUS zbc_parse_builtin(BcParse *p, BcLexType type, uint8_t flags, BcInst *prev) { BcStatus s; s = zbc_lex_next(&p->l); - if (s) return s; - if (p->l.t.t != BC_LEX_LPAREN) return bc_error_bad_token(); + if (s) RETURN_STATUS(s); + if (p->l.t.t != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); flags = (flags & ~(BC_PARSE_PRINT | BC_PARSE_REL)) | BC_PARSE_ARRAY; s = zbc_lex_next(&p->l); - if (s) return s; + if (s) RETURN_STATUS(s); s = zbc_parse_expr(p, flags, bc_parse_next_rel); - if (s) return s; + if (s) RETURN_STATUS(s); - if (p->l.t.t != BC_LEX_RPAREN) return bc_error_bad_token(); + if (p->l.t.t != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); *prev = (type == BC_LEX_KEY_LENGTH) ? BC_INST_LENGTH : BC_INST_SQRT; bc_parse_push(p, *prev); - return zbc_lex_next(&p->l); + RETURN_STATUS(zbc_lex_next(&p->l)); } +#if ERRORS_ARE_FATAL +# define zbc_parse_builtin(...) (zbc_parse_builtin(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif -static BcStatus bc_parse_scale(BcParse *p, BcInst *type, uint8_t flags) +static BC_STATUS zbc_parse_scale(BcParse *p, BcInst *type, uint8_t flags) { BcStatus s; s = zbc_lex_next(&p->l); - if (s) return s; + if (s) RETURN_STATUS(s); if (p->l.t.t != BC_LEX_LPAREN) { *type = BC_INST_SCALE; bc_parse_push(p, BC_INST_SCALE); - return BC_STATUS_SUCCESS; + RETURN_STATUS(BC_STATUS_SUCCESS); } *type = BC_INST_SCALE_FUNC; flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL); s = zbc_lex_next(&p->l); - if (s) return s; + if (s) RETURN_STATUS(s); s = zbc_parse_expr(p, flags, bc_parse_next_rel); - if (s) return s; - if (p->l.t.t != BC_LEX_RPAREN) return bc_error_bad_token(); + if (s) RETURN_STATUS(s); + if (p->l.t.t != BC_LEX_RPAREN) + RETURN_STATUS(bc_error_bad_token()); bc_parse_push(p, BC_INST_SCALE_FUNC); - return zbc_lex_next(&p->l); + RETURN_STATUS(zbc_lex_next(&p->l)); } +#if ERRORS_ARE_FATAL +# define zbc_parse_scale(...) (zbc_parse_scale(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif -static BcStatus bc_parse_incdec(BcParse *p, BcInst *prev, bool *paren_expr, +static BC_STATUS zbc_parse_incdec(BcParse *p, BcInst *prev, bool *paren_expr, size_t *nexprs, uint8_t flags) { BcStatus s; @@ -3865,12 +3874,11 @@ static BcStatus bc_parse_incdec(BcParse *p, BcInst *prev, bool *paren_expr, s = zbc_lex_next(&p->l); } else { - *prev = inst = BC_INST_INC_PRE + (p->l.t.t != BC_LEX_OP_INC); *paren_expr = true; s = zbc_lex_next(&p->l); - if (s) return s; + if (s) RETURN_STATUS(s); type = p->l.t.t; // Because we parse the next part of the expression @@ -3878,45 +3886,36 @@ static BcStatus bc_parse_incdec(BcParse *p, BcInst *prev, bool *paren_expr, *nexprs = *nexprs + 1; switch (type) { - case BC_LEX_NAME: - { - s = bc_parse_name(p, prev, flags | BC_PARSE_NOCALL); + s = zbc_parse_name(p, prev, flags | BC_PARSE_NOCALL); break; - } - case BC_LEX_KEY_IBASE: case BC_LEX_KEY_LAST: case BC_LEX_KEY_OBASE: - { bc_parse_push(p, type - BC_LEX_KEY_IBASE + BC_INST_IBASE); s = zbc_lex_next(&p->l); break; - } - case BC_LEX_KEY_SCALE: - { s = zbc_lex_next(&p->l); - if (s) return s; + if (s) RETURN_STATUS(s); if (p->l.t.t == BC_LEX_LPAREN) s = bc_error_bad_token(); else bc_parse_push(p, BC_INST_SCALE); break; - } - default: - { s = bc_error_bad_token(); break; - } } if (!s) bc_parse_push(p, inst); } - return s; + RETURN_STATUS(s); } +#if ERRORS_ARE_FATAL +# define zbc_parse_incdec(...) (zbc_parse_incdec(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static BC_STATUS zbc_parse_minus(BcParse *p, BcInst *prev, size_t ops_bgn, bool rparen, size_t *nexprs) @@ -4634,17 +4633,17 @@ static BC_STATUS zbc_parse_stmt(BcParse *p) # define zbc_parse_stmt(...) (zbc_parse_stmt(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static FAST_FUNC BcStatus bc_parse_parse(BcParse *p) +static FAST_FUNC BC_STATUS zbc_parse_parse(BcParse *p) { BcStatus s; if (p->l.t.t == BC_LEX_EOF) s = p->flags.len > 0 ? bc_error("block end could not be found") : bc_error("end of file"); else if (p->l.t.t == BC_LEX_KEY_DEFINE) { - if (!BC_PARSE_CAN_EXEC(p)) return bc_error_bad_token(); + if (!BC_PARSE_CAN_EXEC(p)) + RETURN_STATUS(bc_error_bad_token()); s = zbc_parse_func(p); - } - else + } else s = zbc_parse_stmt(p); if (s || G_interrupt) { @@ -4652,8 +4651,11 @@ static FAST_FUNC BcStatus bc_parse_parse(BcParse *p) s = BC_STATUS_FAILURE; } - return s; + RETURN_STATUS(s); } +#if ERRORS_ARE_FATAL +# define zbc_parse_parse(...) (zbc_parse_parse(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif // This is not a "z" function: can also return BC_STATUS_PARSE_EMPTY_EXP static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext next) @@ -4676,7 +4678,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext ne case BC_LEX_OP_INC: case BC_LEX_OP_DEC: { - s = bc_parse_incdec(p, &prev, &paren_expr, &nexprs, flags); + s = zbc_parse_incdec(p, &prev, &paren_expr, &nexprs, flags); rprn = get_token = bin_last = false; break; } @@ -4781,7 +4783,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext ne return bc_error_bad_expression(); paren_expr = true; rprn = get_token = bin_last = false; - s = bc_parse_name(p, &prev, flags & ~BC_PARSE_NOCALL); + s = zbc_parse_name(p, &prev, flags & ~BC_PARSE_NOCALL); ++nexprs; break; @@ -4819,7 +4821,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext ne { if (BC_PARSE_LEAF(prev, rprn)) return bc_error_bad_expression(); - s = bc_parse_builtin(p, t, flags, &prev); + s = zbc_parse_builtin(p, t, flags, &prev); paren_expr = true; rprn = get_token = bin_last = false; ++nexprs; @@ -4848,7 +4850,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext ne { if (BC_PARSE_LEAF(prev, rprn)) return bc_error_bad_expression(); - s = bc_parse_scale(p, &prev, flags); + s = zbc_parse_scale(p, &prev, flags); paren_expr = true; rprn = get_token = bin_last = false; ++nexprs; @@ -4931,7 +4933,7 @@ static BC_STATUS zbc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) static void bc_parse_init(BcParse *p, size_t func) { - bc_parse_create(p, func, bc_parse_parse, zbc_lex_token); + bc_parse_create(p, func, zbc_parse_parse, zbc_lex_token); } static BC_STATUS zbc_parse_expression(BcParse *p, uint8_t flags) @@ -5135,7 +5137,7 @@ static BC_STATUS zdc_parse_expr(BcParse *p, uint8_t flags) # define zdc_parse_expr(...) (zdc_parse_expr(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static FAST_FUNC BcStatus dc_parse_parse(BcParse *p) +static FAST_FUNC BC_STATUS zdc_parse_parse(BcParse *p) { BcStatus s; @@ -5149,12 +5151,15 @@ static FAST_FUNC BcStatus dc_parse_parse(BcParse *p) s = BC_STATUS_FAILURE; } - return s; + RETURN_STATUS(s); } +#if ERRORS_ARE_FATAL +# define zdc_parse_parse(...) (zdc_parse_parse(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static void dc_parse_init(BcParse *p, size_t func) { - bc_parse_create(p, func, dc_parse_parse, zdc_lex_token); + bc_parse_create(p, func, zdc_parse_parse, zdc_lex_token); } #endif // ENABLE_DC @@ -5368,10 +5373,7 @@ static BC_STATUS zbc_program_op(char inst) bc_num_init_DEF_SIZE(&res.d.n); s = BC_STATUS_SUCCESS; -#if !ERRORS_ARE_FATAL - s = -#endif - zbc_program_ops[inst - BC_INST_POWER](n1, n2, &res.d.n, G.prog.scale); + ERROR_RETURN(s =) zbc_program_ops[inst - BC_INST_POWER](n1, n2, &res.d.n, G.prog.scale); if (s) goto err; bc_program_binOpRetire(&res); @@ -5385,7 +5387,7 @@ err: # define zbc_program_op(...) (zbc_program_op(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static BcStatus bc_program_read(void) +static BC_STATUS zbc_program_read(void) { const char *sv_file; BcStatus s; @@ -5395,7 +5397,7 @@ static BcStatus bc_program_read(void) BcFunc *f; if (G.in_read) - return bc_error_nested_read_call(); + RETURN_STATUS(bc_error_nested_read_call()); f = bc_program_func(BC_PROG_READ); bc_vec_pop_all(&f->code); @@ -5411,7 +5413,7 @@ static BcStatus bc_program_read(void) common_parse_init(&parse, BC_PROG_READ); bc_lex_file(&parse.l); - s = bc_parse_text(&parse, buf.v); + s = zbc_parse_text(&parse, buf.v); if (s) goto exec_err; s = zcommon_parse_expr(&parse, BC_PARSE_NOREAD); if (s) goto exec_err; @@ -5437,8 +5439,11 @@ exec_err: G.in_read = 0; G.prog.file = sv_file; bc_vec_free(&buf); - return s; + RETURN_STATUS(s); } +#if ERRORS_ARE_FATAL +# define zbc_program_read(...) (zbc_program_read(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static size_t bc_program_index(char *code, size_t *bgn) { @@ -5958,10 +5963,7 @@ static BC_STATUS zbc_program_assign(char inst) bc_num_copy(l, r); else { s = BC_STATUS_SUCCESS; -#if !ERRORS_ARE_FATAL - s = -#endif - zbc_program_ops[inst - BC_INST_ASSIGN_POWER](l, r, l, G.prog.scale); + ERROR_RETURN(s =) zbc_program_ops[inst - BC_INST_ASSIGN_POWER](l, r, l, G.prog.scale); } if (s) RETURN_STATUS(s); #else @@ -6610,7 +6612,7 @@ static BcStatus bc_program_execStr(char *code, size_t *bgn, if (f->code.len == 0) { common_parse_init(&prs, fidx); - s = bc_parse_text(&prs, *str); + s = zbc_parse_text(&prs, *str); if (s) goto err; s = zcommon_parse_expr(&prs, BC_PARSE_NOCALL); if (s) goto err; @@ -6747,7 +6749,7 @@ static BcStatus bc_program_exec(void) s = zbc_program_logical(inst); break; case BC_INST_READ: - s = bc_program_read(); + s = zbc_program_read(); break; case BC_INST_VAR: s = zbc_program_pushVar(code, &ip->idx, false, false); @@ -7002,12 +7004,12 @@ static unsigned bc_vm_envLen(const char *var) static BcStatus bc_vm_process(const char *text) { - BcStatus s = bc_parse_text(&G.prs, text); + BcStatus s = zbc_parse_text(&G.prs, text); if (s) return s; while (G.prs.l.t.t != BC_LEX_EOF) { - s = G.prs.parse(&G.prs); + ERROR_RETURN(s =) G.prs.parse(&G.prs); if (s) return s; } @@ -7327,11 +7329,11 @@ static BcStatus bc_vm_exec(void) // thus error checking is normally disabled. # define DEBUG_LIB 0 bc_lex_file(&G.prs.l); - s = bc_parse_text(&G.prs, bc_lib); + s = zbc_parse_text(&G.prs, bc_lib); if (DEBUG_LIB && s) return s; while (G.prs.l.t.t != BC_LEX_EOF) { - s = G.prs.parse(&G.prs); + ERROR_RETURN(s =) G.prs.parse(&G.prs); if (DEBUG_LIB && s) return s; } s = bc_program_exec(); -- cgit v1.2.3-55-g6feb From c2da68e896d4253466bed202e71bae7b9b2aeec9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 12 Dec 2018 16:44:34 +0100 Subject: bc: optimize bc_parse_pushIndex() function old new delta bc_parse_pushIndex 80 68 -12 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 73c801c44..dc8e5c761 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -3460,16 +3460,23 @@ static void bc_parse_pushName(BcParse *p, char *name) static void bc_parse_pushIndex(BcParse *p, size_t idx) { - unsigned char amt, i, nums[sizeof(size_t)]; + size_t mask; + unsigned amt; -///oh boy - for (amt = 0; idx; ++amt) { - nums[amt] = (char) idx; - idx = (idx & ((unsigned long) ~(UCHAR_MAX))) >> sizeof(char) * CHAR_BIT; - } + mask = ((size_t)0xff) << (sizeof(idx) * 8 - 8); + amt = sizeof(idx); + do { + if (idx & mask) break; + mask >>= 8; + amt--; + } while (amt != 0); bc_parse_push(p, amt); - for (i = 0; i < amt; ++i) bc_parse_push(p, nums[i]); + + while (idx != 0) { + bc_parse_push(p, (unsigned char)idx); + idx >>= 8; + } } static void bc_parse_number(BcParse *p, BcInst *prev, size_t *nexs) -- cgit v1.2.3-55-g6feb From d6ad3666dc51f475a6e76b07f2c59d039f69f2d4 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 12 Dec 2018 21:39:10 +0100 Subject: bc: further conversions to "z" logic function old new delta bc_program_exec 3876 - -3876 zbc_program_exec - 3963 +3963 bc_program_execStr 429 - -429 zbc_program_execStr - 427 +427 bc_vm_file 197 - -197 zbc_vm_file - 187 +187 bc_vm_process 74 - -74 zbc_vm_process - 61 +61 bc_parse_pushIndex 66 68 +2 bc_vm_run 624 618 -6 dc_main 187 176 -11 bc_program_reset 64 - -64 zbc_program_pushArray 111 - -111 ------------------------------------------------------------------------------ (add/remove: 4/6 grow/shrink: 1/2 up/down: 4640/-4768) Total: -128 bytes text data bss dec hex filename 980922 485 7296 988703 f161f busybox_old 980794 485 7296 988575 f159f busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 67 +++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 40 insertions(+), 27 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index dc8e5c761..3d26c39a7 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -6549,7 +6549,7 @@ static BC_STATUS zbc_program_nquit(void) # define zbc_program_nquit(...) (zbc_program_nquit(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static BcStatus bc_program_execStr(char *code, size_t *bgn, +static BC_STATUS zbc_program_execStr(char *code, size_t *bgn, bool cond) { BcStatus s = BC_STATUS_SUCCESS; @@ -6561,7 +6561,7 @@ static BcStatus bc_program_execStr(char *code, size_t *bgn, size_t fidx, sidx; if (!BC_PROG_STACK(&G.prog.results, 1)) - return bc_error_stack_has_too_few_elements(); + RETURN_STATUS(bc_error_stack_has_too_few_elements()); r = bc_vec_top(&G.prog.results); @@ -6639,7 +6639,7 @@ static BcStatus bc_program_execStr(char *code, size_t *bgn, bc_vec_pop(&G.prog.results); bc_vec_push(&G.prog.stack, &ip); - return BC_STATUS_SUCCESS; + RETURN_STATUS(BC_STATUS_SUCCESS); err: bc_parse_free(&prs); @@ -6647,8 +6647,11 @@ err: bc_vec_pop_all(&f->code); exit: bc_vec_pop(&G.prog.results); - return s; + RETURN_STATUS(s); } +#if ERRORS_ARE_FATAL +# define zbc_program_execStr(...) (zbc_program_execStr(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif #endif // ENABLE_DC static void bc_program_pushGlobal(char inst) @@ -6700,7 +6703,7 @@ static void bc_program_addFunc(char *name, size_t *idx) } } -static BcStatus bc_program_exec(void) +static BC_STATUS zbc_program_exec(void) { BcResult r, *ptr; BcNum *num; @@ -6717,7 +6720,7 @@ static BcStatus bc_program_exec(void) #if ENABLE_BC case BC_INST_JUMP_ZERO: s = zbc_program_prep(&ptr, &num); - if (s) return s; + if (s) RETURN_STATUS(s); cond = !bc_num_cmp(num, &G.prog.zero); bc_vec_pop(&G.prog.results); // Fallthrough. @@ -6813,7 +6816,7 @@ static BcStatus bc_program_exec(void) break; case BC_INST_BOOL_NOT: s = zbc_program_prep(&ptr, &num); - if (s) return s; + if (s) RETURN_STATUS(s); bc_num_init_DEF_SIZE(&r.d.n); if (!bc_num_cmp(num, &G.prog.zero)) bc_num_one(&r.d.n); @@ -6844,7 +6847,7 @@ static BcStatus bc_program_exec(void) case BC_INST_EXECUTE: case BC_INST_EXEC_COND: cond = inst == BC_INST_EXEC_COND; - s = bc_program_execStr(code, &ip->idx, cond); + s = zbc_program_execStr(code, &ip->idx, cond); break; case BC_INST_PRINT_STACK: { size_t idx; @@ -6862,7 +6865,7 @@ static BcStatus bc_program_exec(void) break; case BC_INST_DUPLICATE: if (!BC_PROG_STACK(&G.prog.results, 1)) - return bc_error_stack_has_too_few_elements(); + RETURN_STATUS(bc_error_stack_has_too_few_elements()); ptr = bc_vec_top(&G.prog.results); bc_result_copy(&r, ptr); bc_vec_push(&G.prog.results, &r); @@ -6870,7 +6873,7 @@ static BcStatus bc_program_exec(void) case BC_INST_SWAP: { BcResult *ptr2; if (!BC_PROG_STACK(&G.prog.results, 2)) - return bc_error_stack_has_too_few_elements(); + RETURN_STATUS(bc_error_stack_has_too_few_elements()); ptr = bc_vec_item_rev(&G.prog.results, 0); ptr2 = bc_vec_item_rev(&G.prog.results, 1); memcpy(&r, ptr, sizeof(BcResult)); @@ -6909,7 +6912,7 @@ static BcStatus bc_program_exec(void) if (s || G_interrupt) { bc_program_reset(); - return s; + RETURN_STATUS(s); } // If the stack has changed, pointers may be invalid. @@ -6918,8 +6921,11 @@ static BcStatus bc_program_exec(void) code = func->code.v; } - return BC_STATUS_SUCCESS; + RETURN_STATUS(BC_STATUS_SUCCESS); } +#if ERRORS_ARE_FATAL +# define zbc_program_exec(...) (zbc_program_exec(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif #if ENABLE_BC static void bc_vm_info(void) @@ -7009,28 +7015,31 @@ static unsigned bc_vm_envLen(const char *var) return len; } -static BcStatus bc_vm_process(const char *text) +static BC_STATUS zbc_vm_process(const char *text) { BcStatus s = zbc_parse_text(&G.prs, text); - if (s) return s; + if (s) RETURN_STATUS(s); while (G.prs.l.t.t != BC_LEX_EOF) { ERROR_RETURN(s =) G.prs.parse(&G.prs); - if (s) return s; + if (s) RETURN_STATUS(s); } if (BC_PARSE_CAN_EXEC(&G.prs)) { - s = bc_program_exec(); + s = zbc_program_exec(); fflush_and_check(); if (s) bc_program_reset(); } - return s; + RETURN_STATUS(s); } +#if ERRORS_ARE_FATAL +# define zbc_vm_process(...) (zbc_vm_process(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif -static BcStatus bc_vm_file(const char *file) +static BC_STATUS zbc_vm_file(const char *file) { const char *sv_file; char *data; @@ -7039,12 +7048,12 @@ static BcStatus bc_vm_file(const char *file) BcInstPtr *ip; data = bc_read_file(file); - if (!data) return bc_error_fmt("file '%s' is not text", file); + if (!data) RETURN_STATUS(bc_error_fmt("file '%s' is not text", file)); sv_file = G.prog.file; G.prog.file = file; bc_lex_file(&G.prs.l); - s = bc_vm_process(data); + s = zbc_vm_process(data); if (s) goto err; main_func = bc_program_func(BC_PROG_MAIN); @@ -7056,8 +7065,11 @@ static BcStatus bc_vm_file(const char *file) err: G.prog.file = sv_file; free(data); - return s; + RETURN_STATUS(s); } +#if ERRORS_ARE_FATAL +# define zbc_vm_file(...) (zbc_vm_file(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif static BcStatus bc_vm_stdin(void) { @@ -7120,7 +7132,7 @@ static BcStatus bc_vm_stdin(void) } bc_vec_concat(&buffer, buf.v); - s = bc_vm_process(buffer.v); + s = zbc_vm_process(buffer.v); if (s) { if (ENABLE_FEATURE_CLEAN_UP && !G_ttyin) { // Debug config, non-interactive mode: @@ -7343,14 +7355,14 @@ static BcStatus bc_vm_exec(void) ERROR_RETURN(s =) G.prs.parse(&G.prs); if (DEBUG_LIB && s) return s; } - s = bc_program_exec(); + s = zbc_program_exec(); if (DEBUG_LIB && s) return s; } #endif s = BC_STATUS_SUCCESS; for (i = 0; !s && i < G.files.len; ++i) - s = bc_vm_file(*((char **) bc_vec_item(&G.files, i))); + s = zbc_vm_file(*((char **) bc_vec_item(&G.files, i))); if (ENABLE_FEATURE_CLEAN_UP && s && !G_ttyin) { // Debug config, non-interactive mode: // return all the way back to main. @@ -7362,7 +7374,7 @@ static BcStatus bc_vm_exec(void) s = bc_vm_stdin(); if (!s && !BC_PARSE_CAN_EXEC(&G.prs)) - s = bc_vm_process(""); + s = zbc_vm_process(""); return s; } @@ -7560,12 +7572,13 @@ int dc_main(int argc UNUSED_PARAM, char **argv) switch (n) { case 'e': noscript = 0; - n = bc_vm_process(optarg); + n = zbc_vm_process(optarg); if (n) return n; break; case 'f': noscript = 0; - bc_vm_file(optarg); + n = zbc_vm_file(optarg); + if (n) return n; break; case 'x': option_mask32 |= DC_FLAG_X; -- cgit v1.2.3-55-g6feb From 9a23b07c4c0d06c40d7c0ce91c5fdf7c8449ac49 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 12 Dec 2018 21:41:40 +0100 Subject: testsuite: add bc and dc tests Signed-off-by: Denys Vlasenko --- testsuite/bc.tests | 19 + testsuite/bc_add.bc | 26 ++ testsuite/bc_add_results.txt | 38 ++ testsuite/bc_arctangent.bc | 26 ++ testsuite/bc_arctangent_results.txt | 25 ++ testsuite/bc_array.bc | 35 ++ testsuite/bc_array_results.txt | 426 ++++++++++++++++++ testsuite/bc_arrays.bc | 10 + testsuite/bc_arrays_results.txt | 3 + testsuite/bc_bessel.bc | 844 ++++++++++++++++++++++++++++++++++++ testsuite/bc_bessel_results.txt | 843 +++++++++++++++++++++++++++++++++++ testsuite/bc_boolean.bc | 181 ++++++++ testsuite/bc_boolean_results.txt | 181 ++++++++ testsuite/bc_cosine.bc | 44 ++ testsuite/bc_cosine_results.txt | 41 ++ testsuite/bc_decimal.bc | 36 ++ testsuite/bc_decimal_results.txt | 51 +++ testsuite/bc_divide.bc | 31 ++ testsuite/bc_divide_results.txt | 31 ++ testsuite/bc_exponent.bc | 22 + testsuite/bc_exponent_results.txt | 25 ++ testsuite/bc_large.tar.xz | Bin 0 -> 5118896 bytes testsuite/bc_log.bc | 22 + testsuite/bc_log_results.txt | 22 + testsuite/bc_misc.bc | 13 + testsuite/bc_misc1.bc | 76 ++++ testsuite/bc_misc1_results.txt | 57 +++ testsuite/bc_misc2.bc | 45 ++ testsuite/bc_misc2_results.txt | 20 + testsuite/bc_misc_results.txt | 4 + testsuite/bc_modulus.bc | 70 +++ testsuite/bc_modulus_results.txt | 69 +++ testsuite/bc_multiply.bc | 42 ++ testsuite/bc_multiply_results.txt | 43 ++ testsuite/bc_pi.bc | 4 + testsuite/bc_pi_results.txt | 135 ++++++ testsuite/bc_power.bc | 44 ++ testsuite/bc_power_results.txt | 73 ++++ testsuite/bc_sine.bc | 207 +++++++++ testsuite/bc_sine_results.txt | 204 +++++++++ testsuite/bc_sqrt.bc | 18 + testsuite/bc_sqrt_results.txt | 16 + testsuite/bc_strings.bc | 12 + testsuite/bc_strings_results.txt | 5 + testsuite/bc_subtract.bc | 32 ++ testsuite/bc_subtract_results.txt | 36 ++ testsuite/bc_vars.bc | 7 + testsuite/bc_vars_results.txt | 12 + testsuite/dc.tests | 20 + testsuite/dc_add.dc | 33 ++ testsuite/dc_add_results.txt | 45 ++ testsuite/dc_boolean.dc | 27 ++ testsuite/dc_boolean_results.txt | 27 ++ testsuite/dc_decimal.dc | 36 ++ testsuite/dc_decimal_results.txt | 51 +++ testsuite/dc_divide.dc | 33 ++ testsuite/dc_divide_results.txt | 32 ++ testsuite/dc_divmod.dc | 64 +++ testsuite/dc_divmod_results.txt | 126 ++++++ testsuite/dc_misc.dc | 1 + testsuite/dc_misc_results.txt | 20 + testsuite/dc_modexp.dc | 103 +++++ testsuite/dc_modexp_results.txt | 103 +++++ testsuite/dc_modulus.dc | 70 +++ testsuite/dc_modulus_results.txt | 68 +++ testsuite/dc_multiply.dc | 42 ++ testsuite/dc_multiply_results.txt | 43 ++ testsuite/dc_power.dc | 45 ++ testsuite/dc_power_results.txt | 73 ++++ testsuite/dc_sqrt.dc | 14 + testsuite/dc_sqrt_results.txt | 13 + testsuite/dc_strings.dc | 37 ++ testsuite/dc_strings_results.txt | 36 ++ testsuite/dc_subtract.dc | 33 ++ testsuite/dc_subtract_results.txt | 37 ++ testsuite/dcx_vars.dc | 2 + testsuite/dcx_vars_results.txt | 6 + 77 files changed, 5466 insertions(+) create mode 100755 testsuite/bc.tests create mode 100644 testsuite/bc_add.bc create mode 100644 testsuite/bc_add_results.txt create mode 100644 testsuite/bc_arctangent.bc create mode 100644 testsuite/bc_arctangent_results.txt create mode 100644 testsuite/bc_array.bc create mode 100644 testsuite/bc_array_results.txt create mode 100644 testsuite/bc_arrays.bc create mode 100644 testsuite/bc_arrays_results.txt create mode 100644 testsuite/bc_bessel.bc create mode 100644 testsuite/bc_bessel_results.txt create mode 100644 testsuite/bc_boolean.bc create mode 100644 testsuite/bc_boolean_results.txt create mode 100644 testsuite/bc_cosine.bc create mode 100644 testsuite/bc_cosine_results.txt create mode 100644 testsuite/bc_decimal.bc create mode 100644 testsuite/bc_decimal_results.txt create mode 100644 testsuite/bc_divide.bc create mode 100644 testsuite/bc_divide_results.txt create mode 100644 testsuite/bc_exponent.bc create mode 100644 testsuite/bc_exponent_results.txt create mode 100644 testsuite/bc_large.tar.xz create mode 100644 testsuite/bc_log.bc create mode 100644 testsuite/bc_log_results.txt create mode 100644 testsuite/bc_misc.bc create mode 100644 testsuite/bc_misc1.bc create mode 100644 testsuite/bc_misc1_results.txt create mode 100644 testsuite/bc_misc2.bc create mode 100644 testsuite/bc_misc2_results.txt create mode 100644 testsuite/bc_misc_results.txt create mode 100644 testsuite/bc_modulus.bc create mode 100644 testsuite/bc_modulus_results.txt create mode 100644 testsuite/bc_multiply.bc create mode 100644 testsuite/bc_multiply_results.txt create mode 100644 testsuite/bc_pi.bc create mode 100644 testsuite/bc_pi_results.txt create mode 100644 testsuite/bc_power.bc create mode 100644 testsuite/bc_power_results.txt create mode 100644 testsuite/bc_sine.bc create mode 100644 testsuite/bc_sine_results.txt create mode 100644 testsuite/bc_sqrt.bc create mode 100644 testsuite/bc_sqrt_results.txt create mode 100644 testsuite/bc_strings.bc create mode 100644 testsuite/bc_strings_results.txt create mode 100644 testsuite/bc_subtract.bc create mode 100644 testsuite/bc_subtract_results.txt create mode 100644 testsuite/bc_vars.bc create mode 100644 testsuite/bc_vars_results.txt create mode 100644 testsuite/dc_add.dc create mode 100644 testsuite/dc_add_results.txt create mode 100644 testsuite/dc_boolean.dc create mode 100644 testsuite/dc_boolean_results.txt create mode 100644 testsuite/dc_decimal.dc create mode 100644 testsuite/dc_decimal_results.txt create mode 100644 testsuite/dc_divide.dc create mode 100644 testsuite/dc_divide_results.txt create mode 100644 testsuite/dc_divmod.dc create mode 100644 testsuite/dc_divmod_results.txt create mode 100644 testsuite/dc_misc.dc create mode 100644 testsuite/dc_misc_results.txt create mode 100644 testsuite/dc_modexp.dc create mode 100644 testsuite/dc_modexp_results.txt create mode 100644 testsuite/dc_modulus.dc create mode 100644 testsuite/dc_modulus_results.txt create mode 100644 testsuite/dc_multiply.dc create mode 100644 testsuite/dc_multiply_results.txt create mode 100644 testsuite/dc_power.dc create mode 100644 testsuite/dc_power_results.txt create mode 100644 testsuite/dc_sqrt.dc create mode 100644 testsuite/dc_sqrt_results.txt create mode 100644 testsuite/dc_strings.dc create mode 100644 testsuite/dc_strings_results.txt create mode 100644 testsuite/dc_subtract.dc create mode 100644 testsuite/dc_subtract_results.txt create mode 100644 testsuite/dcx_vars.dc create mode 100644 testsuite/dcx_vars_results.txt diff --git a/testsuite/bc.tests b/testsuite/bc.tests new file mode 100755 index 000000000..32460092b --- /dev/null +++ b/testsuite/bc.tests @@ -0,0 +1,19 @@ +#!/bin/sh +# Copyright 2018 by Denys Vlasenko +# Licensed under GPLv2 or later, see file LICENSE in this source tree. + +. ./testing.sh + +tar xJf bc_large.tar.xz + +for f in bc*.bc; do + r="`basename "$f" .bc`_results.txt" + test -f "$r" || continue + # testing "test name" "command" "expected result" "file input" "stdin" + testing "bc -lq $f" \ + "{ { bc -lq $f 2>&1; echo E:\$? >&2; } | diff -u - $r; echo E:\$?; } 2>&1" \ + "E:0\nE:0\n" \ + "" "" +done + +exit $FAILCOUNT diff --git a/testsuite/bc_add.bc b/testsuite/bc_add.bc new file mode 100644 index 000000000..ee03b4bb6 --- /dev/null +++ b/testsuite/bc_add.bc @@ -0,0 +1,26 @@ +0 + 0 +0 + 1 +1 + 1 +1 + 0 +2 + 5 +237 + 483 +999 + 999 +2374623 + 324869356734856 +2378639084586723980562 + 23468729367839 +37298367203972395108367910823465293084561329084561390845613409516734503870691837451 + 785621394067928346918023476190834672198467134908618723249671349062187346898241093486139046139084613490817356023871869102746182749061872609129847 +1.1 + 0 +0 + 1.1 +457283.731284923576 + 37842934672834.3874629385672354 +1.0 + 0.1 +3746289134067138046 + 0.138375863945672398456712389456273486293 +-1 + -1 +-4 + -15 +-1346782 + -1287904651762468913476 +99999999999999999999999999999999999999999999999999999999999.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 + 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +99999999999999999999999999999999999999999999999999999999999.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999995 + 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005 +99999999999999999999999999999999999999999999999999999999999.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 + 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +99999999999999999999999999999999999999999999999999999999999.999999999999999999999999999999999999999999999999999999999899999999999999999999999999999999999999999999999999999999999999 + 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +99999999999999999999999999999999999989999999999999999999999.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 + 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +-1889985797 + 2012747315 +0 + -14338.391079082 +-2422297 + 1.3134942556 diff --git a/testsuite/bc_add_results.txt b/testsuite/bc_add_results.txt new file mode 100644 index 000000000..c3b4d6d2a --- /dev/null +++ b/testsuite/bc_add_results.txt @@ -0,0 +1,38 @@ +0 +1 +2 +1 +7 +720 +1998 +324869359109479 +2378639108055453348401 +78562139406792834691802347619083467219846713490861872324967138636055\ +45508706362018540498696043776980521464405852627147161556994835657433\ +00967298 +1.1 +1.1 +37842935130118.1187478621432354 +1.1 +3746289134067138046.138375863945672398456712389456273486293 +-2 +-19 +-1287904651762470260258 +100000000000000000000000000000000000000000000000000000000000.0000000\ +00000000000000000000000000000000000000000000000000000000000000000000\ +000000000000000000000000000000000000000000000 +100000000000000000000000000000000000000000000000000000000000.0000000\ +00000000000000000000000000000000000000000000000000000000000000000000\ +000000000000000000000000000000000000000000000 +100000000000000000000000000000000000000000000000000000000000.0000000\ +00000000000000000000000000000000000000000000000000000000000000000000\ +000000000000000000000000000000000000000009999 +99999999999999999999999999999999999999999999999999999999999.99999999\ +99999999999999999999999999999999999999999999999999000000000000000000\ +00000000000000000000000000000000000000009999 +99999999999999999999999999999999999990000000000000000000000.00000000\ +00000000000000000000000000000000000000000000000000000000000000000000\ +00000000000000000000000000000000000000009999 +122761518 +-14338.391079082 +-2422295.6865057444 diff --git a/testsuite/bc_arctangent.bc b/testsuite/bc_arctangent.bc new file mode 100644 index 000000000..f665ea90b --- /dev/null +++ b/testsuite/bc_arctangent.bc @@ -0,0 +1,26 @@ +a(.267) +a(1) +scale = 64 +a(.267) +a(1) +scale = 100 +a(.267) +a(1) +scale = 20 +a(0) +a(.5) +a(0.577350269189625764509148780501) +a(1.5) +a(1.7320508075688772935274463415) +a(2) +a(3) +a(1000) +a(-.5) +a(-0.577350269189625764509148780501) +a(-1.5) +a(-1.7320508075688772935274463415) +a(-2) +a(-3) +a(-1000) +a(-3249917614.2821897119) +a(-694706362.1974670468) diff --git a/testsuite/bc_arctangent_results.txt b/testsuite/bc_arctangent_results.txt new file mode 100644 index 000000000..e77c63779 --- /dev/null +++ b/testsuite/bc_arctangent_results.txt @@ -0,0 +1,25 @@ +.26091356923294057959 +.78539816339744830961 +.2609135692329405795967852677779865639774740239882445822329882917 +.7853981633974483096156608458198757210492923498437764552437361480 +.2609135692329405795967852677779865639774740239882445822329882917230\ +650591934644905491823044536954978 +.7853981633974483096156608458198757210492923498437764552437361480769\ +541015715522496570087063355292669 +0 +.46364760900080611621 +.52359877559829887307 +.98279372324732906798 +1.04719755119659774615 +1.10714871779409050301 +1.24904577239825442582 +1.56979632712822975256 +-.46364760900080611621 +-.52359877559829887307 +-.98279372324732906798 +-1.04719755119659774615 +-1.10714871779409050301 +-1.24904577239825442582 +-1.56979632712822975256 +-1.57079632648719651151 +-1.57079632535543952711 diff --git a/testsuite/bc_array.bc b/testsuite/bc_array.bc new file mode 100644 index 000000000..3bb680178 --- /dev/null +++ b/testsuite/bc_array.bc @@ -0,0 +1,35 @@ +#! /usr/bin/bc -q + +define z(a[]) { + for (i = 0; i < l; ++i) { + a[i] + } +} + +define x(a[]) { + + for (i = 0; i < l; ++i) { + a[i] = -i + } + + z(a[]) +} + +for (i = 0; i < 101; ++i) { + a[i] = i +} + +a[104] = 204 + +l = length(a[]) + +for (i = 0; i <= l; ++i) { + a[i] +} + +z(a[]) +x(a[]) +z(a[]) +l + +halt diff --git a/testsuite/bc_array_results.txt b/testsuite/bc_array_results.txt new file mode 100644 index 000000000..a757b7fb5 --- /dev/null +++ b/testsuite/bc_array_results.txt @@ -0,0 +1,426 @@ +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +0 +0 +0 +204 +0 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +0 +0 +0 +204 +0 +0 +-1 +-2 +-3 +-4 +-5 +-6 +-7 +-8 +-9 +-10 +-11 +-12 +-13 +-14 +-15 +-16 +-17 +-18 +-19 +-20 +-21 +-22 +-23 +-24 +-25 +-26 +-27 +-28 +-29 +-30 +-31 +-32 +-33 +-34 +-35 +-36 +-37 +-38 +-39 +-40 +-41 +-42 +-43 +-44 +-45 +-46 +-47 +-48 +-49 +-50 +-51 +-52 +-53 +-54 +-55 +-56 +-57 +-58 +-59 +-60 +-61 +-62 +-63 +-64 +-65 +-66 +-67 +-68 +-69 +-70 +-71 +-72 +-73 +-74 +-75 +-76 +-77 +-78 +-79 +-80 +-81 +-82 +-83 +-84 +-85 +-86 +-87 +-88 +-89 +-90 +-91 +-92 +-93 +-94 +-95 +-96 +-97 +-98 +-99 +-100 +-101 +-102 +-103 +-104 +0 +0 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +0 +0 +0 +204 +0 +105 diff --git a/testsuite/bc_arrays.bc b/testsuite/bc_arrays.bc new file mode 100644 index 000000000..26a284b8d --- /dev/null +++ b/testsuite/bc_arrays.bc @@ -0,0 +1,10 @@ +a[0] = 1 +a[2-1] = 2 + +a[0]+a[0] + +a[2-1]+a[2-1] + +a[5] = 2 +a[5.789] + diff --git a/testsuite/bc_arrays_results.txt b/testsuite/bc_arrays_results.txt new file mode 100644 index 000000000..200035ffa --- /dev/null +++ b/testsuite/bc_arrays_results.txt @@ -0,0 +1,3 @@ +2 +4 +2 diff --git a/testsuite/bc_bessel.bc b/testsuite/bc_bessel.bc new file mode 100644 index 000000000..a52fa356b --- /dev/null +++ b/testsuite/bc_bessel.bc @@ -0,0 +1,844 @@ +j(0, 0) +j(0, .5) +j(0, -.5) +j(0, 1) +j(0, -1) +j(0, 1.5) +j(0, -1.5) +j(0, 1.74) +j(0, -1.74) +j(0, 2) +j(0, -2) +j(0, 3.2345) +j(0, -3.2345) +j(0, 100) +j(0, -100) +j(0, -.5) +j(0, .5) +j(0, -1) +j(0, 1) +j(0, -1.5) +j(0, 1.5) +j(0, -1.74) +j(0, 1.74) +j(0, -2) +j(0, 2) +j(0, -3.2345) +j(0, 3.2345) +j(0, -100) +j(0, 100) +j(.5, 0) +j(.5, .5) +j(.5, -.5) +j(.5, 1) +j(.5, -1) +j(.5, 1.5) +j(.5, -1.5) +j(.5, 1.74) +j(.5, -1.74) +j(.5, 2) +j(.5, -2) +j(.5, 3.2345) +j(.5, -3.2345) +j(.5, 100) +j(.5, -100) +j(.5, -.5) +j(.5, .5) +j(.5, -1) +j(.5, 1) +j(.5, -1.5) +j(.5, 1.5) +j(.5, -1.74) +j(.5, 1.74) +j(.5, -2) +j(.5, 2) +j(.5, -3.2345) +j(.5, 3.2345) +j(.5, -100) +j(.5, 100) +j(-.5, 0) +j(-.5, .5) +j(-.5, -.5) +j(-.5, 1) +j(-.5, -1) +j(-.5, 1.5) +j(-.5, -1.5) +j(-.5, 1.74) +j(-.5, -1.74) +j(-.5, 2) +j(-.5, -2) +j(-.5, 3.2345) +j(-.5, -3.2345) +j(-.5, 100) +j(-.5, -100) +j(-.5, -.5) +j(-.5, .5) +j(-.5, -1) +j(-.5, 1) +j(-.5, -1.5) +j(-.5, 1.5) +j(-.5, -1.74) +j(-.5, 1.74) +j(-.5, -2) +j(-.5, 2) +j(-.5, -3.2345) +j(-.5, 3.2345) +j(-.5, -100) +j(-.5, 100) +j(1, 0) +j(1, .5) +j(1, -.5) +j(1, 1) +j(1, -1) +j(1, 1.5) +j(1, -1.5) +j(1, 1.74) +j(1, -1.74) +j(1, 2) +j(1, -2) +j(1, 3.2345) +j(1, -3.2345) +j(1, 100) +j(1, -100) +j(1, -.5) +j(1, .5) +j(1, -1) +j(1, 1) +j(1, -1.5) +j(1, 1.5) +j(1, -1.74) +j(1, 1.74) +j(1, -2) +j(1, 2) +j(1, -3.2345) +j(1, 3.2345) +j(1, -100) +j(1, 100) +j(-1, 0) +j(-1, .5) +j(-1, -.5) +j(-1, 1) +j(-1, -1) +j(-1, 1.5) +j(-1, -1.5) +j(-1, 1.74) +j(-1, -1.74) +j(-1, 2) +j(-1, -2) +j(-1, 3.2345) +j(-1, -3.2345) +j(-1, 100) +j(-1, -100) +j(-1, -.5) +j(-1, .5) +j(-1, -1) +j(-1, 1) +j(-1, -1.5) +j(-1, 1.5) +j(-1, -1.74) +j(-1, 1.74) +j(-1, -2) +j(-1, 2) +j(-1, -3.2345) +j(-1, 3.2345) +j(-1, -100) +j(-1, 100) +j(1.5, 0) +j(1.5, .5) +j(1.5, -.5) +j(1.5, 1) +j(1.5, -1) +j(1.5, 1.5) +j(1.5, -1.5) +j(1.5, 1.74) +j(1.5, -1.74) +j(1.5, 2) +j(1.5, -2) +j(1.5, 3.2345) +j(1.5, -3.2345) +j(1.5, 100) +j(1.5, -100) +j(1.5, -.5) +j(1.5, .5) +j(1.5, -1) +j(1.5, 1) +j(1.5, -1.5) +j(1.5, 1.5) +j(1.5, -1.74) +j(1.5, 1.74) +j(1.5, -2) +j(1.5, 2) +j(1.5, -3.2345) +j(1.5, 3.2345) +j(1.5, -100) +j(1.5, 100) +j(-1.5, 0) +j(-1.5, .5) +j(-1.5, -.5) +j(-1.5, 1) +j(-1.5, -1) +j(-1.5, 1.5) +j(-1.5, -1.5) +j(-1.5, 1.74) +j(-1.5, -1.74) +j(-1.5, 2) +j(-1.5, -2) +j(-1.5, 3.2345) +j(-1.5, -3.2345) +j(-1.5, 100) +j(-1.5, -100) +j(-1.5, -.5) +j(-1.5, .5) +j(-1.5, -1) +j(-1.5, 1) +j(-1.5, -1.5) +j(-1.5, 1.5) +j(-1.5, -1.74) +j(-1.5, 1.74) +j(-1.5, -2) +j(-1.5, 2) +j(-1.5, -3.2345) +j(-1.5, 3.2345) +j(-1.5, -100) +j(-1.5, 100) +j(1.74, 0) +j(1.74, .5) +j(1.74, -.5) +j(1.74, 1) +j(1.74, -1) +j(1.74, 1.5) +j(1.74, -1.5) +j(1.74, 1.74) +j(1.74, -1.74) +j(1.74, 2) +j(1.74, -2) +j(1.74, 3.2345) +j(1.74, -3.2345) +j(1.74, 100) +j(1.74, -100) +j(1.74, -.5) +j(1.74, .5) +j(1.74, -1) +j(1.74, 1) +j(1.74, -1.5) +j(1.74, 1.5) +j(1.74, -1.74) +j(1.74, 1.74) +j(1.74, -2) +j(1.74, 2) +j(1.74, -3.2345) +j(1.74, 3.2345) +j(1.74, -100) +j(1.74, 100) +j(-1.74, 0) +j(-1.74, .5) +j(-1.74, -.5) +j(-1.74, 1) +j(-1.74, -1) +j(-1.74, 1.5) +j(-1.74, -1.5) +j(-1.74, 1.74) +j(-1.74, -1.74) +j(-1.74, 2) +j(-1.74, -2) +j(-1.74, 3.2345) +j(-1.74, -3.2345) +j(-1.74, 100) +j(-1.74, -100) +j(-1.74, -.5) +j(-1.74, .5) +j(-1.74, -1) +j(-1.74, 1) +j(-1.74, -1.5) +j(-1.74, 1.5) +j(-1.74, -1.74) +j(-1.74, 1.74) +j(-1.74, -2) +j(-1.74, 2) +j(-1.74, -3.2345) +j(-1.74, 3.2345) +j(-1.74, -100) +j(-1.74, 100) +j(2, 0) +j(2, .5) +j(2, -.5) +j(2, 1) +j(2, -1) +j(2, 1.5) +j(2, -1.5) +j(2, 1.74) +j(2, -1.74) +j(2, 2) +j(2, -2) +j(2, 3.2345) +j(2, -3.2345) +j(2, 100) +j(2, -100) +j(2, -.5) +j(2, .5) +j(2, -1) +j(2, 1) +j(2, -1.5) +j(2, 1.5) +j(2, -1.74) +j(2, 1.74) +j(2, -2) +j(2, 2) +j(2, -3.2345) +j(2, 3.2345) +j(2, -100) +j(2, 100) +j(-2, 0) +j(-2, .5) +j(-2, -.5) +j(-2, 1) +j(-2, -1) +j(-2, 1.5) +j(-2, -1.5) +j(-2, 1.74) +j(-2, -1.74) +j(-2, 2) +j(-2, -2) +j(-2, 3.2345) +j(-2, -3.2345) +j(-2, 100) +j(-2, -100) +j(-2, -.5) +j(-2, .5) +j(-2, -1) +j(-2, 1) +j(-2, -1.5) +j(-2, 1.5) +j(-2, -1.74) +j(-2, 1.74) +j(-2, -2) +j(-2, 2) +j(-2, -3.2345) +j(-2, 3.2345) +j(-2, -100) +j(-2, 100) +j(3.2345, 0) +j(3.2345, .5) +j(3.2345, -.5) +j(3.2345, 1) +j(3.2345, -1) +j(3.2345, 1.5) +j(3.2345, -1.5) +j(3.2345, 1.74) +j(3.2345, -1.74) +j(3.2345, 2) +j(3.2345, -2) +j(3.2345, 3.2345) +j(3.2345, -3.2345) +j(3.2345, 100) +j(3.2345, -100) +j(3.2345, -.5) +j(3.2345, .5) +j(3.2345, -1) +j(3.2345, 1) +j(3.2345, -1.5) +j(3.2345, 1.5) +j(3.2345, -1.74) +j(3.2345, 1.74) +j(3.2345, -2) +j(3.2345, 2) +j(3.2345, -3.2345) +j(3.2345, 3.2345) +j(3.2345, -100) +j(3.2345, 100) +j(-3.2345, 0) +j(-3.2345, .5) +j(-3.2345, -.5) +j(-3.2345, 1) +j(-3.2345, -1) +j(-3.2345, 1.5) +j(-3.2345, -1.5) +j(-3.2345, 1.74) +j(-3.2345, -1.74) +j(-3.2345, 2) +j(-3.2345, -2) +j(-3.2345, 3.2345) +j(-3.2345, -3.2345) +j(-3.2345, 100) +j(-3.2345, -100) +j(-3.2345, -.5) +j(-3.2345, .5) +j(-3.2345, -1) +j(-3.2345, 1) +j(-3.2345, -1.5) +j(-3.2345, 1.5) +j(-3.2345, -1.74) +j(-3.2345, 1.74) +j(-3.2345, -2) +j(-3.2345, 2) +j(-3.2345, -3.2345) +j(-3.2345, 3.2345) +j(-3.2345, -100) +j(-3.2345, 100) +j(100, 0) +j(100, .5) +j(100, -.5) +j(100, 1) +j(100, -1) +j(100, 1.5) +j(100, -1.5) +j(100, 1.74) +j(100, -1.74) +j(100, 2) +j(100, -2) +j(100, 3.2345) +j(100, -3.2345) +j(100, 100) +j(100, -100) +j(100, -.5) +j(100, .5) +j(100, -1) +j(100, 1) +j(100, -1.5) +j(100, 1.5) +j(100, -1.74) +j(100, 1.74) +j(100, -2) +j(100, 2) +j(100, -3.2345) +j(100, 3.2345) +j(100, -100) +j(100, 100) +j(-100, 0) +j(-100, .5) +j(-100, -.5) +j(-100, 1) +j(-100, -1) +j(-100, 1.5) +j(-100, -1.5) +j(-100, 1.74) +j(-100, -1.74) +j(-100, 2) +j(-100, -2) +j(-100, 3.2345) +j(-100, -3.2345) +j(-100, 100) +j(-100, -100) +j(-100, -.5) +j(-100, .5) +j(-100, -1) +j(-100, 1) +j(-100, -1.5) +j(-100, 1.5) +j(-100, -1.74) +j(-100, 1.74) +j(-100, -2) +j(-100, 2) +j(-100, -3.2345) +j(-100, 3.2345) +j(-100, -100) +j(-100, 100) +j(-.5, 0) +j(-.5, .5) +j(-.5, -.5) +j(-.5, 1) +j(-.5, -1) +j(-.5, 1.5) +j(-.5, -1.5) +j(-.5, 1.74) +j(-.5, -1.74) +j(-.5, 2) +j(-.5, -2) +j(-.5, 3.2345) +j(-.5, -3.2345) +j(-.5, 100) +j(-.5, -100) +j(-.5, -.5) +j(-.5, .5) +j(-.5, -1) +j(-.5, 1) +j(-.5, -1.5) +j(-.5, 1.5) +j(-.5, -1.74) +j(-.5, 1.74) +j(-.5, -2) +j(-.5, 2) +j(-.5, -3.2345) +j(-.5, 3.2345) +j(-.5, -100) +j(-.5, 100) +j(.5, 0) +j(.5, .5) +j(.5, -.5) +j(.5, 1) +j(.5, -1) +j(.5, 1.5) +j(.5, -1.5) +j(.5, 1.74) +j(.5, -1.74) +j(.5, 2) +j(.5, -2) +j(.5, 3.2345) +j(.5, -3.2345) +j(.5, 100) +j(.5, -100) +j(.5, -.5) +j(.5, .5) +j(.5, -1) +j(.5, 1) +j(.5, -1.5) +j(.5, 1.5) +j(.5, -1.74) +j(.5, 1.74) +j(.5, -2) +j(.5, 2) +j(.5, -3.2345) +j(.5, 3.2345) +j(.5, -100) +j(.5, 100) +j(-1, 0) +j(-1, .5) +j(-1, -.5) +j(-1, 1) +j(-1, -1) +j(-1, 1.5) +j(-1, -1.5) +j(-1, 1.74) +j(-1, -1.74) +j(-1, 2) +j(-1, -2) +j(-1, 3.2345) +j(-1, -3.2345) +j(-1, 100) +j(-1, -100) +j(-1, -.5) +j(-1, .5) +j(-1, -1) +j(-1, 1) +j(-1, -1.5) +j(-1, 1.5) +j(-1, -1.74) +j(-1, 1.74) +j(-1, -2) +j(-1, 2) +j(-1, -3.2345) +j(-1, 3.2345) +j(-1, -100) +j(-1, 100) +j(1, 0) +j(1, .5) +j(1, -.5) +j(1, 1) +j(1, -1) +j(1, 1.5) +j(1, -1.5) +j(1, 1.74) +j(1, -1.74) +j(1, 2) +j(1, -2) +j(1, 3.2345) +j(1, -3.2345) +j(1, 100) +j(1, -100) +j(1, -.5) +j(1, .5) +j(1, -1) +j(1, 1) +j(1, -1.5) +j(1, 1.5) +j(1, -1.74) +j(1, 1.74) +j(1, -2) +j(1, 2) +j(1, -3.2345) +j(1, 3.2345) +j(1, -100) +j(1, 100) +j(-1.5, 0) +j(-1.5, .5) +j(-1.5, -.5) +j(-1.5, 1) +j(-1.5, -1) +j(-1.5, 1.5) +j(-1.5, -1.5) +j(-1.5, 1.74) +j(-1.5, -1.74) +j(-1.5, 2) +j(-1.5, -2) +j(-1.5, 3.2345) +j(-1.5, -3.2345) +j(-1.5, 100) +j(-1.5, -100) +j(-1.5, -.5) +j(-1.5, .5) +j(-1.5, -1) +j(-1.5, 1) +j(-1.5, -1.5) +j(-1.5, 1.5) +j(-1.5, -1.74) +j(-1.5, 1.74) +j(-1.5, -2) +j(-1.5, 2) +j(-1.5, -3.2345) +j(-1.5, 3.2345) +j(-1.5, -100) +j(-1.5, 100) +j(1.5, 0) +j(1.5, .5) +j(1.5, -.5) +j(1.5, 1) +j(1.5, -1) +j(1.5, 1.5) +j(1.5, -1.5) +j(1.5, 1.74) +j(1.5, -1.74) +j(1.5, 2) +j(1.5, -2) +j(1.5, 3.2345) +j(1.5, -3.2345) +j(1.5, 100) +j(1.5, -100) +j(1.5, -.5) +j(1.5, .5) +j(1.5, -1) +j(1.5, 1) +j(1.5, -1.5) +j(1.5, 1.5) +j(1.5, -1.74) +j(1.5, 1.74) +j(1.5, -2) +j(1.5, 2) +j(1.5, -3.2345) +j(1.5, 3.2345) +j(1.5, -100) +j(1.5, 100) +j(-1.74, 0) +j(-1.74, .5) +j(-1.74, -.5) +j(-1.74, 1) +j(-1.74, -1) +j(-1.74, 1.5) +j(-1.74, -1.5) +j(-1.74, 1.74) +j(-1.74, -1.74) +j(-1.74, 2) +j(-1.74, -2) +j(-1.74, 3.2345) +j(-1.74, -3.2345) +j(-1.74, 100) +j(-1.74, -100) +j(-1.74, -.5) +j(-1.74, .5) +j(-1.74, -1) +j(-1.74, 1) +j(-1.74, -1.5) +j(-1.74, 1.5) +j(-1.74, -1.74) +j(-1.74, 1.74) +j(-1.74, -2) +j(-1.74, 2) +j(-1.74, -3.2345) +j(-1.74, 3.2345) +j(-1.74, -100) +j(-1.74, 100) +j(1.74, 0) +j(1.74, .5) +j(1.74, -.5) +j(1.74, 1) +j(1.74, -1) +j(1.74, 1.5) +j(1.74, -1.5) +j(1.74, 1.74) +j(1.74, -1.74) +j(1.74, 2) +j(1.74, -2) +j(1.74, 3.2345) +j(1.74, -3.2345) +j(1.74, 100) +j(1.74, -100) +j(1.74, -.5) +j(1.74, .5) +j(1.74, -1) +j(1.74, 1) +j(1.74, -1.5) +j(1.74, 1.5) +j(1.74, -1.74) +j(1.74, 1.74) +j(1.74, -2) +j(1.74, 2) +j(1.74, -3.2345) +j(1.74, 3.2345) +j(1.74, -100) +j(1.74, 100) +j(-2, 0) +j(-2, .5) +j(-2, -.5) +j(-2, 1) +j(-2, -1) +j(-2, 1.5) +j(-2, -1.5) +j(-2, 1.74) +j(-2, -1.74) +j(-2, 2) +j(-2, -2) +j(-2, 3.2345) +j(-2, -3.2345) +j(-2, 100) +j(-2, -100) +j(-2, -.5) +j(-2, .5) +j(-2, -1) +j(-2, 1) +j(-2, -1.5) +j(-2, 1.5) +j(-2, -1.74) +j(-2, 1.74) +j(-2, -2) +j(-2, 2) +j(-2, -3.2345) +j(-2, 3.2345) +j(-2, -100) +j(-2, 100) +j(2, 0) +j(2, .5) +j(2, -.5) +j(2, 1) +j(2, -1) +j(2, 1.5) +j(2, -1.5) +j(2, 1.74) +j(2, -1.74) +j(2, 2) +j(2, -2) +j(2, 3.2345) +j(2, -3.2345) +j(2, 100) +j(2, -100) +j(2, -.5) +j(2, .5) +j(2, -1) +j(2, 1) +j(2, -1.5) +j(2, 1.5) +j(2, -1.74) +j(2, 1.74) +j(2, -2) +j(2, 2) +j(2, -3.2345) +j(2, 3.2345) +j(2, -100) +j(2, 100) +j(-3.2345, 0) +j(-3.2345, .5) +j(-3.2345, -.5) +j(-3.2345, 1) +j(-3.2345, -1) +j(-3.2345, 1.5) +j(-3.2345, -1.5) +j(-3.2345, 1.74) +j(-3.2345, -1.74) +j(-3.2345, 2) +j(-3.2345, -2) +j(-3.2345, 3.2345) +j(-3.2345, -3.2345) +j(-3.2345, 100) +j(-3.2345, -100) +j(-3.2345, -.5) +j(-3.2345, .5) +j(-3.2345, -1) +j(-3.2345, 1) +j(-3.2345, -1.5) +j(-3.2345, 1.5) +j(-3.2345, -1.74) +j(-3.2345, 1.74) +j(-3.2345, -2) +j(-3.2345, 2) +j(-3.2345, -3.2345) +j(-3.2345, 3.2345) +j(-3.2345, -100) +j(-3.2345, 100) +j(3.2345, 0) +j(3.2345, .5) +j(3.2345, -.5) +j(3.2345, 1) +j(3.2345, -1) +j(3.2345, 1.5) +j(3.2345, -1.5) +j(3.2345, 1.74) +j(3.2345, -1.74) +j(3.2345, 2) +j(3.2345, -2) +j(3.2345, 3.2345) +j(3.2345, -3.2345) +j(3.2345, 100) +j(3.2345, -100) +j(3.2345, -.5) +j(3.2345, .5) +j(3.2345, -1) +j(3.2345, 1) +j(3.2345, -1.5) +j(3.2345, 1.5) +j(3.2345, -1.74) +j(3.2345, 1.74) +j(3.2345, -2) +j(3.2345, 2) +j(3.2345, -3.2345) +j(3.2345, 3.2345) +j(3.2345, -100) +j(3.2345, 100) +j(-100, 0) +j(-100, .5) +j(-100, -.5) +j(-100, 1) +j(-100, -1) +j(-100, 1.5) +j(-100, -1.5) +j(-100, 1.74) +j(-100, -1.74) +j(-100, 2) +j(-100, -2) +j(-100, 3.2345) +j(-100, -3.2345) +j(-100, 100) +j(-100, -100) +j(-100, -.5) +j(-100, .5) +j(-100, -1) +j(-100, 1) +j(-100, -1.5) +j(-100, 1.5) +j(-100, -1.74) +j(-100, 1.74) +j(-100, -2) +j(-100, 2) +j(-100, -3.2345) +j(-100, 3.2345) +j(-100, -100) +j(-100, 100) +j(100, 0) +j(100, .5) +j(100, -.5) +j(100, 1) +j(100, -1) +j(100, 1.5) +j(100, -1.5) +j(100, 1.74) +j(100, -1.74) +j(100, 2) +j(100, -2) +j(100, 3.2345) +j(100, -3.2345) +j(100, 100) +j(100, -100) +j(100, -.5) +j(100, .5) +j(100, -1) +j(100, 1) +j(100, -1.5) +j(100, 1.5) +j(100, -1.74) +j(100, 1.74) +j(100, -2) +j(100, 2) +j(100, -3.2345) +j(100, 3.2345) +j(100, -100) +j(100, 100) +j(3, 0.75) +scale = 0; j(40, 0.75) +halt \ No newline at end of file diff --git a/testsuite/bc_bessel_results.txt b/testsuite/bc_bessel_results.txt new file mode 100644 index 000000000..4bbb3c86b --- /dev/null +++ b/testsuite/bc_bessel_results.txt @@ -0,0 +1,843 @@ +1.00000000000000000000 +.93846980724081290422 +.93846980724081290422 +.76519768655796655144 +.76519768655796655144 +.51182767173591812874 +.51182767173591812874 +.37483214773176892693 +.37483214773176892693 +.22389077914123566805 +.22389077914123566805 +-.32896462175888702221 +-.32896462175888702221 +.01998585030422312242 +.01998585030422312242 +.93846980724081290422 +.93846980724081290422 +.76519768655796655144 +.76519768655796655144 +.51182767173591812874 +.51182767173591812874 +.37483214773176892693 +.37483214773176892693 +.22389077914123566805 +.22389077914123566805 +-.32896462175888702221 +-.32896462175888702221 +.01998585030422312242 +.01998585030422312242 +1.00000000000000000000 +.93846980724081290422 +.93846980724081290422 +.76519768655796655144 +.76519768655796655144 +.51182767173591812874 +.51182767173591812874 +.37483214773176892693 +.37483214773176892693 +.22389077914123566805 +.22389077914123566805 +-.32896462175888702221 +-.32896462175888702221 +.01998585030422312242 +.01998585030422312242 +.93846980724081290422 +.93846980724081290422 +.76519768655796655144 +.76519768655796655144 +.51182767173591812874 +.51182767173591812874 +.37483214773176892693 +.37483214773176892693 +.22389077914123566805 +.22389077914123566805 +-.32896462175888702221 +-.32896462175888702221 +.01998585030422312242 +.01998585030422312242 +1.00000000000000000000 +.93846980724081290422 +.93846980724081290422 +.76519768655796655144 +.76519768655796655144 +.51182767173591812874 +.51182767173591812874 +.37483214773176892693 +.37483214773176892693 +.22389077914123566805 +.22389077914123566805 +-.32896462175888702221 +-.32896462175888702221 +.01998585030422312242 +.01998585030422312242 +.93846980724081290422 +.93846980724081290422 +.76519768655796655144 +.76519768655796655144 +.51182767173591812874 +.51182767173591812874 +.37483214773176892693 +.37483214773176892693 +.22389077914123566805 +.22389077914123566805 +-.32896462175888702221 +-.32896462175888702221 +.01998585030422312242 +.01998585030422312242 +0 +.24226845767487388638 +-.24226845767487388638 +.44005058574493351595 +-.44005058574493351595 +.55793650791009964199 +-.55793650791009964199 +.57976044202797131452 +-.57976044202797131452 +.57672480775687338720 +-.57672480775687338720 +.24741588607612652213 +-.24741588607612652213 +-.07714535201411215803 +.07714535201411215803 +-.24226845767487388638 +.24226845767487388638 +-.44005058574493351595 +.44005058574493351595 +-.55793650791009964199 +.55793650791009964199 +-.57976044202797131452 +.57976044202797131452 +-.57672480775687338720 +.57672480775687338720 +-.24741588607612652213 +.24741588607612652213 +.07714535201411215803 +-.07714535201411215803 +0 +-.24226845767487388638 +.24226845767487388638 +-.44005058574493351595 +.44005058574493351595 +-.55793650791009964199 +.55793650791009964199 +-.57976044202797131452 +.57976044202797131452 +-.57672480775687338720 +.57672480775687338720 +-.24741588607612652213 +.24741588607612652213 +.07714535201411215803 +-.07714535201411215803 +.24226845767487388638 +-.24226845767487388638 +.44005058574493351595 +-.44005058574493351595 +.55793650791009964199 +-.55793650791009964199 +.57976044202797131452 +-.57976044202797131452 +.57672480775687338720 +-.57672480775687338720 +.24741588607612652213 +-.24741588607612652213 +-.07714535201411215803 +.07714535201411215803 +0 +.24226845767487388638 +-.24226845767487388638 +.44005058574493351595 +-.44005058574493351595 +.55793650791009964199 +-.55793650791009964199 +.57976044202797131452 +-.57976044202797131452 +.57672480775687338720 +-.57672480775687338720 +.24741588607612652213 +-.24741588607612652213 +-.07714535201411215803 +.07714535201411215803 +-.24226845767487388638 +.24226845767487388638 +-.44005058574493351595 +.44005058574493351595 +-.55793650791009964199 +.55793650791009964199 +-.57976044202797131452 +.57976044202797131452 +-.57672480775687338720 +.57672480775687338720 +-.24741588607612652213 +.24741588607612652213 +.07714535201411215803 +-.07714535201411215803 +0 +-.24226845767487388638 +.24226845767487388638 +-.44005058574493351595 +.44005058574493351595 +-.55793650791009964199 +.55793650791009964199 +-.57976044202797131452 +.57976044202797131452 +-.57672480775687338720 +.57672480775687338720 +-.24741588607612652213 +.24741588607612652213 +.07714535201411215803 +-.07714535201411215803 +.24226845767487388638 +-.24226845767487388638 +.44005058574493351595 +-.44005058574493351595 +.55793650791009964199 +-.55793650791009964199 +.57976044202797131452 +-.57976044202797131452 +.57672480775687338720 +-.57672480775687338720 +.24741588607612652213 +-.24741588607612652213 +-.07714535201411215803 +.07714535201411215803 +0 +.24226845767487388638 +-.24226845767487388638 +.44005058574493351595 +-.44005058574493351595 +.55793650791009964199 +-.55793650791009964199 +.57976044202797131452 +-.57976044202797131452 +.57672480775687338720 +-.57672480775687338720 +.24741588607612652213 +-.24741588607612652213 +-.07714535201411215803 +.07714535201411215803 +-.24226845767487388638 +.24226845767487388638 +-.44005058574493351595 +.44005058574493351595 +-.55793650791009964199 +.55793650791009964199 +-.57976044202797131452 +.57976044202797131452 +-.57672480775687338720 +.57672480775687338720 +-.24741588607612652213 +.24741588607612652213 +.07714535201411215803 +-.07714535201411215803 +0 +-.24226845767487388638 +.24226845767487388638 +-.44005058574493351595 +.44005058574493351595 +-.55793650791009964199 +.55793650791009964199 +-.57976044202797131452 +.57976044202797131452 +-.57672480775687338720 +.57672480775687338720 +-.24741588607612652213 +.24741588607612652213 +.07714535201411215803 +-.07714535201411215803 +.24226845767487388638 +-.24226845767487388638 +.44005058574493351595 +-.44005058574493351595 +.55793650791009964199 +-.55793650791009964199 +.57976044202797131452 +-.57976044202797131452 +.57672480775687338720 +-.57672480775687338720 +.24741588607612652213 +-.24741588607612652213 +-.07714535201411215803 +.07714535201411215803 +0 +.03060402345868264130 +.03060402345868264130 +.11490348493190048046 +.11490348493190048046 +.23208767214421472723 +.23208767214421472723 +.29155916494406017021 +.29155916494406017021 +.35283402861563771915 +.35283402861563771915 +.48195017505993913050 +.48195017505993913050 +-.02152875734450536558 +-.02152875734450536558 +.03060402345868264130 +.03060402345868264130 +.11490348493190048046 +.11490348493190048046 +.23208767214421472723 +.23208767214421472723 +.29155916494406017021 +.29155916494406017021 +.35283402861563771915 +.35283402861563771915 +.48195017505993913050 +.48195017505993913050 +-.02152875734450536558 +-.02152875734450536558 +0 +.03060402345868264130 +.03060402345868264130 +.11490348493190048046 +.11490348493190048046 +.23208767214421472723 +.23208767214421472723 +.29155916494406017021 +.29155916494406017021 +.35283402861563771915 +.35283402861563771915 +.48195017505993913050 +.48195017505993913050 +-.02152875734450536558 +-.02152875734450536558 +.03060402345868264130 +.03060402345868264130 +.11490348493190048046 +.11490348493190048046 +.23208767214421472723 +.23208767214421472723 +.29155916494406017021 +.29155916494406017021 +.35283402861563771915 +.35283402861563771915 +.48195017505993913050 +.48195017505993913050 +-.02152875734450536558 +-.02152875734450536558 +0 +.00256372999458724407 +-.00256372999458724407 +.01956335398266840591 +-.01956335398266840591 +.06096395114113963064 +-.06096395114113963064 +.09049051186641988137 +-.09049051186641988137 +.12894324947440205109 +-.12894324947440205109 +.34859607875298354805 +-.34859607875298354805 +.07628420172033194340 +-.07628420172033194340 +-.00256372999458724407 +.00256372999458724407 +-.01956335398266840591 +.01956335398266840591 +-.06096395114113963064 +.06096395114113963064 +-.09049051186641988137 +.09049051186641988137 +-.12894324947440205109 +.12894324947440205109 +-.34859607875298354805 +.34859607875298354805 +-.07628420172033194340 +.07628420172033194340 +0 +-.00256372999458724407 +.00256372999458724407 +-.01956335398266840591 +.01956335398266840591 +-.06096395114113963064 +.06096395114113963064 +-.09049051186641988137 +.09049051186641988137 +-.12894324947440205109 +.12894324947440205109 +-.34859607875298354805 +.34859607875298354805 +-.07628420172033194340 +.07628420172033194340 +.00256372999458724407 +-.00256372999458724407 +.01956335398266840591 +-.01956335398266840591 +.06096395114113963064 +-.06096395114113963064 +.09049051186641988137 +-.09049051186641988137 +.12894324947440205109 +-.12894324947440205109 +.34859607875298354805 +-.34859607875298354805 +.07628420172033194340 +-.07628420172033194340 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +.09636667329586155967 +.09636667329586155967 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +.09636667329586155967 +.09636667329586155967 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +.09636667329586155967 +.09636667329586155967 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +.09636667329586155967 +.09636667329586155967 +1.00000000000000000000 +.93846980724081290422 +.93846980724081290422 +.76519768655796655144 +.76519768655796655144 +.51182767173591812874 +.51182767173591812874 +.37483214773176892693 +.37483214773176892693 +.22389077914123566805 +.22389077914123566805 +-.32896462175888702221 +-.32896462175888702221 +.01998585030422312242 +.01998585030422312242 +.93846980724081290422 +.93846980724081290422 +.76519768655796655144 +.76519768655796655144 +.51182767173591812874 +.51182767173591812874 +.37483214773176892693 +.37483214773176892693 +.22389077914123566805 +.22389077914123566805 +-.32896462175888702221 +-.32896462175888702221 +.01998585030422312242 +.01998585030422312242 +1.00000000000000000000 +.93846980724081290422 +.93846980724081290422 +.76519768655796655144 +.76519768655796655144 +.51182767173591812874 +.51182767173591812874 +.37483214773176892693 +.37483214773176892693 +.22389077914123566805 +.22389077914123566805 +-.32896462175888702221 +-.32896462175888702221 +.01998585030422312242 +.01998585030422312242 +.93846980724081290422 +.93846980724081290422 +.76519768655796655144 +.76519768655796655144 +.51182767173591812874 +.51182767173591812874 +.37483214773176892693 +.37483214773176892693 +.22389077914123566805 +.22389077914123566805 +-.32896462175888702221 +-.32896462175888702221 +.01998585030422312242 +.01998585030422312242 +0 +-.24226845767487388638 +.24226845767487388638 +-.44005058574493351595 +.44005058574493351595 +-.55793650791009964199 +.55793650791009964199 +-.57976044202797131452 +.57976044202797131452 +-.57672480775687338720 +.57672480775687338720 +-.24741588607612652213 +.24741588607612652213 +.07714535201411215803 +-.07714535201411215803 +.24226845767487388638 +-.24226845767487388638 +.44005058574493351595 +-.44005058574493351595 +.55793650791009964199 +-.55793650791009964199 +.57976044202797131452 +-.57976044202797131452 +.57672480775687338720 +-.57672480775687338720 +.24741588607612652213 +-.24741588607612652213 +-.07714535201411215803 +.07714535201411215803 +0 +.24226845767487388638 +-.24226845767487388638 +.44005058574493351595 +-.44005058574493351595 +.55793650791009964199 +-.55793650791009964199 +.57976044202797131452 +-.57976044202797131452 +.57672480775687338720 +-.57672480775687338720 +.24741588607612652213 +-.24741588607612652213 +-.07714535201411215803 +.07714535201411215803 +-.24226845767487388638 +.24226845767487388638 +-.44005058574493351595 +.44005058574493351595 +-.55793650791009964199 +.55793650791009964199 +-.57976044202797131452 +.57976044202797131452 +-.57672480775687338720 +.57672480775687338720 +-.24741588607612652213 +.24741588607612652213 +.07714535201411215803 +-.07714535201411215803 +0 +-.24226845767487388638 +.24226845767487388638 +-.44005058574493351595 +.44005058574493351595 +-.55793650791009964199 +.55793650791009964199 +-.57976044202797131452 +.57976044202797131452 +-.57672480775687338720 +.57672480775687338720 +-.24741588607612652213 +.24741588607612652213 +.07714535201411215803 +-.07714535201411215803 +.24226845767487388638 +-.24226845767487388638 +.44005058574493351595 +-.44005058574493351595 +.55793650791009964199 +-.55793650791009964199 +.57976044202797131452 +-.57976044202797131452 +.57672480775687338720 +-.57672480775687338720 +.24741588607612652213 +-.24741588607612652213 +-.07714535201411215803 +.07714535201411215803 +0 +.24226845767487388638 +-.24226845767487388638 +.44005058574493351595 +-.44005058574493351595 +.55793650791009964199 +-.55793650791009964199 +.57976044202797131452 +-.57976044202797131452 +.57672480775687338720 +-.57672480775687338720 +.24741588607612652213 +-.24741588607612652213 +-.07714535201411215803 +.07714535201411215803 +-.24226845767487388638 +.24226845767487388638 +-.44005058574493351595 +.44005058574493351595 +-.55793650791009964199 +.55793650791009964199 +-.57976044202797131452 +.57976044202797131452 +-.57672480775687338720 +.57672480775687338720 +-.24741588607612652213 +.24741588607612652213 +.07714535201411215803 +-.07714535201411215803 +0 +-.24226845767487388638 +.24226845767487388638 +-.44005058574493351595 +.44005058574493351595 +-.55793650791009964199 +.55793650791009964199 +-.57976044202797131452 +.57976044202797131452 +-.57672480775687338720 +.57672480775687338720 +-.24741588607612652213 +.24741588607612652213 +.07714535201411215803 +-.07714535201411215803 +.24226845767487388638 +-.24226845767487388638 +.44005058574493351595 +-.44005058574493351595 +.55793650791009964199 +-.55793650791009964199 +.57976044202797131452 +-.57976044202797131452 +.57672480775687338720 +-.57672480775687338720 +.24741588607612652213 +-.24741588607612652213 +-.07714535201411215803 +.07714535201411215803 +0 +.24226845767487388638 +-.24226845767487388638 +.44005058574493351595 +-.44005058574493351595 +.55793650791009964199 +-.55793650791009964199 +.57976044202797131452 +-.57976044202797131452 +.57672480775687338720 +-.57672480775687338720 +.24741588607612652213 +-.24741588607612652213 +-.07714535201411215803 +.07714535201411215803 +-.24226845767487388638 +.24226845767487388638 +-.44005058574493351595 +.44005058574493351595 +-.55793650791009964199 +.55793650791009964199 +-.57976044202797131452 +.57976044202797131452 +-.57672480775687338720 +.57672480775687338720 +-.24741588607612652213 +.24741588607612652213 +.07714535201411215803 +-.07714535201411215803 +0 +.03060402345868264130 +.03060402345868264130 +.11490348493190048046 +.11490348493190048046 +.23208767214421472723 +.23208767214421472723 +.29155916494406017021 +.29155916494406017021 +.35283402861563771915 +.35283402861563771915 +.48195017505993913050 +.48195017505993913050 +-.02152875734450536558 +-.02152875734450536558 +.03060402345868264130 +.03060402345868264130 +.11490348493190048046 +.11490348493190048046 +.23208767214421472723 +.23208767214421472723 +.29155916494406017021 +.29155916494406017021 +.35283402861563771915 +.35283402861563771915 +.48195017505993913050 +.48195017505993913050 +-.02152875734450536558 +-.02152875734450536558 +0 +.03060402345868264130 +.03060402345868264130 +.11490348493190048046 +.11490348493190048046 +.23208767214421472723 +.23208767214421472723 +.29155916494406017021 +.29155916494406017021 +.35283402861563771915 +.35283402861563771915 +.48195017505993913050 +.48195017505993913050 +-.02152875734450536558 +-.02152875734450536558 +.03060402345868264130 +.03060402345868264130 +.11490348493190048046 +.11490348493190048046 +.23208767214421472723 +.23208767214421472723 +.29155916494406017021 +.29155916494406017021 +.35283402861563771915 +.35283402861563771915 +.48195017505993913050 +.48195017505993913050 +-.02152875734450536558 +-.02152875734450536558 +0 +-.00256372999458724407 +.00256372999458724407 +-.01956335398266840591 +.01956335398266840591 +-.06096395114113963064 +.06096395114113963064 +-.09049051186641988137 +.09049051186641988137 +-.12894324947440205109 +.12894324947440205109 +-.34859607875298354805 +.34859607875298354805 +-.07628420172033194340 +.07628420172033194340 +.00256372999458724407 +-.00256372999458724407 +.01956335398266840591 +-.01956335398266840591 +.06096395114113963064 +-.06096395114113963064 +.09049051186641988137 +-.09049051186641988137 +.12894324947440205109 +-.12894324947440205109 +.34859607875298354805 +-.34859607875298354805 +.07628420172033194340 +-.07628420172033194340 +0 +.00256372999458724407 +-.00256372999458724407 +.01956335398266840591 +-.01956335398266840591 +.06096395114113963064 +-.06096395114113963064 +.09049051186641988137 +-.09049051186641988137 +.12894324947440205109 +-.12894324947440205109 +.34859607875298354805 +-.34859607875298354805 +.07628420172033194340 +-.07628420172033194340 +-.00256372999458724407 +.00256372999458724407 +-.01956335398266840591 +.01956335398266840591 +-.06096395114113963064 +.06096395114113963064 +-.09049051186641988137 +.09049051186641988137 +-.12894324947440205109 +.12894324947440205109 +-.34859607875298354805 +.34859607875298354805 +-.07628420172033194340 +.07628420172033194340 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +.09636667329586155967 +.09636667329586155967 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +.09636667329586155967 +.09636667329586155967 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +.09636667329586155967 +.09636667329586155967 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +.09636667329586155967 +.09636667329586155967 +.00848438342327410884 +0 diff --git a/testsuite/bc_boolean.bc b/testsuite/bc_boolean.bc new file mode 100644 index 000000000..021afc5f9 --- /dev/null +++ b/testsuite/bc_boolean.bc @@ -0,0 +1,181 @@ +!0 +!1 +!(-129) +4 && 5 +4 && 0 +0 && 5 +4 && 5 && 7 +4 && 0 && 7 +0 && 5 && 7 +4 && 5 && 0 +0 && 0 && 7 +4 && 0 && 0 +0 && 5 && 0 +!4 && 5 +!4 && 0 +!0 && 5 +4 && !5 +4 && !0 +0 && !5 +!4 && 5 && 7 +!4 && 0 && 7 +!0 && 5 && 7 +!4 && 5 && 0 +!0 && 0 && 7 +!4 && 0 && 0 +!0 && 5 && 0 +4 && !5 && 7 +4 && !0 && 7 +0 && !5 && 7 +4 && !5 && 0 +0 && !0 && 7 +4 && !0 && 0 +0 && !5 && 0 +4 && 5 && !7 +4 && 0 && !7 +0 && 5 && !7 +4 && 5 && !0 +0 && 0 && !7 +4 && 0 && !0 +0 && 5 && !0 +!4 && !5 && 7 +!4 && !0 && 7 +!0 && !5 && 7 +!4 && !5 && 0 +!0 && !0 && 7 +!4 && !0 && 0 +!0 && !5 && 0 +!4 && 5 && !7 +!4 && 0 && !7 +!0 && 5 && !7 +!4 && 5 && !0 +!0 && 0 && !7 +!4 && 0 && !0 +!0 && 5 && !0 +4 && !5 && !7 +4 && !0 && !7 +0 && !5 && !7 +4 && !5 && !0 +0 && !0 && !7 +4 && !0 && !0 +0 && !5 && !0 +!4 && !5 && !7 +!4 && !0 && !7 +!0 && !5 && !7 +!4 && !5 && !0 +!0 && !0 && !7 +!4 && !0 && !0 +!0 && !5 && !0 +3 < 4 && 7 +3 && 4 >= 4 +3 > 4 && 7 +3 && 4 >= 5 +3 < 4 && 0 +0 && 4 >= 4 +3 > 4 && 0 +0 && 4 >= 5 +3 > 4 && 0 +0 && 4 < 4 +3 >= 4 && 0 +0 && 4 >= 5 +3 < 4 && 7 +3 && 4 >= 4 +3 > 4 && 7 > 4 +3 >= 2 && 4 >= 5 +3 < 4 && 0 > -1 +4 < 3 && 4 >= 4 +3 > 4 && 3 == 3 +3 != 3 && 4 >= 5 +3 > 4 && 0 > 1 +0 >= 0 && 4 < 4 +3 >= 4 && 0 >= 1 +0 <= -1 && 4 >= 5 +4 || 5 +4 || 0 +0 || 5 +4 || 5 || 7 +4 || 0 || 7 +0 || 5 || 7 +4 || 5 || 0 +0 || 0 || 7 +4 || 0 || 0 +0 || 5 || 0 +!4 || 5 +!4 || 0 +!0 || 5 +4 || !5 +4 || !0 +0 || !5 +!4 || 5 || 7 +!4 || 0 || 7 +!0 || 5 || 7 +!4 || 5 || 0 +!0 || 0 || 7 +!4 || 0 || 0 +!0 || 5 || 0 +4 || !5 || 7 +4 || !0 || 7 +0 || !5 || 7 +4 || !5 || 0 +0 || !0 || 7 +4 || !0 || 0 +0 || !5 || 0 +4 || 5 || !7 +4 || 0 || !7 +0 || 5 || !7 +4 || 5 || !0 +0 || 0 || !7 +4 || 0 || !0 +0 || 5 || !0 +!4 || !5 || 7 +!4 || !0 || 7 +!0 || !5 || 7 +!4 || !5 || 0 +!0 || !0 || 7 +!4 || !0 || 0 +!0 || !5 || 0 +!4 || 5 || !7 +!4 || 0 || !7 +!0 || 5 || !7 +!4 || 5 || !0 +!0 || 0 || !7 +!4 || 0 || !0 +!0 || 5 || !0 +4 || !5 || !7 +4 || !0 || !7 +0 || !5 || !7 +4 || !5 || !0 +0 || !0 || !7 +4 || !0 || !0 +0 || !5 || !0 +!4 || !5 || !7 +!4 || !0 || !7 +!0 || !5 || !7 +!4 || !5 || !0 +!0 || !0 || !7 +!4 || !0 || !0 +!0 || !5 || !0 +3 < 4 || 7 +3 || 4 >= 4 +3 > 4 || 7 +3 || 4 >= 5 +3 < 4 || 0 +0 || 4 >= 4 +3 > 4 || 0 +0 || 4 >= 5 +3 > 4 || 0 +0 || 4 < 4 +3 >= 4 || 0 +0 || 4 >= 5 +3 < 4 || 7 +3 || 4 >= 4 +3 > 4 || 7 > 4 +3 >= 2 || 4 >= 5 +3 < 4 || 0 > -1 +4 < 3 || 4 >= 4 +3 > 4 || 3 == 3 +3 != 3 || 4 >= 5 +3 > 4 || 0 > 1 +0 >= 0 || 4 < 4 +3 >= 4 || 0 >= 1 +0 <= -1 || 4 >= 5 diff --git a/testsuite/bc_boolean_results.txt b/testsuite/bc_boolean_results.txt new file mode 100644 index 000000000..ea59389c0 --- /dev/null +++ b/testsuite/bc_boolean_results.txt @@ -0,0 +1,181 @@ +1 +0 +0 +1 +0 +0 +1 +0 +0 +0 +0 +0 +0 +0 +0 +1 +0 +1 +0 +0 +0 +1 +0 +0 +0 +0 +0 +1 +0 +0 +0 +0 +0 +0 +0 +0 +1 +0 +0 +0 +0 +0 +0 +0 +1 +0 +0 +0 +0 +0 +0 +0 +0 +1 +0 +0 +0 +0 +0 +1 +0 +0 +0 +0 +0 +0 +0 +0 +1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +1 +1 +0 +0 +1 +0 +0 +0 +0 +0 +0 +0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +0 +1 +1 +1 +0 +1 +1 +1 +1 +1 +0 +1 +1 +1 +1 +1 +1 +1 +0 +1 +1 +1 +1 +0 +1 +1 +1 +1 +1 +0 +1 +1 +1 +1 +0 +1 +1 +1 +1 +1 +1 +1 +0 +1 +1 +1 +1 +0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +0 +0 +0 +0 +0 +0 +1 +1 +1 +1 +1 +1 +1 +0 +0 +1 +0 +0 diff --git a/testsuite/bc_cosine.bc b/testsuite/bc_cosine.bc new file mode 100644 index 000000000..9e67df4c6 --- /dev/null +++ b/testsuite/bc_cosine.bc @@ -0,0 +1,44 @@ +scale = 25 +p = 4 * a(1) +scale = 20 +c(0) +c(0.5) +c(1) +c(2) +c(3) +c(-0.5) +c(-1) +c(-2) +c(-3) +c(p / 7) +c(-p / 7) +c(p / 4) +c(-p / 4) +c(p / 3) +c(-p / 3) +c(p / 2) +c(-p / 2) +c(3 * p / 4) +c(3 * -p / 4) +c(p) +c(-p) +c(3 * p / 2) +c(3 * -p / 2) +c(7 * p / 4) +c(7 * -p / 4) +c(13 * p / 4) +c(13 * -p / 4) +c(2 * p) +c(2 * -p) +c(131231) +c(-131231) +c(859799894.3562378245) +c(859799894.3562378245) +c(4307371) +c(3522556.3323810191) +c(44961070) +c(6918619.1574479809) +c(190836996.2180244164) +c(34934) +c(2483599) +c(13720376) diff --git a/testsuite/bc_cosine_results.txt b/testsuite/bc_cosine_results.txt new file mode 100644 index 000000000..43d640f00 --- /dev/null +++ b/testsuite/bc_cosine_results.txt @@ -0,0 +1,41 @@ +1.00000000000000000000 +.87758256189037271611 +.54030230586813971740 +-.41614683654714238699 +-.98999249660044545727 +.87758256189037271611 +.54030230586813971740 +-.41614683654714238699 +-.98999249660044545727 +.90096886790241912623 +.90096886790241912623 +.70710678118654752440 +.70710678118654752440 +.50000000000000000000 +.50000000000000000000 +0 +0 +-.70710678118654752439 +-.70710678118654752439 +-1.00000000000000000000 +-1.00000000000000000000 +0 +0 +.70710678118654752439 +.70710678118654752439 +-.70710678118654752440 +-.70710678118654752440 +1.00000000000000000000 +1.00000000000000000000 +.92427123447397657316 +.92427123447397657316 +-.04198856352825241211 +-.04198856352825241211 +-.75581969921220636368 +-.01644924448939844182 +-.97280717522127222547 +-.92573947460230585966 +-.14343824233852988038 +.87259414746802343203 +.93542606623067050616 +-.52795540572178251550 diff --git a/testsuite/bc_decimal.bc b/testsuite/bc_decimal.bc new file mode 100644 index 000000000..9b1788c67 --- /dev/null +++ b/testsuite/bc_decimal.bc @@ -0,0 +1,36 @@ +0 +0.0 +.00000 +000000000000000000000000.00000000000000000000000 +000000000000000000000000000135482346782356 +000000000000000000000000002 +1 +11 +123 +7505 +1023468723275435238491972521917846 +4343472432431705867392073517038270398027352709027389273920739037937960379637893607893607893670530278200795207952702873892786172916728961783907893607418973587857386079679267926737520730925372983782793652793 +-1 +-203 +-57 +-18586 +-31378682943772818461924738352952347258 +-823945628745673589495067238723986520375698237620834674509627345273096287563846592384526349872634895763257893467523987578690283762897568459072348758071071087813501875908127359018715023841710239872301387278 +.123521346523546 +0.1245923756273856 +-.1024678456387 +-0.8735863475634587 +4.0 +-6.0 +234237468293576.000000000000000000000000000000 +23987623568943567.00000000000000000005677834650000000000000 +23856934568940675.000000000000000435676782300000000000000456784 +77567648698496.000000000000000000587674750000000000458563800000000000000 +2348672354968723.2374823546000000000003256987394502346892435623870000000034578 +-2354768.000000000000000000000000000000000000 +-96739874567.000000000347683456 +-3764568345.000000000004573845000000347683460 +-356784356.934568495770004586495678300000000 +74325437345273852773827101738273127312738521733017537073520735207307570358738257390761276072160719802671980267018728630178.7082681027680521760217867841276127681270867827821768173178207830710978017738178678012767377058785378278207385237085237803278203782037237582795870 +-756752732785273851273728537852738257837283678965738527385272983678372867327835672967385278372637862738627836279863782673862783670.71738178361738718367186378610738617836781603760178367018603760178107735278372832783728367826738627836278378260736270367362073867097307925 +9812734012837410982345719208345712908357412903587192048571920458712.23957182459817249058172945781 diff --git a/testsuite/bc_decimal_results.txt b/testsuite/bc_decimal_results.txt new file mode 100644 index 000000000..275d431c6 --- /dev/null +++ b/testsuite/bc_decimal_results.txt @@ -0,0 +1,51 @@ +0 +0 +0 +0 +135482346782356 +2 +1 +11 +123 +7505 +1023468723275435238491972521917846 +43434724324317058673920735170382703980273527090273892739207390379379\ +60379637893607893607893670530278200795207952702873892786172916728961\ +78390789360741897358785738607967926792673752073092537298378279365279\ +3 +-1 +-203 +-57 +-18586 +-31378682943772818461924738352952347258 +-8239456287456735894950672387239865203756982376208346745096273452730\ +96287563846592384526349872634895763257893467523987578690283762897568\ +45907234875807107108781350187590812735901871502384171023987230138727\ +8 +.123521346523546 +.1245923756273856 +-.1024678456387 +-.8735863475634587 +4.0 +-6.0 +234237468293576.000000000000000000000000000000 +23987623568943567.00000000000000000005677834650000000000000 +23856934568940675.000000000000000435676782300000000000000456784 +77567648698496.00000000000000000058767475000000000045856380000000000\ +0000 +2348672354968723.237482354600000000000325698739450234689243562387000\ +0000034578 +-2354768.000000000000000000000000000000000000 +-96739874567.000000000347683456 +-3764568345.000000000004573845000000347683460 +-356784356.934568495770004586495678300000000 +74325437345273852773827101738273127312738521733017537073520735207307\ +570358738257390761276072160719802671980267018728630178.7082681027680\ +52176021786784127612768127086782782176817317820783071097801773817867\ +8012767377058785378278207385237085237803278203782037237582795870 +-7567527327852738512737285378527382578372836789657385273852729836783\ +72867327835672967385278372637862738627836279863782673862783670.71738\ +17836173871836718637861073861783678160376017836701860376017810773527\ +8372832783728367826738627836278378260736270367362073867097307925 +9812734012837410982345719208345712908357412903587192048571920458712.\ +23957182459817249058172945781 diff --git a/testsuite/bc_divide.bc b/testsuite/bc_divide.bc new file mode 100644 index 000000000..4d0caddc9 --- /dev/null +++ b/testsuite/bc_divide.bc @@ -0,0 +1,31 @@ +0 / 1 +0 / 321566 +0 / 0.3984567238456 +1 / 1 +1 / 1287469297356 +1 / 0.2395672438567234 +1 / 237586239856.0293596728392360 +1249687284356 / 3027949207835207 +378617298617396719 / 35748521 +9348576237845624358 / 0.9857829375461 +35768293846193284 / 2374568947.045762839567823 +-78987234567812345 / 876542837618936 +-356789237555535468 / 0.3375273860984786903 +-5203475364850390 / 435742903748307.70869378534043296404530458 +-0.37861723347576903 / 7385770896 +-0.399454682043962 / 0.34824389304 +-0.6920414523873204 / 356489645223.76076045304879030 +-35872917389671.7573280963748 / 73924708 +-78375896314.4836709876983 / 0.78356798637817 +-2374123896417.143789621437581 / 347821469423789.1473856783960 +-896729350238549726 / -34976289345762 +-2374568293458762348596 / -0.8792370647234987679 +-237584692306721845726038 / -21783910782374529637.978102738746189024761 +-0.23457980123576298375682 / -1375486293874612 +-0.173897061862478951264 / -0.8179327486017634987516298745 +-0.9186739823576829347586 / -0.235678293458756239846 +-0.9375896183746982374568 / -13784962873546.0928729395476283745 +-2930754618923467.12323745862937465 / -734869238465 +-23745861923467.874675129834675 / -0.23542357869124756 +-3878923750692883.7238596702834756902 / -7384192674957215364986723.9738461923487621983 +1 / 0.00000000000000000000000000000000000000000002346728372937352457354204563027 diff --git a/testsuite/bc_divide_results.txt b/testsuite/bc_divide_results.txt new file mode 100644 index 000000000..c19f2f9b0 --- /dev/null +++ b/testsuite/bc_divide_results.txt @@ -0,0 +1,31 @@ +0 +0 +0 +1.00000000000000000000 +.00000000000077671755 +4.17419336592637110778 +.00000000000420899796 +.00041271738677857404 +10591131829.40901859967857131767 +9483402361494453751.52388015648196297248 +15063068.13735316451497043884 +-90.11223545260531110575 +-1057067521778623447.45138528213564485251 +-11.94161814246320631346 +-.00000000005126306228 +-1.14705437777218917343 +-.00000000000194126663 +-485262.88923145638029569727 +-100024372711.74763635544535424582 +-.00682569681609989277 +25638.20711150436682153521 +2700714504347599627864.24626421085374010264 +10906.42973524078145692731 +.00000000000000017054 +.21260557443109085166 +3.89799997647407910677 +.00000000000006801538 +3988.13076601933678578945 +100864416620775.31076855630746548983 +.00000000052530099381 +42612515855353136519261264261472677699404182.78776061098893912189 diff --git a/testsuite/bc_exponent.bc b/testsuite/bc_exponent.bc new file mode 100644 index 000000000..40bcf3c5a --- /dev/null +++ b/testsuite/bc_exponent.bc @@ -0,0 +1,22 @@ +e(0) +e(0.5) +e(1) +e(1.5) +e(1.74) +e(2) +e(3.2345) +e(5.283957) +e(13.23857) +e(100) +e(283.238957) +e(-0.5) +e(-1) +e(-1.5) +e(-1.74) +e(-2) +e(-3.2345) +e(-5.283957) +e(-13.23857) +e(-100) +e(-283.238957) +e(142.749502399) diff --git a/testsuite/bc_exponent_results.txt b/testsuite/bc_exponent_results.txt new file mode 100644 index 000000000..a1f1fe2b4 --- /dev/null +++ b/testsuite/bc_exponent_results.txt @@ -0,0 +1,25 @@ +1.00000000000000000000 +1.64872127070012814684 +2.71828182845904523536 +4.48168907033806482260 +5.69734342267199101193 +7.38905609893065022723 +25.39367176822616278859 +197.14845034328553587817 +561613.96621445383501864766 +26881171418161354484126255515800135873611118.77374192241519160861 +10212124131159922810249757193864245307850725332411569566443792548720\ +75182918653384240389953781407569563117008113027037939783.70141667971\ +570827872 +.60653065971263342360 +.36787944117144232159 +.22313016014842982893 +.17552040061699687169 +.13533528323661269189 +.03937988996342191888 +.00507231985977442865 +.00000178058250000525 +0 +0 +98928445824097165243611240348236907682258759298273030827411201.25833\ +645622510213538 diff --git a/testsuite/bc_large.tar.xz b/testsuite/bc_large.tar.xz new file mode 100644 index 000000000..b2e358a79 Binary files /dev/null and b/testsuite/bc_large.tar.xz differ diff --git a/testsuite/bc_log.bc b/testsuite/bc_log.bc new file mode 100644 index 000000000..54115e380 --- /dev/null +++ b/testsuite/bc_log.bc @@ -0,0 +1,22 @@ +l(0) +l(0.5) +l(1) +l(1.5) +l(1.74) +l(2) +l(3.2345) +l(5.283957) +l(13.23857) +l(100) +l(283.238957) +l(-0.5) +l(-1) +l(-1.5) +l(-1.74) +l(-2) +l(-3.2345) +l(-5.283957) +l(-13.23857) +l(-100) +l(-283.238957) +l(10430710.3325472917) diff --git a/testsuite/bc_log_results.txt b/testsuite/bc_log_results.txt new file mode 100644 index 000000000..ce840a0d9 --- /dev/null +++ b/testsuite/bc_log_results.txt @@ -0,0 +1,22 @@ +-99999999999999999999.00000000000000000000 +-.69314718055994530941 +0 +.40546510810816438197 +.55388511322643765995 +.69314718055994530941 +1.17387435650190306676 +1.66467524885255369652 +2.58313453863349348434 +4.60517018598809136803 +5.64629091238730017971 +-99999999999999999999.00000000000000000000 +-99999999999999999999.00000000000000000000 +-99999999999999999999.00000000000000000000 +-99999999999999999999.00000000000000000000 +-99999999999999999999.00000000000000000000 +-99999999999999999999.00000000000000000000 +-99999999999999999999.00000000000000000000 +-99999999999999999999.00000000000000000000 +-99999999999999999999.00000000000000000000 +-99999999999999999999.00000000000000000000 +16.16026492940839137014 diff --git a/testsuite/bc_misc.bc b/testsuite/bc_misc.bc new file mode 100644 index 000000000..571f4a87e --- /dev/null +++ b/testsuite/bc_misc.bc @@ -0,0 +1,13 @@ +4.1*1.-13^ - 74 - 1284597623841*1.-13^ - 757 +4.1*1.\ +-1\ +3^ - 74 - 1284597623841*1.\ +-1\ +3^ - 757 +obase = 9 +4.1*1.-13^ - 74 - 1284597623841*1.-13^ - 757 +4.1*1.\ +-1\ +3^ - 74 - 1284597623841*1.\ +-1\ +3^ - 757 diff --git a/testsuite/bc_misc1.bc b/testsuite/bc_misc1.bc new file mode 100644 index 000000000..7e9d96604 --- /dev/null +++ b/testsuite/bc_misc1.bc @@ -0,0 +1,76 @@ +define x(x) { + return(x) +} +define y() { + return; +} +define z() { + return (); +} +scale = 0 +x=2 +x[0]=3 +x +x[0] +scale +ibase +obase +x ( 7 ) +x + x( 8 ) +x - x[0] +321 * x +2 ^ x[0] +x++ +--x +x += 9 +x +length(2381) +sqrt(9) +scale(238.1) +x=2 +x[0]=3 +(x) +(x[0]) +(scale) +(ibase) +(obase) +(x ( 7 )) +(x + x( 8 )) +(x - x[0]) +(321 * x) +(2 ^ x[0]) +(x++) +(--x) +(x += 9) +(length(2381)) +(sqrt(9)) +(scale(238.1)) +(scale = 0) +(x = 10) +(x += 100) +(x -= 10) +(x *= 10) +(x /= 100) +(x ^= 10) +(x = sqrt(x)) +(x[1 - 1]) +x[(1 - 1)] +2 + \ +3 +++ibase +--ibase +++obase +--obase +++last +--last +last +last = 100 +last +. = 150 +. +++scale +--scale +y() +z() +2 + /* +*/3 diff --git a/testsuite/bc_misc1_results.txt b/testsuite/bc_misc1_results.txt new file mode 100644 index 000000000..a9c278069 --- /dev/null +++ b/testsuite/bc_misc1_results.txt @@ -0,0 +1,57 @@ +2 +3 +0 +10 +10 +7 +10 +-1 +642 +8 +2 +2 +11 +4 +3 +1 +2 +3 +0 +10 +10 +7 +10 +-1 +642 +8 +2 +2 +11 +4 +3 +1 +0 +10 +110 +100 +1000 +10 +10000000000 +100000 +3 +3 +5 +11 +10 +10 +10 +11 +10 +10 +100 +150 +1 +0 +0 +0 +5 diff --git a/testsuite/bc_misc2.bc b/testsuite/bc_misc2.bc new file mode 100644 index 000000000..f5a6a6b13 --- /dev/null +++ b/testsuite/bc_misc2.bc @@ -0,0 +1,45 @@ +define x() { +"x" +return ( 1 ) +} +define y() { +"y" +return (2) +} +define z() { +"z" +return (3) +} + +if ( x() == y() ) {1} +1 +if ( x() <= y() ) {2} +if ( y() >= x() ) {3} +if ( x() != y() ) {4} +if ( x() < y() ) {5} +if ( y() > x() ) {6} + +if ( x() == z() ) {11} +11 +if ( x() <= z() ) {12} +if ( z() >= x() ) {13} +if ( x() != z() ) {14} +if ( x() < z() ) {15} +if ( z() > x() ) {16} + +x = -10 +while (x <= 0) { + x + if (x == -5) break; + x += 1 +} + +define u() { + auto a[]; + return a[0] +} + +u() + +if (x == -4) x +else x - 4 diff --git a/testsuite/bc_misc2_results.txt b/testsuite/bc_misc2_results.txt new file mode 100644 index 000000000..022ca8728 --- /dev/null +++ b/testsuite/bc_misc2_results.txt @@ -0,0 +1,20 @@ +xy1 +xy2 +yx3 +xy4 +xy5 +yx6 +xz11 +xz12 +zx13 +xz14 +xz15 +zx16 +-10 +-9 +-8 +-7 +-6 +-5 +0 +-9 diff --git a/testsuite/bc_misc_results.txt b/testsuite/bc_misc_results.txt new file mode 100644 index 000000000..e2db76e0e --- /dev/null +++ b/testsuite/bc_misc_results.txt @@ -0,0 +1,4 @@ +-1284597623836.9 +-1284597623836.9 +-4483684050181.80 +-4483684050181.80 diff --git a/testsuite/bc_modulus.bc b/testsuite/bc_modulus.bc new file mode 100644 index 000000000..e2656a6e9 --- /dev/null +++ b/testsuite/bc_modulus.bc @@ -0,0 +1,70 @@ +1 % 1 +2 % 1 +16 % 4 +15 % 4 +17 % 4 +2389473 % 5 +39240687239 % 1 +346728934 % 23958 +3496723859067234 % 298375462837546928347623059375486 +-1 % 1 +-2 % 1 +-47589634875689345 % 37869235 +-1274852934765 % 2387628935486273546 +-6324758963 % 237854962 +1 % -1 +2 % -1 +2 % -2 +2 % -3 +16 % 5 +15 % 5 +14 % 5 +89237423 % -237856923854 +123647238946 % -12467 +-1 % -1 +-2 % -1 +-2 % -2 +-2 % -3 +-13 % -7 +-14 % -7 +-15 % -7 +-12784956 % -32746 +-127849612 % -23712347682193 +1 % 0.2395672438567234 +scale = 0 +1 % 1 +2 % 1 +16 % 4 +15 % 4 +17 % 4 +2389473 % 5 +39240687239 % 1 +346728934 % 23958 +3496723859067234 % 298375462837546928347623059375486 +-1 % 1 +-2 % 1 +-47589634875689345 % 37869235 +-1274852934765 % 2387628935486273546 +-6324758963 % 237854962 +1 % -1 +2 % -1 +2 % -2 +2 % -3 +16 % 5 +15 % 5 +14 % 5 +89237423 % -237856923854 +123647238946 % -12467 +-1 % -1 +-2 % -1 +-2 % -2 +-2 % -3 +-13 % -7 +-14 % -7 +-15 % -7 +-12784956 % -32746 +-127849612 % -23712347682193 +-3191280681 % 641165986 +scale = 0; -899510228 % -2448300078.40314 +scale = 0; -7424863 % -207.2609738667 +scale = 0; 3769798918 % 0.6 diff --git a/testsuite/bc_modulus_results.txt b/testsuite/bc_modulus_results.txt new file mode 100644 index 000000000..e85145be7 --- /dev/null +++ b/testsuite/bc_modulus_results.txt @@ -0,0 +1,69 @@ +0 +0 +0 +0 +0 +0 +0 +.00000000000000002026 +2747189239559.46904933397471305894 +0 +0 +-.00000000000011057855 +-.00076922992566770712 +-.00000000000050364144 +0 +0 +0 +.00000000000000000002 +0 +0 +0 +.00000000070585524350 +.00000000000000002898 +0 +0 +0 +-.00000000000000000002 +-.00000000000000000005 +0 +-.00000000000000000002 +-.00000000000000011722 +-.00000002640923745817 +.000000000000000000000404744340951948 +0 +0 +0 +3 +1 +3 +0 +8758 +3496723859067234 +0 +0 +-8236960 +-1274852934765 +-140529951 +0 +0 +0 +2 +1 +0 +4 +89237423 +6692 +0 +0 +0 +-2 +-6 +0 +-1 +-14016 +-127849612 +-626616737 +-899510228.00000 +-153.1331732059 +.4 diff --git a/testsuite/bc_multiply.bc b/testsuite/bc_multiply.bc new file mode 100644 index 000000000..8d5aa36d5 --- /dev/null +++ b/testsuite/bc_multiply.bc @@ -0,0 +1,42 @@ +0 * 0 +0.000 * 0 +1 * 0 +0 * 1 +0 * 2498752389672835476 +873246913745129084576134 * 0 +1 * 472638590273489273456 +12374861230476103672835496 * 1 +1 * 1 +2 * 1 +1 * 2 +2 * 2 +3 * 14 +17 * 8 +1892467513846753 * 1872439821374591038746 +328962735862.2973546835638947635 * 1728465791348762356 +38745962374538.387427384672934867234 * 0.1932476528394672837568923754 +9878894576289457634856.2738627161689017387608947567654 * 37842939768237596237854203.29874372139852739126739621793162 +-1 * 1 +-1 * 2 +78893457 * -34876238956 +235678324957634 * -0.2349578349672389576 +-12849567821934 * 12738462937681 +1274861293467.927843682937462 * -28935678239 +2936077239872.12937462836 * -0.012842357682435762 +2387692387566.2378569237546 * -272189345628.123875629835876 +0.012348629356782835962 * -23487692356 +0.4768349567348675934 * -0.23756834576934857638495 +0.98748395367485962735486 * -4675839462354867.376834956738456 +-321784627934586 * -235762378596 +-32578623567892356 * -0.32567384579638456 +-35768232346876 * -2348672935602387620.28375682349576237856 +-0.2356728394765234 * -238759624356978 +-0.2345768212346780 * -0.235768124697074385948943532045 +-0.370873860736785306278630 * -7835678398607.7086378076867096270 +-78365713707.7089637863786730 * -738580798679306780 +-73867038956790490258249 * -0.7379862716391723672803679 +-378621971598721837710387 * -98465373878350798.09743896037963078560 +37164201 * 2931559660 +679468076118972457796560530571.46287161642138401685 * 93762.2836 +.000000000000000000000000001 * .0000000000000000000000001 +scale = 0; 237854962 * -26 diff --git a/testsuite/bc_multiply_results.txt b/testsuite/bc_multiply_results.txt new file mode 100644 index 000000000..1dee19c37 --- /dev/null +++ b/testsuite/bc_multiply_results.txt @@ -0,0 +1,43 @@ +0 +0 +0 +0 +0 +0 +472638590273489273456 +12374861230476103672835496 +1 +2 +2 +4 +42 +136 +3543531533584430580556128344529291738 +568600835566479683035874339053.4411638427543228060 +7487566285885.8557453089005171423976251098 +373846412427291014394738378015501363938345620046.7869650248829232267\ +2297002026819 +-1 +-2 +-2751507058396910892 +-55374468980751.0837656919743223184 +-163683743464924630346895054 +-36888976187143312550878.567134791289418 +-37706154097.69662826215753378160 +-649904428532907022680241.94791869424754101064 +-290040807.350385412976669306472 +-.11328089187650139309272 +-4617316439035114.40320367843985107357898 +75864709277486862054521256 +10610005628108234.92015040406042336 +84007879267445533366251128067927.91168012197674537856 +56269158624557.1027018519702852 +.055305737239900889424090264801 +2906048299183.472237078104362540110129 +57879411419313585866282299201.3825582163029400 +54512860676747314187949.9414724679950990587298071 +37281153992026463004361915151761464058058.54968338992209002720 +108949072447731660 +63708478450213482928510139572007971.83536929222529239687 +0 +-6184229012 diff --git a/testsuite/bc_pi.bc b/testsuite/bc_pi.bc new file mode 100644 index 000000000..b98419f12 --- /dev/null +++ b/testsuite/bc_pi.bc @@ -0,0 +1,4 @@ +for (i = 0; i <= 100; ++i) { + scale = i + 4 * a(1) +} diff --git a/testsuite/bc_pi_results.txt b/testsuite/bc_pi_results.txt new file mode 100644 index 000000000..128d6c0ca --- /dev/null +++ b/testsuite/bc_pi_results.txt @@ -0,0 +1,135 @@ +0 +2.8 +3.12 +3.140 +3.1412 +3.14156 +3.141592 +3.1415924 +3.14159264 +3.141592652 +3.1415926532 +3.14159265356 +3.141592653588 +3.1415926535896 +3.14159265358976 +3.141592653589792 +3.1415926535897932 +3.14159265358979320 +3.141592653589793236 +3.1415926535897932384 +3.14159265358979323844 +3.141592653589793238460 +3.1415926535897932384624 +3.14159265358979323846264 +3.141592653589793238462640 +3.1415926535897932384626432 +3.14159265358979323846264336 +3.141592653589793238462643380 +3.1415926535897932384626433832 +3.14159265358979323846264338324 +3.141592653589793238462643383276 +3.1415926535897932384626433832792 +3.14159265358979323846264338327948 +3.141592653589793238462643383279500 +3.1415926535897932384626433832795028 +3.14159265358979323846264338327950288 +3.141592653589793238462643383279502884 +3.1415926535897932384626433832795028840 +3.14159265358979323846264338327950288416 +3.141592653589793238462643383279502884196 +3.1415926535897932384626433832795028841968 +3.14159265358979323846264338327950288419716 +3.141592653589793238462643383279502884197168 +3.1415926535897932384626433832795028841971692 +3.14159265358979323846264338327950288419716936 +3.141592653589793238462643383279502884197169396 +3.1415926535897932384626433832795028841971693992 +3.14159265358979323846264338327950288419716939936 +3.141592653589793238462643383279502884197169399372 +3.1415926535897932384626433832795028841971693993748 +3.14159265358979323846264338327950288419716939937508 +3.141592653589793238462643383279502884197169399375104 +3.1415926535897932384626433832795028841971693993751056 +3.14159265358979323846264338327950288419716939937510580 +3.141592653589793238462643383279502884197169399375105820 +3.1415926535897932384626433832795028841971693993751058208 +3.14159265358979323846264338327950288419716939937510582096 +3.141592653589793238462643383279502884197169399375105820972 +3.1415926535897932384626433832795028841971693993751058209748 +3.14159265358979323846264338327950288419716939937510582097492 +3.141592653589793238462643383279502884197169399375105820974944 +3.1415926535897932384626433832795028841971693993751058209749444 +3.14159265358979323846264338327950288419716939937510582097494456 +3.141592653589793238462643383279502884197169399375105820974944592 +3.1415926535897932384626433832795028841971693993751058209749445920 +3.14159265358979323846264338327950288419716939937510582097494459228 +3.141592653589793238462643383279502884197169399375105820974944592304 +3.141592653589793238462643383279502884197169399375105820974944592307\ +6 +3.141592653589793238462643383279502884197169399375105820974944592307\ +80 +3.141592653589793238462643383279502884197169399375105820974944592307\ +816 +3.141592653589793238462643383279502884197169399375105820974944592307\ +8164 +3.141592653589793238462643383279502884197169399375105820974944592307\ +81640 +3.141592653589793238462643383279502884197169399375105820974944592307\ +816404 +3.141592653589793238462643383279502884197169399375105820974944592307\ +8164060 +3.141592653589793238462643383279502884197169399375105820974944592307\ +81640628 +3.141592653589793238462643383279502884197169399375105820974944592307\ +816406284 +3.141592653589793238462643383279502884197169399375105820974944592307\ +8164062860 +3.141592653589793238462643383279502884197169399375105820974944592307\ +81640628620 +3.141592653589793238462643383279502884197169399375105820974944592307\ +816406286208 +3.141592653589793238462643383279502884197169399375105820974944592307\ +8164062862088 +3.141592653589793238462643383279502884197169399375105820974944592307\ +81640628620896 +3.141592653589793238462643383279502884197169399375105820974944592307\ +816406286208996 +3.141592653589793238462643383279502884197169399375105820974944592307\ +8164062862089984 +3.141592653589793238462643383279502884197169399375105820974944592307\ +81640628620899860 +3.141592653589793238462643383279502884197169399375105820974944592307\ +816406286208998628 +3.141592653589793238462643383279502884197169399375105820974944592307\ +8164062862089986280 +3.141592653589793238462643383279502884197169399375105820974944592307\ +81640628620899862800 +3.141592653589793238462643383279502884197169399375105820974944592307\ +816406286208998628032 +3.141592653589793238462643383279502884197169399375105820974944592307\ +8164062862089986280348 +3.141592653589793238462643383279502884197169399375105820974944592307\ +81640628620899862803480 +3.141592653589793238462643383279502884197169399375105820974944592307\ +816406286208998628034824 +3.141592653589793238462643383279502884197169399375105820974944592307\ +8164062862089986280348252 +3.141592653589793238462643383279502884197169399375105820974944592307\ +81640628620899862803482532 +3.141592653589793238462643383279502884197169399375105820974944592307\ +816406286208998628034825340 +3.141592653589793238462643383279502884197169399375105820974944592307\ +8164062862089986280348253420 +3.141592653589793238462643383279502884197169399375105820974944592307\ +81640628620899862803482534208 +3.141592653589793238462643383279502884197169399375105820974944592307\ +816406286208998628034825342116 +3.141592653589793238462643383279502884197169399375105820974944592307\ +8164062862089986280348253421168 +3.141592653589793238462643383279502884197169399375105820974944592307\ +81640628620899862803482534211704 +3.141592653589793238462643383279502884197169399375105820974944592307\ +816406286208998628034825342117064 +3.141592653589793238462643383279502884197169399375105820974944592307\ +8164062862089986280348253421170676 diff --git a/testsuite/bc_power.bc b/testsuite/bc_power.bc new file mode 100644 index 000000000..5657cdd7b --- /dev/null +++ b/testsuite/bc_power.bc @@ -0,0 +1,44 @@ +0 ^ 0 +0 ^ 1 +0 ^ 1894 +1 ^ 0 +39746823 ^ 0 +0.238672983047682 ^ 0 +18394762374689237468.97354862973846 ^ 0 +1 ^ 1 +2 ^ 1 +18927361346 ^ 1 +0.23523785962738592635777 ^ 1 +328956734869213746.89782398457234 ^ 1 +8937 ^ 98 +0.124876812394 ^ 2396 +93762.2836 ^ 13 +1 ^ -1 +2 ^ -1 +10 ^ -1 +683734768 ^ -1 +38579623756.897937568235 ^ -1 +1 ^ -32467 +2 ^ -53 +23897 ^ -213 +-1 ^ 1 +-1 ^ 2 +-2 ^ 1 +-2 ^ 2 +-237 ^ 294 +-3746 ^ 28 +-0.3548 ^ 35 +-4267.234 ^ 37 +-326.3246 ^ 78 +-1 ^ -1 +-1 ^ -2 +-2 ^ -1 +-2 ^ -2 +-237 ^ -293 +-784 ^ -23 +-86 ^ -7 +-0.23424398 ^ -781 +-178.234786 ^ -879 +-1274.346 ^ -768 +0 ^ -251 +-0.2959371298 ^ 227 diff --git a/testsuite/bc_power_results.txt b/testsuite/bc_power_results.txt new file mode 100644 index 000000000..997f44f59 --- /dev/null +++ b/testsuite/bc_power_results.txt @@ -0,0 +1,73 @@ +1 +0 +0 +1 +1 +1 +1 +1 +2 +18927361346 +.23523785962738592635777 +328956734869213746.89782398457234 +16473742664221279051571200630760751138799221376964991600670000200609\ +08006052596520320731708604393844468006290371918262741885989163144389\ +39367835091560809036359941703341471396407660150658436796925310445979\ +21333166245765946557344383284626113908419359990042883048537750217279\ +17481980123593363177308481941550382845381799410533956718500484099889\ +610805653325917409549921909941664118421333562129 +0 +43287877285033571298394739716218787350087163435619825150259705419.98\ +016445740928054425 +1.00000000000000000000 +.50000000000000000000 +.10000000000000000000 +.00000000146255543348 +.00000000002592041867 +1.00000000000000000000 +.00000000000000011102 +0 +-1 +1 +-2 +4 +14997322375665265051328725757939209353051902095893907150382724666290\ +49749481660976421019742616298227588464420182758442163654172400528243\ +00885441207762486233574213374503090372518590691583139696652847404883\ +08573912261119588874308960204159666762789603037188471170006223907416\ +60492840269152716750700089148882139254399347568222390231015487895905\ +73727080561379177721440905866857248917982113340543176658480139248897\ +54802503253413282808814063861470711399810899724515727713334909764746\ +27910290211411231279325882505708287941671508154740003122373284699097\ +78346501539634198926772266511968381368929692275950529960923432771985\ +12597189390708050983487158873301681237787429436264801751664042999180\ +3448659818912436089 +11478830555358864333472551120140548480416206583184496764727387456058\ +792742209537931243951391229607936 +-.00000000000000017759 +-2067373624686414405470850679965010694114490999957199847684803894306\ +56243666149296582304582679590231948238805965642713928910384741502707\ +.23224479257866798694 +11606078892843496082360561256965139908586179418605021706789617179085\ +85768049299693425729565480314913006780973928345684673490252494674985\ +0186164225375953066263609289359900615361965737717208159874390.293769\ +70206344604971 +-1.00000000000000000000 +1.00000000000000000000 +-.50000000000000000000 +.25000000000000000000 +0 +0 +-.00000000000002874159 +-1945134149489344891879057554905782841936258356736314337975569799825\ +94091939572752348215929683891336730843553721422164737465108229034947\ +87333189564755763444242676978610321731298729194092653999616928308494\ +26419468484566422775668903315088810746121307679948574976162519479931\ +18935243698160094347216562490000767121041786977792546155155934655909\ +14123833869470494708767968978717730012864171105540029928688274136791\ +98175053824022144065005509214813689232148489884560100200475909009813\ +340098100705258138.98542904577525702068 +0 +0 +0 +0 diff --git a/testsuite/bc_sine.bc b/testsuite/bc_sine.bc new file mode 100644 index 000000000..d3a547bcd --- /dev/null +++ b/testsuite/bc_sine.bc @@ -0,0 +1,207 @@ +scale = 25 +p = 4 * a(1) +scale = 20 +s(0) +s(0.5) +s(1) +s(2) +s(3) +s(-0.5) +s(-1) +s(-2) +s(-3) +s(p / 7) +s(-p / 7) +s(p / 4) +s(-p / 4) +s(p / 3) +s(-p / 3) +s(p / 2) +s(-p / 2) +s(3 * p / 4) +s(3 * -p / 4) +s(p) +s(-p) +s(3 * p / 2) +s(3 * -p / 2) +s(7 * p / 4) +s(7 * -p / 4) +s(13 * p / 4) +s(13 * -p / 4) +s(2 * p) +s(2 * -p) +s(131231) +s(-131231) +s(69.1967507777) +s(10828) +s(-16248506.847013148) +s(2050281000) +s(8224939) +s(11334231.1154662464) +s(-4109411249.2986954846) +s(-2395915402.13984) +s(-2795874313) +s(-2262647256) +s(3323158182.1239222084) +s(99901384) +s(-4202726050.2780080957) +s(2870000621.3228830588) +s(-4230239450.981045150) +s(-1517506941.2678857223) +s(4004582176) +s(-4193724543.1108508063) +s(-3432511261) +s(1804484812) +s(3229084127) +s(-3565317246.583937244) +s(3503281621) +s(-3469146313.1766891244) +s(-2257308049.307721068) +s(-3978441809) +s(3431564304.3752537) +s(1249644440.2464914559) +s(2395558891.1188487974) +s(-2607820706.4079280116) +s(1208310007) +s(-3758597557.863203175) +s(1186920672) +s(-3988103872) +s(-4280635328.4194857577) +s(1051748072) +s(-1884006279) +s(-1046568719.2698663389) +s(2482991410) +s(-2106101268.1154045959) +s(3530359346.77217900) +s(-3373362543) +s(2601598062) +s(2987020862) +s(-12033356.2057140648) +s(-3721760707) +s(2842387705.4145759704) +s(3515832681.1808393297) +s(-3658522034.16149) +s(3963658030.2860423992) +s(2977802215.597946655) +s(-4271392570.4091498761) +s(2378692585) +s(-3545193743.629374782) +s(-1762458738) +s(-1174277828.4264040126) +s(-1724994857) +s(2802750230.1783499408) +s(-3068133550) +s(3324811474.621822235) +s(2873024984) +s(-3509056632.3888206298) +s(1772903162.647192879) +s(2836543102) +s(4117858580.186) +s(2988632386.4063754522) +s(-4256784971.1770067447) +s(2280820447) +s(-2865200306) +s(-3329592486) +s(519126268) +s(-2452430452) +s(-2693220186.62104082) +s(-3796811992.14485798) +s(3619792326) +s(2697791049.3038381550) +s(3751267834.2808166557) +s(-3761719074) +s(-3824087631) +s(2119301150) +s(1398148974) +s(-3386564819.1351816969) +s(-3171483098) +s(3688944941.3273318162) +s(3060521119) +s(-3527110404) +s(3699631193) +s(3872838898) +s(3880350192) +s(-4109411249.2986954846) +s(-2395915402.13984) +s(-2795874313) +s(-2262647256) +s(3323158182.1239222084) +s(99901384) +s(-4202726050.2780080957) +s(2870000621.3228830588) +s(-4230239450.981045150) +s(-1517506941.2678857223) +s(4004582176) +s(-4193724543.1108508063) +s(-3432511261) +s(1804484812) +s(3229084127) +s(-3565317246.583937244) +s(3503281621) +s(-3469146313.1766891244) +s(-2257308049.307721068) +s(-3978441809) +s(3431564304.3752537) +s(1249644440.2464914559) +s(2395558891.1188487974) +s(-2607820706.4079280116) +s(1208310007) +s(-3758597557.863203175) +s(1186920672) +s(-3988103872) +s(-4280635328.4194857577) +s(1051748072) +s(-1884006279) +s(-1046568719.2698663389) +s(2482991410) +s(-2106101268.1154045959) +s(3530359346.77217900) +s(-3373362543) +s(2601598062) +s(2576349783.2446436039) +s(2987020862) +s(-12033356.2057140648) +s(-3721760707) +s(2842387705.4145759704) +s(3515832681.1808393297) +s(-3658522034.16149) +s(3963658030.2860423992) +s(2977802215.597946655) +s(-4271392570.4091498761) +s(2378692585) +s(-3545193743.629374782) +s(-1762458738) +s(-1174277828.4264040126) +s(-1724994857) +s(2802750230.1783499408) +s(-3068133550) +s(3324811474.621822235) +s(2873024984) +s(-3509056632.3888206298) +s(1772903162.647192879) +s(2836543102) +s(4117858580.186) +s(2988632386.4063754522) +s(-4256784971.1770067447) +s(2280820447) +s(-2865200306) +s(-3329592486) +s(519126268) +s(-2452430452) +s(-2693220186.62104082) +s(-3796811992.14485798) +s(3619792326) +s(2697791049.3038381550) +s(3751267834.2808166557) +s(-3761719074) +s(-3824087631) +s(2119301150) +s(1398148974) +s(-3386564819.1351816969) +s(-3171483098) +s(3688944941.3273318162) +s(3060521119) +s(-3527110404) +s(3699631193) +s(3872838898) +s(3880350192) diff --git a/testsuite/bc_sine_results.txt b/testsuite/bc_sine_results.txt new file mode 100644 index 000000000..7a4a1ab0c --- /dev/null +++ b/testsuite/bc_sine_results.txt @@ -0,0 +1,204 @@ +0 +.47942553860420300027 +.84147098480789650665 +.90929742682568169539 +.14112000805986722210 +-.47942553860420300027 +-.84147098480789650665 +-.90929742682568169539 +-.14112000805986722210 +.43388373911755812047 +-.43388373911755812047 +.70710678118654752439 +-.70710678118654752439 +.86602540378443864676 +-.86602540378443864676 +1.00000000000000000000 +-1.00000000000000000000 +.70710678118654752440 +-.70710678118654752440 +0 +0 +-1.00000000000000000000 +1.00000000000000000000 +-.70710678118654752440 +.70710678118654752440 +-.70710678118654752439 +.70710678118654752439 +0 +0 +.38173640790989719211 +-.38173640790989719211 +.08162149793819434415 +.87714140586973771462 +-.91157035998052051623 +-.69638975047120679880 +-.94806056135672896231 +-.54548669379730874215 +.14605234154783145589 +-.12183062787430962391 +-.89832305526331682409 +-.99513029384033555290 +.76528428398894958149 +.51077956237618482050 +-.75908868040685122962 +-.37015497140201575652 +-.51432535569032144654 +.68890201397514289831 +.88200006249578882510 +-.01188893762444044480 +-.55298206739629427055 +-.39165958853437135625 +.17732674488831117445 +-.09648816960119759281 +.15728984163381104344 +-.31554983227150461370 +-.72225704678824601977 +.96170480789326775287 +-.47636475887571231114 +-.98999375714278585763 +-.06715264746977580303 +-.69464867397161089634 +.58037673122614640119 +-.44244898040675115062 +.04242496278231069061 +.96417934585711006987 +-.54513053517818430563 +-.28604677908958958915 +-.68003854521180919710 +.26597321569379963920 +-.34591048991595943570 +-.17084074152217894535 +-.42880744669595980174 +.36518031021580667844 +-.03514839609475800827 +.93891962312087620513 +-.69421849362562852947 +.15169857474887222961 +-.00226070393499995347 +.96209233301706432156 +-.79937182245558378826 +.99966966326862290520 +.85234799672007656117 +-.20824280061137520443 +-.00761257856348159450 +.10708922858398661064 +-.80233147080821341443 +.26521358383069223461 +-.95173930946495828679 +.66210405748455769256 +.30054820568403786217 +.21640593048970779808 +-.87596287572245980692 +.74627849623707962934 +-.25747200288605259984 +-.14700538617135227740 +-.06294254604551440990 +.67948313824962059899 +.83714389089726798409 +.33805040346429707760 +.80273418514828673749 +.72262501870089953244 +-.77469383027517310713 +-.15575896025754423345 +.22191568853026376075 +.25137052589938954082 +-.80534308288073574163 +-.44963537508211028805 +-.92368907556208259630 +-.80963411623457804531 +-.96822928101198069490 +-.46604999828123759716 +.63275578793565409192 +-.40563425346575205109 +.13095444406203282638 +.96217617474547242151 +-.16256793375739137005 +.71791623784197898982 +-.10713685791219679248 +.50758780541979250307 +-.09795373670371402656 +.14605234154783145589 +-.12183062787430962391 +-.89832305526331682409 +-.99513029384033555290 +.76528428398894958149 +.51077956237618482050 +-.75908868040685122962 +-.37015497140201575652 +-.51432535569032144654 +.68890201397514289831 +.88200006249578882510 +-.01188893762444044480 +-.55298206739629427055 +-.39165958853437135625 +.17732674488831117445 +-.09648816960119759281 +.15728984163381104344 +-.31554983227150461370 +-.72225704678824601977 +.96170480789326775287 +-.47636475887571231114 +-.98999375714278585763 +-.06715264746977580303 +-.69464867397161089634 +.58037673122614640119 +-.44244898040675115062 +.04242496278231069061 +.96417934585711006987 +-.54513053517818430563 +-.28604677908958958915 +-.68003854521180919710 +.26597321569379963920 +-.34591048991595943570 +-.17084074152217894535 +-.42880744669595980174 +.36518031021580667844 +-.03514839609475800827 +.75884554410943292265 +.93891962312087620513 +-.69421849362562852947 +.15169857474887222961 +-.00226070393499995347 +.96209233301706432156 +-.79937182245558378826 +.99966966326862290520 +.85234799672007656117 +-.20824280061137520443 +-.00761257856348159450 +.10708922858398661064 +-.80233147080821341443 +.26521358383069223461 +-.95173930946495828679 +.66210405748455769256 +.30054820568403786217 +.21640593048970779808 +-.87596287572245980692 +.74627849623707962934 +-.25747200288605259984 +-.14700538617135227740 +-.06294254604551440990 +.67948313824962059899 +.83714389089726798409 +.33805040346429707760 +.80273418514828673749 +.72262501870089953244 +-.77469383027517310713 +-.15575896025754423345 +.22191568853026376075 +.25137052589938954082 +-.80534308288073574163 +-.44963537508211028805 +-.92368907556208259630 +-.80963411623457804531 +-.96822928101198069490 +-.46604999828123759716 +.63275578793565409192 +-.40563425346575205109 +.13095444406203282638 +.96217617474547242151 +-.16256793375739137005 +.71791623784197898982 +-.10713685791219679248 +.50758780541979250307 +-.09795373670371402656 diff --git a/testsuite/bc_sqrt.bc b/testsuite/bc_sqrt.bc new file mode 100644 index 000000000..afd87ff0f --- /dev/null +++ b/testsuite/bc_sqrt.bc @@ -0,0 +1,18 @@ +scale = 20 +sqrt(0) +sqrt(2) +sqrt(4) +sqrt(9) +sqrt(16) +sqrt(25) +sqrt(121) +sqrt(48765) +sqrt(9287356207356) +sqrt(0.189274385967238956872354) +sqrt(12389467137496823.134567829387456283946) +sqrt(.0000000000000000000000000000123) +sqrt(1) +scale = 0; +sqrt(1407) +sqrt(79101) +scale = 6; sqrt(88.1247699921300025847737099094480986051698668662822009535526240) diff --git a/testsuite/bc_sqrt_results.txt b/testsuite/bc_sqrt_results.txt new file mode 100644 index 000000000..10a4fa95d --- /dev/null +++ b/testsuite/bc_sqrt_results.txt @@ -0,0 +1,16 @@ +0 +1.41421356237309504880 +2.00000000000000000000 +3.00000000000000000000 +4.00000000000000000000 +5.00000000000000000000 +11.00000000000000000000 +220.82798735667542192643 +3047516.39985021245496456781 +.435056761776252544285578 +111307983.260397019622398608908 +.0000000000000035071355833500363 +1.00000000000000000000 +37 +281 +9.3874794269883757005315658512340070115147163425837869223395574 diff --git a/testsuite/bc_strings.bc b/testsuite/bc_strings.bc new file mode 100644 index 000000000..1cb7d6a61 --- /dev/null +++ b/testsuite/bc_strings.bc @@ -0,0 +1,12 @@ +"string" +"another string" +"yet +another +string" +"noescapes\n" +"newline +" +print "string" +print "newline\n" + +print "\\\e\n" diff --git a/testsuite/bc_strings_results.txt b/testsuite/bc_strings_results.txt new file mode 100644 index 000000000..89b01ac49 --- /dev/null +++ b/testsuite/bc_strings_results.txt @@ -0,0 +1,5 @@ +stringanother stringyet +another +stringnoescapes\nnewline +stringnewline +\\ diff --git a/testsuite/bc_subtract.bc b/testsuite/bc_subtract.bc new file mode 100644 index 000000000..61ea953ea --- /dev/null +++ b/testsuite/bc_subtract.bc @@ -0,0 +1,32 @@ +0 - 0 +0 - 1 +1 - 0 +1 - 1 +5 - 2 +2 - 9 +321974 - 12845976238457 +2874519803456710938465 - 384723854 +10000000000000000000000000000000000000000 - 999999999999999999999999999999999999999 +10000000000000000000000000000000000000000 - 9999999999999999999999999999999999999999 +10000000000000000000000000000000000000000 - 999999999999999999999999999999999999999.99999999999999999999999999999999999 +10000000000000000000000000000000000000000 - 9999999999999999999999999999999999999999.9999999999999999999999999999999999 +10000000000000000000000000000000000000000 - 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +10000000000000000000000000000000000000001 - 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +10000000000000000000000000000000000000000.0000000001 - 0.0000000000000000000000000000000000000000000000000000000000000000000000000001 +-2 - 6 +-23784692345 - 182934721309467230894628735496027345 +-224352354962873059862 - -1245723576829456278354960278345 +-3468273598 - -12354243 +-0.92345768293 - -2354768923 +-712384634.123476823 - -24768293376 +-1879234638 - -0.917234869234 +-0.9172438692134 - -0.971284967124 +-0.1283475123465 - -0.937462346 +-124765829346.2837468293562 - -0.923467829346 +-12476829385769 - -1928476259034.8378629356 +-0.38476284395876345 - -94875394587623.2357869324857 +-4674596708467.34754789403674343567 - -48672394852354698.237548629345 +979519669 - 3018100865 +929002449 - 3280677283 +0 - -525898 +3- - -3 diff --git a/testsuite/bc_subtract_results.txt b/testsuite/bc_subtract_results.txt new file mode 100644 index 000000000..6850b5bc1 --- /dev/null +++ b/testsuite/bc_subtract_results.txt @@ -0,0 +1,36 @@ +0 +-1 +1 +0 +3 +-7 +-12845975916483 +2874519803456326214611 +9000000000000000000000000000000000000001 +1 +9000000000000000000000000000000000000000.000000000000000000000000000\ +00000001 +.0000000000000000000000000000000001 +9999999999999999999999999999999999999999.999999999999999999999999999\ +99999999999999999999999999999999999999999999999999999999999 +10000000000000000000000000000000000000000.99999999999999999999999999\ +999999999999999999999999999999999999999999999999999999999999 +10000000000000000000000000000000000000000.00000000009999999999999999\ +99999999999999999999999999999999999999999999999999 +-8 +-182934721309467230894628759280719690 +1245723576605103923392087218483 +-3455919355 +2354768922.07654231707 +24055908741.876523177 +-1879234637.082765130766 +.0540410979106 +.8091148336535 +-124765829345.3602790000102 +-10548353126734.1621370644 +94875394587622.85102408852693655 +48667720255646230.89000073530825656433 +-2038581196 +-2351674834 +525898 +0 diff --git a/testsuite/bc_vars.bc b/testsuite/bc_vars.bc new file mode 100644 index 000000000..91e3572c2 --- /dev/null +++ b/testsuite/bc_vars.bc @@ -0,0 +1,7 @@ +scale=10;123981239.981273987 * 12983791827398.29836472638 +scale=100;759634576394.3946587934658364895 / 9834759834895386.36459364958346 +34895734986539489834759837489573498573.398475984759837485734987598345 + 9823749832749872384234872934.28347982374987239847982374 +a=123123123.987239874; b=123123123.239479823748; a+b +20347023.23498723984 - 28934723874.234720384 +scale=100;a=739534985.895347284957;b=238746782364.2374623784; c = a / b; c +s7298367203972395108367910823465293084561329084561390845613409516734503870691837451 + 785621394067928346918023476190834672198467134908618723249671349062187346898241093486139046139084613490817356023871869102746182749061872609129847 diff --git a/testsuite/bc_vars_results.txt b/testsuite/bc_vars_results.txt new file mode 100644 index 000000000..6597d8439 --- /dev/null +++ b/testsuite/bc_vars_results.txt @@ -0,0 +1,12 @@ +1609746610419572350599.59456175545 +.0000772397688552681359718594121969204138521230712049526233926741658\ +845368495051158801794834809672994 +34895734996363239667509709873808371507.68195580850970988421481133834\ +5 +246246247.226719697748 +-28914376850.99973314416 +.0030975704827179453786044330548590249517387192084765414205077089498\ +482709063381782183114683451531598 +78562139406792834691802347619083467219846713490861872324967134906218\ +73468982410934861390461390846134908173560238718691027461827490618726\ +09129847 diff --git a/testsuite/dc.tests b/testsuite/dc.tests index d7a332b9c..8edfa07ca 100755 --- a/testsuite/dc.tests +++ b/testsuite/dc.tests @@ -41,4 +41,24 @@ testing "dc complex without spaces (multiple args)" \ "16\n" \ "" "" +for f in dc_*.dc; do + r="`basename "$f" .dc`_results.txt" + test -f "$r" || continue + # testing "test name" "command" "expected result" "file input" "stdin" + testing "dc $f" \ + "{ { dc $f 2>&1; echo E:\$? >&2; } | diff -u - $r; echo E:\$?; } 2>&1" \ + "E:0\nE:0\n" \ + "" "" +done + +for f in dcx_*.dc; do + r="`basename "$f" .dc`_results.txt" + test -f "$r" || continue + # testing "test name" "command" "expected result" "file input" "stdin" + testing "dc -x $f" \ + "{ { dc -x $f 2>&1; echo E:\$? >&2; } | diff -u - $r; echo E:\$?; } 2>&1" \ + "E:0\nE:0\n" \ + "" "" +done + exit $FAILCOUNT diff --git a/testsuite/dc_add.dc b/testsuite/dc_add.dc new file mode 100644 index 000000000..42da2f1f3 --- /dev/null +++ b/testsuite/dc_add.dc @@ -0,0 +1,33 @@ +0 0+pR +0 0 0++pR +0 1+pR +0 1 1++pR +1 1+pR +1 0+pR +2 5+pR +237 483+pR +999 999+pR +2374623 324869356734856+pR +2378639084586723980562 23468729367839+pR +37298367203972395108367910823465293084561329084561390845613409516734503870691837451 785621394067928346918023476190834672198467134908618723249671349062187346898241093486139046139084613490817356023871869102746182749061872609129847+pR +1.1 0+pR +0 1.1+pR +457283.731284923576 37842934672834.3874629385672354+pR +1.0 0.1+pR +3746289134067138046 0.138375863945672398456712389456273486293+pR +_1 _1+pR +_4 _15+pR +_1346782 _1287904651762468913476+pR +99999999999999999999999999999999999999999999999999999999999.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+pR +99999999999999999999999999999999999999999999999999999999999.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999995 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005+pR +99999999999999999999999999999999999999999999999999999999999.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+pR +99999999999999999999999999999999999999999999999999999999999.999999999999999999999999999999999999999999999999999999999899999999999999999999999999999999999999999999999999999999999999 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+pR +99999999999999999999999999999999999989999999999999999999999.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+pR +_1889985797 2012747315+pR +0 _14338.391079082+pR +_2422297 1.3134942556+pR +_1289374 1289374.2893417 0.238971 28937.28971+++pR +1289374 1289374.2893417 _0.238971 28937.28971+++pR +1289374 1289374.2893417 0.238971 _28937.28971+++pR +1289374 1289374.2893417 _0.238971 _28937.28971+++pR +1289374 _1289374.2893417 _0.238971 _28937.28971+++pR diff --git a/testsuite/dc_add_results.txt b/testsuite/dc_add_results.txt new file mode 100644 index 000000000..542a62ea3 --- /dev/null +++ b/testsuite/dc_add_results.txt @@ -0,0 +1,45 @@ +0 +0 +1 +2 +2 +1 +7 +720 +1998 +324869359109479 +2378639108055453348401 +78562139406792834691802347619083467219846713490861872324967138636055\ +45508706362018540498696043776980521464405852627147161556994835657433\ +00967298 +1.1 +1.1 +37842935130118.1187478621432354 +1.1 +3746289134067138046.138375863945672398456712389456273486293 +-2 +-19 +-1287904651762470260258 +100000000000000000000000000000000000000000000000000000000000.0000000\ +00000000000000000000000000000000000000000000000000000000000000000000\ +000000000000000000000000000000000000000000000 +100000000000000000000000000000000000000000000000000000000000.0000000\ +00000000000000000000000000000000000000000000000000000000000000000000\ +000000000000000000000000000000000000000000000 +100000000000000000000000000000000000000000000000000000000000.0000000\ +00000000000000000000000000000000000000000000000000000000000000000000\ +000000000000000000000000000000000000000009999 +99999999999999999999999999999999999999999999999999999999999.99999999\ +99999999999999999999999999999999999999999999999999000000000000000000\ +00000000000000000000000000000000000000009999 +99999999999999999999999999999999999990000000000000000000000.00000000\ +00000000000000000000000000000000000000000000000000000000000000000000\ +00000000000000000000000000000000000000009999 +122761518 +-14338.391079082 +-2422295.6865057444 +28937.8180227 +2607685.3400807 +2549811.2386027 +2549810.7606607 +-28937.8180227 diff --git a/testsuite/dc_boolean.dc b/testsuite/dc_boolean.dc new file mode 100644 index 000000000..ea72623b8 --- /dev/null +++ b/testsuite/dc_boolean.dc @@ -0,0 +1,27 @@ +0 1(pR +1 1(pR +2 1(pR +_1 1(pR +_1 0(pR +_1 _1(pR +_1 _2(pR +0 1{pR +1 1{pR +2 1{pR +_1 1{pR +_1 0{pR +_1 _1{pR +_1 _2{pR +0 0GpR +0 1GpR +1 0GpR +_1 _1GpR +0 _1GpR +_1 0GpR +1 1GpR +238 2GpR +0NpR +1NpR +_1NpR +2398NpR +_2983.2389NpR diff --git a/testsuite/dc_boolean_results.txt b/testsuite/dc_boolean_results.txt new file mode 100644 index 000000000..6d29c5b60 --- /dev/null +++ b/testsuite/dc_boolean_results.txt @@ -0,0 +1,27 @@ +0 +0 +1 +0 +0 +0 +1 +0 +1 +1 +0 +0 +1 +1 +1 +0 +0 +1 +0 +0 +1 +0 +1 +0 +0 +0 +0 diff --git a/testsuite/dc_decimal.dc b/testsuite/dc_decimal.dc new file mode 100644 index 000000000..ebbb2dc91 --- /dev/null +++ b/testsuite/dc_decimal.dc @@ -0,0 +1,36 @@ +0pR +0.0pR +.0000pR +000000000000000000000000.00000000000000000000000pR +000000000000000000000000000135482346782356pR +000000000000000000000000002pR +1pR +11pR +123pR +7505pR +1023468723275435238491972521917846pR +4343472432431705867392073517038270398027352709027389273920739037937960379637893607893607893670530278200795207952702873892786172916728961783907893607418973587857386079679267926737520730925372983782793652793pR +_1pR +_203pR +_57pR +_18586pR +_31378682943772818461924738352952347258pR +_823945628745673589495067238723986520375698237620834674509627345273096287563846592384526349872634895763257893467523987578690283762897568459072348758071071087813501875908127359018715023841710239872301387278pR +.123521346523546pR +0.1245923756273856pR +_.1024678456387pR +_0.8735863475634587pR +4.0pR +_6.0pR +234237468293576.000000000000000000000000000000pR +23987623568943567.00000000000000000005677834650000000000000pR +23856934568940675.000000000000000435676782300000000000000456784pR +77567648698496.000000000000000000587674750000000000458563800000000000000pR +2348672354968723.2374823546000000000003256987394502346892435623870000000034578pR +_2354768.000000000000000000000000000000000000pR +_96739874567.000000000347683456pR +_3764568345.000000000004573845000000347683460pR +_356784356.934568495770004586495678300000000pR +74325437345273852773827101738273127312738521733017537073520735207307570358738257390761276072160719802671980267018728630178.7082681027680521760217867841276127681270867827821768173178207830710978017738178678012767377058785378278207385237085237803278203782037237582795870pR +_756752732785273851273728537852738257837283678965738527385272983678372867327835672967385278372637862738627836279863782673862783670.71738178361738718367186378610738617836781603760178367018603760178107735278372832783728367826738627836278378260736270367362073867097307925pR +9812734012837410982345719208345712908357412903587192048571920458712.23957182459817249058172945781pR diff --git a/testsuite/dc_decimal_results.txt b/testsuite/dc_decimal_results.txt new file mode 100644 index 000000000..275d431c6 --- /dev/null +++ b/testsuite/dc_decimal_results.txt @@ -0,0 +1,51 @@ +0 +0 +0 +0 +135482346782356 +2 +1 +11 +123 +7505 +1023468723275435238491972521917846 +43434724324317058673920735170382703980273527090273892739207390379379\ +60379637893607893607893670530278200795207952702873892786172916728961\ +78390789360741897358785738607967926792673752073092537298378279365279\ +3 +-1 +-203 +-57 +-18586 +-31378682943772818461924738352952347258 +-8239456287456735894950672387239865203756982376208346745096273452730\ +96287563846592384526349872634895763257893467523987578690283762897568\ +45907234875807107108781350187590812735901871502384171023987230138727\ +8 +.123521346523546 +.1245923756273856 +-.1024678456387 +-.8735863475634587 +4.0 +-6.0 +234237468293576.000000000000000000000000000000 +23987623568943567.00000000000000000005677834650000000000000 +23856934568940675.000000000000000435676782300000000000000456784 +77567648698496.00000000000000000058767475000000000045856380000000000\ +0000 +2348672354968723.237482354600000000000325698739450234689243562387000\ +0000034578 +-2354768.000000000000000000000000000000000000 +-96739874567.000000000347683456 +-3764568345.000000000004573845000000347683460 +-356784356.934568495770004586495678300000000 +74325437345273852773827101738273127312738521733017537073520735207307\ +570358738257390761276072160719802671980267018728630178.7082681027680\ +52176021786784127612768127086782782176817317820783071097801773817867\ +8012767377058785378278207385237085237803278203782037237582795870 +-7567527327852738512737285378527382578372836789657385273852729836783\ +72867327835672967385278372637862738627836279863782673862783670.71738\ +17836173871836718637861073861783678160376017836701860376017810773527\ +8372832783728367826738627836278378260736270367362073867097307925 +9812734012837410982345719208345712908357412903587192048571920458712.\ +23957182459817249058172945781 diff --git a/testsuite/dc_divide.dc b/testsuite/dc_divide.dc new file mode 100644 index 000000000..38b874e9f --- /dev/null +++ b/testsuite/dc_divide.dc @@ -0,0 +1,33 @@ +20k +0 1/pR +0 321566/pR +0 0.3984567238456/pR +1 1/pR +1 1287469297356/pR +1 0.2395672438567234/pR +1 237586239856.0293596728392360/pR +1249687284356 3027949207835207/pR +378617298617396719 35748521/pR +9348576237845624358 0.9857829375461/pR +35768293846193284 2374568947.045762839567823/pR +_78987234567812345 876542837618936/pR +_356789237555535468 0.3375273860984786903/pR +_5203475364850390 435742903748307.70869378534043296404530458/pR +_0.37861723347576903 7385770896/pR +_0.399454682043962 0.34824389304/pR +_0.6920414523873204 356489645223.76076045304879030/pR +_35872917389671.7573280963748 73924708/pR +_78375896314.4836709876983 0.78356798637817/pR +_2374123896417.143789621437581 347821469423789.1473856783960/pR +_896729350238549726 _34976289345762/pR +_2374568293458762348596 _0.8792370647234987679/pR +_237584692306721845726038 _21783910782374529637.978102738746189024761/pR +_0.23457980123576298375682 _1375486293874612/pR +_0.173897061862478951264 _0.8179327486017634987516298745/pR +_0.9186739823576829347586 _0.235678293458756239846/pR +_0.9375896183746982374568 _13784962873546.0928729395476283745/pR +_2930754618923467.12323745862937465 _734869238465/pR +_23745861923467.874675129834675 _0.23542357869124756/pR +_3878923750692883.7238596702834756902 _7384192674957215364986723.9738461923487621983/pR +1 0.00000000000000000000000000000000000000000002346728372937352457354204563027/pR +239854711289345712 2891374 182 .2893 ///pR diff --git a/testsuite/dc_divide_results.txt b/testsuite/dc_divide_results.txt new file mode 100644 index 000000000..340ae94c1 --- /dev/null +++ b/testsuite/dc_divide_results.txt @@ -0,0 +1,32 @@ +0 +0 +0 +1.00000000000000000000 +.00000000000077671755 +4.17419336592637110778 +.00000000000420899796 +.00041271738677857404 +10591131829.40901859967857131767 +9483402361494453751.52388015648196297248 +15063068.13735316451497043884 +-90.11223545260531110575 +-1057067521778623447.45138528213564485251 +-11.94161814246320631346 +-.00000000005126306228 +-1.14705437777218917343 +-.00000000000194126663 +-485262.88923145638029569727 +-100024372711.74763635544535424582 +-.00682569681609989277 +25638.20711150436682153521 +2700714504347599627864.24626421085374010264 +10906.42973524078145692731 +.00000000000000017054 +.21260557443109085166 +3.89799997647407910677 +.00000000000006801538 +3988.13076601933678578945 +100864416620775.31076855630746548983 +.00000000052530099381 +42612515855353136519261264261472677699404182.78776061098893912189 +52187553294928.31582417732156163799 diff --git a/testsuite/dc_divmod.dc b/testsuite/dc_divmod.dc new file mode 100644 index 000000000..1633203ff --- /dev/null +++ b/testsuite/dc_divmod.dc @@ -0,0 +1,64 @@ +20k +0 1~pRpR +0 321566~pRpR +0 0.3984567238456~pRpR +1 1~pRpR +1 1287469297356~pRpR +1 0.2395672438567234~pRpR +1 237586239856.0293596728392360~pRpR +1249687284356 3027949207835207~pRpR +378617298617396719 35748521~pRpR +9348576237845624358 0.9857829375461~pRpR +35768293846193284 2374568947.045762839567823~pRpR +_78987234567812345 876542837618936~pRpR +_356789237555535468 0.3375273860984786903~pRpR +_5203475364850390 435742903748307.70869378534043296404530458~pRpR +_0.37861723347576903 7385770896~pRpR +_0.399454682043962 0.34824389304~pRpR +_0.6920414523873204 356489645223.76076045304879030~pRpR +_35872917389671.7573280963748 73924708~pRpR +_78375896314.4836709876983 0.78356798637817~pRpR +_2374123896417.143789621437581 347821469423789.1473856783960~pRpR +_896729350238549726 _34976289345762~pRpR +_2374568293458762348596 _0.8792370647234987679~pRpR +_237584692306721845726038 _21783910782374529637.978102738746189024761~pRpR +_0.23457980123576298375682 _1375486293874612~pRpR +_0.173897061862478951264 _0.8179327486017634987516298745~pRpR +_0.9186739823576829347586 _0.235678293458756239846~pRpR +_0.9375896183746982374568 _13784962873546.0928729395476283745~pRpR +_2930754618923467.12323745862937465 _734869238465~pRpR +_23745861923467.874675129834675 _0.23542357869124756~pRpR +_3878923750692883.7238596702834756902 _7384192674957215364986723.9738461923487621983~pRpR +1 0.00000000000000000000000000000000000000000002346728372937352457354204563027~pRpR +0k +0 1~pRpR +0 321566~pRpR +0 0.3984567238456~pRpR +1 1~pRpR +1 1287469297356~pRpR +1 0.2395672438567234~pRpR +1 237586239856.0293596728392360~pRpR +1249687284356 3027949207835207~pRpR +378617298617396719 35748521~pRpR +9348576237845624358 0.9857829375461~pRpR +35768293846193284 2374568947.045762839567823~pRpR +_78987234567812345 876542837618936~pRpR +_356789237555535468 0.3375273860984786903~pRpR +_5203475364850390 435742903748307.70869378534043296404530458~pRpR +_0.37861723347576903 7385770896~pRpR +_0.399454682043962 0.34824389304~pRpR +_0.6920414523873204 356489645223.76076045304879030~pRpR +_35872917389671.7573280963748 73924708~pRpR +_78375896314.4836709876983 0.78356798637817~pRpR +_2374123896417.143789621437581 347821469423789.1473856783960~pRpR +_896729350238549726 _34976289345762~pRpR +_2374568293458762348596 _0.8792370647234987679~pRpR +_237584692306721845726038 _21783910782374529637.978102738746189024761~pRpR +_0.23457980123576298375682 _1375486293874612~pRpR +_0.173897061862478951264 _0.8179327486017634987516298745~pRpR +_0.9186739823576829347586 _0.235678293458756239846~pRpR +_0.9375896183746982374568 _13784962873546.0928729395476283745~pRpR +_2930754618923467.12323745862937465 _734869238465~pRpR +_23745861923467.874675129834675 _0.23542357869124756~pRpR +_3878923750692883.7238596702834756902 _7384192674957215364986723.9738461923487621983~pRpR +1 0.00000000000000000000000000000000000000000002346728372937352457354204563027~pRpR diff --git a/testsuite/dc_divmod_results.txt b/testsuite/dc_divmod_results.txt new file mode 100644 index 000000000..c55e9303d --- /dev/null +++ b/testsuite/dc_divmod_results.txt @@ -0,0 +1,126 @@ +0 +0 +0 +0 +0 +0 +0 +1.00000000000000000000 +.00000000165742620220 +.00000000000077671755 +.000000000000000000000404744340951948 +4.17419336592637110778 +.000000001121901731436913388268041440 +.00000000000420899796 +.00000053204123177372 +.00041271738677857404 +.00000000000027633393 +10591131829.40901859967857131767 +.000000000000000000008615446968672 +9483402361494453751.52388015648196297248 +.00000000001477790730322167374655468 +15063068.13735316451497043884 +-.00000456715270151800 +-90.11223545260531110575 +-.000000000000000000002529869118878532347 +-1057067521778623447.45138528213564485251 +-.0000022326265743225222025732006233770753463532 +-11.94161814246320631346 +-.00000000004830962712 +-.00000000005126306228 +-.0000000000000000000013970700728 +-1.14705437777218917343 +-.0000000001738947526290727016287423110 +-.00000000000194126663 +-.00000000000045885284 +-485262.88923145638029569727 +-.0000000000000000000075040663382506 +-100024372711.74763635544535424582 +-.000001609445227594519190694403080 +-.00682569681609989277 +-.00000019041665271998 +25638.20711150436682153521 +-.000000000000000000005200979673140462744 +2700714504347599627864.24626421085374010264 +-.15832010238185026960887316509782343287709 +10906.42973524078145692731 +-.00000436867838665327682 +.00000000000000017054 +-.000000000000000000004322546241638067588696083330 +.21260557443109085166 +-.00000000000000000000103666428264443764258 +3.89799997647407910677 +-.000000130244568783188524951028009600190 +.00000000000006801538 +-.00000000467404345575 +3988.13076601933678578945 +-.0000000000000000000004406586308076852 +100864416620775.31076855630746548983 +-53336.193401942302558132911110799109649707477 +.00000000052530099381 +.0000000000000000000000000000000000000000000000000000000000000001907\ +266929376630027064745963897 +42612515855353136519261264261472677699404182.78776061098893912189 +0 +0 +0 +0 +0 +0 +0 +1 +1 +0 +.0417310245731064 +4 +1.0000000000000000 +0 +1249687284356 +0 +14621810 +10591131829 +.5164321195789 +9483402361494453751 +326154559.235716791539036 +15063068 +-98379182108105 +-90 +-.1523548944025685359 +-1057067521778623447 +-410303423619005.20436836125523739550164962 +-11 +-.37861723347576903 +0 +-.051210789003962 +-1 +-.69204145238732040 +0 +-65736175.7573280963748 +-485262 +-.58582391357943 +-100024372711 +-2374123896417.143789621437581 +0 +-7243991903570 +25638 +-.2165246218974912344 +2700714504347599627864 +-9361314145225494248.811531234062495956534 +10906 +-.23457980123576298375682 +0 +-.1738970618624789512640000000 +0 +-.2116391019814142152206 +3 +-.9375896183746982374568 +0 +-96095925047.12323745862937465 +3988 +-.07316224567061600 +100864416620775 +-3878923750692883.7238596702834756902 +0 +.0000000000000000000000000000000000000000000184866017689020776005643\ +3621086 +42612515855353136519261264261472677699404182 diff --git a/testsuite/dc_misc.dc b/testsuite/dc_misc.dc new file mode 100644 index 000000000..222a3ad26 --- /dev/null +++ b/testsuite/dc_misc.dc @@ -0,0 +1 @@ +zp198202389.289374pzp[Hello, World!]pzpzpfrfczpfR diff --git a/testsuite/dc_misc_results.txt b/testsuite/dc_misc_results.txt new file mode 100644 index 000000000..fb321a817 --- /dev/null +++ b/testsuite/dc_misc_results.txt @@ -0,0 +1,20 @@ +0 +198202389.289374 +2 +Hello, World! +4 +5 +5 +4 +Hello, World! +2 +198202389.289374 +0 +4 +5 +Hello, World! +2 +198202389.289374 +0 +0 +0 diff --git a/testsuite/dc_modexp.dc b/testsuite/dc_modexp.dc new file mode 100644 index 000000000..a6afb9985 --- /dev/null +++ b/testsuite/dc_modexp.dc @@ -0,0 +1,103 @@ +0 0 1|pR +1 0 1|pR +1 0 2|pR +0 10 1|pR +1 293 1|pR +1 2789365 2|pR +100 8 7|pR +10922384 15031007 201|pR +3346529 189 254|pR +4113416930 197 14|pR +7709 5887 111|pR +5487406 3252 128|pR +2080527 2279453822 219|pR +48895 50678 232|pR +1535808383 2902995144 18|pR +8437837 2882198 69|pR +35363 25806 2|pR +3221177403 1560419989 189|pR +227 42775 163|pR +2811398069 37500 173|pR +15046850 3859895697 195|pR +15770756 3621999893 119|pR +6937927 3719297189 183|pR +12573 43819 209|pR +42098463 7584603 136|pR +8656683 1328292415 226|pR +209 81 157|pR +141 13317429 26|pR +809485795 60745 101|pR +4882 1388217898 38|pR +750704 78 119|pR +668879580 2888860497 179|pR +1152725844 15295742 154|pR +16160694 8981529 154|pR +216 102 3|pR +3691227289 5344109 232|pR +2195559299 61 222|pR +2478990626 13007440 30|pR +45083 44 117|pR +224 55824 53|pR +1372700133 89 94|pR +205 10422 48|pR +11887 12 73|pR +5955 24353 114|pR +1201697310 789722419 6|pR +56577 231 229|pR +96 38841 189|pR +6529661 5636520 209|pR +11005 15955685 27|pR +9709 231 132|pR +59790 1034579699 166|pR +47892 14536879 79|pR +48 208 21|pR +33036 3877 65|pR +164 6527085 249|pR +12146850 224 37|pR +218 16425679 62|pR +51 27641 95|pR +3076735605 49154 32|pR +515652717 4117874315 143|pR +300672671 720768884 110|pR +9422066 206 5|pR +43 97 13|pR +545174510 65319 126|pR +3317462730 704990271 51|pR +47316 23231 202|pR +7236571 4379567 106|pR +2584584521 2459274189 29|pR +61562 5035178 178|pR +65302 112 151|pR +63040 2168854052 213|pR +9039611 2370306559 62|pR +16414384 1020652061 83|pR +7491 3853569905 172|pR +1180322494 46670 84|pR +3823343557 3865107254 127|pR +6240872 55335 39|pR +2281401897 1098411 251|pR +61 2949190429 231|pR +8981024 162 43|pR +1 3568883218 212|pR +4217100969 3471787779 8|pR +3232237 13 243|pR +29280 3972452706 100|pR +13077 6431923 216|pR +104 3098510775 140|pR +9503298 174 242|pR +3424695712 12184 23|pR +184 15066347 151|pR +2935856 14003205 184|pR +1386637762 2128151420 71|pR +154 11960656 12|pR +743976432 4004778779 136|pR +3909160595 3575680922 21|pR +26133 3580 147|pR +409154 170 68|pR +149 55629 40|pR +5753 13776176 32|pR +3831447473 658273178 98|pR +1527252003 2300622 207|pR +3363824553 8244645 215|pR +20 145 101|pR +4005077294 2196555621 94|pR diff --git a/testsuite/dc_modexp_results.txt b/testsuite/dc_modexp_results.txt new file mode 100644 index 000000000..5bf0f146e --- /dev/null +++ b/testsuite/dc_modexp_results.txt @@ -0,0 +1,103 @@ +1 +1 +1 +0 +0 +1 +4 +74 +1 +0 +98 +0 +72 +1 +1 +1 +1 +108 +36 +52 +65 +8 +181 +22 +7 +123 +93 +21 +17 +20 +1 +108 +58 +22 +0 +105 +161 +16 +40 +15 +45 +25 +64 +69 +0 +225 +27 +1 +22 +73 +92 +38 +15 +16 +173 +33 +32 +21 +25 +109 +71 +1 +4 +62 +15 +90 +29 +5 +40 +84 +40 +53 +8 +31 +64 +44 +14 +13 +145 +1 +1 +1 +76 +0 +189 +104 +192 +9 +119 +56 +45 +4 +32 +16 +135 +4 +29 +1 +49 +0 +128 +6 +18 diff --git a/testsuite/dc_modulus.dc b/testsuite/dc_modulus.dc new file mode 100644 index 000000000..613944b20 --- /dev/null +++ b/testsuite/dc_modulus.dc @@ -0,0 +1,70 @@ +20k +1 1%pR +2 1%pR +16 4%pR +15 4%pR +17 4%pR +2389473 5%pR +39240687239 1%pR +346728934 23958%pR +3496723859067234 298375462837546928347623059375486%pR +_1 1%pR +_2 1%pR +_47589634875689345 37869235%pR +_1274852934765 2387628935486273546%pR +_6324758963 237854962%pR +1 _1%pR +2 _1%pR +2 _2%pR +2 _3%pR +16 5%pR +15 5%pR +14 5%pR +89237423 _237856923854%pR +123647238946 _12467%pR +_1 _1%pR +_2 _1%pR +_2 _2%pR +_2 _3%pR +_13 _7%pR +_14 _7%pR +_15 _7%pR +_12784956 _32746%pR +_127849612 _23712347682193%pR +0k +1 1%pR +2 1%pR +16 4%pR +15 4%pR +17 4%pR +2389473 5%pR +39240687239 1%pR +346728934 23958%pR +3496723859067234 298375462837546928347623059375486%pR +_1 1%pR +_2 1%pR +_47589634875689345 37869235%pR +_1274852934765 2387628935486273546%pR +_6324758963 237854962%pR +1 _1%pR +2 _1%pR +2 _2%pR +2 _3%pR +16 5%pR +15 5%pR +14 5%pR +89237423 _237856923854%pR +123647238946 _12467%pR +_1 _1%pR +_2 _1%pR +_2 _2%pR +_2 _3%pR +_13 _7%pR +_14 _7%pR +_15 _7%pR +_12784956 _32746%pR +_127849612 _23712347682193%pR +_3191280681 641165986%pR +0k _899510228 _2448300078.40314%pR +0k _7424863 _207.2609738667%pR +0k 3769798918 0.6%pR diff --git a/testsuite/dc_modulus_results.txt b/testsuite/dc_modulus_results.txt new file mode 100644 index 000000000..7d718d22a --- /dev/null +++ b/testsuite/dc_modulus_results.txt @@ -0,0 +1,68 @@ +0 +0 +0 +0 +0 +0 +0 +.00000000000000002026 +2747189239559.46904933397471305894 +0 +0 +-.00000000000011057855 +-.00076922992566770712 +-.00000000000050364144 +0 +0 +0 +.00000000000000000002 +0 +0 +0 +.00000000070585524350 +.00000000000000002898 +0 +0 +0 +-.00000000000000000002 +-.00000000000000000005 +0 +-.00000000000000000002 +-.00000000000000011722 +-.00000002640923745817 +0 +0 +0 +3 +1 +3 +0 +8758 +3496723859067234 +0 +0 +-8236960 +-1274852934765 +-140529951 +0 +0 +0 +2 +1 +0 +4 +89237423 +6692 +0 +0 +0 +-2 +-6 +0 +-1 +-14016 +-127849612 +-626616737 +-899510228.00000 +-153.1331732059 +.4 diff --git a/testsuite/dc_multiply.dc b/testsuite/dc_multiply.dc new file mode 100644 index 000000000..1f9041d06 --- /dev/null +++ b/testsuite/dc_multiply.dc @@ -0,0 +1,42 @@ +0 0*pR +0.000 0*pR +1 0*pR +0 1*pR +0 2498752389672835476*pR +873246913745129084576134 0*pR +1 472638590273489273456*pR +12374861230476103672835496 1*pR +1 1*pR +2 1*pR +1 2*pR +2 2*pR +3 14*pR +17 8*pR +1892467513846753 1872439821374591038746*pR +328962735862.2973546835638947635 1728465791348762356*pR +38745962374538.387427384672934867234 0.1932476528394672837568923754*pR +9878894576289457634856.2738627161689017387608947567654 37842939768237596237854203.29874372139852739126739621793162*pR +_1 1*pR +_1 2*pR +78893457 _34876238956*pR +235678324957634 _0.2349578349672389576*pR +_12849567821934 12738462937681*pR +1274861293467.927843682937462 _28935678239*pR +2936077239872.12937462836 _0.012842357682435762*pR +2387692387566.2378569237546 _272189345628.123875629835876*pR +0.012348629356782835962 _23487692356*pR +0.4768349567348675934 _0.23756834576934857638495*pR +0.98748395367485962735486 _4675839462354867.376834956738456*pR +_321784627934586 _235762378596*pR +_32578623567892356 _0.32567384579638456*pR +_35768232346876 _2348672935602387620.28375682349576237856*pR +_0.2356728394765234 _238759624356978*pR +_0.2345768212346780 _0.235768124697074385948943532045*pR +_0.370873860736785306278630 _7835678398607.7086378076867096270*pR +_78365713707.7089637863786730 _738580798679306780*pR +_73867038956790490258249 _0.7379862716391723672803679*pR +_378621971598721837710387 _98465373878350798.09743896037963078560*pR +37164201 2931559660*pR +679468076118972457796560530571.46287161642138401685 93762.2836*pR +.000000000000000000000000001 .0000000000000000000000001*pR +239 289 _98 .8937 _.1893 28937*****pR diff --git a/testsuite/dc_multiply_results.txt b/testsuite/dc_multiply_results.txt new file mode 100644 index 000000000..9666059a5 --- /dev/null +++ b/testsuite/dc_multiply_results.txt @@ -0,0 +1,43 @@ +0 +0 +0 +0 +0 +0 +472638590273489273456 +12374861230476103672835496 +1 +2 +2 +4 +42 +136 +3543531533584430580556128344529291738 +568600835566479683035874339053.4411638427543228060 +7487566285885.8557453089005171423976251098 +373846412427291014394738378015501363938345620046.7869650248829232267\ +2297002026819 +-1 +-2 +-2751507058396910892 +-55374468980751.0837656919743223184 +-163683743464924630346895054 +-36888976187143312550878.567134791289418 +-37706154097.696628262157533781 +-649904428532907022680241.947918694247541 +-290040807.350385412976669306472 +-.11328089187650139309272 +-4617316439035114.40320367843985107357898 +75864709277486862054521256 +10610005628108234.92015040406042336 +84007879267445533366251128067927.91168012197674537856 +56269158624557.1027018519702852 +.055305737239900889424090264801 +2906048299183.472237078104362540110129 +57879411419313585866282299201.3825582163029400 +54512860676747314187949.9414724679950990587298071 +37281153992026463004361915151761464058058.54968338992209002720 +108949072447731660 +63708478450213482928510139572007971.83536929222529239687 +0 +33137343861.8586 diff --git a/testsuite/dc_power.dc b/testsuite/dc_power.dc new file mode 100644 index 000000000..b58ae0cbc --- /dev/null +++ b/testsuite/dc_power.dc @@ -0,0 +1,45 @@ +20k +0 0^pR +0 1^pR +0 1894^pR +1 0^pR +39746823 0^pR +0.238672983047682 0^pR +18394762374689237468.97354862973846 0^pR +1 1^pR +2 1^pR +18927361346 1^pR +0.23523785962738592635777 1^pR +328956734869213746.89782398457234 1^pR +8937 98^pR +0.124876812394 2396^pR +93762.2836 13^pR +1 _1^pR +2 _1^pR +10 _1^pR +683734768 _1^pR +38579623756.897937568235 _1^pR +1 _32467^pR +2 _53^pR +23897 _213^pR +_1 1^pR +_1 2^pR +_2 1^pR +_2 2^pR +_237 294^pR +_3746 28^pR +_0.3548 35^pR +_4267.234 37^pR +_326.3246 78^pR +_1 _1^pR +_1 _2^pR +_2 _1^pR +_2 _2^pR +_237 _293^pR +_784 _23^pR +_86 _7^pR +_0.23424398 _781^pR +_178.234786 _879^pR +_1274.346 _768^pR +0 _251^pR +_0.2959371298 227^pR diff --git a/testsuite/dc_power_results.txt b/testsuite/dc_power_results.txt new file mode 100644 index 000000000..997f44f59 --- /dev/null +++ b/testsuite/dc_power_results.txt @@ -0,0 +1,73 @@ +1 +0 +0 +1 +1 +1 +1 +1 +2 +18927361346 +.23523785962738592635777 +328956734869213746.89782398457234 +16473742664221279051571200630760751138799221376964991600670000200609\ +08006052596520320731708604393844468006290371918262741885989163144389\ +39367835091560809036359941703341471396407660150658436796925310445979\ +21333166245765946557344383284626113908419359990042883048537750217279\ +17481980123593363177308481941550382845381799410533956718500484099889\ +610805653325917409549921909941664118421333562129 +0 +43287877285033571298394739716218787350087163435619825150259705419.98\ +016445740928054425 +1.00000000000000000000 +.50000000000000000000 +.10000000000000000000 +.00000000146255543348 +.00000000002592041867 +1.00000000000000000000 +.00000000000000011102 +0 +-1 +1 +-2 +4 +14997322375665265051328725757939209353051902095893907150382724666290\ +49749481660976421019742616298227588464420182758442163654172400528243\ +00885441207762486233574213374503090372518590691583139696652847404883\ +08573912261119588874308960204159666762789603037188471170006223907416\ +60492840269152716750700089148882139254399347568222390231015487895905\ +73727080561379177721440905866857248917982113340543176658480139248897\ +54802503253413282808814063861470711399810899724515727713334909764746\ +27910290211411231279325882505708287941671508154740003122373284699097\ +78346501539634198926772266511968381368929692275950529960923432771985\ +12597189390708050983487158873301681237787429436264801751664042999180\ +3448659818912436089 +11478830555358864333472551120140548480416206583184496764727387456058\ +792742209537931243951391229607936 +-.00000000000000017759 +-2067373624686414405470850679965010694114490999957199847684803894306\ +56243666149296582304582679590231948238805965642713928910384741502707\ +.23224479257866798694 +11606078892843496082360561256965139908586179418605021706789617179085\ +85768049299693425729565480314913006780973928345684673490252494674985\ +0186164225375953066263609289359900615361965737717208159874390.293769\ +70206344604971 +-1.00000000000000000000 +1.00000000000000000000 +-.50000000000000000000 +.25000000000000000000 +0 +0 +-.00000000000002874159 +-1945134149489344891879057554905782841936258356736314337975569799825\ +94091939572752348215929683891336730843553721422164737465108229034947\ +87333189564755763444242676978610321731298729194092653999616928308494\ +26419468484566422775668903315088810746121307679948574976162519479931\ +18935243698160094347216562490000767121041786977792546155155934655909\ +14123833869470494708767968978717730012864171105540029928688274136791\ +98175053824022144065005509214813689232148489884560100200475909009813\ +340098100705258138.98542904577525702068 +0 +0 +0 +0 diff --git a/testsuite/dc_sqrt.dc b/testsuite/dc_sqrt.dc new file mode 100644 index 000000000..7c13fdd0b --- /dev/null +++ b/testsuite/dc_sqrt.dc @@ -0,0 +1,14 @@ +20k +0vpR +2vpR +4vpR +9vpR +16vpR +25vpR +121vpR +48765vpR +9287356207356vpR +0.189274385967238956872354vpR +12389467137496823.134567829387456283946vpR +.0000000000000000000000000000123vpR +1vpR diff --git a/testsuite/dc_sqrt_results.txt b/testsuite/dc_sqrt_results.txt new file mode 100644 index 000000000..5ded8c294 --- /dev/null +++ b/testsuite/dc_sqrt_results.txt @@ -0,0 +1,13 @@ +0 +1.41421356237309504880 +2.00000000000000000000 +3.00000000000000000000 +4.00000000000000000000 +5.00000000000000000000 +11.00000000000000000000 +220.82798735667542192643 +3047516.39985021245496456781 +.435056761776252544285578 +111307983.260397019622398608908 +.0000000000000035071355833500363 +1.00000000000000000000 diff --git a/testsuite/dc_strings.dc b/testsuite/dc_strings.dc new file mode 100644 index 000000000..2f6b38d88 --- /dev/null +++ b/testsuite/dc_strings.dc @@ -0,0 +1,37 @@ +[Hello, World!]ZpR +[Hello, World!]pR +[Hello, \[ World!]ZpR +[Hello, \[ World!]pR +[Hello, \] World!]ZpR +[Hello, \] World!]pR +[30pR] +[29pR] +[28pR] +[27pR] +[26pR] +[25pR] +[24pR] +[23pR] +[22pR] +[21pR] +[20pR] +[19pR] +[18pR] +[17pR] +[16pR] +[15pR] +[14pR] +[13pR] +[12pR] +[11pR] +[10pR] +[9pR] +[8pR] +[7pR] +[6pR] +[5pR] +[4pR] +[3pR] +[2pR] +[1pR] +[xz0 Date: Wed, 12 Dec 2018 21:56:06 +0100 Subject: dc: fix EOF handling in case of last line being incomplete This wasn't working correctly: $ echo -ne '10 20+p' | dc 30 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 3d26c39a7..9cc29f0ea 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1425,7 +1425,9 @@ static BcStatus bc_read_line(BcVec *vec) if (c == EOF) { if (ferror(stdin)) quit(); // this emits error message - s = BC_STATUS_EOF; + // If we had some input before EOF, do not report EOF yet: + if (vec->len == 0) + s = BC_STATUS_EOF; // Note: EOF does not append '\n', therefore: // printf 'print 123\n' | bc - works // printf 'print 123' | bc - fails (syntax error) -- cgit v1.2.3-55-g6feb From 8a89247e0a82b328958e010be5da4c815f9121be Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 12 Dec 2018 22:43:58 +0100 Subject: bc: remove BC_STATUS_EOF (again), the condition is detectable as len==0 function old new delta bc_read_line 147 129 -18 bc_vm_run 618 591 -27 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-45) Total: -45 bytes text data bss dec hex filename 980802 485 7296 988583 f15a7 busybox_old 980757 485 7296 988538 f157a busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 9cc29f0ea..9809fa72f 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -187,7 +187,6 @@ typedef enum BcStatus { BC_STATUS_SUCCESS = 0, BC_STATUS_FAILURE = 1, BC_STATUS_PARSE_EMPTY_EXP = 2, // bc_parse_expr_empty_ok() uses this - BC_STATUS_EOF = 3, // bc_vm_stdin() uses this } BcStatus; #define BC_VEC_INVALID_IDX ((size_t) -1) @@ -1364,15 +1363,10 @@ static int push_input_byte(BcVec *vec, char c) return 0; } -// This is not a "z" function: -// can return success (0) or BC_STATUS_EOF. -// Exits with error message if read error is detected. -static BcStatus bc_read_line(BcVec *vec) +static void bc_read_line(BcVec *vec) { - BcStatus s; bool bad_chars; - s = BC_STATUS_SUCCESS; do { int c; @@ -1397,7 +1391,6 @@ static BcStatus bc_read_line(BcVec *vec) if (n <= 0) { // read errors or EOF, or ^D, or ^C if (n == 0) // ^C goto intr; - s = BC_STATUS_EOF; break; } i = 0; @@ -1425,9 +1418,6 @@ static BcStatus bc_read_line(BcVec *vec) if (c == EOF) { if (ferror(stdin)) quit(); // this emits error message - // If we had some input before EOF, do not report EOF yet: - if (vec->len == 0) - s = BC_STATUS_EOF; // Note: EOF does not append '\n', therefore: // printf 'print 123\n' | bc - works // printf 'print 123' | bc - fails (syntax error) @@ -1439,8 +1429,6 @@ static BcStatus bc_read_line(BcVec *vec) } while (bad_chars); bc_vec_pushZeroByte(vec); - - return s; } static char* bc_read_file(const char *path) @@ -5416,8 +5404,7 @@ static BC_STATUS zbc_program_read(void) G.prog.file = NULL; G.in_read = 1; - s = bc_read_line(&buf); - //if (s) goto io_err; - wrong, nonzero return means EOF, not error + bc_read_line(&buf); common_parse_init(&parse, BC_PROG_READ); bc_lex_file(&parse.l); @@ -7091,13 +7078,18 @@ static BcStatus bc_vm_stdin(void) // with a backslash to the parser. The reason for that is because the parser // treats a backslash+newline combo as whitespace, per the bc spec. In that // case, and for strings and comments, the parser will expect more stuff. + s = BC_STATUS_SUCCESS; comment = false; str = 0; - while ((s = bc_read_line(&buf)) == BC_STATUS_SUCCESS) { + for (;;) { size_t len; - char *string = buf.v; + char *string; + bc_read_line(&buf); len = buf.len - 1; + if (len == 0) // "" buf means EOF + break; + string = buf.v; if (len == 1) { if (str && buf.v[0] == G.send) str -= 1; @@ -7146,8 +7138,6 @@ static BcStatus bc_vm_stdin(void) bc_vec_pop_all(&buffer); } - if (s == BC_STATUS_EOF) // input EOF (^D) is not an error - s = BC_STATUS_SUCCESS; if (str) { s = bc_error("string end could not be found"); -- cgit v1.2.3-55-g6feb From 19f110751d333bc4ddb74b8d23b25516d649986c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 12 Dec 2018 22:48:19 +0100 Subject: bc: convert two more functions to "z" logic Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 9809fa72f..1bf3e373e 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -7060,7 +7060,7 @@ err: # define zbc_vm_file(...) (zbc_vm_file(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static BcStatus bc_vm_stdin(void) +static BC_STATUS zbc_vm_stdin(void) { BcStatus s; BcVec buf, buffer; @@ -7148,8 +7148,11 @@ static BcStatus bc_vm_stdin(void) bc_vec_free(&buf); bc_vec_free(&buffer); - return s; + RETURN_STATUS(s); } +#if ERRORS_ARE_FATAL +# define zbc_vm_stdin(...) (zbc_vm_stdin(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif #if ENABLE_BC static const char bc_lib[] = { @@ -7328,7 +7331,7 @@ static const char bc_lib[] = { }; #endif // ENABLE_BC -static BcStatus bc_vm_exec(void) +static BC_STATUS zbc_vm_exec(void) { BcStatus s; size_t i; @@ -7341,14 +7344,14 @@ static BcStatus bc_vm_exec(void) # define DEBUG_LIB 0 bc_lex_file(&G.prs.l); s = zbc_parse_text(&G.prs, bc_lib); - if (DEBUG_LIB && s) return s; + if (DEBUG_LIB && s) RETURN_STATUS(s); while (G.prs.l.t.t != BC_LEX_EOF) { ERROR_RETURN(s =) G.prs.parse(&G.prs); - if (DEBUG_LIB && s) return s; + if (DEBUG_LIB && s) RETURN_STATUS(s); } s = zbc_program_exec(); - if (DEBUG_LIB && s) return s; + if (DEBUG_LIB && s) RETURN_STATUS(s); } #endif @@ -7359,17 +7362,20 @@ static BcStatus bc_vm_exec(void) // Debug config, non-interactive mode: // return all the way back to main. // Non-debug builds do not come here, they exit. - return s; + RETURN_STATUS(s); } if (IS_BC || (option_mask32 & BC_FLAG_I)) - s = bc_vm_stdin(); + s = zbc_vm_stdin(); if (!s && !BC_PARSE_CAN_EXEC(&G.prs)) s = zbc_vm_process(""); - return s; + RETURN_STATUS(s); } +#if ERRORS_ARE_FATAL +# define zbc_vm_exec(...) (zbc_vm_exec(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif #if ENABLE_FEATURE_CLEAN_UP static void bc_program_free(void) @@ -7499,7 +7505,7 @@ static int bc_vm_init(const char *env_len) static BcStatus bc_vm_run(void) { - BcStatus st = bc_vm_exec(); + BcStatus st = zbc_vm_exec(); #if ENABLE_FEATURE_CLEAN_UP if (G_exiting) // it was actually "halt" or "quit" st = EXIT_SUCCESS; -- cgit v1.2.3-55-g6feb From c0ef23ca400012ca0f4c1cd098e32b685e8f4f09 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 12 Dec 2018 23:03:10 +0100 Subject: bc: remove parse function pointer function old new delta zbc_program_asciify - 372 +372 zcommon_parse - 341 +341 zbc_program_printStream - 141 +141 zbc_program_pushArray - 111 +111 zbc_program_nquit - 92 +92 zbc_vm_process 61 63 +2 zbc_parse_text 122 123 +1 bc_vm_run 591 592 +1 zdc_parse_mem 108 107 -1 zbc_parse_operator 175 174 -1 zbc_parse_else 133 132 -1 zbc_parse_body 104 103 -1 zbc_program_read 261 259 -2 zdc_parse_register 40 37 -3 zbc_parse_string 100 97 -3 zbc_parse_endBody 343 339 -4 zdc_parse_expr 688 680 -8 zbc_parse_auto 198 188 -10 zbc_parse_name 414 401 -13 common_parse_init 45 31 -14 zdc_parse_parse 23 - -23 bc_parse_create 158 131 -27 zbc_parse_stmt 1540 1502 -38 bc_parse_expr_empty_ok 1882 1840 -42 zbc_program_exec 3963 3837 -126 zbc_parse_parse 311 - -311 zbc_program_modexp 556 - -556 ------------------------------------------------------------------------------ (add/remove: 5/3 grow/shrink: 3/16 up/down: 1061/-1184) Total: -123 bytes text data bss dec hex filename 980757 485 7296 988538 f157a busybox_old 980634 485 7296 988415 f14ff busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 1bf3e373e..630a343d1 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -617,12 +617,8 @@ struct BcParse; struct BcProgram; -typedef BC_STATUS (*BcParseParse)(struct BcParse *) FAST_FUNC; - typedef struct BcParse { - BcParseParse parse; - BcLex l; BcVec flags; @@ -3483,6 +3479,17 @@ static void bc_parse_number(BcParse *p, BcInst *prev, size_t *nexs) (*prev) = BC_INST_NUM; } +static BC_STATUS zbc_parse_parse(BcParse *p); +static BC_STATUS zdc_parse_parse(BcParse *p); + +static BC_STATUS zcommon_parse(BcParse *p) +{ + if (IS_BC) { + IF_BC(RETURN_STATUS(zbc_parse_parse(p));) + } + IF_DC(RETURN_STATUS(zdc_parse_parse(p));) +} + static BC_STATUS zbc_parse_text(BcParse *p, const char *text) { BcStatus s; @@ -3492,7 +3499,7 @@ static BC_STATUS zbc_parse_text(BcParse *p, const char *text) if (!text[0] && !BC_PARSE_CAN_EXEC(p)) { p->l.t.t = BC_LEX_INVALID; s = BC_STATUS_SUCCESS; - ERROR_RETURN(s =) p->parse(p); + ERROR_RETURN(s =) zcommon_parse(p); if (s) RETURN_STATUS(s); if (!BC_PARSE_CAN_EXEC(p)) RETURN_STATUS(bc_error("file is not executable")); @@ -3556,8 +3563,7 @@ static void bc_parse_free(BcParse *p) bc_lex_free(&p->l); } -static void bc_parse_create(BcParse *p, size_t func, - BcParseParse parse, BcLexNext next) +static void bc_parse_create(BcParse *p, size_t func, BcLexNext next) { memset(p, 0, sizeof(BcParse)); @@ -3568,7 +3574,6 @@ static void bc_parse_create(BcParse *p, size_t func, bc_vec_pushZeroByte(&p->flags); bc_vec_init(&p->ops, sizeof(BcLexType), NULL); - p->parse = parse; // p->auto_part = p->nbraces = 0; - already is bc_parse_updateFunc(p, func); } @@ -4630,7 +4635,7 @@ static BC_STATUS zbc_parse_stmt(BcParse *p) # define zbc_parse_stmt(...) (zbc_parse_stmt(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static FAST_FUNC BC_STATUS zbc_parse_parse(BcParse *p) +static BC_STATUS zbc_parse_parse(BcParse *p) { BcStatus s; @@ -4930,7 +4935,7 @@ static BC_STATUS zbc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) static void bc_parse_init(BcParse *p, size_t func) { - bc_parse_create(p, func, zbc_parse_parse, zbc_lex_token); + bc_parse_create(p, func, zbc_lex_token); } static BC_STATUS zbc_parse_expression(BcParse *p, uint8_t flags) @@ -5134,7 +5139,7 @@ static BC_STATUS zdc_parse_expr(BcParse *p, uint8_t flags) # define zdc_parse_expr(...) (zdc_parse_expr(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static FAST_FUNC BC_STATUS zdc_parse_parse(BcParse *p) +static BC_STATUS zdc_parse_parse(BcParse *p) { BcStatus s; @@ -5156,7 +5161,7 @@ static FAST_FUNC BC_STATUS zdc_parse_parse(BcParse *p) static void dc_parse_init(BcParse *p, size_t func) { - bc_parse_create(p, func, zdc_parse_parse, zdc_lex_token); + bc_parse_create(p, func, zdc_lex_token); } #endif // ENABLE_DC @@ -7011,7 +7016,7 @@ static BC_STATUS zbc_vm_process(const char *text) if (s) RETURN_STATUS(s); while (G.prs.l.t.t != BC_LEX_EOF) { - ERROR_RETURN(s =) G.prs.parse(&G.prs); + ERROR_RETURN(s =) zcommon_parse(&G.prs); if (s) RETURN_STATUS(s); } @@ -7347,7 +7352,7 @@ static BC_STATUS zbc_vm_exec(void) if (DEBUG_LIB && s) RETURN_STATUS(s); while (G.prs.l.t.t != BC_LEX_EOF) { - ERROR_RETURN(s =) G.prs.parse(&G.prs); + ERROR_RETURN(s =) zcommon_parse(&G.prs); if (DEBUG_LIB && s) RETURN_STATUS(s); } s = zbc_program_exec(); -- cgit v1.2.3-55-g6feb From c2265f526ee638fa6f9cbb6e13be69e49e1a0f71 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 12 Dec 2018 23:10:08 +0100 Subject: bc: remove lexer function pointer function old new delta zbc_lex_next 81 1930 +1849 bc_parse_create 131 124 -7 common_parse_init 31 - -31 zdc_lex_token 672 - -672 zbc_lex_token 1193 - -1193 ------------------------------------------------------------------------------ (add/remove: 0/3 grow/shrink: 1/1 up/down: 1849/-1903) Total: -54 bytes text data bss dec hex filename 980634 485 7296 988415 f14ff busybox_old 980580 485 7296 988361 f14c9 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 54 ++++++++++++++++++++---------------------------------- 1 file changed, 20 insertions(+), 34 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 630a343d1..70ef0fa4a 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -549,9 +549,6 @@ enum { # define BC_STATUS void #endif -struct BcLex; -typedef BC_STATUS (*BcLexNext)(struct BcLex *) FAST_FUNC; - typedef struct BcLex { const char *buf; @@ -566,8 +563,6 @@ typedef struct BcLex { BcVec v; } t; - BcLexNext next; - } BcLex; #define BC_PARSE_STREND ((char) UCHAR_MAX) @@ -2911,9 +2906,8 @@ static void bc_lex_name(BcLex *l) //return BC_STATUS_SUCCESS; } -static void bc_lex_init(BcLex *l, BcLexNext next) +static void bc_lex_init(BcLex *l) { - l->next = next; bc_char_vec_init(&l->t.v); } @@ -2928,6 +2922,17 @@ static void bc_lex_file(BcLex *l) l->newline = false; } +static BC_STATUS zbc_lex_token(BcLex *l); +static BC_STATUS zdc_lex_token(BcLex *l); + +static BC_STATUS zcommon_lex_token(BcLex *l) +{ + if (IS_BC) { + IF_BC(RETURN_STATUS(zbc_lex_token(l));) + } + IF_DC(RETURN_STATUS(zdc_lex_token(l));) +} + static BC_STATUS zbc_lex_next(BcLex *l) { BcStatus s; @@ -2947,7 +2952,7 @@ static BC_STATUS zbc_lex_next(BcLex *l) s = BC_STATUS_SUCCESS; do { //TODO: replace pointer with if(IS_BC) - ERROR_RETURN(s =) l->next(l); + ERROR_RETURN(s =) zcommon_lex_token(l); } while (!s && l->t.t == BC_LEX_WHITESPACE); RETURN_STATUS(s); @@ -3091,7 +3096,7 @@ static BC_STATUS zbc_lex_comment(BcLex *l) # define zbc_lex_comment(...) (zbc_lex_comment(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static FAST_FUNC BC_STATUS zbc_lex_token(BcLex *l) +static BC_STATUS zbc_lex_token(BcLex *l) { BcStatus s = BC_STATUS_SUCCESS; char c = l->buf[l->i++], c2; @@ -3341,7 +3346,7 @@ static BC_STATUS zdc_lex_string(BcLex *l) # define zdc_lex_string(...) (zdc_lex_string(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static FAST_FUNC BC_STATUS zdc_lex_token(BcLex *l) +static BC_STATUS zdc_lex_token(BcLex *l) { BcStatus s = BC_STATUS_SUCCESS; char c = l->buf[l->i++], c2; @@ -3563,11 +3568,11 @@ static void bc_parse_free(BcParse *p) bc_lex_free(&p->l); } -static void bc_parse_create(BcParse *p, size_t func, BcLexNext next) +static void bc_parse_create(BcParse *p, size_t func) { memset(p, 0, sizeof(BcParse)); - bc_lex_init(&p->l, next); + bc_lex_init(&p->l); bc_vec_init(&p->flags, sizeof(uint8_t), NULL); bc_vec_init(&p->exits, sizeof(BcInstPtr), NULL); bc_vec_init(&p->conds, sizeof(size_t), NULL); @@ -4933,11 +4938,6 @@ static BC_STATUS zbc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) # define zbc_parse_expr(...) (zbc_parse_expr(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static void bc_parse_init(BcParse *p, size_t func) -{ - bc_parse_create(p, func, zbc_lex_token); -} - static BC_STATUS zbc_parse_expression(BcParse *p, uint8_t flags) { RETURN_STATUS(zbc_parse_expr(p, flags, bc_parse_next_read)); @@ -5159,22 +5159,8 @@ static BC_STATUS zdc_parse_parse(BcParse *p) # define zdc_parse_parse(...) (zdc_parse_parse(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static void dc_parse_init(BcParse *p, size_t func) -{ - bc_parse_create(p, func, zdc_lex_token); -} - #endif // ENABLE_DC -static void common_parse_init(BcParse *p, size_t func) -{ - if (IS_BC) { - IF_BC(bc_parse_init(p, func);) - } else { - IF_DC(dc_parse_init(p, func);) - } -} - static BC_STATUS zcommon_parse_expr(BcParse *p, uint8_t flags) { if (IS_BC) { @@ -5411,7 +5397,7 @@ static BC_STATUS zbc_program_read(void) bc_read_line(&buf); - common_parse_init(&parse, BC_PROG_READ); + bc_parse_create(&parse, BC_PROG_READ); bc_lex_file(&parse.l); s = zbc_parse_text(&parse, buf.v); @@ -6612,7 +6598,7 @@ static BC_STATUS zbc_program_execStr(char *code, size_t *bgn, f = bc_program_func(fidx); if (f->code.len == 0) { - common_parse_init(&prs, fidx); + bc_parse_create(&prs, fidx); s = zbc_parse_text(&prs, *str); if (s) goto err; s = zcommon_parse_expr(&prs, BC_PARSE_NOCALL); @@ -7480,7 +7466,7 @@ static int bc_vm_init(const char *env_len) if (IS_BC) IF_BC(bc_vm_envArgs();) bc_program_init(); - common_parse_init(&G.prs, BC_PROG_MAIN); + bc_parse_create(&G.prs, BC_PROG_MAIN); if (isatty(0)) { #if ENABLE_FEATURE_BC_SIGNALS -- cgit v1.2.3-55-g6feb From 9811ad02bdbd9dbec9f1e929808d305d4ebb0f14 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 12 Dec 2018 23:25:13 +0100 Subject: bc: unbreak CONFIG_FEATURE_BC_SIGNALS=y config Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 70ef0fa4a..c7e0e39e0 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -3038,7 +3038,7 @@ static BC_STATUS zbc_lex_string(BcLex *l) // This check makes sense only if size_t is (much) larger than BC_MAX_STRING. if (SIZE_MAX > (BC_MAX_STRING | 0xff)) { if (len > BC_MAX_STRING) - RETURN_STATUS(("string too long: must be [1,"BC_MAX_STRING_STR"]")); + RETURN_STATUS(bc_error("string too long: must be [1,"BC_MAX_STRING_STR"]")); } bc_vec_string(&l->t.v, len, l->buf + l->i); -- cgit v1.2.3-55-g6feb From 89e785af98acb71ae495c76e1f1cf4944431a3db Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 13 Dec 2018 16:35:52 +0100 Subject: bc: trim config help text, add a few comments, no code changes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 88 +++++++++++++++++++++++++--------------------------------- 1 file changed, 38 insertions(+), 50 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index c7e0e39e0..47acd7fc3 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -10,49 +10,34 @@ //config: bc is a command-line, arbitrary-precision calculator with a //config: Turing-complete language. See the GNU bc manual //config: (https://www.gnu.org/software/bc/manual/bc.html) and bc spec -//config: (http://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html) -//config: for details. +//config: (http://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html). //config: -//config: This bc has four differences to the GNU bc: -//config: -//config: 1) The period (.) can also be used as a shortcut for "last", as in -//config: the BSD bc. +//config: This bc has five differences to the GNU bc: +//config: 1) The period (.) is a shortcut for "last", as in the BSD bc. //config: 2) Arrays are copied before being passed as arguments to //config: functions. This behavior is required by the bc spec. //config: 3) Arrays can be passed to the builtin "length" function to get -//config: the number of elements currently in the array. The following -//config: example prints "1": -//config: -//config: a[0] = 0 -//config: length(a[]) -//config: +//config: the number of elements in the array. This prints "1": +//config: a[0] = 0; length(a[]) //config: 4) The precedence of the boolean "not" operator (!) is equal to -//config: that of the unary minus (-), or negation, operator. This still +//config: that of the unary minus (-) negation operator. This still //config: allows POSIX-compliant scripts to work while somewhat //config: preserving expected behavior (versus C) and making parsing //config: easier. +//config: 5) "read()" accepts expressions, not only numeric literals. //config: //config: Options: -//config: //config: -i --interactive force interactive mode +//config: -q --quiet don't print version and copyright +//config: -s --standard error if any non-POSIX extensions are used +//config: -w --warn warn if any non-POSIX extensions are used //config: -l --mathlib use predefined math routines: -//config: -//config: s(expr) = sine of expr in radians -//config: c(expr) = cosine of expr in radians -//config: a(expr) = arctangent of expr, returning -//config: radians -//config: l(expr) = natural log of expr -//config: e(expr) = raises e to the power of expr -//config: j(n, x) = Bessel function of integer order -//config: n of x -//config: -//config: -q --quiet don't print version and copyright. -//config: -s --standard error if any non-POSIX extensions are used. -//config: -w --warn warn if any non-POSIX extensions are used. -//config: -v --version print version and copyright and exit. -//config: -//config: Long options are only available if FEATURE_BC_LONG_OPTIONS is -//config: enabled. +//config: s(expr) sine in radians +//config: c(expr) cosine in radians +//config: a(expr) arctangent, returning radians +//config: l(expr) natural log +//config: e(expr) raises e to the power of expr +//config: j(n, x) Bessel function of integer order n of x //config: //config:config DC //config: bool "dc (38 kb; 49 kb when combined with bc)" @@ -61,33 +46,24 @@ //config: dc is a reverse-polish notation command-line calculator which //config: supports unlimited precision arithmetic. See the FreeBSD man page //config: (https://www.unix.com/man-page/FreeBSD/1/dc/) and GNU dc manual -//config: (https://www.gnu.org/software/bc/manual/dc-1.05/html_mono/dc.html) -//config: for details. +//config: (https://www.gnu.org/software/bc/manual/dc-1.05/html_mono/dc.html). //config: //config: This dc has a few differences from the two above: -//config: -//config: 1) When printing a byte stream (command "P"), this bc follows what +//config: 1) When printing a byte stream (command "P"), this dc follows what //config: the FreeBSD dc does. -//config: 2) This dc implements the GNU extensions for divmod ("~") and +//config: 2) Implements the GNU extensions for divmod ("~") and //config: modular exponentiation ("|"). -//config: 3) This dc implements all FreeBSD extensions, except for "J" and -//config: "M". +//config: 3) Implements all FreeBSD extensions, except for "J" and "M". //config: 4) Like the FreeBSD dc, this dc supports extended registers. //config: However, they are implemented differently. When it encounters //config: whitespace where a register should be, it skips the whitespace. //config: If the character following is not a lowercase letter, an error //config: is issued. Otherwise, the register name is parsed by the //config: following regex: -//config: -//config: [a-z][a-z0-9_]* -//config: +//config: [a-z][a-z0-9_]* //config: This generally means that register names will be surrounded by -//config: whitespace. -//config: -//config: Examples: -//config: -//config: l idx s temp L index S temp2 < do_thing -//config: +//config: whitespace. Examples: +//config: l idx s temp L index S temp2 < do_thing //config: Also note that, like the FreeBSD dc, extended registers are not //config: allowed unless the "-x" option is given. //config: @@ -105,11 +81,19 @@ //config: NOTE: This will require libm to be present for linking. //config: //config:config FEATURE_BC_SIGNALS -//config: bool "Enable bc/dc signal handling" +//config: bool "Interactive mode (+4kb)" //config: default y //config: depends on (BC || DC) && !FEATURE_DC_SMALL //config: help -//config: Enable signal handling for bc and dc. +//config: Enable interactive mode: when started on a tty, +//config: ^C interrupts execution and returns to command line, +//config: errors also return to command line instead of exiting, +//config: line editing with history is available. +//config: +//config: With this option off, input can still be taken from tty, +//config: but all errors are fatal, ^C is fatal, +//config: tty is treated exactly the same as any other +//config: standard input (IOW: no line editing). //config: //config:config FEATURE_BC_LONG_OPTIONS //config: bool "Enable bc/dc long options" @@ -7468,6 +7452,8 @@ static int bc_vm_init(const char *env_len) bc_program_init(); bc_parse_create(&G.prs, BC_PROG_MAIN); +//TODO: in GNU bc, the check is (isatty(0) && isatty(1)), +//-i option unconditionally enables this regardless of isatty(): if (isatty(0)) { #if ENABLE_FEATURE_BC_SIGNALS G_ttyin = 1; @@ -7476,10 +7462,12 @@ static int bc_vm_init(const char *env_len) // In particular, this means ^C won't cause // stdout to get into "error state" if SIGINT hits // within write() syscall. - // The downside is that ^C while line input is taken + // + // The downside is that ^C while tty input is taken // will only be handled after [Enter] since read() // from stdin is not interrupted by ^C either, // it restarts, thus fgetc() does not return on ^C. + // (This problem manifests only if line editing is disabled) signal_SA_RESTART_empty_mask(SIGINT, record_signo); // Without SA_RESTART, this exhibits a bug: -- cgit v1.2.3-55-g6feb From 40534bb6e2910a931ae77f0275b048f62896e2a7 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 13 Dec 2018 16:59:24 +0100 Subject: bc: shrink zbc_vm_stdin() function old new delta bc_vm_run 592 534 -58 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 47acd7fc3..7ab320a4d 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -758,6 +758,7 @@ struct globals { # define G_exiting 0 #endif #define IS_BC (ENABLE_BC && (!ENABLE_DC || applet_name[0] == 'b')) +#define IS_DC (ENABLE_DC && (!ENABLE_BC || applet_name[0] != 'b')) #if ENABLE_BC @@ -7070,27 +7071,28 @@ static BC_STATUS zbc_vm_stdin(void) str -= 1; else if (buf.v[0] == G.sbgn) str += 1; - } - else if (len > 1 || comment) { + } else { size_t i; for (i = 0; i < len; ++i) { - bool notend = len > i + 1; char c = string[i]; if (i - 1 > len || string[i - 1] != '\\') { - if (G.sbgn == G.send) - str ^= c == G.sbgn; - else if (c == G.send) - str -= 1; - else if (c == G.sbgn) - str += 1; + // checking applet type is cheaper than accessing sbgn/send + if (IS_DC) // dc: sbgn = send = '"' + str ^= (c == '"'); + else { // bc: sbgn = '[', send = ']' + if (c == ']') + str -= 1; + else if (c == '[') + str += 1; + } } - if (c == '/' && notend && !comment && string[i + 1] == '*') { + if (c == '/' && !comment && string[i + 1] == '*') { comment = true; break; } - else if (c == '*' && notend && comment && string[i + 1] == '/') + else if (c == '*' && comment && string[i + 1] == '/') comment = false; } -- cgit v1.2.3-55-g6feb From 7dc0a51286b7898fcc17033dce1f1856e78494b4 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 13 Dec 2018 17:36:41 +0100 Subject: bc: further zbc_vm_stdin() optimizations function old new delta bc_vm_run 534 514 -20 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 7ab320a4d..9c7e69fc1 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -7072,11 +7072,9 @@ static BC_STATUS zbc_vm_stdin(void) else if (buf.v[0] == G.sbgn) str += 1; } else { - size_t i; - for (i = 0; i < len; ++i) { - char c = string[i]; - - if (i - 1 > len || string[i - 1] != '\\') { + while (*string) { + char c = *string; + if (string != buf.v && string[-1] != '\\') { // checking applet type is cheaper than accessing sbgn/send if (IS_DC) // dc: sbgn = send = '"' str ^= (c == '"'); @@ -7087,16 +7085,15 @@ static BC_STATUS zbc_vm_stdin(void) str += 1; } } - - if (c == '/' && !comment && string[i + 1] == '*') { + string++; + if (c == '/' && *string == '*') { comment = true; break; } - else if (c == '*' && comment && string[i + 1] == '/') + if (c == '*' && *string == '/') comment = false; } - - if (str || comment || string[len - 2] == '\\') { + if (str || comment || string[-2] == '\\') { bc_vec_concat(&buffer, buf.v); continue; } -- cgit v1.2.3-55-g6feb From 766f67250f01dc5458093c31ec0d2ec09cad65a2 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 13 Dec 2018 17:23:24 +0100 Subject: bc: fix comment handling function old new delta bc_vm_run 514 513 -1 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 7 +++++-- testsuite/bc.tests | 12 ++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 9c7e69fc1..dc9a7da8e 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -7088,10 +7088,13 @@ static BC_STATUS zbc_vm_stdin(void) string++; if (c == '/' && *string == '*') { comment = true; - break; + string++; + continue; } - if (c == '*' && *string == '/') + if (c == '*' && *string == '/') { comment = false; + string++; + } } if (str || comment || string[-2] == '\\') { bc_vec_concat(&buffer, buf.v); diff --git a/testsuite/bc.tests b/testsuite/bc.tests index 32460092b..4f0d50f73 100755 --- a/testsuite/bc.tests +++ b/testsuite/bc.tests @@ -4,6 +4,18 @@ . ./testing.sh +# testing "test name" "command" "expected result" "file input" "stdin" + +testing "bc comment 1" \ + "bc" \ + "3\n" \ + "" "1 /* comment */ + 2" + +testing "bc comment 2: /*/ is not a closed comment" \ + "bc" \ + "4\n" \ + "" "1 /*/ + 2 */ + 3" + tar xJf bc_large.tar.xz for f in bc*.bc; do -- cgit v1.2.3-55-g6feb From 335b4efd2f5627b52290e0a6320bab4e6b3aa568 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 13 Dec 2018 17:46:26 +0100 Subject: bc: fix a thinko: dc uses [] string delimiters, bot bc! Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index dc9a7da8e..a78cd591a 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -7076,9 +7076,9 @@ static BC_STATUS zbc_vm_stdin(void) char c = *string; if (string != buf.v && string[-1] != '\\') { // checking applet type is cheaper than accessing sbgn/send - if (IS_DC) // dc: sbgn = send = '"' + if (IS_BC) // bc: sbgn = send = '"' str ^= (c == '"'); - else { // bc: sbgn = '[', send = ']' + else { // dc: sbgn = '[', send = ']' if (c == ']') str -= 1; else if (c == '[') -- cgit v1.2.3-55-g6feb From 818b602c8859cd935083e183eb772becc26acfb3 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 13 Dec 2018 17:56:35 +0100 Subject: bc: fix another thinko Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 5 ++--- testsuite/bc.tests | 10 ++++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index a78cd591a..74847a328 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -7059,22 +7059,21 @@ static BC_STATUS zbc_vm_stdin(void) str = 0; for (;;) { size_t len; - char *string; bc_read_line(&buf); len = buf.len - 1; if (len == 0) // "" buf means EOF break; - string = buf.v; if (len == 1) { if (str && buf.v[0] == G.send) str -= 1; else if (buf.v[0] == G.sbgn) str += 1; } else { + char *string = buf.v; while (*string) { char c = *string; - if (string != buf.v && string[-1] != '\\') { + if (string == buf.v || string[-1] != '\\') { // checking applet type is cheaper than accessing sbgn/send if (IS_BC) // bc: sbgn = send = '"' str ^= (c == '"'); diff --git a/testsuite/bc.tests b/testsuite/bc.tests index 4f0d50f73..5e8c47c0f 100755 --- a/testsuite/bc.tests +++ b/testsuite/bc.tests @@ -16,6 +16,16 @@ testing "bc comment 2: /*/ is not a closed comment" \ "4\n" \ "" "1 /*/ + 2 */ + 3" +testing "bc backslash 1" \ + "bc" \ + "3\n" \ + "" "1 \\\\\n + 2" + +testing "bc string 1" \ + "bc" \ + "STR\n" \ + "" "\"STR\n\"" + tar xJf bc_large.tar.xz for f in bc*.bc; do -- cgit v1.2.3-55-g6feb From b7e61e3e4adc774d18b6377cdd6434dd7ce0c2be Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 13 Dec 2018 18:16:39 +0100 Subject: bc: further simplification in zbc_vm_stdin() function old new delta bc_vm_run 500 523 +23 bc_vec_concat 66 - -66 ------------------------------------------------------------------------------ (add/remove: 0/1 grow/shrink: 1/0 up/down: 23/-66) Total: -43 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 69 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 34 insertions(+), 35 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 74847a328..bc2947161 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -7058,50 +7058,49 @@ static BC_STATUS zbc_vm_stdin(void) comment = false; str = 0; for (;;) { - size_t len; + char *string; bc_read_line(&buf); - len = buf.len - 1; - if (len == 0) // "" buf means EOF + if (buf.len <= 1) // "" buf means EOF break; - if (len == 1) { - if (str && buf.v[0] == G.send) - str -= 1; - else if (buf.v[0] == G.sbgn) - str += 1; - } else { - char *string = buf.v; - while (*string) { - char c = *string; - if (string == buf.v || string[-1] != '\\') { - // checking applet type is cheaper than accessing sbgn/send - if (IS_BC) // bc: sbgn = send = '"' - str ^= (c == '"'); - else { // dc: sbgn = '[', send = ']' - if (c == ']') - str -= 1; - else if (c == '[') - str += 1; - } - } - string++; - if (c == '/' && *string == '*') { - comment = true; - string++; - continue; - } - if (c == '*' && *string == '/') { - comment = false; - string++; + + string = buf.v; + while (*string) { + char c = *string; + if (string == buf.v || string[-1] != '\\') { + // checking applet type is cheaper than accessing sbgn/send + if (IS_BC) // bc: sbgn = send = '"' + str ^= (c == '"'); + else { // dc: sbgn = '[', send = ']' + if (c == ']') + str -= 1; + else if (c == '[') + str += 1; } } - if (str || comment || string[-2] == '\\') { - bc_vec_concat(&buffer, buf.v); + string++; + if (c == '/' && *string == '*') { + comment = true; + string++; continue; } + if (c == '*' && *string == '/') { + comment = false; + string++; + } } - bc_vec_concat(&buffer, buf.v); + if (str || comment) + continue; + + // Check for backslash+newline. + // we do not check that last char is '\n' - + // if it is not, then it's EOF, and looping back + // to bc_read_line() will detect it: + string -= 2; + if (string >= buf.v && *string == '\\') + continue; + s = zbc_vm_process(buffer.v); if (s) { if (ENABLE_FEATURE_CLEAN_UP && !G_ttyin) { -- cgit v1.2.3-55-g6feb From 82ea67fbfa98cfd6b8b422db764cb8c97fc3ea7b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 13 Dec 2018 19:23:45 +0100 Subject: bc: change bc_read_line() and zbc_vm_stdin() to avoid double buffers function old new delta bc_read_line 129 124 -5 bc_vm_run 523 433 -90 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-95) Total: -95 bytes text data bss dec hex filename 980445 485 7296 988226 f1442 busybox_old 980350 485 7296 988131 f13e3 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 61 ++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index bc2947161..7c4dfbb20 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1226,6 +1226,7 @@ static void bc_vec_string(BcVec *v, size_t len, const char *str) bc_vec_pushZeroByte(v); } +#if ENABLE_FEATURE_BC_SIGNALS && ENABLE_FEATURE_EDITING static void bc_vec_concat(BcVec *v, const char *str) { size_t len, slen; @@ -1240,6 +1241,7 @@ static void bc_vec_concat(BcVec *v, const char *str) v->len = len; } +#endif static void *bc_vec_item(const BcVec *v, size_t idx) { @@ -1326,29 +1328,21 @@ static size_t bc_map_index(const BcVec *v, const void *ptr) } #endif -static int push_input_byte(BcVec *vec, char c) +static int bad_input_byte(char c) { if ((c < ' ' && c != '\t' && c != '\r' && c != '\n') // also allow '\v' '\f'? || c > 0x7e ) { - // Bad chars on this line, ignore entire line bc_error_fmt("illegal character 0x%02x", c); return 1; } - bc_vec_pushByte(vec, (char)c); return 0; } +// Note: it _appends_ data from the stdin to vec. static void bc_read_line(BcVec *vec) { - bool bad_chars; - - do { - int c; - - bad_chars = 0; - bc_vec_pop_all(vec); - + again: fflush_and_check(); #if ENABLE_FEATURE_BC_SIGNALS @@ -1359,6 +1353,7 @@ static void bc_read_line(BcVec *vec) // GNU dc says "Interrupt!" fputs("\ninterrupted execution\n", stderr); } + # if ENABLE_FEATURE_EDITING if (G_ttyin) { int n, i; @@ -1371,15 +1366,20 @@ static void bc_read_line(BcVec *vec) } i = 0; for (;;) { - c = line_buf[i++]; + char c = line_buf[i++]; if (!c) break; - bad_chars |= push_input_byte(vec, c); + if (bad_input_byte(c)) goto again; } + bc_vec_concat(vec, line_buf); # undef line_buf } else # endif #endif { + int c; + bool bad_chars = 0; + size_t len = vec->len; + IF_FEATURE_BC_SIGNALS(errno = 0;) do { c = fgetc(stdin); @@ -1399,10 +1399,15 @@ static void bc_read_line(BcVec *vec) // printf 'print 123' | bc - fails (syntax error) break; } - bad_chars |= push_input_byte(vec, c); + bad_chars |= bad_input_byte(c); + bc_vec_pushByte(vec, (char)c); } while (c != '\n'); + if (bad_chars) { + // Bad chars on this line, ignore entire line + vec->len = len; + goto again; + } } - } while (bad_chars); bc_vec_pushZeroByte(vec); } @@ -5374,12 +5379,12 @@ static BC_STATUS zbc_program_read(void) f = bc_program_func(BC_PROG_READ); bc_vec_pop_all(&f->code); - bc_char_vec_init(&buf); sv_file = G.prog.file; G.prog.file = NULL; G.in_read = 1; + bc_char_vec_init(&buf); bc_read_line(&buf); bc_parse_create(&parse, BC_PROG_READ); @@ -7039,7 +7044,7 @@ err: static BC_STATUS zbc_vm_stdin(void) { BcStatus s; - BcVec buf, buffer; + BcVec buffer; size_t str; bool comment; @@ -7047,8 +7052,6 @@ static BC_STATUS zbc_vm_stdin(void) bc_lex_file(&G.prs.l); bc_char_vec_init(&buffer); - bc_char_vec_init(&buf); - bc_vec_pushZeroByte(&buffer); // This loop is complex because the vm tries not to send any lines that end // with a backslash to the parser. The reason for that is because the parser @@ -7058,16 +7061,18 @@ static BC_STATUS zbc_vm_stdin(void) comment = false; str = 0; for (;;) { + size_t prevlen = buffer.len; char *string; - bc_read_line(&buf); - if (buf.len <= 1) // "" buf means EOF + bc_read_line(&buffer); + // No more input means EOF + if (buffer.len <= prevlen + 1) // (we expect +1 for NUL byte) break; - string = buf.v; + string = buffer.v + prevlen; while (*string) { char c = *string; - if (string == buf.v || string[-1] != '\\') { + if (string == buffer.v || string[-1] != '\\') { // checking applet type is cheaper than accessing sbgn/send if (IS_BC) // bc: sbgn = send = '"' str ^= (c == '"'); @@ -7089,17 +7094,20 @@ static BC_STATUS zbc_vm_stdin(void) string++; } } - bc_vec_concat(&buffer, buf.v); - if (str || comment) + if (str || comment) { + buffer.len--; // backstep over the trailing NUL byte continue; + } // Check for backslash+newline. // we do not check that last char is '\n' - // if it is not, then it's EOF, and looping back // to bc_read_line() will detect it: string -= 2; - if (string >= buf.v && *string == '\\') + if (string >= buffer.v && *string == '\\') { + buffer.len--; continue; + } s = zbc_vm_process(buffer.v); if (s) { @@ -7121,7 +7129,6 @@ static BC_STATUS zbc_vm_stdin(void) s = bc_error("comment end could not be found"); } - bc_vec_free(&buf); bc_vec_free(&buffer); RETURN_STATUS(s); } -- cgit v1.2.3-55-g6feb From 915c72b27301c933a8efbf4036293ddc1ea35b7d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 13 Dec 2018 19:28:41 +0100 Subject: bc: do not append duplicate NUL, reduce indentation in bc_read_line() Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 105 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 52 insertions(+), 53 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 7c4dfbb20..57c9ca565 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1343,73 +1343,72 @@ static int bad_input_byte(char c) static void bc_read_line(BcVec *vec) { again: - fflush_and_check(); + fflush_and_check(); #if ENABLE_FEATURE_BC_SIGNALS - if (G_interrupt) { // ^C was pressed + if (G_interrupt) { // ^C was pressed intr: - G_interrupt = 0; - // GNU bc says "interrupted execution." - // GNU dc says "Interrupt!" - fputs("\ninterrupted execution\n", stderr); - } + G_interrupt = 0; + // GNU bc says "interrupted execution." + // GNU dc says "Interrupt!" + fputs("\ninterrupted execution\n", stderr); + } # if ENABLE_FEATURE_EDITING - if (G_ttyin) { - int n, i; + if (G_ttyin) { + int n, i; # define line_buf bb_common_bufsiz1 - n = read_line_input(G.line_input_state, "", line_buf, COMMON_BUFSIZE); - if (n <= 0) { // read errors or EOF, or ^D, or ^C - if (n == 0) // ^C - goto intr; - break; - } - i = 0; - for (;;) { - char c = line_buf[i++]; - if (!c) break; - if (bad_input_byte(c)) goto again; - } - bc_vec_concat(vec, line_buf); + n = read_line_input(G.line_input_state, "", line_buf, COMMON_BUFSIZE); + if (n <= 0) { // read errors or EOF, or ^D, or ^C + if (n == 0) // ^C + goto intr; + break; + } + i = 0; + for (;;) { + char c = line_buf[i++]; + if (!c) break; + if (bad_input_byte(c)) goto again; + } + bc_vec_concat(vec, line_buf); # undef line_buf - } else + } else # endif #endif - { - int c; - bool bad_chars = 0; - size_t len = vec->len; + { + int c; + bool bad_chars = 0; + size_t len = vec->len; - IF_FEATURE_BC_SIGNALS(errno = 0;) - do { - c = fgetc(stdin); + IF_FEATURE_BC_SIGNALS(errno = 0;) + do { + c = fgetc(stdin); #if ENABLE_FEATURE_BC_SIGNALS && !ENABLE_FEATURE_EDITING - // Both conditions appear simultaneously, check both just in case - if (errno == EINTR || G_interrupt) { - // ^C was pressed - clearerr(stdin); - goto intr; - } + // Both conditions appear simultaneously, check both just in case + if (errno == EINTR || G_interrupt) { + // ^C was pressed + clearerr(stdin); + goto intr; + } #endif - if (c == EOF) { - if (ferror(stdin)) - quit(); // this emits error message - // Note: EOF does not append '\n', therefore: - // printf 'print 123\n' | bc - works - // printf 'print 123' | bc - fails (syntax error) - break; - } - bad_chars |= bad_input_byte(c); - bc_vec_pushByte(vec, (char)c); - } while (c != '\n'); - if (bad_chars) { - // Bad chars on this line, ignore entire line - vec->len = len; - goto again; + if (c == EOF) { + if (ferror(stdin)) + quit(); // this emits error message + // Note: EOF does not append '\n', therefore: + // printf 'print 123\n' | bc - works + // printf 'print 123' | bc - fails (syntax error) + break; } + bad_chars |= bad_input_byte(c); + bc_vec_pushByte(vec, (char)c); + } while (c != '\n'); + if (bad_chars) { + // Bad chars on this line, ignore entire line + vec->len = len; + goto again; } - - bc_vec_pushZeroByte(vec); + bc_vec_pushZeroByte(vec); + } } static char* bc_read_file(const char *path) -- cgit v1.2.3-55-g6feb From 0fe270e77536c8248bbf1c6045229d7ec3aaf8d3 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 13 Dec 2018 19:58:58 +0100 Subject: bc: simplify filename saving in zbc_vm_file() function old new delta bc_vm_run 433 423 -10 zbc_vm_file 187 174 -13 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-23) Total: -23 bytes text data bss dec hex filename 980350 485 7296 988131 f13e3 busybox_old 980327 485 7296 988108 f13cc busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 57c9ca565..5930caa32 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -7010,7 +7010,9 @@ static BC_STATUS zbc_vm_process(const char *text) static BC_STATUS zbc_vm_file(const char *file) { - const char *sv_file; + // So far bc/dc have no way to include a file from another file, + // therefore we know G.prog.file == NULL on entry + //const char *sv_file; char *data; BcStatus s; BcFunc *main_func; @@ -7019,7 +7021,7 @@ static BC_STATUS zbc_vm_file(const char *file) data = bc_read_file(file); if (!data) RETURN_STATUS(bc_error_fmt("file '%s' is not text", file)); - sv_file = G.prog.file; + //sv_file = G.prog.file; G.prog.file = file; bc_lex_file(&G.prs.l); s = zbc_vm_process(data); @@ -7032,7 +7034,8 @@ static BC_STATUS zbc_vm_file(const char *file) s = bc_error_fmt("file '%s' is not executable", file); err: - G.prog.file = sv_file; + //G.prog.file = sv_file; + G.prog.file = NULL; free(data); RETURN_STATUS(s); } @@ -7047,7 +7050,7 @@ static BC_STATUS zbc_vm_stdin(void) size_t str; bool comment; - G.prog.file = NULL; + //G.prog.file = NULL; - already is bc_lex_file(&G.prs.l); bc_char_vec_init(&buffer); -- cgit v1.2.3-55-g6feb From bbcecc4118416390571170868447fd2773a741bd Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 13 Dec 2018 21:17:43 +0100 Subject: bc: G.sbgn and G.send are unused, remove them function old new delta bc_program_index 66 64 -2 bc_parse_expr_empty_ok 1840 1838 -2 dc_main 176 168 -8 bc_main 73 65 -8 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/4 up/down: 0/-20) Total: -20 bytes text data bss dec hex filename 980327 485 7296 988108 f13cc busybox_old 980307 485 7296 988088 f13b8 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 5930caa32..a271a2040 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -717,8 +717,6 @@ struct globals { IF_FEATURE_BC_SIGNALS(smallint ttyin;) IF_FEATURE_CLEAN_UP(smallint exiting;) smallint in_read; - char sbgn; - char send; BcParse prs; BcProgram prog; @@ -7075,10 +7073,9 @@ static BC_STATUS zbc_vm_stdin(void) while (*string) { char c = *string; if (string == buffer.v || string[-1] != '\\') { - // checking applet type is cheaper than accessing sbgn/send - if (IS_BC) // bc: sbgn = send = '"' + if (IS_BC) str ^= (c == '"'); - else { // dc: sbgn = '[', send = ']' + else { if (c == ']') str -= 1; else if (c == '[') @@ -7513,7 +7510,6 @@ int bc_main(int argc UNUSED_PARAM, char **argv) int is_tty; INIT_G(); - G.sbgn = G.send = '"'; is_tty = bc_vm_init("BC_LINE_LENGTH"); @@ -7533,8 +7529,6 @@ int dc_main(int argc UNUSED_PARAM, char **argv) int noscript; INIT_G(); - G.sbgn = '['; - G.send = ']'; /* * TODO: dc (GNU bc 1.07.1) 1.4.1 seems to use width * 1 char wider than bc from the same package. -- cgit v1.2.3-55-g6feb From 89198a9e5d4e599a25a839c4d193f834bcd8c617 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 13 Dec 2018 21:31:29 +0100 Subject: bc: simplify bc_lex_whitespace() function old new delta bc_lex_whitespace 52 41 -11 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index a271a2040..5938e54ab 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -2790,9 +2790,13 @@ static void bc_lex_lineComment(BcLex *l) static void bc_lex_whitespace(BcLex *l) { - char c; l->t.t = BC_LEX_WHITESPACE; - for (c = l->buf[l->i]; c != '\n' && isspace(c); c = l->buf[++l->i]); + for (;;) { + char c = l->buf[l->i]; + if (c == '\n' || !isspace(c)) + break; + l->i++; + } } static BC_STATUS zbc_lex_number(BcLex *l, char start) -- cgit v1.2.3-55-g6feb From e755e30402e1e8071563e03f442998cac162f295 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 13 Dec 2018 22:25:28 +0100 Subject: bc: unbreak "only bc" and "only dc" configs Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 5938e54ab..1f0802a4d 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1360,7 +1360,8 @@ static void bc_read_line(BcVec *vec) if (n <= 0) { // read errors or EOF, or ^D, or ^C if (n == 0) // ^C goto intr; - break; + bc_vec_pushZeroByte(vec); + return; } i = 0; for (;;) { @@ -2913,8 +2914,8 @@ static void bc_lex_file(BcLex *l) l->newline = false; } -static BC_STATUS zbc_lex_token(BcLex *l); -static BC_STATUS zdc_lex_token(BcLex *l); +IF_BC(static BC_STATUS zbc_lex_token(BcLex *l);) +IF_DC(static BC_STATUS zdc_lex_token(BcLex *l);) static BC_STATUS zcommon_lex_token(BcLex *l) { @@ -3475,8 +3476,8 @@ static void bc_parse_number(BcParse *p, BcInst *prev, size_t *nexs) (*prev) = BC_INST_NUM; } -static BC_STATUS zbc_parse_parse(BcParse *p); -static BC_STATUS zdc_parse_parse(BcParse *p); +IF_BC(static BC_STATUS zbc_parse_parse(BcParse *p);) +IF_DC(static BC_STATUS zdc_parse_parse(BcParse *p);) static BC_STATUS zcommon_parse(BcParse *p) { -- cgit v1.2.3-55-g6feb From 5f263f406c99ebdf7d9c850c72f67ea0da095662 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 13 Dec 2018 22:49:59 +0100 Subject: bc: fix "dc only" bug Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 1f0802a4d..606037abc 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -7458,8 +7458,7 @@ static int bc_vm_init(const char *env_len) G.prog.len = bc_vm_envLen(env_len); bc_vec_init(&G.files, sizeof(char *), NULL); - if (IS_BC) - IF_BC(bc_vm_envArgs();) + IF_BC(if (IS_BC) bc_vm_envArgs();) bc_program_init(); bc_parse_create(&G.prs, BC_PROG_MAIN); -- cgit v1.2.3-55-g6feb From 57b6918b0a12e52207709070d0712910cb4323b9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 14 Dec 2018 00:12:13 +0100 Subject: bc: group ENABLE_BC code a bit better, no logic changes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 144 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 71 insertions(+), 73 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 606037abc..a572ad30a 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -6899,78 +6899,6 @@ static BC_STATUS zbc_program_exec(void) # define zbc_program_exec(...) (zbc_program_exec(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -#if ENABLE_BC -static void bc_vm_info(void) -{ - printf("%s "BB_VER"\n" - "Copyright (c) 2018 Gavin D. Howard and contributors\n" - , applet_name); -} - -static void bc_args(char **argv) -{ - unsigned opts; - int i; - - GETOPT_RESET(); -#if ENABLE_FEATURE_BC_LONG_OPTIONS - opts = option_mask32 |= getopt32long(argv, "wvsqli", - "warn\0" No_argument "w" - "version\0" No_argument "v" - "standard\0" No_argument "s" - "quiet\0" No_argument "q" - "mathlib\0" No_argument "l" - "interactive\0" No_argument "i" - ); -#else - opts = option_mask32 |= getopt32(argv, "wvsqli"); -#endif - if (getenv("POSIXLY_CORRECT")) - option_mask32 |= BC_FLAG_S; - - if (opts & BC_FLAG_V) { - bc_vm_info(); - exit(0); - } - - for (i = optind; argv[i]; ++i) - bc_vec_push(&G.files, argv + i); -} - -static void bc_vm_envArgs(void) -{ - BcVec v; - char *buf; - char *env_args = getenv("BC_ENV_ARGS"); - - if (!env_args) return; - - G.env_args = xstrdup(env_args); - buf = G.env_args; - - bc_vec_init(&v, sizeof(char *), NULL); - - while (*(buf = skip_whitespace(buf)) != '\0') { - bc_vec_push(&v, &buf); - buf = skip_non_whitespace(buf); - if (!*buf) - break; - *buf++ = '\0'; - } - - // NULL terminate, and pass argv[] so that first arg is argv[1] - if (sizeof(int) == sizeof(char*)) { - bc_vec_push(&v, &const_int_0); - } else { - static char *const nullptr = NULL; - bc_vec_push(&v, &nullptr); - } - bc_args(((char **)v.v) - 1); - - bc_vec_free(&v); -} -#endif // ENABLE_BC - static unsigned bc_vm_envLen(const char *var) { char *lenv; @@ -7141,7 +7069,77 @@ static BC_STATUS zbc_vm_stdin(void) #endif #if ENABLE_BC -static const char bc_lib[] = { +static void bc_vm_info(void) +{ + printf("%s "BB_VER"\n" + "Copyright (c) 2018 Gavin D. Howard and contributors\n" + , applet_name); +} + +static void bc_args(char **argv) +{ + unsigned opts; + int i; + + GETOPT_RESET(); +#if ENABLE_FEATURE_BC_LONG_OPTIONS + opts = option_mask32 |= getopt32long(argv, "wvsqli", + "warn\0" No_argument "w" + "version\0" No_argument "v" + "standard\0" No_argument "s" + "quiet\0" No_argument "q" + "mathlib\0" No_argument "l" + "interactive\0" No_argument "i" + ); +#else + opts = option_mask32 |= getopt32(argv, "wvsqli"); +#endif + if (getenv("POSIXLY_CORRECT")) + option_mask32 |= BC_FLAG_S; + + if (opts & BC_FLAG_V) { + bc_vm_info(); + exit(0); + } + + for (i = optind; argv[i]; ++i) + bc_vec_push(&G.files, argv + i); +} + +static void bc_vm_envArgs(void) +{ + BcVec v; + char *buf; + char *env_args = getenv("BC_ENV_ARGS"); + + if (!env_args) return; + + G.env_args = xstrdup(env_args); + buf = G.env_args; + + bc_vec_init(&v, sizeof(char *), NULL); + + while (*(buf = skip_whitespace(buf)) != '\0') { + bc_vec_push(&v, &buf); + buf = skip_non_whitespace(buf); + if (!*buf) + break; + *buf++ = '\0'; + } + + // NULL terminate, and pass argv[] so that first arg is argv[1] + if (sizeof(int) == sizeof(char*)) { + bc_vec_push(&v, &const_int_0); + } else { + static char *const nullptr = NULL; + bc_vec_push(&v, &nullptr); + } + bc_args(((char **)v.v) - 1); + + bc_vec_free(&v); +} + +static const char bc_lib[] ALIGN1 = { "scale=20" "\n" "define e(x){" "\n" "auto b,s,n,r,d,i,p,f,v" -- cgit v1.2.3-55-g6feb From 3ac0c21a1fe902c7bebadc0fc454ee047e13c58f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 14 Dec 2018 01:01:01 +0100 Subject: bc: shrink internal library function old new delta bc_lib 1674 1618 -56 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index a572ad30a..0a2da6cf8 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -7161,16 +7161,16 @@ static const char bc_lib[] ALIGN1 = { "\n" "r=x+1" "\n" "p=x" "\n" "f=v=1" -"\n" "for(i=2;v!=0;++i){" +"\n" "for(i=2;v;++i){" "\n" "p*=x" "\n" "f*=i" "\n" "v=p/f" "\n" "r+=v" "\n" "}" -"\n" "while((d--)!=0)r*=r" +"\n" "while(d--)r*=r" "\n" "scale=s" "\n" "ibase=b" -"\n" "if(n!=0)return(1/r)" +"\n" "if(n)return(1/r)" "\n" "return(r/1)" "\n" "}" "\n" "define l(x){" @@ -7195,8 +7195,8 @@ static const char bc_lib[] ALIGN1 = { "\n" "}" "\n" "r=a=(x-1)/(x+1)" "\n" "q=a*a" -"\n" "v=1" -"\n" "for(i=3;v!=0;i+=2){" +"\n" "v=1" +"\n" "for(i=3;v;i+=2){" "\n" "a*=q" "\n" "v=a/i" "\n" "r+=v" @@ -7220,17 +7220,17 @@ static const char bc_lib[] ALIGN1 = { "\n" "scale=0" "\n" "q=(x/a+2)/4" "\n" "x=x-4*q*a" -"\n" "if(q%2!=0)x=-x" +"\n" "if(q%2)x=-x" "\n" "scale=s+2" "\n" "r=a=x" "\n" "q=-x*x" -"\n" "for(i=3;a!=0;i+=2){" +"\n" "for(i=3;a;i+=2){" "\n" "a*=q/(i*(i-1))" "\n" "r+=a" "\n" "}" "\n" "scale=s" "\n" "ibase=b" -"\n" "if(n!=0)return(-r/1)" +"\n" "if(n)return(-r/1)" "\n" "return(r/1)" "\n" "}" "\n" "define c(x){" @@ -7253,15 +7253,9 @@ static const char bc_lib[] ALIGN1 = { "\n" "n=-1" "\n" "x=-x" "\n" "}" -"\n" "if(x==1){" -"\n" "if(scale<65){" -"\n" "return(.7853981633974483096156608458198757210492923498437764552437361480/n)" -"\n" "}" -"\n" "}" -"\n" "if(x==.2){" -"\n" "if(scale<65){" -"\n" "return(.1973955598498807583700497651947902934475851037878521015176889402/n)" -"\n" "}" +"\n" "if(scale<65){" +"\n" "if(x==1)return(.7853981633974483096156608458198757210492923498437764552437361480/n)" +"\n" "if(x==.2)return(.1973955598498807583700497651947902934475851037878521015176889402/n)" "\n" "}" "\n" "s=scale" "\n" "if(x>.2){" @@ -7276,7 +7270,7 @@ static const char bc_lib[] ALIGN1 = { "\n" "r=u=x" "\n" "f=-x*x" "\n" "t=1" -"\n" "for(i=3;t!=0;i+=2){" +"\n" "for(i=3;t;i+=2){" "\n" "u*=f" "\n" "t=u/i" "\n" "r+=t" @@ -7303,13 +7297,13 @@ static const char bc_lib[] ALIGN1 = { "\n" "r=v=1" "\n" "f=-x*x/4" "\n" "scale=scale+length(a)-scale(a)" -"\n" "for(i=1;v!=0;++i){" +"\n" "for(i=1;v;++i){" "\n" "v=v*f/i/(n+i)" "\n" "r+=v" "\n" "}" "\n" "scale=s" "\n" "ibase=b" -"\n" "if(o!=0)a=-a" +"\n" "if(o)a=-a" "\n" "return(a*r/1)" "\n" "}" }; -- cgit v1.2.3-55-g6feb From 203210e2535e7543e415b052e1d7182f3ca32959 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 14 Dec 2018 09:53:50 +0100 Subject: bc: shrink internal library more function old new delta bc_lib 1618 1609 -9 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 0a2da6cf8..8befc8e3f 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -7143,6 +7143,12 @@ static const char bc_lib[] ALIGN1 = { "scale=20" "\n" "define e(x){" "\n" "auto b,s,n,r,d,i,p,f,v" +////////////////"if(x<0)return(1/e(-x))" // and drop 'n' and x<0 logic below +//^^^^^^^^^^^^^^^^ this would work, and is even more precise than GNU bc: +//e(-.998896): GNU:.36828580434569428695 +// above code:.36828580434569428696 +// actual value:.3682858043456942869594... +// but for now let's be "GNU compatible" "\n" "b=ibase" "\n" "ibase=A" "\n" "if(x<0){" @@ -7219,7 +7225,7 @@ static const char bc_lib[] ALIGN1 = { "\n" "}" "\n" "scale=0" "\n" "q=(x/a+2)/4" -"\n" "x=x-4*q*a" +"\n" "x-=4*q*a" "\n" "if(q%2)x=-x" "\n" "scale=s+2" "\n" "r=a=x" @@ -7288,7 +7294,7 @@ static const char bc_lib[] ALIGN1 = { "\n" "n/=1" "\n" "if(n<0){" "\n" "n=-n" -"\n" "if(n%2==1)o=1" +"\n" "o=n%2" "\n" "}" "\n" "a=1" "\n" "for(i=2;i<=n;++i)a*=i" -- cgit v1.2.3-55-g6feb From c06537d9bbeb5d7ad0e310ce7f345699e3cfc90d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 14 Dec 2018 10:10:37 +0100 Subject: bc: shrink internal library yet more function old new delta bc_lib 1609 1604 -5 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-5) Total: -5 bytes text data bss dec hex filename 980165 485 7296 987946 f132a busybox_old 980160 485 7296 987941 f1325 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 8befc8e3f..dd2d7f22c 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -7302,7 +7302,7 @@ static const char bc_lib[] ALIGN1 = { "\n" "a=(x^n)/2^n/a" "\n" "r=v=1" "\n" "f=-x*x/4" -"\n" "scale=scale+length(a)-scale(a)" +"\n" "scale+=length(a)-scale(a)" "\n" "for(i=1;v;++i){" "\n" "v=v*f/i/(n+i)" "\n" "r+=v" -- cgit v1.2.3-55-g6feb From fc9d26902ba30340d1eef2153cc5823a53e72919 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 14 Dec 2018 11:00:23 +0100 Subject: bc: yet another library shrink function old new delta bc_lib 1604 1596 -8 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-8) Total: -8 bytes text data bss dec hex filename 980160 485 7296 987941 f1325 busybox_old 980152 485 7296 987933 f131d busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index dd2d7f22c..f0c323d93 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -7236,7 +7236,7 @@ static const char bc_lib[] ALIGN1 = { "\n" "}" "\n" "scale=s" "\n" "ibase=b" -"\n" "if(n)return(-r/1)" +"\n" "if(n)r=-r" "\n" "return(r/1)" "\n" "}" "\n" "define c(x){" -- cgit v1.2.3-55-g6feb From 240d7ee3fcff86b557cfac12cb74073e119957a1 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 14 Dec 2018 11:27:09 +0100 Subject: bc: shrink s() in library again function old new delta bc_lib 1596 1586 -10 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-10) Total: -10 bytes text data bss dec hex filename 980152 485 7296 987933 f131d busybox_old 980142 485 7296 987923 f1313 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index f0c323d93..547af8eaf 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -7213,16 +7213,13 @@ static const char bc_lib[] ALIGN1 = { "\n" "return(r/1)" "\n" "}" "\n" "define s(x){" -"\n" "auto b,s,r,n,a,q,i" +"\n" "auto b,s,r,a,q,i" +"\n" "if(x<0)return(-s(-x))" "\n" "b=ibase" "\n" "ibase=A" "\n" "s=scale" "\n" "scale=1.1*s+2" "\n" "a=a(1)" -"\n" "if(x<0){" -"\n" "n=1" -"\n" "x=-x" -"\n" "}" "\n" "scale=0" "\n" "q=(x/a+2)/4" "\n" "x-=4*q*a" @@ -7236,7 +7233,6 @@ static const char bc_lib[] ALIGN1 = { "\n" "}" "\n" "scale=s" "\n" "ibase=b" -"\n" "if(n)r=-r" "\n" "return(r/1)" "\n" "}" "\n" "define c(x){" -- cgit v1.2.3-55-g6feb From 87b49beeda51ef708e5b83c908edeab1ca88339b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 14 Dec 2018 16:24:01 +0100 Subject: bc: tweak bc_num_parseDecimal() for readability, logic is not changed function old new delta zbc_program_num 836 835 -1 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 547af8eaf..2e8d04460 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -2334,13 +2334,13 @@ static void bc_num_parseDecimal(BcNum *n, const char *val) n->num[n->len] = val[i] - '0'; ++n->len; skip_dot: - if ((ssize_t)--i == (ssize_t)-1) break; - if (val[i] == '.') goto skip_dot; + if (i == 0) break; + if (val[--i] == '.') goto skip_dot; } break; } } - // if this is reached, the value is entirely zero + // if for() exits without hitting if(), the value is entirely zero } // Note: n is already "bc_num_zero()"ed, -- cgit v1.2.3-55-g6feb From 8226912b2c00ed8a2cb38d63337c7f67e21de642 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 14 Dec 2018 16:30:56 +0100 Subject: bc: remove stale comment, empty lines, regularize comment style Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 78 +++++++++++++++++++++++++--------------------------------- 1 file changed, 34 insertions(+), 44 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 2e8d04460..b22cd41f1 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -475,22 +475,18 @@ static const struct BcLexKeyword bc_lex_kws[20] = { BC_LEX_KW_ENTRY("break" , 1), // 1 BC_LEX_KW_ENTRY("continue", 0), // 2 note: this one has no terminating NUL BC_LEX_KW_ENTRY("define" , 1), // 3 - BC_LEX_KW_ENTRY("else" , 0), // 4 BC_LEX_KW_ENTRY("for" , 1), // 5 BC_LEX_KW_ENTRY("halt" , 0), // 6 BC_LEX_KW_ENTRY("ibase" , 1), // 7 - BC_LEX_KW_ENTRY("if" , 1), // 8 BC_LEX_KW_ENTRY("last" , 0), // 9 BC_LEX_KW_ENTRY("length" , 1), // 10 BC_LEX_KW_ENTRY("limits" , 0), // 11 - BC_LEX_KW_ENTRY("obase" , 1), // 12 BC_LEX_KW_ENTRY("print" , 0), // 13 BC_LEX_KW_ENTRY("quit" , 1), // 14 BC_LEX_KW_ENTRY("read" , 0), // 15 - BC_LEX_KW_ENTRY("return" , 1), // 16 BC_LEX_KW_ENTRY("scale" , 1), // 17 BC_LEX_KW_ENTRY("sqrt" , 1), // 18 @@ -499,30 +495,26 @@ static const struct BcLexKeyword bc_lex_kws[20] = { #undef BC_LEX_KW_ENTRY enum { POSIX_KWORD_MASK = 0 - | (1 << 0) - | (1 << 1) - | (0 << 2) - | (1 << 3) - \ - | (0 << 4) - | (1 << 5) - | (0 << 6) - | (1 << 7) - \ - | (1 << 8) - | (0 << 9) - | (1 << 10) - | (0 << 11) - \ - | (1 << 12) - | (0 << 13) - | (1 << 14) - | (0 << 15) - \ - | (1 << 16) - | (1 << 17) - | (1 << 18) - | (1 << 19) + | (1 << 0) // 0 + | (1 << 1) // 1 + | (0 << 2) // 2 + | (1 << 3) // 3 + | (0 << 4) // 4 + | (1 << 5) // 5 + | (0 << 6) // 6 + | (1 << 7) // 7 + | (1 << 8) // 8 + | (0 << 9) // 9 + | (1 << 10) // 10 + | (0 << 11) // 11 + | (1 << 12) // 12 + | (0 << 13) // 13 + | (1 << 14) // 14 + | (0 << 15) // 15 + | (1 << 16) // 16 + | (1 << 17) // 17 + | (1 << 18) // 18 + | (1 << 19) // 19 }; #define bc_lex_kws_POSIX(i) ((1 << (i)) & POSIX_KWORD_MASK) #endif @@ -1027,7 +1019,7 @@ static void quit(void) static void bc_verror_msg(const char *fmt, va_list p) { - const char *sv = sv; /* for compiler */ + const char *sv = sv; // for compiler if (G.prog.file) { sv = applet_name; applet_name = xasprintf("%s: %s:%u", applet_name, G.prog.file, G.err_line); @@ -2943,7 +2935,6 @@ static BC_STATUS zbc_lex_next(BcLex *l) // is so the parser doesn't get inundated with whitespace. s = BC_STATUS_SUCCESS; do { -//TODO: replace pointer with if(IS_BC) ERROR_RETURN(s =) zcommon_lex_token(l); } while (!s && l->t.t == BC_LEX_WHITESPACE); @@ -7395,10 +7386,10 @@ static void bc_program_init(void) size_t idx; BcInstPtr ip; - /* memset(&G.prog, 0, sizeof(G.prog)); - already is */ + // memset(&G.prog, 0, sizeof(G.prog)); - already is memset(&ip, 0, sizeof(BcInstPtr)); - /* G.prog.nchars = G.prog.scale = 0; - already is */ + // G.prog.nchars = G.prog.scale = 0; - already is bc_num_init_DEF_SIZE(&G.prog.ib); bc_num_ten(&G.prog.ib); G.prog.ib_t = 10; @@ -7527,18 +7518,17 @@ int dc_main(int argc UNUSED_PARAM, char **argv) int noscript; INIT_G(); - /* - * TODO: dc (GNU bc 1.07.1) 1.4.1 seems to use width - * 1 char wider than bc from the same package. - * Both default width, and xC_LINE_LENGTH=N are wider: - * "DC_LINE_LENGTH=5 dc -e'123456 p'" prints: - * 1234\ - * 56 - * "echo '123456' | BC_LINE_LENGTH=5 bc" prints: - * 123\ - * 456 - * Do the same, or it's a bug? - */ + + // TODO: dc (GNU bc 1.07.1) 1.4.1 seems to use width + // 1 char wider than bc from the same package. + // Both default width, and xC_LINE_LENGTH=N are wider: + // "DC_LINE_LENGTH=5 dc -e'123456 p'" prints: + // 1234\ + // 56 + // "echo '123456' | BC_LINE_LENGTH=5 bc" prints: + // 123\ + // 456 + // Do the same, or it's a bug? bc_vm_init("DC_LINE_LENGTH"); // Run -e'SCRIPT' and -fFILE in order of appearance, then handle FILEs -- cgit v1.2.3-55-g6feb From 0a23814e98fd764b4cbbe5c464fd6f72cb0f97af Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 14 Dec 2018 16:48:34 +0100 Subject: bc: compress two constant arguments of bc_lex_assign() to one function old new delta zbc_program_num 836 835 -1 bc_lex_assign 34 31 -3 zbc_lex_next 1930 1880 -50 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/3 up/down: 0/-54) Total: -54 bytes text data bss dec hex filename 980208 485 7296 987989 f1355 busybox_old 980154 485 7296 987935 f131f busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index b22cd41f1..918cf4638 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -167,6 +167,12 @@ # include "dc.c" #else +#if 0 +# define dbg_lex(...) bb_error_msg(__VA_ARGS__) +#else +# define dbg_lex(...) ((void)0) +#endif + typedef enum BcStatus { BC_STATUS_SUCCESS = 0, BC_STATUS_FAILURE = 1, @@ -2935,8 +2941,12 @@ static BC_STATUS zbc_lex_next(BcLex *l) // is so the parser doesn't get inundated with whitespace. s = BC_STATUS_SUCCESS; do { + dbg_lex("next token:'%.*s'", + (int)(strchrnul(l->buf + l->i, '\n') - (l->buf + l->i)), + l->buf + l->i); ERROR_RETURN(s =) zcommon_lex_token(l); } while (!s && l->t.t == BC_LEX_WHITESPACE); + dbg_lex("next l->t.t:%d", l->t.t); RETURN_STATUS(s); } @@ -3035,15 +3045,16 @@ static BC_STATUS zbc_lex_string(BcLex *l) # define zbc_lex_string(...) (zbc_lex_string(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static void bc_lex_assign(BcLex *l, BcLexType with, BcLexType without) +static void bc_lex_assign(BcLex *l, unsigned with_and_without) { if (l->buf[l->i] == '=') { ++l->i; - l->t.t = with; - } - else - l->t.t = without; + with_and_without >>= 8; // store "with" value + } // else store "without" value + l->t.t = (with_and_without & 0xff); } +#define bc_lex_assign(l, with, without) \ + bc_lex_assign(l, ((with)<<8)|(without)) static BC_STATUS zbc_lex_comment(BcLex *l) { @@ -7523,11 +7534,11 @@ int dc_main(int argc UNUSED_PARAM, char **argv) // 1 char wider than bc from the same package. // Both default width, and xC_LINE_LENGTH=N are wider: // "DC_LINE_LENGTH=5 dc -e'123456 p'" prints: - // 1234\ - // 56 + // |1234\ | + // |56 | // "echo '123456' | BC_LINE_LENGTH=5 bc" prints: - // 123\ - // 456 + // |123\ | + // |456 | // Do the same, or it's a bug? bc_vm_init("DC_LINE_LENGTH"); -- cgit v1.2.3-55-g6feb From f86e960e7c2a0491dc2564fb0bf6cef10ae24ee2 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 14 Dec 2018 17:01:56 +0100 Subject: bc: rename zbc_parse_text() to ..._init(), reuse existing code for library parsing function old new delta zbc_parse_text_init - 123 +123 bc_vm_run 423 398 -25 zbc_parse_text 123 - -123 ------------------------------------------------------------------------------ (add/remove: 1/1 grow/shrink: 0/1 up/down: 123/-148) Total: -25 bytes text data bss dec hex filename 980154 485 7296 987935 f131f busybox_old 980129 485 7296 987910 f1306 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 918cf4638..8685f2c8e 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -3489,7 +3489,7 @@ static BC_STATUS zcommon_parse(BcParse *p) IF_DC(RETURN_STATUS(zdc_parse_parse(p));) } -static BC_STATUS zbc_parse_text(BcParse *p, const char *text) +static BC_STATUS zbc_parse_text_init(BcParse *p, const char *text) { BcStatus s; @@ -3507,7 +3507,7 @@ static BC_STATUS zbc_parse_text(BcParse *p, const char *text) RETURN_STATUS(zbc_lex_text(&p->l, text)); } #if ERRORS_ARE_FATAL -# define zbc_parse_text(...) (zbc_parse_text(__VA_ARGS__), BC_STATUS_SUCCESS) +# define zbc_parse_text_init(...) (zbc_parse_text_init(__VA_ARGS__), BC_STATUS_SUCCESS) #endif // Called when parsing or execution detects a failure, @@ -5394,7 +5394,7 @@ static BC_STATUS zbc_program_read(void) bc_parse_create(&parse, BC_PROG_READ); bc_lex_file(&parse.l); - s = zbc_parse_text(&parse, buf.v); + s = zbc_parse_text_init(&parse, buf.v); if (s) goto exec_err; s = zcommon_parse_expr(&parse, BC_PARSE_NOREAD); if (s) goto exec_err; @@ -6593,7 +6593,7 @@ static BC_STATUS zbc_program_execStr(char *code, size_t *bgn, if (f->code.len == 0) { bc_parse_create(&prs, fidx); - s = zbc_parse_text(&prs, *str); + s = zbc_parse_text_init(&prs, *str); if (s) goto err; s = zcommon_parse_expr(&prs, BC_PARSE_NOCALL); if (s) goto err; @@ -6919,7 +6919,7 @@ static unsigned bc_vm_envLen(const char *var) static BC_STATUS zbc_vm_process(const char *text) { - BcStatus s = zbc_parse_text(&G.prs, text); + BcStatus s = zbc_parse_text_init(&G.prs, text); if (s) RETURN_STATUS(s); @@ -7320,19 +7320,11 @@ static BC_STATUS zbc_vm_exec(void) #if ENABLE_BC if (option_mask32 & BC_FLAG_L) { - // We know that internal library is not buggy, // thus error checking is normally disabled. # define DEBUG_LIB 0 bc_lex_file(&G.prs.l); - s = zbc_parse_text(&G.prs, bc_lib); - if (DEBUG_LIB && s) RETURN_STATUS(s); - - while (G.prs.l.t.t != BC_LEX_EOF) { - ERROR_RETURN(s =) zcommon_parse(&G.prs); - if (DEBUG_LIB && s) RETURN_STATUS(s); - } - s = zbc_program_exec(); + ERROR_RETURN(s =) zbc_vm_process(bc_lib); if (DEBUG_LIB && s) RETURN_STATUS(s); } #endif -- cgit v1.2.3-55-g6feb From 2ea53a45b7cbad94d9fffcc56eb488aea882449a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 14 Dec 2018 17:51:17 +0100 Subject: bc: convert macro bc_parse_push() to function, add debug infrastructure function old new delta bc_parse_push - 14 +14 zbc_parse_else 132 134 +2 bc_parse_pushName 63 61 -2 zbc_parse_operator 174 170 -4 bc_parse_number 87 83 -4 zbc_parse_string 97 89 -8 bc_parse_pushIndex 68 60 -8 zbc_parse_endBody 339 326 -13 zbc_parse_name 401 387 -14 zdc_parse_mem 107 91 -16 zdc_parse_expr 680 638 -42 zbc_parse_stmt 1502 1456 -46 bc_parse_expr_empty_ok 1838 1788 -50 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 1/11 up/down: 16/-207) Total: -191 bytes text data bss dec hex filename 980129 485 7296 987910 f1306 busybox_old 979938 485 7296 987719 f1247 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 53 insertions(+), 11 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 8685f2c8e..06fcc8efa 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -167,10 +167,29 @@ # include "dc.c" #else -#if 0 -# define dbg_lex(...) bb_error_msg(__VA_ARGS__) +#define DEBUG_LEXER 0 + +#if DEBUG_LEXER +static unsigned lex_indent; +#define dbg_lex(...) \ + do { \ + fprintf(stderr, "%*s", lex_indent, ""); \ + bb_error_msg(__VA_ARGS__); \ + } while (0) +#define dbg_lex_enter(...) \ + do { \ + dbg_lex(__VA_ARGS__); \ + lex_indent++; \ + } while (0) +#define dbg_lex_done(...) \ + do { \ + lex_indent--; \ + dbg_lex(__VA_ARGS__); \ + } while (0) #else -# define dbg_lex(...) ((void)0) +# define dbg_lex(...) ((void)0) +# define dbg_lex_enter(...) ((void)0) +# define dbg_lex_done(...) ((void)0) #endif typedef enum BcStatus { @@ -2941,7 +2960,7 @@ static BC_STATUS zbc_lex_next(BcLex *l) // is so the parser doesn't get inundated with whitespace. s = BC_STATUS_SUCCESS; do { - dbg_lex("next token:'%.*s'", + dbg_lex("next string to parse:'%.*s'", (int)(strchrnul(l->buf + l->i, '\n') - (l->buf + l->i)), l->buf + l->i); ERROR_RETURN(s =) zcommon_lex_token(l); @@ -2954,7 +2973,7 @@ static BC_STATUS zbc_lex_next(BcLex *l) # define zbc_lex_next(...) (zbc_lex_next(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static BC_STATUS zbc_lex_text(BcLex *l, const char *text) +static BC_STATUS zbc_lex_text_init(BcLex *l, const char *text) { l->buf = text; l->i = 0; @@ -2963,7 +2982,7 @@ static BC_STATUS zbc_lex_text(BcLex *l, const char *text) RETURN_STATUS(zbc_lex_next(l)); } #if ERRORS_ARE_FATAL -# define zbc_lex_text(...) (zbc_lex_text(__VA_ARGS__), BC_STATUS_SUCCESS) +# define zbc_lex_text_init(...) (zbc_lex_text_init(__VA_ARGS__), BC_STATUS_SUCCESS) #endif #if ENABLE_BC @@ -3431,7 +3450,11 @@ static void bc_parse_addFunc(BcParse *p, char *name, size_t *idx) p->func = bc_program_func(p->fidx); } -#define bc_parse_push(p, i) bc_vec_pushByte(&(p)->func->code, (char) (i)) +static void bc_parse_push(BcParse *p, char i) +{ + dbg_lex("%s:%d pushing opcode %d", __func__, __LINE__, i); + bc_vec_pushByte(&p->func->code, i); +} static void bc_parse_pushName(BcParse *p, char *name) { @@ -3448,6 +3471,7 @@ static void bc_parse_pushIndex(BcParse *p, size_t idx) size_t mask; unsigned amt; + dbg_lex("%s:%d pushing index %d", __func__, __LINE__, idx); mask = ((size_t)0xff) << (sizeof(idx) * 8 - 8); amt = sizeof(idx); do { @@ -3504,7 +3528,7 @@ static BC_STATUS zbc_parse_text_init(BcParse *p, const char *text) RETURN_STATUS(bc_error("file is not executable")); } - RETURN_STATUS(zbc_lex_text(&p->l, text)); + RETURN_STATUS(zbc_lex_text_init(&p->l, text)); } #if ERRORS_ARE_FATAL # define zbc_parse_text_init(...) (zbc_parse_text_init(__VA_ARGS__), BC_STATUS_SUCCESS) @@ -3662,6 +3686,7 @@ static BC_STATUS zbc_parse_params(BcParse *p, uint8_t flags) bool comma = false; size_t nparams; + dbg_lex("%s:%d p->l.t.t:%d", __func__, __LINE__, p->l.t.t); s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); @@ -4140,6 +4165,7 @@ static BC_STATUS zbc_parse_if(BcParse *p) BcStatus s; BcInstPtr ip; + dbg_lex_enter("%s:%d entered", __func__, __LINE__); s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); if (p->l.t.t != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); @@ -4162,6 +4188,7 @@ static BC_STATUS zbc_parse_if(BcParse *p) bc_vec_push(&p->func->labels, &ip.idx); bc_parse_startBody(p, BC_PARSE_FLAG_IF); + dbg_lex_done("%s:%d done", __func__, __LINE__); RETURN_STATUS(BC_STATUS_SUCCESS); } #if ERRORS_ARE_FATAL @@ -4173,6 +4200,7 @@ static BC_STATUS zbc_parse_else(BcParse *p) { BcInstPtr ip; + dbg_lex("%s:%d p->l.t.t:%d", __func__, __LINE__, p->l.t.t); if (!BC_PARSE_IF_END(p)) RETURN_STATUS(bc_error_bad_token()); ip.idx = p->func->labels.len; @@ -4238,6 +4266,7 @@ static BC_STATUS zbc_parse_for(BcParse *p) BcInstPtr ip; size_t cond_idx, exit_idx, body_idx, update_idx; + dbg_lex("%s:%d p->l.t.t:%d", __func__, __LINE__, p->l.t.t); s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); if (p->l.t.t != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); @@ -4521,6 +4550,7 @@ static BC_STATUS zbc_parse_stmt(BcParse *p) { BcStatus s = BC_STATUS_SUCCESS; + dbg_lex_enter("%s:%d entered, p->l.t.t:%d", __func__, __LINE__, p->l.t.t); switch (p->l.t.t) { case BC_LEX_NLINE: RETURN_STATUS(zbc_lex_next(&p->l)); @@ -4550,6 +4580,7 @@ static BC_STATUS zbc_parse_stmt(BcParse *p) break; } + dbg_lex("%s:%d p->l.t.t:%d", __func__, __LINE__, p->l.t.t); switch (p->l.t.t) { case BC_LEX_OP_INC: case BC_LEX_OP_DEC: @@ -4628,6 +4659,7 @@ static BC_STATUS zbc_parse_stmt(BcParse *p) break; } + dbg_lex_done("%s:%d done", __func__, __LINE__); RETURN_STATUS(s); } #if ERRORS_ARE_FATAL @@ -4638,20 +4670,25 @@ static BC_STATUS zbc_parse_parse(BcParse *p) { BcStatus s; + dbg_lex_enter("%s:%d entered", __func__, __LINE__); if (p->l.t.t == BC_LEX_EOF) s = p->flags.len > 0 ? bc_error("block end could not be found") : bc_error("end of file"); else if (p->l.t.t == BC_LEX_KEY_DEFINE) { + dbg_lex("%s:%d p->l.t.t:BC_LEX_KEY_DEFINE", __func__, __LINE__); if (!BC_PARSE_CAN_EXEC(p)) RETURN_STATUS(bc_error_bad_token()); s = zbc_parse_func(p); - } else + } else { + dbg_lex("%s:%d p->l.t.t:%d (not BC_LEX_KEY_DEFINE)", __func__, __LINE__, p->l.t.t); s = zbc_parse_stmt(p); + } if (s || G_interrupt) { bc_parse_reset(p); s = BC_STATUS_FAILURE; } + dbg_lex_done("%s:%d done", __func__, __LINE__); RETURN_STATUS(s); } #if ERRORS_ARE_FATAL @@ -6919,14 +6956,18 @@ static unsigned bc_vm_envLen(const char *var) static BC_STATUS zbc_vm_process(const char *text) { - BcStatus s = zbc_parse_text_init(&G.prs, text); + BcStatus s; + dbg_lex_enter("%s:%d entered", __func__, __LINE__); + s = zbc_parse_text_init(&G.prs, text); if (s) RETURN_STATUS(s); while (G.prs.l.t.t != BC_LEX_EOF) { + dbg_lex("%s:%d G.prs.l.t.t:%d", __func__, __LINE__, G.prs.l.t.t); ERROR_RETURN(s =) zcommon_parse(&G.prs); if (s) RETURN_STATUS(s); } + dbg_lex("%s:%d G.prs.l.t.t:BC_LEX_EOF", __func__, __LINE__); if (BC_PARSE_CAN_EXEC(&G.prs)) { s = zbc_program_exec(); @@ -6935,6 +6976,7 @@ static BC_STATUS zbc_vm_process(const char *text) bc_program_reset(); } + dbg_lex_done("%s:%d done", __func__, __LINE__); RETURN_STATUS(s); } #if ERRORS_ARE_FATAL @@ -7324,7 +7366,7 @@ static BC_STATUS zbc_vm_exec(void) // thus error checking is normally disabled. # define DEBUG_LIB 0 bc_lex_file(&G.prs.l); - ERROR_RETURN(s =) zbc_vm_process(bc_lib); + s = zbc_vm_process(bc_lib); if (DEBUG_LIB && s) RETURN_STATUS(s); } #endif -- cgit v1.2.3-55-g6feb From 17df882a575d4cba216abdfabefbebea66907b10 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 14 Dec 2018 23:00:24 +0100 Subject: bx: add more debug scaffolding Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 06fcc8efa..b3ffe7bfd 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -2965,7 +2965,7 @@ static BC_STATUS zbc_lex_next(BcLex *l) l->buf + l->i); ERROR_RETURN(s =) zcommon_lex_token(l); } while (!s && l->t.t == BC_LEX_WHITESPACE); - dbg_lex("next l->t.t:%d", l->t.t); + dbg_lex("l->t.t from string:%d", l->t.t); RETURN_STATUS(s); } @@ -4094,6 +4094,7 @@ static BC_STATUS zbc_parse_endBody(BcParse *p, bool brace) bc_vec_pop(&p->flags); flag_ptr = BC_PARSE_TOP_FLAG_PTR(p); + dbg_lex("%s:%d setting BC_PARSE_FLAG_IF_END bit", __func__, __LINE__); *flag_ptr = (*flag_ptr | BC_PARSE_FLAG_IF_END); if (p->l.t.t == BC_LEX_KEY_ELSE) @@ -4151,6 +4152,7 @@ static void bc_parse_noElse(BcParse *p) size_t *label; uint8_t *flag_ptr = BC_PARSE_TOP_FLAG_PTR(p); + dbg_lex("%s:%d clearing BC_PARSE_FLAG_IF_END bit", __func__, __LINE__); *flag_ptr = (*flag_ptr & ~(BC_PARSE_FLAG_IF_END)); ip = bc_vec_top(&p->exits); @@ -4200,7 +4202,7 @@ static BC_STATUS zbc_parse_else(BcParse *p) { BcInstPtr ip; - dbg_lex("%s:%d p->l.t.t:%d", __func__, __LINE__, p->l.t.t); + dbg_lex_enter("%s:%d entered", __func__, __LINE__); if (!BC_PARSE_IF_END(p)) RETURN_STATUS(bc_error_bad_token()); ip.idx = p->func->labels.len; @@ -4209,12 +4211,14 @@ static BC_STATUS zbc_parse_else(BcParse *p) bc_parse_push(p, BC_INST_JUMP); bc_parse_pushIndex(p, ip.idx); + dbg_lex("%s:%d calling bc_parse_noElse()", __func__, __LINE__); bc_parse_noElse(p); bc_vec_push(&p->exits, &ip); bc_vec_push(&p->func->labels, &ip.idx); bc_parse_startBody(p, BC_PARSE_FLAG_ELSE); + dbg_lex_done("%s:%d done", __func__, __LINE__); RETURN_STATUS(zbc_lex_next(&p->l)); } #if ERRORS_ARE_FATAL @@ -4520,9 +4524,11 @@ static BC_STATUS zbc_parse_body(BcParse *p, bool brace) BcStatus s = BC_STATUS_SUCCESS; uint8_t *flag_ptr = bc_vec_top(&p->flags); + dbg_lex_enter("%s:%d entered", __func__, __LINE__); *flag_ptr &= ~(BC_PARSE_FLAG_BODY); if (*flag_ptr & BC_PARSE_FLAG_FUNC_INNER) { + dbg_lex("%s:%d BC_PARSE_FLAG_FUNC_INNER", __func__, __LINE__); if (!brace) RETURN_STATUS(bc_error_bad_token()); p->auto_part = p->l.t.t != BC_LEX_KEY_AUTO; @@ -4535,10 +4541,12 @@ static BC_STATUS zbc_parse_body(BcParse *p, bool brace) if (p->l.t.t == BC_LEX_NLINE) s = zbc_lex_next(&p->l); } else { + dbg_lex("%s:%d !BC_PARSE_FLAG_FUNC_INNER", __func__, __LINE__); s = zbc_parse_stmt(p); if (!s && !brace) s = zbc_parse_endBody(p, false); } + dbg_lex_done("%s:%d done", __func__, __LINE__); RETURN_STATUS(s); } #if ERRORS_ARE_FATAL @@ -4553,6 +4561,7 @@ static BC_STATUS zbc_parse_stmt(BcParse *p) dbg_lex_enter("%s:%d entered, p->l.t.t:%d", __func__, __LINE__, p->l.t.t); switch (p->l.t.t) { case BC_LEX_NLINE: + dbg_lex_done("%s:%d done (seen BC_LEX_NLINE)", __func__, __LINE__); RETURN_STATUS(zbc_lex_next(&p->l)); case BC_LEX_KEY_ELSE: @@ -4564,6 +4573,7 @@ static BC_STATUS zbc_parse_stmt(BcParse *p) ++p->nbraces; s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); + dbg_lex_done("%s:%d done (returning zbc_parse_body())", __func__, __LINE__); RETURN_STATUS(zbc_parse_body(p, true)); case BC_LEX_KEY_AUTO: @@ -4573,10 +4583,13 @@ static BC_STATUS zbc_parse_stmt(BcParse *p) p->auto_part = false; if (BC_PARSE_IF_END(p)) { bc_parse_noElse(p); + dbg_lex_done("%s:%d done (BC_PARSE_IF_END is true)", __func__, __LINE__); RETURN_STATUS(BC_STATUS_SUCCESS); } - if (BC_PARSE_BODY(p)) + if (BC_PARSE_BODY(p)) { + dbg_lex_done("%s:%d done (returning zbc_parse_body())", __func__, __LINE__); RETURN_STATUS(zbc_parse_body(p, false)); + } break; } @@ -4705,6 +4718,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext ne unsigned nparens, nrelops; bool paren_first, paren_expr, rprn, done, get_token, assign, bin_last; + dbg_lex_enter("%s:%d entered", __func__, __LINE__); paren_first = p->l.t.t == BC_LEX_LPAREN; nparens = nrelops = 0; paren_expr = rprn = done = get_token = assign = false; @@ -4803,8 +4817,10 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext ne get_token = false; break; } - else if (!paren_expr) + else if (!paren_expr) { + dbg_lex_done("%s:%d done (returning EMPTY_EXP)", __func__, __LINE__); return BC_STATUS_PARSE_EMPTY_EXP; + } --nparens; paren_expr = rprn = true; @@ -4952,6 +4968,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext ne bc_parse_push(p, BC_INST_POP); } + dbg_lex_done("%s:%d done", __func__, __LINE__); return s; } -- cgit v1.2.3-55-g6feb From 7b1df3db975c97799a23cf0699d8f0fd1d046f22 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 14 Dec 2018 23:12:48 +0100 Subject: bc: pull zbc_lex_next() call out of zbc_parse_operator() into one caller that uses it function old new delta bc_parse_operator - 144 +144 bc_parse_expr_empty_ok 1788 1792 +4 zbc_parse_operator 170 - -170 ------------------------------------------------------------------------------ (add/remove: 1/1 grow/shrink: 1/0 up/down: 148/-170) Total: -22 bytes text data bss dec hex filename 979938 485 7296 987719 f1247 busybox_old 979916 485 7296 987697 f1231 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index b3ffe7bfd..e1a4b8f52 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -3611,7 +3611,7 @@ static void bc_parse_create(BcParse *p, size_t func) // We can calculate the conversion between tokens and exprs by subtracting the // position of the first operator in the lex enum and adding the position of the // first in the expr enum. Note: This only works for binary operators. -#define BC_PARSE_TOKEN_INST(t) ((char) ((t) -BC_LEX_NEG + BC_INST_NEG)) +#define BC_PARSE_TOKEN_INST(t) ((char) ((t) - BC_LEX_NEG + BC_INST_NEG)) static BC_STATUS zbc_parse_else(BcParse *p); static BC_STATUS zbc_parse_stmt(BcParse *p); @@ -3623,17 +3623,14 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext ne # define zbc_parse_expr(...) (zbc_parse_expr(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static BC_STATUS zbc_parse_operator(BcParse *p, BcLexType type, size_t start, - size_t *nexprs, bool next) +static void bc_parse_operator(BcParse *p, BcLexType type, size_t start, + size_t *nexprs) { - BcStatus s = BC_STATUS_SUCCESS; - BcLexType t; char l, r = bc_parse_op_PREC(type - BC_LEX_OP_INC); bool left = bc_parse_op_LEFT(type - BC_LEX_OP_INC); while (p->ops.len > start) { - - t = BC_PARSE_TOP_OP(p); + BcLexType t = BC_PARSE_TOP_OP(p); if (t == BC_LEX_LPAREN) break; l = bc_parse_op_PREC(t - BC_LEX_OP_INC); @@ -3641,17 +3638,11 @@ static BC_STATUS zbc_parse_operator(BcParse *p, BcLexType type, size_t start, bc_parse_push(p, BC_PARSE_TOKEN_INST(t)); bc_vec_pop(&p->ops); - *nexprs -= t != BC_LEX_OP_BOOL_NOT && t != BC_LEX_NEG; + *nexprs -= (t != BC_LEX_OP_BOOL_NOT && t != BC_LEX_NEG); } bc_vec_push(&p->ops, &type); - if (next) s = zbc_lex_next(&p->l); - - RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_parse_operator(...) (zbc_parse_operator(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif static BC_STATUS zbc_parse_rightParen(BcParse *p, size_t ops_bgn, size_t *nexs) { @@ -3964,7 +3955,7 @@ static BC_STATUS zbc_parse_minus(BcParse *p, BcInst *prev, size_t ops_bgn, if (type != BC_LEX_OP_MINUS) bc_vec_push(&p->ops, &type); else - s = zbc_parse_operator(p, type, ops_bgn, nexprs, false); + bc_parse_operator(p, type, ops_bgn, nexprs); RETURN_STATUS(s); } @@ -4787,7 +4778,8 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext ne nrelops += t >= BC_LEX_OP_REL_EQ && t <= BC_LEX_OP_REL_GT; prev = BC_PARSE_TOKEN_INST(t); - s = zbc_parse_operator(p, t, ops_bgn, &nexprs, true); + bc_parse_operator(p, t, ops_bgn, &nexprs); + s = zbc_lex_next(&p->l); rprn = get_token = false; bin_last = t != BC_LEX_OP_BOOL_NOT; -- cgit v1.2.3-55-g6feb From 0154d78738da5f56c09665e804d94fdcd31cb081 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 14 Dec 2018 23:32:51 +0100 Subject: bc: shorten one message, make defines more readable text data bss dec hex filename 979916 485 7296 987697 f1231 busybox_old 979893 485 7296 987674 f121a busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 89 +++++++++++++++++++++++++--------------------------------- 1 file changed, 38 insertions(+), 51 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index e1a4b8f52..9a501a25e 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -566,48 +566,37 @@ typedef struct BcLex { } BcLex; -#define BC_PARSE_STREND ((char) UCHAR_MAX) +#define BC_PARSE_STREND ((char) UCHAR_MAX) -#define BC_PARSE_REL (1 << 0) -#define BC_PARSE_PRINT (1 << 1) -#define BC_PARSE_NOCALL (1 << 2) -#define BC_PARSE_NOREAD (1 << 3) -#define BC_PARSE_ARRAY (1 << 4) +#define BC_PARSE_REL (1 << 0) +#define BC_PARSE_PRINT (1 << 1) +#define BC_PARSE_NOCALL (1 << 2) +#define BC_PARSE_NOREAD (1 << 3) +#define BC_PARSE_ARRAY (1 << 4) #define BC_PARSE_TOP_FLAG_PTR(parse) ((uint8_t *) bc_vec_top(&(parse)->flags)) -#define BC_PARSE_TOP_FLAG(parse) (*(BC_PARSE_TOP_FLAG_PTR(parse))) - -#define BC_PARSE_FLAG_FUNC_INNER (1 << 0) -#define BC_PARSE_FUNC_INNER(parse) \ - (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_FUNC_INNER) - -#define BC_PARSE_FLAG_FUNC (1 << 1) -#define BC_PARSE_FUNC(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_FUNC) - -#define BC_PARSE_FLAG_BODY (1 << 2) -#define BC_PARSE_BODY(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_BODY) - -#define BC_PARSE_FLAG_LOOP (1 << 3) -#define BC_PARSE_LOOP(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_LOOP) - -#define BC_PARSE_FLAG_LOOP_INNER (1 << 4) -#define BC_PARSE_LOOP_INNER(parse) \ - (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_LOOP_INNER) - -#define BC_PARSE_FLAG_IF (1 << 5) -#define BC_PARSE_IF(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_IF) - -#define BC_PARSE_FLAG_ELSE (1 << 6) -#define BC_PARSE_ELSE(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_ELSE) - -#define BC_PARSE_FLAG_IF_END (1 << 7) -#define BC_PARSE_IF_END(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_IF_END) - -#define BC_PARSE_CAN_EXEC(parse) \ - (!(BC_PARSE_TOP_FLAG(parse) & \ - (BC_PARSE_FLAG_FUNC_INNER | BC_PARSE_FLAG_FUNC | BC_PARSE_FLAG_BODY | \ - BC_PARSE_FLAG_LOOP | BC_PARSE_FLAG_LOOP_INNER | BC_PARSE_FLAG_IF | \ - BC_PARSE_FLAG_ELSE | BC_PARSE_FLAG_IF_END))) +#define BC_PARSE_TOP_FLAG(parse) (*(BC_PARSE_TOP_FLAG_PTR(parse))) + +#define BC_PARSE_FLAG_FUNC_INNER (1 << 0) +#define BC_PARSE_FLAG_FUNC (1 << 1) +#define BC_PARSE_FLAG_BODY (1 << 2) +#define BC_PARSE_FLAG_LOOP (1 << 3) +#define BC_PARSE_FLAG_LOOP_INNER (1 << 4) +#define BC_PARSE_FLAG_IF (1 << 5) +#define BC_PARSE_FLAG_ELSE (1 << 6) +#define BC_PARSE_FLAG_IF_END (1 << 7) + +// If we have none of the above bits, we can stop parsing and execute already parsed chunk +#define BC_PARSE_CAN_EXEC(parse) (BC_PARSE_TOP_FLAG(parse) == 0) + +#define BC_PARSE_FUNC_INNER(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_FUNC_INNER) +#define BC_PARSE_FUNC(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_FUNC) +#define BC_PARSE_BODY(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_BODY) +#define BC_PARSE_LOOP(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_LOOP) +#define BC_PARSE_LOOP_INNER(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_LOOP_INNER) +#define BC_PARSE_IF(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_IF) +#define BC_PARSE_ELSE(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_ELSE) +#define BC_PARSE_IF_END(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_IF_END) struct BcParse; @@ -3611,7 +3600,7 @@ static void bc_parse_create(BcParse *p, size_t func) // We can calculate the conversion between tokens and exprs by subtracting the // position of the first operator in the lex enum and adding the position of the // first in the expr enum. Note: This only works for binary operators. -#define BC_PARSE_TOKEN_INST(t) ((char) ((t) - BC_LEX_NEG + BC_INST_NEG)) +#define BC_TOKEN_2_INST(t) ((char) ((t) - BC_LEX_NEG + BC_INST_NEG)) static BC_STATUS zbc_parse_else(BcParse *p); static BC_STATUS zbc_parse_stmt(BcParse *p); @@ -3636,7 +3625,7 @@ static void bc_parse_operator(BcParse *p, BcLexType type, size_t start, l = bc_parse_op_PREC(t - BC_LEX_OP_INC); if (l >= r && (l != r || !left)) break; - bc_parse_push(p, BC_PARSE_TOKEN_INST(t)); + bc_parse_push(p, BC_TOKEN_2_INST(t)); bc_vec_pop(&p->ops); *nexprs -= (t != BC_LEX_OP_BOOL_NOT && t != BC_LEX_NEG); } @@ -3653,7 +3642,7 @@ static BC_STATUS zbc_parse_rightParen(BcParse *p, size_t ops_bgn, size_t *nexs) top = BC_PARSE_TOP_OP(p); while (top != BC_LEX_LPAREN) { - bc_parse_push(p, BC_PARSE_TOKEN_INST(top)); + bc_parse_push(p, BC_TOKEN_2_INST(top)); bc_vec_pop(&p->ops); *nexs -= top != BC_LEX_OP_BOOL_NOT && top != BC_LEX_NEG; @@ -3948,7 +3937,7 @@ static BC_STATUS zbc_parse_minus(BcParse *p, BcInst *prev, size_t ops_bgn, (etype >= BC_INST_NUM && etype <= BC_INST_SQRT) ? BC_LEX_OP_MINUS : BC_LEX_NEG; - *prev = BC_PARSE_TOKEN_INST(type); + *prev = BC_TOKEN_2_INST(type); // We can just push onto the op stack because this is the largest // precedence operator that gets pushed. Inc/dec does not. @@ -4747,10 +4736,9 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext ne prev != BC_INST_OBASE && prev != BC_INST_LAST) { s = bc_error("bad assignment:" - " left side must be scale," - " ibase, obase, last, var," + " left side must be variable" " or array element" - ); + ); // note: shared string break; } } @@ -4777,7 +4765,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext ne } nrelops += t >= BC_LEX_OP_REL_EQ && t <= BC_LEX_OP_REL_GT; - prev = BC_PARSE_TOKEN_INST(t); + prev = BC_TOKEN_2_INST(t); bc_parse_operator(p, t, ops_bgn, &nexprs); s = zbc_lex_next(&p->l); rprn = get_token = false; @@ -4926,7 +4914,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext ne if (top == BC_LEX_LPAREN || top == BC_LEX_RPAREN) return bc_error_bad_expression(); - bc_parse_push(p, BC_PARSE_TOKEN_INST(top)); + bc_parse_push(p, BC_TOKEN_2_INST(top)); nexprs -= top != BC_LEX_OP_BOOL_NOT && top != BC_LEX_NEG; bc_vec_pop(&p->ops); @@ -5977,10 +5965,9 @@ static BC_STATUS zbc_program_assign(char inst) if (left->t == BC_RESULT_CONSTANT || left->t == BC_RESULT_TEMP) RETURN_STATUS(bc_error("bad assignment:" - " left side must be scale," - " ibase, obase, last, var," + " left side must be variable" " or array element" - )); + )); // note: shared string #if ENABLE_BC if (inst == BC_INST_ASSIGN_DIVIDE && !bc_num_cmp(r, &G.prog.zero)) -- cgit v1.2.3-55-g6feb From f10f17f8d3ee77c469fc57634a458e8a45aeb681 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 14 Dec 2018 23:41:33 +0100 Subject: bc: drop zbc_parse_endBody() bool parameter, move its code to caller which uses it function old new delta zbc_parse_stmt 1456 1479 +23 zbc_parse_body 103 101 -2 zbc_parse_endBody 326 292 -34 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/2 up/down: 23/-36) Total: -13 bytes text data bss dec hex filename 979893 485 7296 987674 f121a busybox_old 979880 485 7296 987661 f120d busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 9a501a25e..4024a08df 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -4046,23 +4046,13 @@ static BC_STATUS zbc_parse_return(BcParse *p) # define zbc_parse_return(...) (zbc_parse_return(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static BC_STATUS zbc_parse_endBody(BcParse *p, bool brace) +static BC_STATUS zbc_parse_endBody(BcParse *p) { BcStatus s = BC_STATUS_SUCCESS; - if (p->flags.len <= 1 || (brace && p->nbraces == 0)) + if (p->flags.len <= 1) RETURN_STATUS(bc_error_bad_token()); - if (brace) { - if (p->l.t.t != BC_LEX_RBRACE) - RETURN_STATUS(bc_error_bad_token()); - if (!p->nbraces) - RETURN_STATUS(bc_error_bad_token()); - --p->nbraces; - s = zbc_lex_next(&p->l); - if (s) RETURN_STATUS(s); - } - if (BC_PARSE_IF(p)) { uint8_t *flag_ptr; @@ -4523,7 +4513,7 @@ static BC_STATUS zbc_parse_body(BcParse *p, bool brace) else { dbg_lex("%s:%d !BC_PARSE_FLAG_FUNC_INNER", __func__, __LINE__); s = zbc_parse_stmt(p); - if (!s && !brace) s = zbc_parse_endBody(p, false); + if (!s && !brace) s = zbc_parse_endBody(p); } dbg_lex_done("%s:%d done", __func__, __LINE__); @@ -4598,7 +4588,12 @@ static BC_STATUS zbc_parse_stmt(BcParse *p) while (!s && p->l.t.t == BC_LEX_SCOLON) s = zbc_lex_next(&p->l); break; case BC_LEX_RBRACE: - s = zbc_parse_endBody(p, true); + if (p->nbraces == 0) + RETURN_STATUS(bc_error_bad_token()); + --p->nbraces; + s = zbc_lex_next(&p->l); + if (!s) + s = zbc_parse_endBody(p); break; case BC_LEX_STR: s = zbc_parse_string(p, BC_INST_PRINT_STR); -- cgit v1.2.3-55-g6feb From 7db384338a803fc74a0e8eb62e9369e10a49ffdb Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 15 Dec 2018 00:39:17 +0100 Subject: bc: rewrite "block flag stack" using simple realloc'ed byte array Each access to current top flag took a function call + fetch of three data items + multiplication and some additions + and then following the resulting pointer. After the change, it is: fetch pointer value + one byte access via this pointer. function old new delta bc_parse_startBody 45 49 +4 bc_parse_free 46 47 +1 zbc_parse_auto 188 185 -3 bc_parse_push 14 11 -3 bc_vm_run 398 394 -4 zbc_vm_process 63 58 -5 zdc_parse_expr 638 632 -6 zbc_parse_body 101 95 -6 bc_parse_addFunc 31 25 -6 bc_parse_noElse 56 48 -8 zcommon_parse 341 331 -10 zbc_parse_else 134 123 -11 bc_parse_create 124 108 -16 zbc_parse_text_init 123 104 -19 zbc_parse_endBody 292 252 -40 zbc_parse_stmt 1479 1420 -59 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/14 up/down: 5/-196) Total: -191 bytes text data bss dec hex filename 979880 485 7296 987661 f120d busybox_old 979689 485 7296 987470 f114e busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 43 +++++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 4024a08df..2feaf7bf3 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -574,8 +574,9 @@ typedef struct BcLex { #define BC_PARSE_NOREAD (1 << 3) #define BC_PARSE_ARRAY (1 << 4) -#define BC_PARSE_TOP_FLAG_PTR(parse) ((uint8_t *) bc_vec_top(&(parse)->flags)) +#define BC_PARSE_TOP_FLAG_PTR(parse) ((parse)->bf_top) #define BC_PARSE_TOP_FLAG(parse) (*(BC_PARSE_TOP_FLAG_PTR(parse))) +#define BC_PARSE_FLAG_STACK_EMPTY(p) ((p)->bf_top == (p)->bf_base) #define BC_PARSE_FLAG_FUNC_INNER (1 << 0) #define BC_PARSE_FLAG_FUNC (1 << 1) @@ -598,15 +599,11 @@ typedef struct BcLex { #define BC_PARSE_ELSE(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_ELSE) #define BC_PARSE_IF_END(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_IF_END) -struct BcParse; - -struct BcProgram; - typedef struct BcParse { - BcLex l; - BcVec flags; + uint8_t *bf_base; + uint8_t *bf_top; BcVec exits; BcVec conds; @@ -618,7 +615,6 @@ typedef struct BcParse { size_t nbraces; bool auto_part; - } BcParse; typedef struct BcProgram { @@ -3558,7 +3554,7 @@ static void bc_parse_reset(BcParse *p) p->l.t.t = BC_LEX_EOF; p->auto_part = (p->nbraces = 0); - bc_vec_npop(&p->flags, p->flags.len - 1); + p->bf_top = p->bf_base; // pop all flags bc_vec_pop_all(&p->exits); bc_vec_pop_all(&p->conds); bc_vec_pop_all(&p->ops); @@ -3568,7 +3564,7 @@ static void bc_parse_reset(BcParse *p) static void bc_parse_free(BcParse *p) { - bc_vec_free(&p->flags); + free(p->bf_base); bc_vec_free(&p->exits); bc_vec_free(&p->conds); bc_vec_free(&p->ops); @@ -3580,10 +3576,9 @@ static void bc_parse_create(BcParse *p, size_t func) memset(p, 0, sizeof(BcParse)); bc_lex_init(&p->l); - bc_vec_init(&p->flags, sizeof(uint8_t), NULL); + p->bf_top = p->bf_base = xzalloc(1); bc_vec_init(&p->exits, sizeof(BcInstPtr), NULL); bc_vec_init(&p->conds, sizeof(size_t), NULL); - bc_vec_pushZeroByte(&p->flags); bc_vec_init(&p->ops, sizeof(BcLexType), NULL); // p->auto_part = p->nbraces = 0; - already is @@ -4050,7 +4045,7 @@ static BC_STATUS zbc_parse_endBody(BcParse *p) { BcStatus s = BC_STATUS_SUCCESS; - if (p->flags.len <= 1) + if (BC_PARSE_FLAG_STACK_EMPTY(p)) RETURN_STATUS(bc_error_bad_token()); if (BC_PARSE_IF(p)) { @@ -4061,7 +4056,7 @@ static BC_STATUS zbc_parse_endBody(BcParse *p) if (s) RETURN_STATUS(s); } - bc_vec_pop(&p->flags); + p->bf_top--; flag_ptr = BC_PARSE_TOP_FLAG_PTR(p); dbg_lex("%s:%d setting BC_PARSE_FLAG_IF_END bit", __func__, __LINE__); @@ -4074,7 +4069,7 @@ static BC_STATUS zbc_parse_endBody(BcParse *p) BcInstPtr *ip; size_t *label; - bc_vec_pop(&p->flags); + p->bf_top--; ip = bc_vec_top(&p->exits); label = bc_vec_item(&p->func->labels, ip->idx); @@ -4085,7 +4080,7 @@ static BC_STATUS zbc_parse_endBody(BcParse *p) else if (BC_PARSE_FUNC_INNER(p)) { bc_parse_push(p, BC_INST_RET0); bc_parse_updateFunc(p, BC_PROG_MAIN); - bc_vec_pop(&p->flags); + p->bf_top--; } else { BcInstPtr *ip = bc_vec_top(&p->exits); @@ -4097,7 +4092,7 @@ static BC_STATUS zbc_parse_endBody(BcParse *p) label = bc_vec_item(&p->func->labels, ip->idx); *label = p->func->code.len; - bc_vec_pop(&p->flags); + p->bf_top--; bc_vec_pop(&p->exits); bc_vec_pop(&p->conds); } @@ -4110,10 +4105,15 @@ static BC_STATUS zbc_parse_endBody(BcParse *p) static void bc_parse_startBody(BcParse *p, uint8_t flags) { + size_t size; uint8_t *flag_ptr = BC_PARSE_TOP_FLAG_PTR(p); flags |= (*flag_ptr & (BC_PARSE_FLAG_FUNC | BC_PARSE_FLAG_LOOP)); flags |= BC_PARSE_FLAG_BODY; - bc_vec_push(&p->flags, &flags); + + size = p->bf_top - p->bf_base; + p->bf_base = xrealloc(p->bf_base, size + 2); + p->bf_top = p->bf_base + size + 1; + *p->bf_top = flags; } static void bc_parse_noElse(BcParse *p) @@ -4492,7 +4492,7 @@ err: static BC_STATUS zbc_parse_body(BcParse *p, bool brace) { BcStatus s = BC_STATUS_SUCCESS; - uint8_t *flag_ptr = bc_vec_top(&p->flags); + uint8_t *flag_ptr = BC_PARSE_TOP_FLAG_PTR(p); dbg_lex_enter("%s:%d entered", __func__, __LINE__); *flag_ptr &= ~(BC_PARSE_FLAG_BODY); @@ -4535,10 +4535,12 @@ static BC_STATUS zbc_parse_stmt(BcParse *p) RETURN_STATUS(zbc_lex_next(&p->l)); case BC_LEX_KEY_ELSE: + dbg_lex("%s:%d BC_LEX_KEY_ELSE:", __func__, __LINE__); p->auto_part = false; break; case BC_LEX_LBRACE: + dbg_lex("%s:%d BC_LEX_LBRACE:", __func__, __LINE__); if (!BC_PARSE_BODY(p)) RETURN_STATUS(bc_error_bad_token()); ++p->nbraces; s = zbc_lex_next(&p->l); @@ -4547,6 +4549,7 @@ static BC_STATUS zbc_parse_stmt(BcParse *p) RETURN_STATUS(zbc_parse_body(p, true)); case BC_LEX_KEY_AUTO: + dbg_lex("%s:%d BC_LEX_KEY_AUTO:", __func__, __LINE__); RETURN_STATUS(zbc_parse_auto(p)); default: @@ -4660,7 +4663,7 @@ static BC_STATUS zbc_parse_parse(BcParse *p) dbg_lex_enter("%s:%d entered", __func__, __LINE__); if (p->l.t.t == BC_LEX_EOF) - s = p->flags.len > 0 ? bc_error("block end could not be found") : bc_error("end of file"); + s = BC_PARSE_FLAG_STACK_EMPTY(p) ? bc_error("end of file") : bc_error("block end could not be found"); else if (p->l.t.t == BC_LEX_KEY_DEFINE) { dbg_lex("%s:%d p->l.t.t:BC_LEX_KEY_DEFINE", __func__, __LINE__); if (!BC_PARSE_CAN_EXEC(p)) -- cgit v1.2.3-55-g6feb From fd51e0c4d22825282f3e38be0655db36b3e716d2 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 15 Dec 2018 15:07:14 +0100 Subject: bc: simplify BC_INST_JUMP[_ZERO] handling function old new delta zbc_program_exec 4063 4050 -13 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 2feaf7bf3..aeb29a971 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -6715,7 +6715,6 @@ static BC_STATUS zbc_program_exec(void) BcInstPtr *ip = bc_vec_top(&G.prog.stack); BcFunc *func = bc_program_func(ip->func); char *code = func->code.v; - bool cond = false; while (ip->idx < func->code.len) { BcStatus s = BC_STATUS_SUCCESS; @@ -6723,17 +6722,22 @@ static BC_STATUS zbc_program_exec(void) switch (inst) { #if ENABLE_BC - case BC_INST_JUMP_ZERO: + case BC_INST_JUMP_ZERO: { + bool zero; s = zbc_program_prep(&ptr, &num); if (s) RETURN_STATUS(s); - cond = !bc_num_cmp(num, &G.prog.zero); + zero = (bc_num_cmp(num, &G.prog.zero) == 0); bc_vec_pop(&G.prog.results); - // Fallthrough. + if (!zero) { + bc_program_index(code, &ip->idx); + break; + } + // else: fall through + } case BC_INST_JUMP: { - size_t *addr; size_t idx = bc_program_index(code, &ip->idx); - addr = bc_vec_item(&func->labels, idx); - if (inst == BC_INST_JUMP || cond) ip->idx = *addr; + size_t *addr = bc_vec_item(&func->labels, idx); + ip->idx = *addr; break; } case BC_INST_CALL: @@ -6851,8 +6855,7 @@ static BC_STATUS zbc_program_exec(void) break; case BC_INST_EXECUTE: case BC_INST_EXEC_COND: - cond = inst == BC_INST_EXEC_COND; - s = zbc_program_execStr(code, &ip->idx, cond); + s = zbc_program_execStr(code, &ip->idx, inst == BC_INST_EXEC_COND); break; case BC_INST_PRINT_STACK: { size_t idx; -- cgit v1.2.3-55-g6feb From 99b37623356a1555359df1c011d4a6732918a5c4 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 15 Dec 2018 20:06:59 +0100 Subject: bc: lexer debugging, added some failing test cases function old new delta bc_parse_push_block_flag - 47 +47 zbc_parse_body 107 121 +14 zbc_num_divmod 156 150 -6 zbc_lex_number 200 192 -8 zbc_parse_endBody 264 254 -10 bc_parse_startBody 47 - -47 ------------------------------------------------------------------------------ (add/remove: 1/1 grow/shrink: 1/3 up/down: 61/-71) Total: -10 bytes text data bss dec hex filename 982596 485 7296 990377 f1ca9 busybox_old 982586 485 7296 990367 f1c9f busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 107 ++++++++++++++++++++++++++++++++++------------------- testsuite/bc.tests | 20 ++++++++++ 2 files changed, 89 insertions(+), 38 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index aeb29a971..374279889 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -168,6 +168,7 @@ #else #define DEBUG_LEXER 0 +#define DEBUG_EXEC 0 #if DEBUG_LEXER static unsigned lex_indent; @@ -192,6 +193,12 @@ static unsigned lex_indent; # define dbg_lex_done(...) ((void)0) #endif +#if DEBUG_EXEC +# define dbg_exec(...) bb_error_msg(__VA_ARGS__) +#else +# define dbg_exec(...) ((void)0) +#endif + typedef enum BcStatus { BC_STATUS_SUCCESS = 0, BC_STATUS_FAILURE = 1, @@ -614,6 +621,7 @@ typedef struct BcParse { size_t fidx; size_t nbraces; +//FIXME: "define w(x) { auto z; return 1; }" fails to parse bool auto_part; } BcParse; @@ -658,6 +666,26 @@ typedef struct BcProgram { } BcProgram; +static void bc_parse_push_block_flag(BcParse *p, uint8_t flags) +{ + size_t size; + uint8_t *flag_ptr = BC_PARSE_TOP_FLAG_PTR(p); + flags |= (*flag_ptr & (BC_PARSE_FLAG_FUNC | BC_PARSE_FLAG_LOOP)); + flags |= BC_PARSE_FLAG_BODY; + + size = p->bf_top - p->bf_base; + p->bf_base = xrealloc(p->bf_base, size + 2); + p->bf_top = p->bf_base + size + 1; + dbg_lex("%s:%d pushed block flag lvl:%d bits:0x%02x", __func__, __LINE__, size + 1, flags); + *p->bf_top = flags; +} + +static ALWAYS_INLINE void bc_parse_pop_block_flag(BcParse *p) +{ + p->bf_top--; + dbg_lex("%s:%d popped block flag lvl:%d bits:0x%02x", __func__, __LINE__, p->bf_top - p->bf_base, *p->bf_top); +} + #define BC_PROG_STACK(s, n) ((s)->len >= ((size_t) n)) #define BC_PROG_MAIN (0) @@ -3487,13 +3515,13 @@ static void bc_parse_number(BcParse *p, BcInst *prev, size_t *nexs) (*prev) = BC_INST_NUM; } -IF_BC(static BC_STATUS zbc_parse_parse(BcParse *p);) +IF_BC(static BC_STATUS zbc_parse_stmt_or_funcdef(BcParse *p);) IF_DC(static BC_STATUS zdc_parse_parse(BcParse *p);) static BC_STATUS zcommon_parse(BcParse *p) { if (IS_BC) { - IF_BC(RETURN_STATUS(zbc_parse_parse(p));) + IF_BC(RETURN_STATUS(zbc_parse_stmt_or_funcdef(p));) } IF_DC(RETURN_STATUS(zdc_parse_parse(p));) } @@ -4056,7 +4084,7 @@ static BC_STATUS zbc_parse_endBody(BcParse *p) if (s) RETURN_STATUS(s); } - p->bf_top--; + bc_parse_pop_block_flag(p); flag_ptr = BC_PARSE_TOP_FLAG_PTR(p); dbg_lex("%s:%d setting BC_PARSE_FLAG_IF_END bit", __func__, __LINE__); @@ -4069,32 +4097,34 @@ static BC_STATUS zbc_parse_endBody(BcParse *p) BcInstPtr *ip; size_t *label; - p->bf_top--; - ip = bc_vec_top(&p->exits); label = bc_vec_item(&p->func->labels, ip->idx); + dbg_lex("%s:%d rewriting label: %d -> %d", __func__, __LINE__, *label, p->func->code.len); *label = p->func->code.len; bc_vec_pop(&p->exits); + bc_parse_pop_block_flag(p); } else if (BC_PARSE_FUNC_INNER(p)) { bc_parse_push(p, BC_INST_RET0); bc_parse_updateFunc(p, BC_PROG_MAIN); - p->bf_top--; + bc_parse_pop_block_flag(p); } else { BcInstPtr *ip = bc_vec_top(&p->exits); size_t *label = bc_vec_top(&p->conds); + dbg_lex("%s:%d BC_INST_JUMP to %d", __func__, __LINE__, *label); bc_parse_push(p, BC_INST_JUMP); bc_parse_pushIndex(p, *label); label = bc_vec_item(&p->func->labels, ip->idx); + dbg_lex("%s:%d rewriting label: %d -> %d", __func__, __LINE__, *label, p->func->code.len); *label = p->func->code.len; - p->bf_top--; bc_vec_pop(&p->exits); bc_vec_pop(&p->conds); + bc_parse_pop_block_flag(p); } RETURN_STATUS(s); @@ -4103,19 +4133,6 @@ static BC_STATUS zbc_parse_endBody(BcParse *p) # define zbc_parse_endBody(...) (zbc_parse_endBody(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static void bc_parse_startBody(BcParse *p, uint8_t flags) -{ - size_t size; - uint8_t *flag_ptr = BC_PARSE_TOP_FLAG_PTR(p); - flags |= (*flag_ptr & (BC_PARSE_FLAG_FUNC | BC_PARSE_FLAG_LOOP)); - flags |= BC_PARSE_FLAG_BODY; - - size = p->bf_top - p->bf_base; - p->bf_base = xrealloc(p->bf_base, size + 2); - p->bf_top = p->bf_base + size + 1; - *p->bf_top = flags; -} - static void bc_parse_noElse(BcParse *p) { BcInstPtr *ip; @@ -4127,6 +4144,7 @@ static void bc_parse_noElse(BcParse *p) ip = bc_vec_top(&p->exits); label = bc_vec_item(&p->func->labels, ip->idx); + dbg_lex("%s:%d rewriting label: %d -> %d", __func__, __LINE__, *label, p->func->code.len); *label = p->func->code.len; bc_vec_pop(&p->exits); @@ -4158,7 +4176,7 @@ static BC_STATUS zbc_parse_if(BcParse *p) bc_parse_pushIndex(p, ip.idx); bc_vec_push(&p->exits, &ip); bc_vec_push(&p->func->labels, &ip.idx); - bc_parse_startBody(p, BC_PARSE_FLAG_IF); + bc_parse_push_block_flag(p, BC_PARSE_FLAG_IF); dbg_lex_done("%s:%d done", __func__, __LINE__); RETURN_STATUS(BC_STATUS_SUCCESS); @@ -4178,6 +4196,7 @@ static BC_STATUS zbc_parse_else(BcParse *p) ip.idx = p->func->labels.len; ip.func = ip.len = 0; + dbg_lex("%s:%d after if() body: BC_INST_JUMP to %d", __func__, __LINE__, ip.idx); bc_parse_push(p, BC_INST_JUMP); bc_parse_pushIndex(p, ip.idx); @@ -4186,7 +4205,7 @@ static BC_STATUS zbc_parse_else(BcParse *p) bc_vec_push(&p->exits, &ip); bc_vec_push(&p->func->labels, &ip.idx); - bc_parse_startBody(p, BC_PARSE_FLAG_ELSE); + bc_parse_push_block_flag(p, BC_PARSE_FLAG_ELSE); dbg_lex_done("%s:%d done", __func__, __LINE__); RETURN_STATUS(zbc_lex_next(&p->l)); @@ -4226,7 +4245,7 @@ static BC_STATUS zbc_parse_while(BcParse *p) bc_parse_push(p, BC_INST_JUMP_ZERO); bc_parse_pushIndex(p, ip.idx); - bc_parse_startBody(p, BC_PARSE_FLAG_LOOP | BC_PARSE_FLAG_LOOP_INNER); + bc_parse_push_block_flag(p, BC_PARSE_FLAG_LOOP | BC_PARSE_FLAG_LOOP_INNER); RETURN_STATUS(BC_STATUS_SUCCESS); } @@ -4305,7 +4324,7 @@ static BC_STATUS zbc_parse_for(BcParse *p) bc_vec_push(&p->func->labels, &ip.idx); s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); - bc_parse_startBody(p, BC_PARSE_FLAG_LOOP | BC_PARSE_FLAG_LOOP_INNER); + bc_parse_push_block_flag(p, BC_PARSE_FLAG_LOOP | BC_PARSE_FLAG_LOOP_INNER); RETURN_STATUS(BC_STATUS_SUCCESS); } @@ -4412,7 +4431,7 @@ static BC_STATUS zbc_parse_func(BcParse *p) if (comma) RETURN_STATUS(bc_error("bad function definition")); flags = BC_PARSE_FLAG_FUNC | BC_PARSE_FLAG_FUNC_INNER | BC_PARSE_FLAG_BODY; - bc_parse_startBody(p, flags); + bc_parse_push_block_flag(p, flags); s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); @@ -4513,7 +4532,7 @@ static BC_STATUS zbc_parse_body(BcParse *p, bool brace) else { dbg_lex("%s:%d !BC_PARSE_FLAG_FUNC_INNER", __func__, __LINE__); s = zbc_parse_stmt(p); - if (!s && !brace) s = zbc_parse_endBody(p); + if (!s && !brace && !BC_PARSE_BODY(p)) s = zbc_parse_endBody(p); } dbg_lex_done("%s:%d done", __func__, __LINE__); @@ -4657,7 +4676,7 @@ static BC_STATUS zbc_parse_stmt(BcParse *p) # define zbc_parse_stmt(...) (zbc_parse_stmt(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static BC_STATUS zbc_parse_parse(BcParse *p) +static BC_STATUS zbc_parse_stmt_or_funcdef(BcParse *p) { BcStatus s; @@ -4683,7 +4702,7 @@ static BC_STATUS zbc_parse_parse(BcParse *p) RETURN_STATUS(s); } #if ERRORS_ARE_FATAL -# define zbc_parse_parse(...) (zbc_parse_parse(__VA_ARGS__), BC_STATUS_SUCCESS) +# define zbc_parse_stmt_or_funcdef(...) (zbc_parse_stmt_or_funcdef(__VA_ARGS__), BC_STATUS_SUCCESS) #endif // This is not a "z" function: can also return BC_STATUS_PARSE_EMPTY_EXP @@ -4964,14 +4983,6 @@ static BC_STATUS zbc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) # define zbc_parse_expr(...) (zbc_parse_expr(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static BC_STATUS zbc_parse_expression(BcParse *p, uint8_t flags) -{ - RETURN_STATUS(zbc_parse_expr(p, flags, bc_parse_next_read)); -} -#if ERRORS_ARE_FATAL -# define zbc_parse_expression(...) (zbc_parse_expression(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif - #endif // ENABLE_BC #if ENABLE_DC @@ -5190,9 +5201,9 @@ static BC_STATUS zdc_parse_parse(BcParse *p) static BC_STATUS zcommon_parse_expr(BcParse *p, uint8_t flags) { if (IS_BC) { - IF_BC(RETURN_STATUS(zbc_parse_expression(p, flags));) + IF_BC(RETURN_STATUS(zbc_parse_expr(p, flags, bc_parse_next_read))); } else { - IF_DC(RETURN_STATUS(zdc_parse_expr(p, flags));) + IF_DC(RETURN_STATUS(zdc_parse_expr(p, flags))); } } #if ERRORS_ARE_FATAL @@ -6720,10 +6731,12 @@ static BC_STATUS zbc_program_exec(void) BcStatus s = BC_STATUS_SUCCESS; char inst = code[(ip->idx)++]; + dbg_exec("inst:%d", inst); switch (inst) { #if ENABLE_BC case BC_INST_JUMP_ZERO: { bool zero; + dbg_exec("BC_INST_JUMP_ZERO:"); s = zbc_program_prep(&ptr, &num); if (s) RETURN_STATUS(s); zero = (bc_num_cmp(num, &G.prog.zero) == 0); @@ -6737,16 +6750,19 @@ static BC_STATUS zbc_program_exec(void) case BC_INST_JUMP: { size_t idx = bc_program_index(code, &ip->idx); size_t *addr = bc_vec_item(&func->labels, idx); + dbg_exec("BC_INST_JUMP: to %ld", (long)*addr); ip->idx = *addr; break; } case BC_INST_CALL: + dbg_exec("BC_INST_CALL:"); s = zbc_program_call(code, &ip->idx); break; case BC_INST_INC_PRE: case BC_INST_DEC_PRE: case BC_INST_INC_POST: case BC_INST_DEC_POST: + dbg_exec("BC_INST_INCDEC:"); s = zbc_program_incdec(inst); break; case BC_INST_HALT: @@ -6754,6 +6770,7 @@ static BC_STATUS zbc_program_exec(void) break; case BC_INST_RET: case BC_INST_RET0: + dbg_exec("BC_INST_RET[0]:"); s = zbc_program_return(inst); break; case BC_INST_BOOL_OR: @@ -6765,16 +6782,20 @@ static BC_STATUS zbc_program_exec(void) case BC_INST_REL_NE: case BC_INST_REL_LT: case BC_INST_REL_GT: + dbg_exec("BC_INST_BOOL:"); s = zbc_program_logical(inst); break; case BC_INST_READ: + dbg_exec("BC_INST_READ:"); s = zbc_program_read(); break; case BC_INST_VAR: + dbg_exec("BC_INST_VAR:"); s = zbc_program_pushVar(code, &ip->idx, false, false); break; case BC_INST_ARRAY_ELEM: case BC_INST_ARRAY: + dbg_exec("BC_INST_ARRAY[_ELEM]:"); s = zbc_program_pushArray(code, &ip->idx, inst); break; case BC_INST_LAST: @@ -6789,28 +6810,34 @@ static BC_STATUS zbc_program_exec(void) case BC_INST_SCALE_FUNC: case BC_INST_LENGTH: case BC_INST_SQRT: + dbg_exec("BC_INST_builtin:"); s = zbc_program_builtin(inst); break; case BC_INST_NUM: + dbg_exec("BC_INST_NUM:"); r.t = BC_RESULT_CONSTANT; r.d.id.idx = bc_program_index(code, &ip->idx); bc_vec_push(&G.prog.results, &r); break; case BC_INST_POP: + dbg_exec("BC_INST_POP:"); if (!BC_PROG_STACK(&G.prog.results, 1)) s = bc_error_stack_has_too_few_elements(); else bc_vec_pop(&G.prog.results); break; case BC_INST_POP_EXEC: + dbg_exec("BC_INST_POP_EXEC:"); bc_vec_pop(&G.prog.stack); break; case BC_INST_PRINT: case BC_INST_PRINT_POP: case BC_INST_PRINT_STR: + dbg_exec("BC_INST_PRINTxyz:"); s = zbc_program_print(inst, 0); break; case BC_INST_STR: + dbg_exec("BC_INST_STR:"); r.t = BC_RESULT_STR; r.d.id.idx = bc_program_index(code, &ip->idx); bc_vec_push(&G.prog.results, &r); @@ -6821,9 +6848,11 @@ static BC_STATUS zbc_program_exec(void) case BC_INST_MODULUS: case BC_INST_PLUS: case BC_INST_MINUS: + dbg_exec("BC_INST_binaryop:"); s = zbc_program_op(inst); break; case BC_INST_BOOL_NOT: + dbg_exec("BC_INST_BOOL_NOT:"); s = zbc_program_prep(&ptr, &num); if (s) RETURN_STATUS(s); bc_num_init_DEF_SIZE(&r.d.n); @@ -6833,6 +6862,7 @@ static BC_STATUS zbc_program_exec(void) bc_program_retire(&r, BC_RESULT_TEMP); break; case BC_INST_NEG: + dbg_exec("BC_INST_NEG:"); s = zbc_program_negate(); break; #if ENABLE_BC @@ -6844,6 +6874,7 @@ static BC_STATUS zbc_program_exec(void) case BC_INST_ASSIGN_MINUS: #endif case BC_INST_ASSIGN: + dbg_exec("BC_INST_ASSIGNxyz:"); s = zbc_program_assign(inst); break; #if ENABLE_DC diff --git a/testsuite/bc.tests b/testsuite/bc.tests index 5e8c47c0f..79ece2669 100755 --- a/testsuite/bc.tests +++ b/testsuite/bc.tests @@ -26,6 +26,26 @@ testing "bc string 1" \ "STR\n" \ "" "\"STR\n\"" +testing "bc if 0 else" \ + "bc" \ + "2\n9\n" \ + "" "if (0) 1 else 2; 9" + +testing "bc if 1 else" \ + "bc" \ + "1\n9\n" \ + "" "if (1) 1 else 2; 9" + +testing "bc if 1 if 1 else else" \ + "bc" \ + "1\n9\n" \ + "" "if (1) if (1) 1 else 2 else 3; 9" + +testing "bc if 0 else if 1" \ + "bc" \ + "2\n9\n" \ + "" "if (0) 1 else if (1) 2; 9" + tar xJf bc_large.tar.xz for f in bc*.bc; do -- cgit v1.2.3-55-g6feb From d1d29b4245a29e56ca598d7a03d93bdf11ebc5d0 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 16 Dec 2018 16:03:03 +0100 Subject: bc: partially rewrite parser, tests pass, ^C might be broken now The entire control construct (if/while/for/funcdef) or {} block is "eaten" by the corresponding parsing function, instead of maintaining special "block flag stack" with magic bits in it, and returning to main input loop after every inner statement (every input line, essentially). This required moving line input deep into lexer - now zbc_lex_next() triggers more reading when needed. "block flag stack" is gone. Correctness of ^C handling wasn't checked, might need fixing now. if/else syntax is changed to match GNU bc: "else" can not be on the next line (the rationale is that "if (1) 2" statement in interactive mode should execute and print 2 instead of waiting for possible "else ..." line). This change fixes the following examples: if (1) if (1) 1 else 2 else 3 if (0) 1 else if (1) 2 define w() { auto z; return 1; } function old new delta zbc_parse_stmt_possibly_auto - 2232 +2232 zbc_vm_process 89 561 +472 zbc_lex_next 1982 2296 +314 bc_vm_init 749 757 +8 bc_parse_expr_empty_ok 2016 2021 +5 bc_num_printNewline 54 51 -3 zbc_program_read 289 280 -9 bc_parse_free 47 38 -9 bc_parse_reset 126 113 -13 bc_parse_create 108 92 -16 bc_parse_push_block_flag 47 - -47 bc_parse_noElse 48 - -48 zbc_parse_text_init 113 59 -54 zbc_parse_body 121 - -121 zbc_parse_else 125 - -125 zbc_parse_endBody 254 - -254 bc_vm_run 421 134 -287 zbc_parse_auto 290 - -290 zcommon_parse 476 - -476 zbc_parse_stmt 1682 7 -1675 ------------------------------------------------------------------------------ (add/remove: 1/7 grow/shrink: 4/8 up/down: 3031/-3427) Total: -396 bytes text data bss dec hex filename 982586 485 7296 990367 f1c9f busybox_old 982138 485 7296 989919 f1adf busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 631 +++++++++++++++++++++----------------------------- testsuite/bc.tests | 5 + testsuite/bc_misc2.bc | 3 +- 3 files changed, 266 insertions(+), 373 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 374279889..95ba8b094 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -171,7 +171,7 @@ #define DEBUG_EXEC 0 #if DEBUG_LEXER -static unsigned lex_indent; +static uint8_t lex_indent; #define dbg_lex(...) \ do { \ fprintf(stderr, "%*s", lex_indent, ""); \ @@ -558,19 +558,16 @@ enum { #endif typedef struct BcLex { - const char *buf; size_t i; size_t line; size_t len; bool newline; - struct { BcLexType t; BcLexType last; BcVec v; } t; - } BcLex; #define BC_PARSE_STREND ((char) UCHAR_MAX) @@ -581,37 +578,9 @@ typedef struct BcLex { #define BC_PARSE_NOREAD (1 << 3) #define BC_PARSE_ARRAY (1 << 4) -#define BC_PARSE_TOP_FLAG_PTR(parse) ((parse)->bf_top) -#define BC_PARSE_TOP_FLAG(parse) (*(BC_PARSE_TOP_FLAG_PTR(parse))) -#define BC_PARSE_FLAG_STACK_EMPTY(p) ((p)->bf_top == (p)->bf_base) - -#define BC_PARSE_FLAG_FUNC_INNER (1 << 0) -#define BC_PARSE_FLAG_FUNC (1 << 1) -#define BC_PARSE_FLAG_BODY (1 << 2) -#define BC_PARSE_FLAG_LOOP (1 << 3) -#define BC_PARSE_FLAG_LOOP_INNER (1 << 4) -#define BC_PARSE_FLAG_IF (1 << 5) -#define BC_PARSE_FLAG_ELSE (1 << 6) -#define BC_PARSE_FLAG_IF_END (1 << 7) - -// If we have none of the above bits, we can stop parsing and execute already parsed chunk -#define BC_PARSE_CAN_EXEC(parse) (BC_PARSE_TOP_FLAG(parse) == 0) - -#define BC_PARSE_FUNC_INNER(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_FUNC_INNER) -#define BC_PARSE_FUNC(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_FUNC) -#define BC_PARSE_BODY(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_BODY) -#define BC_PARSE_LOOP(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_LOOP) -#define BC_PARSE_LOOP_INNER(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_LOOP_INNER) -#define BC_PARSE_IF(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_IF) -#define BC_PARSE_ELSE(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_ELSE) -#define BC_PARSE_IF_END(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_IF_END) - typedef struct BcParse { BcLex l; - uint8_t *bf_base; - uint8_t *bf_top; - BcVec exits; BcVec conds; @@ -620,9 +589,8 @@ typedef struct BcParse { BcFunc *func; size_t fidx; +//TODO: needed? Example? size_t nbraces; -//FIXME: "define w(x) { auto z; return 1; }" fails to parse - bool auto_part; } BcParse; typedef struct BcProgram { @@ -666,26 +634,6 @@ typedef struct BcProgram { } BcProgram; -static void bc_parse_push_block_flag(BcParse *p, uint8_t flags) -{ - size_t size; - uint8_t *flag_ptr = BC_PARSE_TOP_FLAG_PTR(p); - flags |= (*flag_ptr & (BC_PARSE_FLAG_FUNC | BC_PARSE_FLAG_LOOP)); - flags |= BC_PARSE_FLAG_BODY; - - size = p->bf_top - p->bf_base; - p->bf_base = xrealloc(p->bf_base, size + 2); - p->bf_top = p->bf_base + size + 1; - dbg_lex("%s:%d pushed block flag lvl:%d bits:0x%02x", __func__, __LINE__, size + 1, flags); - *p->bf_top = flags; -} - -static ALWAYS_INLINE void bc_parse_pop_block_flag(BcParse *p) -{ - p->bf_top--; - dbg_lex("%s:%d popped block flag lvl:%d bits:0x%02x", __func__, __LINE__, p->bf_top - p->bf_base, *p->bf_top); -} - #define BC_PROG_STACK(s, n) ((s)->len >= ((size_t) n)) #define BC_PROG_MAIN (0) @@ -747,6 +695,7 @@ struct globals { IF_FEATURE_BC_SIGNALS(smallint ttyin;) IF_FEATURE_CLEAN_UP(smallint exiting;) smallint in_read; + smallint use_stdin; BcParse prs; BcProgram prog; @@ -756,6 +705,7 @@ struct globals { unsigned err_line; BcVec files; + BcVec stdin_buffer; char *env_args; @@ -1052,6 +1002,7 @@ static void quit(void) if (ferror(stdin)) bb_perror_msg_and_die("input error"); fflush_and_check(); + dbg_exec("quit(): exiting with exitcode SUCCESS"); exit(0); } @@ -2955,6 +2906,79 @@ static BC_STATUS zcommon_lex_token(BcLex *l) IF_DC(RETURN_STATUS(zdc_lex_token(l));) } +static bool bc_lex_more_input(BcLex *l) +{ + size_t str; + bool comment; + + bc_vec_pop_all(&G.stdin_buffer); + + // This loop is complex because the vm tries not to send any lines that end + // with a backslash to the parser. The reason for that is because the parser + // treats a backslash+newline combo as whitespace, per the bc spec. In that + // case, and for strings and comments, the parser will expect more stuff. + comment = false; + str = 0; + for (;;) { + size_t prevlen = G.stdin_buffer.len; + char *string; + + bc_read_line(&G.stdin_buffer); + // No more input means EOF + if (G.stdin_buffer.len <= prevlen + 1) // (we expect +1 for NUL byte) + break; + + string = G.stdin_buffer.v + prevlen; + while (*string) { + char c = *string; + if (string == G.stdin_buffer.v || string[-1] != '\\') { + if (IS_BC) + str ^= (c == '"'); + else { + if (c == ']') + str -= 1; + else if (c == '[') + str += 1; + } + } + string++; + if (c == '/' && *string == '*') { + comment = true; + string++; + continue; + } + if (c == '*' && *string == '/') { + comment = false; + string++; + } + } + if (str != 0 || comment) { + G.stdin_buffer.len--; // backstep over the trailing NUL byte + continue; + } + + // Check for backslash+newline. + // we do not check that last char is '\n' - + // if it is not, then it's EOF, and looping back + // to bc_read_line() will detect it: + string -= 2; + if (string >= G.stdin_buffer.v && *string == '\\') { + G.stdin_buffer.len--; + continue; + } + + break; + } + + l->buf = G.stdin_buffer.v; + l->i = 0; +//bb_error_msg("G.stdin_buffer.len:%d '%s'", G.stdin_buffer.len, G.stdin_buffer.v); + l->len = G.stdin_buffer.len - 1; // do not include NUL + + G.use_stdin = (l->len != 0); + return G.use_stdin; +} + static BC_STATUS zbc_lex_next(BcLex *l) { BcStatus s; @@ -2964,10 +2988,16 @@ static BC_STATUS zbc_lex_next(BcLex *l) l->line += l->newline; G.err_line = l->line; - l->t.t = BC_LEX_EOF; + l->t.t = BC_LEX_EOF; +//this NL handling is bogus l->newline = (l->i == l->len); - if (l->newline) RETURN_STATUS(BC_STATUS_SUCCESS); + if (l->newline) { + if (!G.use_stdin || !bc_lex_more_input(l)) + RETURN_STATUS(BC_STATUS_SUCCESS); + // here it's guaranteed that l->i is below l->len + l->newline = false; + } // Loop until failure or we don't have whitespace. This // is so the parser doesn't get inundated with whitespace. @@ -3528,19 +3558,8 @@ static BC_STATUS zcommon_parse(BcParse *p) static BC_STATUS zbc_parse_text_init(BcParse *p, const char *text) { - BcStatus s; - p->func = bc_program_func(p->fidx); - if (!text[0] && !BC_PARSE_CAN_EXEC(p)) { - p->l.t.t = BC_LEX_INVALID; - s = BC_STATUS_SUCCESS; - ERROR_RETURN(s =) zcommon_parse(p); - if (s) RETURN_STATUS(s); - if (!BC_PARSE_CAN_EXEC(p)) - RETURN_STATUS(bc_error("file is not executable")); - } - RETURN_STATUS(zbc_lex_text_init(&p->l, text)); } #if ERRORS_ARE_FATAL @@ -3580,9 +3599,8 @@ static void bc_parse_reset(BcParse *p) p->l.i = p->l.len; p->l.t.t = BC_LEX_EOF; - p->auto_part = (p->nbraces = 0); + p->nbraces = 0; - p->bf_top = p->bf_base; // pop all flags bc_vec_pop_all(&p->exits); bc_vec_pop_all(&p->conds); bc_vec_pop_all(&p->ops); @@ -3592,7 +3610,6 @@ static void bc_parse_reset(BcParse *p) static void bc_parse_free(BcParse *p) { - free(p->bf_base); bc_vec_free(&p->exits); bc_vec_free(&p->conds); bc_vec_free(&p->ops); @@ -3604,12 +3621,11 @@ static void bc_parse_create(BcParse *p, size_t func) memset(p, 0, sizeof(BcParse)); bc_lex_init(&p->l); - p->bf_top = p->bf_base = xzalloc(1); bc_vec_init(&p->exits, sizeof(BcInstPtr), NULL); bc_vec_init(&p->conds, sizeof(size_t), NULL); bc_vec_init(&p->ops, sizeof(BcLexType), NULL); - // p->auto_part = p->nbraces = 0; - already is + // p->nbraces = 0; - already is bc_parse_updateFunc(p, func); } @@ -3625,14 +3641,20 @@ static void bc_parse_create(BcParse *p, size_t func) // first in the expr enum. Note: This only works for binary operators. #define BC_TOKEN_2_INST(t) ((char) ((t) - BC_LEX_NEG + BC_INST_NEG)) -static BC_STATUS zbc_parse_else(BcParse *p); -static BC_STATUS zbc_parse_stmt(BcParse *p); +static BC_STATUS zbc_parse_stmt_possibly_auto(BcParse *p, bool auto_allowed); static BC_STATUS zbc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next); static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext next); #if ERRORS_ARE_FATAL -# define zbc_parse_else(...) (zbc_parse_else(__VA_ARGS__), BC_STATUS_SUCCESS) -# define zbc_parse_stmt(...) (zbc_parse_stmt(__VA_ARGS__), BC_STATUS_SUCCESS) # define zbc_parse_expr(...) (zbc_parse_expr(__VA_ARGS__), BC_STATUS_SUCCESS) +# defone zbc_parse_stmt_possibly_auto(...) (zbc_parse_stmt_possibly_auto(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif + +static BC_STATUS zbc_parse_stmt(BcParse *p) +{ + RETURN_STATUS(zbc_parse_stmt_possibly_auto(p, false)); +} +#if ERRORS_ARE_FATAL +# define zbc_parse_stmt(...) (zbc_parse_stmt(__VA_ARGS__), BC_STATUS_SUCCESS) #endif static void bc_parse_operator(BcParse *p, BcLexType type, size_t start, @@ -4037,7 +4059,7 @@ static BC_STATUS zbc_parse_return(BcParse *p) BcLexType t; bool paren; - if (!BC_PARSE_FUNC(p)) RETURN_STATUS(bc_error_bad_token()); + dbg_lex_enter("%s:%d entered", __func__, __LINE__); s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); @@ -4063,97 +4085,62 @@ static BC_STATUS zbc_parse_return(BcParse *p) bc_parse_push(p, BC_INST_RET); } + dbg_lex_done("%s:%d done", __func__, __LINE__); RETURN_STATUS(s); } #if ERRORS_ARE_FATAL # define zbc_parse_return(...) (zbc_parse_return(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static BC_STATUS zbc_parse_endBody(BcParse *p) +static void bc_parse_noElse(BcParse *p) { - BcStatus s = BC_STATUS_SUCCESS; - - if (BC_PARSE_FLAG_STACK_EMPTY(p)) - RETURN_STATUS(bc_error_bad_token()); - - if (BC_PARSE_IF(p)) { - uint8_t *flag_ptr; + BcInstPtr *ip; + size_t *label; - while (p->l.t.t == BC_LEX_NLINE) { - s = zbc_lex_next(&p->l); - if (s) RETURN_STATUS(s); - } + ip = bc_vec_top(&p->exits); + label = bc_vec_item(&p->func->labels, ip->idx); + dbg_lex("%s:%d rewriting label: %d -> %d", __func__, __LINE__, *label, p->func->code.len); + *label = p->func->code.len; - bc_parse_pop_block_flag(p); + bc_vec_pop(&p->exits); +} - flag_ptr = BC_PARSE_TOP_FLAG_PTR(p); - dbg_lex("%s:%d setting BC_PARSE_FLAG_IF_END bit", __func__, __LINE__); - *flag_ptr = (*flag_ptr | BC_PARSE_FLAG_IF_END); +static BC_STATUS zbc_parse_else(BcParse *p) +{ + BcStatus s; + BcInstPtr ip; - if (p->l.t.t == BC_LEX_KEY_ELSE) - s = zbc_parse_else(p); - } - else if (BC_PARSE_ELSE(p)) { - BcInstPtr *ip; - size_t *label; + dbg_lex_enter("%s:%d entered", __func__, __LINE__); - ip = bc_vec_top(&p->exits); - label = bc_vec_item(&p->func->labels, ip->idx); - dbg_lex("%s:%d rewriting label: %d -> %d", __func__, __LINE__, *label, p->func->code.len); - *label = p->func->code.len; + ip.idx = p->func->labels.len; + ip.func = ip.len = 0; - bc_vec_pop(&p->exits); - bc_parse_pop_block_flag(p); - } - else if (BC_PARSE_FUNC_INNER(p)) { - bc_parse_push(p, BC_INST_RET0); - bc_parse_updateFunc(p, BC_PROG_MAIN); - bc_parse_pop_block_flag(p); - } - else { - BcInstPtr *ip = bc_vec_top(&p->exits); - size_t *label = bc_vec_top(&p->conds); + dbg_lex("%s:%d after if() body: BC_INST_JUMP to %d", __func__, __LINE__, ip.idx); + bc_parse_push(p, BC_INST_JUMP); + bc_parse_pushIndex(p, ip.idx); - dbg_lex("%s:%d BC_INST_JUMP to %d", __func__, __LINE__, *label); - bc_parse_push(p, BC_INST_JUMP); - bc_parse_pushIndex(p, *label); + dbg_lex("%s:%d calling bc_parse_noElse()", __func__, __LINE__); + bc_parse_noElse(p); - label = bc_vec_item(&p->func->labels, ip->idx); - dbg_lex("%s:%d rewriting label: %d -> %d", __func__, __LINE__, *label, p->func->code.len); - *label = p->func->code.len; + bc_vec_push(&p->exits, &ip); + bc_vec_push(&p->func->labels, &ip.idx); - bc_vec_pop(&p->exits); - bc_vec_pop(&p->conds); - bc_parse_pop_block_flag(p); - } + s = zbc_parse_stmt(p); + if (s) RETURN_STATUS(s); + dbg_lex_done("%s:%d done", __func__, __LINE__); RETURN_STATUS(s); } #if ERRORS_ARE_FATAL -# define zbc_parse_endBody(...) (zbc_parse_endBody(__VA_ARGS__), BC_STATUS_SUCCESS) +# define zbc_parse_else(...) (zbc_parse_else(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static void bc_parse_noElse(BcParse *p) -{ - BcInstPtr *ip; - size_t *label; - uint8_t *flag_ptr = BC_PARSE_TOP_FLAG_PTR(p); - - dbg_lex("%s:%d clearing BC_PARSE_FLAG_IF_END bit", __func__, __LINE__); - *flag_ptr = (*flag_ptr & ~(BC_PARSE_FLAG_IF_END)); - - ip = bc_vec_top(&p->exits); - label = bc_vec_item(&p->func->labels, ip->idx); - dbg_lex("%s:%d rewriting label: %d -> %d", __func__, __LINE__, *label, p->func->code.len); - *label = p->func->code.len; - - bc_vec_pop(&p->exits); -} - static BC_STATUS zbc_parse_if(BcParse *p) { BcStatus s; BcInstPtr ip; + BcInstPtr *ipp; + size_t *label; dbg_lex_enter("%s:%d entered", __func__, __LINE__); s = zbc_lex_next(&p->l); @@ -4164,60 +4151,50 @@ static BC_STATUS zbc_parse_if(BcParse *p) if (s) RETURN_STATUS(s); s = zbc_parse_expr(p, BC_PARSE_REL, bc_parse_next_rel); if (s) RETURN_STATUS(s); - if (p->l.t.t != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); + if (p->l.t.t != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); - bc_parse_push(p, BC_INST_JUMP_ZERO); + bc_parse_push(p, BC_INST_JUMP_ZERO); ip.idx = p->func->labels.len; ip.func = ip.len = 0; - bc_parse_pushIndex(p, ip.idx); +//TODO: can get rid of p->exits stack? bc_vec_push(&p->exits, &ip); bc_vec_push(&p->func->labels, &ip.idx); - bc_parse_push_block_flag(p, BC_PARSE_FLAG_IF); - dbg_lex_done("%s:%d done", __func__, __LINE__); - RETURN_STATUS(BC_STATUS_SUCCESS); -} -#if ERRORS_ARE_FATAL -# define zbc_parse_if(...) (zbc_parse_if(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif - -#undef zbc_parse_else -static BC_STATUS zbc_parse_else(BcParse *p) -{ - BcInstPtr ip; - - dbg_lex_enter("%s:%d entered", __func__, __LINE__); - if (!BC_PARSE_IF_END(p)) RETURN_STATUS(bc_error_bad_token()); - - ip.idx = p->func->labels.len; - ip.func = ip.len = 0; - - dbg_lex("%s:%d after if() body: BC_INST_JUMP to %d", __func__, __LINE__, ip.idx); - bc_parse_push(p, BC_INST_JUMP); - bc_parse_pushIndex(p, ip.idx); + s = zbc_parse_stmt(p); + if (s) RETURN_STATUS(s); + dbg_lex("%s:%d in if after stmt: p->l.t.t:%d", __func__, __LINE__, p->l.t.t); + if (p->l.t.t == BC_LEX_KEY_ELSE) { + s = zbc_lex_next(&p->l); + if (s) RETURN_STATUS(s); + dbg_lex("%s:%d calling zbc_parse_else(), p->l.t.t:%d", __func__, __LINE__, p->l.t.t); + s = zbc_parse_else(p); + } - dbg_lex("%s:%d calling bc_parse_noElse()", __func__, __LINE__); - bc_parse_noElse(p); + ipp = bc_vec_top(&p->exits); + label = bc_vec_item(&p->func->labels, ipp->idx); + dbg_lex("%s:%d rewriting label: %d -> %d", __func__, __LINE__, *label, p->func->code.len); + *label = p->func->code.len; - bc_vec_push(&p->exits, &ip); - bc_vec_push(&p->func->labels, &ip.idx); - bc_parse_push_block_flag(p, BC_PARSE_FLAG_ELSE); + bc_vec_pop(&p->exits); dbg_lex_done("%s:%d done", __func__, __LINE__); - RETURN_STATUS(zbc_lex_next(&p->l)); + RETURN_STATUS(s); } #if ERRORS_ARE_FATAL -# define zbc_parse_else(...) (zbc_parse_else(__VA_ARGS__), BC_STATUS_SUCCESS) +# define zbc_parse_if(...) (zbc_parse_if(__VA_ARGS__), BC_STATUS_SUCCESS) #endif static BC_STATUS zbc_parse_while(BcParse *p) { BcStatus s; BcInstPtr ip; + BcInstPtr *ipp; + size_t *label; + size_t n; s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); @@ -4245,9 +4222,29 @@ static BC_STATUS zbc_parse_while(BcParse *p) bc_parse_push(p, BC_INST_JUMP_ZERO); bc_parse_pushIndex(p, ip.idx); - bc_parse_push_block_flag(p, BC_PARSE_FLAG_LOOP | BC_PARSE_FLAG_LOOP_INNER); - RETURN_STATUS(BC_STATUS_SUCCESS); + s = zbc_parse_stmt(p); + if (s) RETURN_STATUS(s); + + n = *((size_t *) bc_vec_top(&p->conds)); + bc_parse_push(p, BC_INST_JUMP); + bc_parse_pushIndex(p, n); + + ipp = bc_vec_top(&p->exits); + label = bc_vec_top(&p->conds); + + dbg_lex("%s:%d BC_INST_JUMP to %d", __func__, __LINE__, *label); + bc_parse_push(p, BC_INST_JUMP); + bc_parse_pushIndex(p, *label); + + label = bc_vec_item(&p->func->labels, ipp->idx); + dbg_lex("%s:%d rewriting label: %d -> %d", __func__, __LINE__, *label, p->func->code.len); + *label = p->func->code.len; + + bc_vec_pop(&p->exits); + bc_vec_pop(&p->conds); + + RETURN_STATUS(s); } #if ERRORS_ARE_FATAL # define zbc_parse_while(...) (zbc_parse_while(__VA_ARGS__), BC_STATUS_SUCCESS) @@ -4257,7 +4254,10 @@ static BC_STATUS zbc_parse_for(BcParse *p) { BcStatus s; BcInstPtr ip; + BcInstPtr *ipp; + size_t *label; size_t cond_idx, exit_idx, body_idx, update_idx; + size_t n; dbg_lex("%s:%d p->l.t.t:%d", __func__, __LINE__, p->l.t.t); s = zbc_lex_next(&p->l); @@ -4324,7 +4324,28 @@ static BC_STATUS zbc_parse_for(BcParse *p) bc_vec_push(&p->func->labels, &ip.idx); s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); - bc_parse_push_block_flag(p, BC_PARSE_FLAG_LOOP | BC_PARSE_FLAG_LOOP_INNER); + + s = zbc_parse_stmt(p); + if (s) RETURN_STATUS(s); + + n = *((size_t *) bc_vec_top(&p->conds)); + bc_parse_push(p, BC_INST_JUMP); + bc_parse_pushIndex(p, n); + + ipp = bc_vec_top(&p->exits); + label = bc_vec_top(&p->conds); + +//TODO: commonalize? + dbg_lex("%s:%d BC_INST_JUMP to %d", __func__, __LINE__, *label); + bc_parse_push(p, BC_INST_JUMP); + bc_parse_pushIndex(p, *label); + + label = bc_vec_item(&p->func->labels, ipp->idx); + dbg_lex("%s:%d rewriting label: %d -> %d", __func__, __LINE__, *label, p->func->code.len); + *label = p->func->code.len; + + bc_vec_pop(&p->exits); + bc_vec_pop(&p->conds); RETURN_STATUS(BC_STATUS_SUCCESS); } @@ -4332,14 +4353,12 @@ static BC_STATUS zbc_parse_for(BcParse *p) # define zbc_parse_for(...) (zbc_parse_for(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static BC_STATUS zbc_parse_loopExit(BcParse *p, BcLexType type) +static BC_STATUS zbc_parse_break_or_continue(BcParse *p, BcLexType type) { BcStatus s; size_t i; BcInstPtr *ip; - if (!BC_PARSE_LOOP(p)) RETURN_STATUS(bc_error_bad_token()); - if (type == BC_LEX_KEY_BREAK) { if (p->exits.len == 0) RETURN_STATUS(bc_error_bad_token()); @@ -4368,14 +4387,13 @@ static BC_STATUS zbc_parse_loopExit(BcParse *p, BcLexType type) RETURN_STATUS(zbc_lex_next(&p->l)); } #if ERRORS_ARE_FATAL -# define zbc_parse_loopExit(...) (zbc_parse_loopExit(__VA_ARGS__), BC_STATUS_SUCCESS) +# define zbc_parse_break_or_continue(...) (zbc_parse_break_or_continue(__VA_ARGS__), BC_STATUS_SUCCESS) #endif static BC_STATUS zbc_parse_func(BcParse *p) { BcStatus s; bool var, comma = false; - uint8_t flags; char *name; s = zbc_lex_next(&p->l); @@ -4430,15 +4448,18 @@ static BC_STATUS zbc_parse_func(BcParse *p) if (comma) RETURN_STATUS(bc_error("bad function definition")); - flags = BC_PARSE_FLAG_FUNC | BC_PARSE_FLAG_FUNC_INNER | BC_PARSE_FLAG_BODY; - bc_parse_push_block_flag(p, flags); - s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); if (p->l.t.t != BC_LEX_LBRACE) s = bc_POSIX_requires("the left brace be on the same line as the function header"); + s = zbc_parse_stmt_possibly_auto(p, true); + if (s) RETURN_STATUS(s); + + bc_parse_push(p, BC_INST_RET0); + bc_parse_updateFunc(p, BC_PROG_MAIN); + RETURN_STATUS(s); err: @@ -4455,12 +4476,11 @@ static BC_STATUS zbc_parse_auto(BcParse *p) bool comma, var, one; char *name; - if (!p->auto_part) RETURN_STATUS(bc_error_bad_token()); - + dbg_lex_enter("%s:%d entered", __func__, __LINE__); s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); - p->auto_part = comma = false; + comma = false; one = p->l.t.t == BC_LEX_NAME; while (p->l.t.t == BC_LEX_NAME) { @@ -4498,91 +4518,53 @@ static BC_STATUS zbc_parse_auto(BcParse *p) if (p->l.t.t != BC_LEX_NLINE && p->l.t.t != BC_LEX_SCOLON) RETURN_STATUS(bc_error_bad_token()); + dbg_lex_done("%s:%d done", __func__, __LINE__); RETURN_STATUS(zbc_lex_next(&p->l)); err: free(name); + dbg_lex_done("%s:%d done (ERROR)", __func__, __LINE__); RETURN_STATUS(s); } #if ERRORS_ARE_FATAL # define zbc_parse_auto(...) (zbc_parse_auto(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static BC_STATUS zbc_parse_body(BcParse *p, bool brace) +#undef zbc_parse_stmt_possibly_auto +static BC_STATUS zbc_parse_stmt_possibly_auto(BcParse *p, bool auto_allowed) { BcStatus s = BC_STATUS_SUCCESS; - uint8_t *flag_ptr = BC_PARSE_TOP_FLAG_PTR(p); - - dbg_lex_enter("%s:%d entered", __func__, __LINE__); - *flag_ptr &= ~(BC_PARSE_FLAG_BODY); - if (*flag_ptr & BC_PARSE_FLAG_FUNC_INNER) { - dbg_lex("%s:%d BC_PARSE_FLAG_FUNC_INNER", __func__, __LINE__); - if (!brace) RETURN_STATUS(bc_error_bad_token()); - - p->auto_part = p->l.t.t != BC_LEX_KEY_AUTO; - - if (!p->auto_part) { - s = zbc_parse_auto(p); - if (s) RETURN_STATUS(s); - } + dbg_lex_enter("%s:%d entered, p->l.t.t:%d", __func__, __LINE__, p->l.t.t); - if (p->l.t.t == BC_LEX_NLINE) s = zbc_lex_next(&p->l); + if (p->l.t.t == BC_LEX_NLINE) { + dbg_lex_done("%s:%d done (seen BC_LEX_NLINE)", __func__, __LINE__); + RETURN_STATUS(zbc_lex_next(&p->l)); } - else { - dbg_lex("%s:%d !BC_PARSE_FLAG_FUNC_INNER", __func__, __LINE__); - s = zbc_parse_stmt(p); - if (!s && !brace && !BC_PARSE_BODY(p)) s = zbc_parse_endBody(p); + if (p->l.t.t == BC_LEX_SCOLON) { + dbg_lex_done("%s:%d done (seen BC_LEX_SCOLON)", __func__, __LINE__); + RETURN_STATUS(zbc_lex_next(&p->l)); } - dbg_lex_done("%s:%d done", __func__, __LINE__); - RETURN_STATUS(s); -} -#if ERRORS_ARE_FATAL -# define zbc_parse_body(...) (zbc_parse_body(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif - -#undef zbc_parse_stmt -static BC_STATUS zbc_parse_stmt(BcParse *p) -{ - BcStatus s = BC_STATUS_SUCCESS; - - dbg_lex_enter("%s:%d entered, p->l.t.t:%d", __func__, __LINE__, p->l.t.t); - switch (p->l.t.t) { - case BC_LEX_NLINE: - dbg_lex_done("%s:%d done (seen BC_LEX_NLINE)", __func__, __LINE__); - RETURN_STATUS(zbc_lex_next(&p->l)); - - case BC_LEX_KEY_ELSE: - dbg_lex("%s:%d BC_LEX_KEY_ELSE:", __func__, __LINE__); - p->auto_part = false; - break; - - case BC_LEX_LBRACE: - dbg_lex("%s:%d BC_LEX_LBRACE:", __func__, __LINE__); - if (!BC_PARSE_BODY(p)) RETURN_STATUS(bc_error_bad_token()); - ++p->nbraces; + if (p->l.t.t == BC_LEX_LBRACE) { + dbg_lex("%s:%d BC_LEX_LBRACE: (auto_allowed:%d)", __func__, __LINE__, auto_allowed); + do { s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); - dbg_lex_done("%s:%d done (returning zbc_parse_body())", __func__, __LINE__); - RETURN_STATUS(zbc_parse_body(p, true)); - - case BC_LEX_KEY_AUTO: - dbg_lex("%s:%d BC_LEX_KEY_AUTO:", __func__, __LINE__); - RETURN_STATUS(zbc_parse_auto(p)); - - default: - p->auto_part = false; - if (BC_PARSE_IF_END(p)) { - bc_parse_noElse(p); - dbg_lex_done("%s:%d done (BC_PARSE_IF_END is true)", __func__, __LINE__); - RETURN_STATUS(BC_STATUS_SUCCESS); - } - if (BC_PARSE_BODY(p)) { - dbg_lex_done("%s:%d done (returning zbc_parse_body())", __func__, __LINE__); - RETURN_STATUS(zbc_parse_body(p, false)); - } - break; + } while (p->l.t.t == BC_LEX_NLINE); + if (auto_allowed && p->l.t.t == BC_LEX_KEY_AUTO) { + dbg_lex("%s:%d calling zbc_parse_auto()", __func__, __LINE__); + s = zbc_parse_auto(p); + if (s) RETURN_STATUS(s); + } + while (p->l.t.t != BC_LEX_RBRACE) { + dbg_lex("%s:%d block parsing loop", __func__, __LINE__); + s = zbc_parse_stmt(p); + if (s) RETURN_STATUS(s); + } + s = zbc_lex_next(&p->l); + dbg_lex_done("%s:%d done (seen BC_LEX_RBRACE)", __func__, __LINE__); + RETURN_STATUS(s); } dbg_lex("%s:%d p->l.t.t:%d", __func__, __LINE__, p->l.t.t); @@ -4603,26 +4585,12 @@ static BC_STATUS zbc_parse_stmt(BcParse *p) case BC_LEX_KEY_SQRT: s = zbc_parse_expr(p, BC_PARSE_PRINT, bc_parse_next_expr); break; - case BC_LEX_KEY_ELSE: - s = zbc_parse_else(p); - break; - case BC_LEX_SCOLON: - while (!s && p->l.t.t == BC_LEX_SCOLON) s = zbc_lex_next(&p->l); - break; - case BC_LEX_RBRACE: - if (p->nbraces == 0) - RETURN_STATUS(bc_error_bad_token()); - --p->nbraces; - s = zbc_lex_next(&p->l); - if (!s) - s = zbc_parse_endBody(p); - break; case BC_LEX_STR: s = zbc_parse_string(p, BC_INST_PRINT_STR); break; case BC_LEX_KEY_BREAK: case BC_LEX_KEY_CONTINUE: - s = zbc_parse_loopExit(p, p->l.t.t); + s = zbc_parse_break_or_continue(p, p->l.t.t); break; case BC_LEX_KEY_FOR: s = zbc_parse_for(p); @@ -4637,8 +4605,6 @@ static BC_STATUS zbc_parse_stmt(BcParse *p) case BC_LEX_KEY_LIMITS: // "limits" is a compile-time command, // the output is produced at _parse time_. - s = zbc_lex_next(&p->l); - if (s) RETURN_STATUS(s); printf( "BC_BASE_MAX = "BC_MAX_OBASE_STR "\n" "BC_DIM_MAX = "BC_MAX_DIM_STR "\n" @@ -4649,6 +4615,7 @@ static BC_STATUS zbc_parse_stmt(BcParse *p) "MAX Exponent = "BC_MAX_EXP_STR "\n" "Number of vars = "BC_MAX_VARS_STR "\n" ); + s = zbc_lex_next(&p->l); break; case BC_LEX_KEY_PRINT: s = zbc_parse_print(p); @@ -4669,11 +4636,16 @@ static BC_STATUS zbc_parse_stmt(BcParse *p) break; } + if (s || G_interrupt) { + bc_parse_reset(p); + s = BC_STATUS_FAILURE; + } + dbg_lex_done("%s:%d done", __func__, __LINE__); RETURN_STATUS(s); } #if ERRORS_ARE_FATAL -# define zbc_parse_stmt(...) (zbc_parse_stmt(__VA_ARGS__), BC_STATUS_SUCCESS) +# define zbc_parse_stmt_possibly_auto(...) (zbc_parse_stmt_possibly_auto(__VA_ARGS__), BC_STATUS_SUCCESS) #endif static BC_STATUS zbc_parse_stmt_or_funcdef(BcParse *p) @@ -4682,22 +4654,15 @@ static BC_STATUS zbc_parse_stmt_or_funcdef(BcParse *p) dbg_lex_enter("%s:%d entered", __func__, __LINE__); if (p->l.t.t == BC_LEX_EOF) - s = BC_PARSE_FLAG_STACK_EMPTY(p) ? bc_error("end of file") : bc_error("block end could not be found"); + s = bc_error("end of file"); else if (p->l.t.t == BC_LEX_KEY_DEFINE) { dbg_lex("%s:%d p->l.t.t:BC_LEX_KEY_DEFINE", __func__, __LINE__); - if (!BC_PARSE_CAN_EXEC(p)) - RETURN_STATUS(bc_error_bad_token()); s = zbc_parse_func(p); } else { dbg_lex("%s:%d p->l.t.t:%d (not BC_LEX_KEY_DEFINE)", __func__, __LINE__, p->l.t.t); s = zbc_parse_stmt(p); } - if (s || G_interrupt) { - bc_parse_reset(p); - s = BC_STATUS_FAILURE; - } - dbg_lex_done("%s:%d done", __func__, __LINE__); RETURN_STATUS(s); } @@ -4940,6 +4905,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext ne if (prev == BC_INST_BOOL_NOT || nexprs != 1) return bc_error_bad_expression(); +//TODO: why is this needed at all? // next is BcParseNext, byte array of up to 4 BC_LEX's, packed into 32-bit word for (;;) { if (t == (next & 0x7f)) @@ -4948,7 +4914,8 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext ne break; next >>= 8; } - return bc_error_bad_expression(); + if (t != BC_LEX_KEY_ELSE) + return bc_error_bad_expression(); ok: if (!(flags & BC_PARSE_REL) && nrelops) { @@ -6766,6 +6733,7 @@ static BC_STATUS zbc_program_exec(void) s = zbc_program_incdec(inst); break; case BC_INST_HALT: + dbg_exec("BC_INST_HALT:"); QUIT_OR_RETURN_TO_MAIN; break; case BC_INST_RET: @@ -6939,6 +6907,7 @@ static BC_STATUS zbc_program_exec(void) break; } case BC_INST_QUIT: + dbg_exec("BC_INST_NEG:"); if (G.prog.stack.len <= 2) QUIT_OR_RETURN_TO_MAIN; bc_vec_npop(&G.prog.stack, 2); @@ -6994,14 +6963,12 @@ static BC_STATUS zbc_vm_process(const char *text) dbg_lex("%s:%d G.prs.l.t.t:%d", __func__, __LINE__, G.prs.l.t.t); ERROR_RETURN(s =) zcommon_parse(&G.prs); if (s) RETURN_STATUS(s); - } - dbg_lex("%s:%d G.prs.l.t.t:BC_LEX_EOF", __func__, __LINE__); - - if (BC_PARSE_CAN_EXEC(&G.prs)) { s = zbc_program_exec(); - fflush_and_check(); - if (s) + if (s) { bc_program_reset(); + break; + } + fflush_and_check(); } dbg_lex_done("%s:%d done", __func__, __LINE__); @@ -7049,91 +7016,12 @@ err: static BC_STATUS zbc_vm_stdin(void) { BcStatus s; - BcVec buffer; - size_t str; - bool comment; //G.prog.file = NULL; - already is bc_lex_file(&G.prs.l); - bc_char_vec_init(&buffer); - - // This loop is complex because the vm tries not to send any lines that end - // with a backslash to the parser. The reason for that is because the parser - // treats a backslash+newline combo as whitespace, per the bc spec. In that - // case, and for strings and comments, the parser will expect more stuff. - s = BC_STATUS_SUCCESS; - comment = false; - str = 0; - for (;;) { - size_t prevlen = buffer.len; - char *string; - - bc_read_line(&buffer); - // No more input means EOF - if (buffer.len <= prevlen + 1) // (we expect +1 for NUL byte) - break; - - string = buffer.v + prevlen; - while (*string) { - char c = *string; - if (string == buffer.v || string[-1] != '\\') { - if (IS_BC) - str ^= (c == '"'); - else { - if (c == ']') - str -= 1; - else if (c == '[') - str += 1; - } - } - string++; - if (c == '/' && *string == '*') { - comment = true; - string++; - continue; - } - if (c == '*' && *string == '/') { - comment = false; - string++; - } - } - if (str || comment) { - buffer.len--; // backstep over the trailing NUL byte - continue; - } - - // Check for backslash+newline. - // we do not check that last char is '\n' - - // if it is not, then it's EOF, and looping back - // to bc_read_line() will detect it: - string -= 2; - if (string >= buffer.v && *string == '\\') { - buffer.len--; - continue; - } - - s = zbc_vm_process(buffer.v); - if (s) { - if (ENABLE_FEATURE_CLEAN_UP && !G_ttyin) { - // Debug config, non-interactive mode: - // return all the way back to main. - // Non-debug builds do not come here, they exit. - break; - } - } - - bc_vec_pop_all(&buffer); - } - - if (str) { - s = bc_error("string end could not be found"); - } - else if (comment) { - s = bc_error("comment end could not be found"); - } - - bc_vec_free(&buffer); + G.use_stdin = 1; + s = zbc_vm_process(""); RETURN_STATUS(s); } #if ERRORS_ARE_FATAL @@ -7412,9 +7300,6 @@ static BC_STATUS zbc_vm_exec(void) if (IS_BC || (option_mask32 & BC_FLAG_I)) s = zbc_vm_stdin(); - if (!s && !BC_PARSE_CAN_EXEC(&G.prs)) - s = zbc_vm_process(""); - RETURN_STATUS(s); } #if ERRORS_ARE_FATAL @@ -7443,6 +7328,7 @@ static void bc_program_free(void) bc_num_free(&G.prog.last); bc_num_free(&G.prog.zero); bc_num_free(&G.prog.one); + bc_vec_free(&G.stdin_buffer); } static void bc_vm_free(void) @@ -7506,6 +7392,8 @@ static void bc_program_init(void) bc_vec_init(&G.prog.results, sizeof(BcResult), bc_result_free); bc_vec_init(&G.prog.stack, sizeof(BcInstPtr), NULL); bc_vec_push(&G.prog.stack, &ip); + + bc_char_vec_init(&G.stdin_buffer); } static int bc_vm_init(const char *env_len) @@ -7562,6 +7450,7 @@ static BcStatus bc_vm_run(void) # endif FREE_G(); #endif + dbg_exec("exiting with exitcode %d", st); return st; } diff --git a/testsuite/bc.tests b/testsuite/bc.tests index 79ece2669..86220ad19 100755 --- a/testsuite/bc.tests +++ b/testsuite/bc.tests @@ -46,6 +46,11 @@ testing "bc if 0 else if 1" \ "2\n9\n" \ "" "if (0) 1 else if (1) 2; 9" +testing "bc define auto" \ + "bc" \ + "8\n9\n" \ + "" "define w() { auto z; return 8; }; w(); 9" + tar xJf bc_large.tar.xz for f in bc*.bc; do diff --git a/testsuite/bc_misc2.bc b/testsuite/bc_misc2.bc index f5a6a6b13..44fc40fa1 100644 --- a/testsuite/bc_misc2.bc +++ b/testsuite/bc_misc2.bc @@ -41,5 +41,4 @@ define u() { u() -if (x == -4) x -else x - 4 +if (x == -4) x else x - 4 -- cgit v1.2.3-55-g6feb From e9519e44a65fa80fa473cfd2041af4e7f428b81a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 16 Dec 2018 17:06:07 +0100 Subject: bc: fix handling of 'return' not in functions, and 'define f(){...}' function old new delta zbc_vm_process 561 597 +36 zbc_parse_stmt_possibly_auto 2232 2253 +21 zbc_lex_number 192 200 +8 zbc_num_divmod 150 156 +6 bc_vm_run 134 139 +5 bc_vm_init 757 760 +3 bc_num_printNewline 51 54 +3 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 7/0 up/down: 82/0) Total: 82 bytes text data bss dec hex filename 982138 485 7296 989919 f1adf busybox_old 982247 485 7296 990028 f1b4c busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 32 ++++++++++++++++++++++++-------- testsuite/bc.tests | 5 +++++ 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 95ba8b094..4dc382476 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -591,6 +591,8 @@ typedef struct BcParse { //TODO: needed? Example? size_t nbraces; + + size_t in_funcdef; } BcParse; typedef struct BcProgram { @@ -4057,19 +4059,16 @@ static BC_STATUS zbc_parse_return(BcParse *p) { BcStatus s; BcLexType t; - bool paren; dbg_lex_enter("%s:%d entered", __func__, __LINE__); - s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); t = p->l.t.t; - paren = t == BC_LEX_LPAREN; - if (t == BC_LEX_NLINE || t == BC_LEX_SCOLON) bc_parse_push(p, BC_INST_RET0); else { + bool paren = (t == BC_LEX_LPAREN); s = bc_parse_expr_empty_ok(p, 0, bc_parse_next_expr); if (s == BC_STATUS_PARSE_EMPTY_EXP) { bc_parse_push(p, BC_INST_RET0); @@ -4390,7 +4389,7 @@ static BC_STATUS zbc_parse_break_or_continue(BcParse *p, BcLexType type) # define zbc_parse_break_or_continue(...) (zbc_parse_break_or_continue(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static BC_STATUS zbc_parse_func(BcParse *p) +static BC_STATUS zbc_parse_funcdef(BcParse *p) { BcStatus s; bool var, comma = false; @@ -4454,7 +4453,16 @@ static BC_STATUS zbc_parse_func(BcParse *p) if (p->l.t.t != BC_LEX_LBRACE) s = bc_POSIX_requires("the left brace be on the same line as the function header"); + // Prevent "define z()" to be interpreted as function with empty stmt as body + while (p->l.t.t == BC_LEX_NLINE) { + s = zbc_lex_next(&p->l); + if (s) RETURN_STATUS(s); + } +//TODO: GNU bc requires a {} block even if function body has single stmt, enforce this? + + p->in_funcdef++; // to determine whether "return" stmt is allowed, and such s = zbc_parse_stmt_possibly_auto(p, true); + p->in_funcdef--; if (s) RETURN_STATUS(s); bc_parse_push(p, BC_INST_RET0); @@ -4467,7 +4475,7 @@ err: RETURN_STATUS(s); } #if ERRORS_ARE_FATAL -# define zbc_parse_func(...) (zbc_parse_func(__VA_ARGS__), BC_STATUS_SUCCESS) +# define zbc_parse_funcdef(...) (zbc_parse_funcdef(__VA_ARGS__), BC_STATUS_SUCCESS) #endif static BC_STATUS zbc_parse_auto(BcParse *p) @@ -4626,6 +4634,8 @@ static BC_STATUS zbc_parse_stmt_possibly_auto(BcParse *p, bool auto_allowed) // not when it is executed QUIT_OR_RETURN_TO_MAIN; case BC_LEX_KEY_RETURN: + if (!p->in_funcdef) + RETURN_STATUS(bc_error("'return' not in a function")); s = zbc_parse_return(p); break; case BC_LEX_KEY_WHILE: @@ -4657,7 +4667,7 @@ static BC_STATUS zbc_parse_stmt_or_funcdef(BcParse *p) s = bc_error("end of file"); else if (p->l.t.t == BC_LEX_KEY_DEFINE) { dbg_lex("%s:%d p->l.t.t:BC_LEX_KEY_DEFINE", __func__, __LINE__); - s = zbc_parse_func(p); + s = zbc_parse_funcdef(p); } else { dbg_lex("%s:%d p->l.t.t:%d (not BC_LEX_KEY_DEFINE)", __func__, __LINE__, p->l.t.t); s = zbc_parse_stmt(p); @@ -7021,7 +7031,13 @@ static BC_STATUS zbc_vm_stdin(void) bc_lex_file(&G.prs.l); G.use_stdin = 1; - s = zbc_vm_process(""); + do { + s = zbc_vm_process(""); + // We do not stop looping on errors here. + // Example: start interactive bc and enter "return". + // It should say "'return' not in a function" + // but should not exit. + } while (G.use_stdin); RETURN_STATUS(s); } #if ERRORS_ARE_FATAL diff --git a/testsuite/bc.tests b/testsuite/bc.tests index 86220ad19..093b3950e 100755 --- a/testsuite/bc.tests +++ b/testsuite/bc.tests @@ -51,6 +51,11 @@ testing "bc define auto" \ "8\n9\n" \ "" "define w() { auto z; return 8; }; w(); 9" +testing "bc define with body on next line" \ + "bc" \ + "8\n9\n" \ + "" "define w()\n{ auto z; return 8; }\nw()\n9" + tar xJf bc_large.tar.xz for f in bc*.bc; do -- cgit v1.2.3-55-g6feb From 202dd1943c90dea3c5c3365dd75d4e7ac9499c5f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 16 Dec 2018 17:30:35 +0100 Subject: bc: fixes for multi-line if/while/for function old new delta zbc_vm_process 561 589 +28 zbc_lex_next_and_skip_NLINE - 22 +22 zbc_parse_stmt_possibly_auto 2232 2253 +21 zbc_lex_skip_if_at_NLINE - 14 +14 zbc_lex_number 192 200 +8 zbc_num_divmod 150 156 +6 bc_vm_run 134 139 +5 bc_vm_init 757 760 +3 bc_num_printNewline 51 54 +3 ------------------------------------------------------------------------------ (add/remove: 2/0 grow/shrink: 7/0 up/down: 110/0) Total: 110 bytes text data bss dec hex filename 982138 485 7296 989919 f1adf busybox_old 982275 485 7296 990056 f1b68 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 43 +++++++++++++++++++++++++++++++++++-------- testsuite/bc.tests | 10 ++++++++++ 2 files changed, 45 insertions(+), 8 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 4dc382476..a5d7a01c0 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -3018,6 +3018,29 @@ static BC_STATUS zbc_lex_next(BcLex *l) # define zbc_lex_next(...) (zbc_lex_next(__VA_ARGS__), BC_STATUS_SUCCESS) #endif +static BC_STATUS zbc_lex_skip_if_at_NLINE(BcLex *l) +{ + if (l->t.t == BC_LEX_NLINE) + RETURN_STATUS(zbc_lex_next(l)); + RETURN_STATUS(BC_STATUS_SUCCESS); +} +#if ERRORS_ARE_FATAL +# define zbc_lex_skip_if_at_NLINE(...) (zbc_lex_skip_if_at_NLINE(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif + +static BC_STATUS zbc_lex_next_and_skip_NLINE(BcLex *l) +{ + BcStatus s; + s = zbc_lex_next(l); + if (s) RETURN_STATUS(s); + // if(cond)stmt is accepted too (but not 2+ newlines) + s = zbc_lex_skip_if_at_NLINE(l); + RETURN_STATUS(s); +} +#if ERRORS_ARE_FATAL +# define zbc_lex_next_and_skip_NLINE(...) (zbc_lex_next_and_skip_NLINE(__VA_ARGS__), BC_STATUS_SUCCESS) +#endif + static BC_STATUS zbc_lex_text_init(BcLex *l, const char *text) { l->buf = text; @@ -4152,7 +4175,8 @@ static BC_STATUS zbc_parse_if(BcParse *p) if (s) RETURN_STATUS(s); if (p->l.t.t != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); - s = zbc_lex_next(&p->l); + // if(cond)stmt is accepted too (but not 2+ newlines) + s = zbc_lex_next_and_skip_NLINE(&p->l); if (s) RETURN_STATUS(s); bc_parse_push(p, BC_INST_JUMP_ZERO); @@ -4216,12 +4240,15 @@ static BC_STATUS zbc_parse_while(BcParse *p) s = zbc_parse_expr(p, BC_PARSE_REL, bc_parse_next_rel); if (s) RETURN_STATUS(s); if (p->l.t.t != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); - s = zbc_lex_next(&p->l); + + // while(cond)stmt is accepted too + s = zbc_lex_next_and_skip_NLINE(&p->l); if (s) RETURN_STATUS(s); bc_parse_push(p, BC_INST_JUMP_ZERO); bc_parse_pushIndex(p, ip.idx); +//TODO: diagnose "while(cond)"? Now it is seen as "while() with empty body" s = zbc_parse_stmt(p); if (s) RETURN_STATUS(s); @@ -4321,7 +4348,9 @@ static BC_STATUS zbc_parse_for(BcParse *p) bc_vec_push(&p->exits, &ip); bc_vec_push(&p->func->labels, &ip.idx); - s = zbc_lex_next(&p->l); + + // for(...)stmt is accepted as well + s = zbc_lex_next_and_skip_NLINE(&p->l); if (s) RETURN_STATUS(s); s = zbc_parse_stmt(p); @@ -4453,11 +4482,9 @@ static BC_STATUS zbc_parse_funcdef(BcParse *p) if (p->l.t.t != BC_LEX_LBRACE) s = bc_POSIX_requires("the left brace be on the same line as the function header"); - // Prevent "define z()" to be interpreted as function with empty stmt as body - while (p->l.t.t == BC_LEX_NLINE) { - s = zbc_lex_next(&p->l); - if (s) RETURN_STATUS(s); - } + // Prevent "define z()" from being interpreted as function with empty stmt as body + s = zbc_lex_skip_if_at_NLINE(&p->l); + if (s) RETURN_STATUS(s); //TODO: GNU bc requires a {} block even if function body has single stmt, enforce this? p->in_funcdef++; // to determine whether "return" stmt is allowed, and such diff --git a/testsuite/bc.tests b/testsuite/bc.tests index 093b3950e..95cc28dad 100755 --- a/testsuite/bc.tests +++ b/testsuite/bc.tests @@ -56,6 +56,16 @@ testing "bc define with body on next line" \ "8\n9\n" \ "" "define w()\n{ auto z; return 8; }\nw()\n9" +testing "bc if(cond)" \ + "bc" \ + "9\n" \ + "" "if(0)\n3\n9" + +testing "bc while(cond)" \ + "bc" \ + "8\n7\n6\n5\n4\n3\n2\n1\n9\n" \ + "" "i=9;while(--i)\ni\n9" + tar xJf bc_large.tar.xz for f in bc*.bc; do -- cgit v1.2.3-55-g6feb From 9dc5d08baa4f409b2b6f9b98e2eefd87b8eb29be Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 16 Dec 2018 18:43:51 +0100 Subject: bc: delete unused (write-only) BcParse::nbraces member function old new delta zbc_lex_next 2296 2309 +13 bc_parse_expr_empty_ok 2021 2025 +4 bc_vm_init 760 757 -3 bc_num_printNewline 54 51 -3 zbc_num_divmod 156 150 -6 bc_parse_reset 113 106 -7 zbc_lex_number 200 192 -8 bc_parse_number 83 66 -17 zdc_parse_expr 707 671 -36 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/7 up/down: 17/-80) Total: -63 bytes text data bss dec hex filename 982275 485 7296 990056 f1b68 busybox_old 982212 485 7296 989993 f1b29 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index a5d7a01c0..0e61642a7 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -435,9 +435,9 @@ typedef enum BcLexType { BC_LEX_COMMA, BC_LEX_RBRACKET, - BC_LEX_LBRACE, + BC_LEX_LBRACE, // '{' is 0x7B, '}' is 0x7D, BC_LEX_SCOLON, - BC_LEX_RBRACE, + BC_LEX_RBRACE, // should be LBRACE+2: code uses (c - '{' + BC_LEX_LBRACE) BC_LEX_STR, BC_LEX_NAME, @@ -589,9 +589,6 @@ typedef struct BcParse { BcFunc *func; size_t fidx; -//TODO: needed? Example? - size_t nbraces; - size_t in_funcdef; } BcParse; @@ -2777,7 +2774,9 @@ static void bc_lex_whitespace(BcLex *l) l->t.t = BC_LEX_WHITESPACE; for (;;) { char c = l->buf[l->i]; - if (c == '\n' || !isspace(c)) + if (c == '\n') // this is BC_LEX_NLINE, not BC_LEX_WHITESPACE + break; + if (!isspace(c)) break; l->i++; } @@ -3003,6 +3002,7 @@ static BC_STATUS zbc_lex_next(BcLex *l) // Loop until failure or we don't have whitespace. This // is so the parser doesn't get inundated with whitespace. + // Comments are also BC_LEX_WHITESPACE tokens and eaten here. s = BC_STATUS_SUCCESS; do { dbg_lex("next string to parse:'%.*s'", @@ -3149,9 +3149,9 @@ static BC_STATUS zbc_lex_comment(BcLex *l) const char *buf = l->buf; l->t.t = BC_LEX_WHITESPACE; - i = ++l->i; + i = l->i; /* here buf[l->i] is the '*' of opening comment delimiter */ for (;;) { - char c = buf[i]; + char c = buf[++i]; check_star: if (c == '*') { c = buf[++i]; @@ -3164,7 +3164,6 @@ static BC_STATUS zbc_lex_comment(BcLex *l) RETURN_STATUS(bc_error("comment end could not be found")); } nls += (c == '\n'); - i++; } l->i = i + 1; @@ -3184,10 +3183,14 @@ static BC_STATUS zbc_lex_token(BcLex *l) // This is the workhorse of the lexer. switch (c) { - case '\0': + case '\0': // probably never reached + l->i--; + l->t.t = BC_LEX_EOF; + l->newline = true; + break; case '\n': + l->t.t = BC_LEX_NLINE; l->newline = true; - l->t.t = !c ? BC_LEX_EOF : BC_LEX_NLINE; break; case '\t': case '\v': @@ -3556,7 +3559,7 @@ static void bc_parse_pushIndex(BcParse *p, size_t idx) } } -static void bc_parse_number(BcParse *p, BcInst *prev, size_t *nexs) +static void bc_parse_number(BcParse *p) { char *num = xstrdup(p->l.t.v.v); size_t idx = G.prog.consts.len; @@ -3565,9 +3568,6 @@ static void bc_parse_number(BcParse *p, BcInst *prev, size_t *nexs) bc_parse_push(p, BC_INST_NUM); bc_parse_pushIndex(p, idx); - - ++(*nexs); - (*prev) = BC_INST_NUM; } IF_BC(static BC_STATUS zbc_parse_stmt_or_funcdef(BcParse *p);) @@ -3624,7 +3624,6 @@ static void bc_parse_reset(BcParse *p) p->l.i = p->l.len; p->l.t.t = BC_LEX_EOF; - p->nbraces = 0; bc_vec_pop_all(&p->exits); bc_vec_pop_all(&p->conds); @@ -3650,7 +3649,6 @@ static void bc_parse_create(BcParse *p, size_t func) bc_vec_init(&p->conds, sizeof(size_t), NULL); bc_vec_init(&p->ops, sizeof(BcLexType), NULL); - // p->nbraces = 0; - already is bc_parse_updateFunc(p, func); } @@ -4846,7 +4844,9 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext ne { if (BC_PARSE_LEAF(prev, rprn)) return bc_error_bad_expression(); - bc_parse_number(p, &prev, &nexprs); + bc_parse_number(p); + nexprs++; + prev = BC_INST_NUM; paren_expr = get_token = true; rprn = bin_last = false; @@ -5111,7 +5111,8 @@ static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t, uint8_t flags) if (p->l.t.t != BC_LEX_NUMBER) RETURN_STATUS(bc_error_bad_token()); } - bc_parse_number(p, &prev, &p->nbraces); + bc_parse_number(p); + prev = BC_INST_NUM; if (t == BC_LEX_NEG) bc_parse_push(p, BC_INST_NEG); get_token = true; break; @@ -5159,8 +5160,6 @@ static BC_STATUS zdc_parse_expr(BcParse *p, uint8_t flags) BcInst inst; BcLexType t; - if (flags & BC_PARSE_NOCALL) p->nbraces = G.prog.results.len; - for (t = p->l.t.t; !s && t != BC_LEX_EOF; t = p->l.t.t) { inst = dc_parse_insts[t]; -- cgit v1.2.3-55-g6feb From 6d29879c676a636656c7b29ab5be76518346b19c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 16 Dec 2018 19:10:38 +0100 Subject: bc: fold bc_parse_noElse() into its only caller Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 0e61642a7..cca64eaf5 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -4112,23 +4112,12 @@ static BC_STATUS zbc_parse_return(BcParse *p) # define zbc_parse_return(...) (zbc_parse_return(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static void bc_parse_noElse(BcParse *p) -{ - BcInstPtr *ip; - size_t *label; - - ip = bc_vec_top(&p->exits); - label = bc_vec_item(&p->func->labels, ip->idx); - dbg_lex("%s:%d rewriting label: %d -> %d", __func__, __LINE__, *label, p->func->code.len); - *label = p->func->code.len; - - bc_vec_pop(&p->exits); -} - static BC_STATUS zbc_parse_else(BcParse *p) { BcStatus s; BcInstPtr ip; + BcInstPtr *ipp; + size_t *label; dbg_lex_enter("%s:%d entered", __func__, __LINE__); @@ -4139,8 +4128,11 @@ static BC_STATUS zbc_parse_else(BcParse *p) bc_parse_push(p, BC_INST_JUMP); bc_parse_pushIndex(p, ip.idx); - dbg_lex("%s:%d calling bc_parse_noElse()", __func__, __LINE__); - bc_parse_noElse(p); + ipp = bc_vec_top(&p->exits); + label = bc_vec_item(&p->func->labels, ipp->idx); + dbg_lex("%s:%d rewriting label: %d -> %d", __func__, __LINE__, *label, p->func->code.len); + *label = p->func->code.len; + bc_vec_pop(&p->exits); bc_vec_push(&p->exits, &ip); bc_vec_push(&p->func->labels, &ip.idx); -- cgit v1.2.3-55-g6feb From a50576a415a9b5d384a28c9bd4b55a4df2974248 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 16 Dec 2018 19:21:57 +0100 Subject: bc: fold zbc_parse_else() into its only caller While at it, allow newline between "else" and its body Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 59 +++++++++++++++++++----------------------------------- testsuite/bc.tests | 5 +++++ 2 files changed, 26 insertions(+), 38 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index cca64eaf5..9ce6ab667 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -4112,41 +4112,6 @@ static BC_STATUS zbc_parse_return(BcParse *p) # define zbc_parse_return(...) (zbc_parse_return(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static BC_STATUS zbc_parse_else(BcParse *p) -{ - BcStatus s; - BcInstPtr ip; - BcInstPtr *ipp; - size_t *label; - - dbg_lex_enter("%s:%d entered", __func__, __LINE__); - - ip.idx = p->func->labels.len; - ip.func = ip.len = 0; - - dbg_lex("%s:%d after if() body: BC_INST_JUMP to %d", __func__, __LINE__, ip.idx); - bc_parse_push(p, BC_INST_JUMP); - bc_parse_pushIndex(p, ip.idx); - - ipp = bc_vec_top(&p->exits); - label = bc_vec_item(&p->func->labels, ipp->idx); - dbg_lex("%s:%d rewriting label: %d -> %d", __func__, __LINE__, *label, p->func->code.len); - *label = p->func->code.len; - bc_vec_pop(&p->exits); - - bc_vec_push(&p->exits, &ip); - bc_vec_push(&p->func->labels, &ip.idx); - - s = zbc_parse_stmt(p); - if (s) RETURN_STATUS(s); - - dbg_lex_done("%s:%d done", __func__, __LINE__); - RETURN_STATUS(s); -} -#if ERRORS_ARE_FATAL -# define zbc_parse_else(...) (zbc_parse_else(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif - static BC_STATUS zbc_parse_if(BcParse *p) { BcStatus s; @@ -4179,12 +4144,30 @@ static BC_STATUS zbc_parse_if(BcParse *p) s = zbc_parse_stmt(p); if (s) RETURN_STATUS(s); + dbg_lex("%s:%d in if after stmt: p->l.t.t:%d", __func__, __LINE__, p->l.t.t); if (p->l.t.t == BC_LEX_KEY_ELSE) { - s = zbc_lex_next(&p->l); + s = zbc_lex_next_and_skip_NLINE(&p->l); + if (s) RETURN_STATUS(s); + + ip.idx = p->func->labels.len; + ip.func = ip.len = 0; + + dbg_lex("%s:%d after if() body: BC_INST_JUMP to %d", __func__, __LINE__, ip.idx); + bc_parse_push(p, BC_INST_JUMP); + bc_parse_pushIndex(p, ip.idx); + + ipp = bc_vec_top(&p->exits); + label = bc_vec_item(&p->func->labels, ipp->idx); + dbg_lex("%s:%d rewriting label: %d -> %d", __func__, __LINE__, *label, p->func->code.len); + *label = p->func->code.len; + bc_vec_pop(&p->exits); + + bc_vec_push(&p->exits, &ip); + bc_vec_push(&p->func->labels, &ip.idx); + + s = zbc_parse_stmt(p); if (s) RETURN_STATUS(s); - dbg_lex("%s:%d calling zbc_parse_else(), p->l.t.t:%d", __func__, __LINE__, p->l.t.t); - s = zbc_parse_else(p); } ipp = bc_vec_top(&p->exits); diff --git a/testsuite/bc.tests b/testsuite/bc.tests index 95cc28dad..36baeea89 100755 --- a/testsuite/bc.tests +++ b/testsuite/bc.tests @@ -61,6 +61,11 @@ testing "bc if(cond)" \ "9\n" \ "" "if(0)\n3\n9" +testing "bc if(cond) stmt else" \ + "bc" \ + "4\n9\n" \ + "" "if(0)3 else\n4\n9" + testing "bc while(cond)" \ "bc" \ "8\n7\n6\n5\n4\n3\n2\n1\n9\n" \ -- cgit v1.2.3-55-g6feb From 563d93c9a4e2a784dfbec6703c572fb88eb99332 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 16 Dec 2018 19:47:40 +0100 Subject: bc: simplify zbc_parse_break_or_continue(), logic is the same function old new delta zbc_parse_stmt_possibly_auto 2259 2224 -35 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-35) Total: -35 bytes text data bss dec hex filename 982218 485 7296 989999 f1b2f busybox_old 982183 485 7296 989964 f1b0c busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 9ce6ab667..8aaeeaf9f 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -4358,20 +4358,19 @@ static BC_STATUS zbc_parse_break_or_continue(BcParse *p, BcLexType type) { BcStatus s; size_t i; - BcInstPtr *ip; if (type == BC_LEX_KEY_BREAK) { - if (p->exits.len == 0) RETURN_STATUS(bc_error_bad_token()); - - i = p->exits.len - 1; - ip = bc_vec_item(&p->exits, i); - - while (!ip->func && i < p->exits.len) - ip = bc_vec_item(&p->exits, i--); - if (i >= p->exits.len && !ip->func) - RETURN_STATUS(bc_error_bad_token()); + BcInstPtr *ipp; - i = ip->idx; + i = p->exits.len; + for (;;) { + if (i == 0) // none of the enclosing blocks is a loop + RETURN_STATUS(bc_error_bad_token()); + ipp = bc_vec_item(&p->exits, --i); + if (ipp->func != 0) + break; + } + i = ipp->idx; } else i = *((size_t *) bc_vec_top(&p->conds)); -- cgit v1.2.3-55-g6feb From e6c40c48d96169ff27471c63c33e568e96fd5b82 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 16 Dec 2018 20:32:58 +0100 Subject: bc: simplify bc_parse_pushName(), do not free name in it - avoids one strdup function old new delta zbc_parse_name 511 509 -2 zdc_parse_register 50 43 -7 bc_parse_pushName 61 39 -22 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/3 up/down: 0/-31) Total: -31 bytes text data bss dec hex filename 982183 485 7296 989964 f1b0c busybox_old 982152 485 7296 989933 f1aed busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 8aaeeaf9f..6e39aeed3 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -3529,12 +3529,9 @@ static void bc_parse_push(BcParse *p, char i) static void bc_parse_pushName(BcParse *p, char *name) { - size_t i = 0, len = strlen(name); - - for (; i < len; ++i) bc_parse_push(p, name[i]); + while (*name) + bc_parse_push(p, *name++); bc_parse_push(p, BC_PARSE_STREND); - - free(name); } static void bc_parse_pushIndex(BcParse *p, size_t idx) @@ -3828,6 +3825,7 @@ static BC_STATUS zbc_parse_name(BcParse *p, BcInst *type, uint8_t flags) if (s) goto err; bc_parse_push(p, *type); bc_parse_pushName(p, name); + free(name); } else if (p->l.t.t == BC_LEX_LPAREN) { if (flags & BC_PARSE_NOCALL) { @@ -3840,6 +3838,7 @@ static BC_STATUS zbc_parse_name(BcParse *p, BcInst *type, uint8_t flags) *type = BC_INST_VAR; bc_parse_push(p, BC_INST_VAR); bc_parse_pushName(p, name); + free(name); } RETURN_STATUS(s); @@ -4970,14 +4969,12 @@ static BC_STATUS zbc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) static BC_STATUS zdc_parse_register(BcParse *p) { BcStatus s; - char *name; s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); if (p->l.t.t != BC_LEX_NAME) RETURN_STATUS(bc_error_bad_token()); - name = xstrdup(p->l.t.v.v); - bc_parse_pushName(p, name); + bc_parse_pushName(p, p->l.t.v.v); RETURN_STATUS(s); } -- cgit v1.2.3-55-g6feb From 2e8be023cbd96c54256b5908837039100dc4fc45 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 16 Dec 2018 20:41:32 +0100 Subject: bc: allow only one between if() and stmt Attempt to have more than one causes this error message: $ bc -q if (1) bc: no statement after 'if' Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 6e39aeed3..ed2497c4c 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -3677,6 +3677,16 @@ static BC_STATUS zbc_parse_stmt(BcParse *p) # define zbc_parse_stmt(...) (zbc_parse_stmt(__VA_ARGS__), BC_STATUS_SUCCESS) #endif +static BC_STATUS zbc_parse_stmt_fail_if_bare_NLINE(BcParse *p, const char *after_X) +{ + if (p->l.t.t == BC_LEX_NLINE) + RETURN_STATUS(bc_error_fmt("no statement after '%s'", after_X)); + RETURN_STATUS(zbc_parse_stmt(p)); +} +#if ERRORS_ARE_FATAL +# define zbc_parse_stmt_fail_if_bare_NLINE((...) (zbc_parse_stmt_fail_if_bare_NLINE((__VA_ARGS__), BC_STATUS_SUCCESS) +#endif + static void bc_parse_operator(BcParse *p, BcLexType type, size_t start, size_t *nexprs) { @@ -4141,7 +4151,7 @@ static BC_STATUS zbc_parse_if(BcParse *p) bc_vec_push(&p->exits, &ip); bc_vec_push(&p->func->labels, &ip.idx); - s = zbc_parse_stmt(p); + s = zbc_parse_stmt_fail_if_bare_NLINE(p, "if"); if (s) RETURN_STATUS(s); dbg_lex("%s:%d in if after stmt: p->l.t.t:%d", __func__, __LINE__, p->l.t.t); @@ -4220,8 +4230,7 @@ static BC_STATUS zbc_parse_while(BcParse *p) bc_parse_push(p, BC_INST_JUMP_ZERO); bc_parse_pushIndex(p, ip.idx); -//TODO: diagnose "while(cond)"? Now it is seen as "while() with empty body" - s = zbc_parse_stmt(p); + s = zbc_parse_stmt_fail_if_bare_NLINE(p, "while"); if (s) RETURN_STATUS(s); n = *((size_t *) bc_vec_top(&p->conds)); @@ -4325,7 +4334,7 @@ static BC_STATUS zbc_parse_for(BcParse *p) s = zbc_lex_next_and_skip_NLINE(&p->l); if (s) RETURN_STATUS(s); - s = zbc_parse_stmt(p); + s = zbc_parse_stmt_fail_if_bare_NLINE(p, "for"); if (s) RETURN_STATUS(s); n = *((size_t *) bc_vec_top(&p->conds)); -- cgit v1.2.3-55-g6feb From cb18b546f7ee9d1c9315c7357ab620e55f0fa8f3 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 16 Dec 2018 20:46:15 +0100 Subject: bc: disallow empty statement as function body $ bc define z() bc: no statement after 'define' function old new delta zbc_parse_stmt_possibly_auto 2239 2245 +6 zbc_vm_process 589 594 +5 zbc_parse_stmt_fail_if_bare_NLINE 25 28 +3 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 3/0 up/down: 14/0) Total: 14 bytes text data bss dec hex filename 982216 485 7296 989997 f1b2d busybox_old 982237 485 7296 990018 f1b42 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index ed2497c4c..2dc64dbc6 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -3677,14 +3677,14 @@ static BC_STATUS zbc_parse_stmt(BcParse *p) # define zbc_parse_stmt(...) (zbc_parse_stmt(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static BC_STATUS zbc_parse_stmt_fail_if_bare_NLINE(BcParse *p, const char *after_X) +static BC_STATUS zbc_parse_stmt_fail_if_bare_NLINE(BcParse *p, bool auto_allowed, const char *after_X) { if (p->l.t.t == BC_LEX_NLINE) RETURN_STATUS(bc_error_fmt("no statement after '%s'", after_X)); - RETURN_STATUS(zbc_parse_stmt(p)); + RETURN_STATUS(zbc_parse_stmt_possibly_auto(p, auto_allowed)); } #if ERRORS_ARE_FATAL -# define zbc_parse_stmt_fail_if_bare_NLINE((...) (zbc_parse_stmt_fail_if_bare_NLINE((__VA_ARGS__), BC_STATUS_SUCCESS) +# define zbc_parse_stmt_fail_if_bare_NLINE(...) (zbc_parse_stmt_fail_if_bare_NLINE(__VA_ARGS__), BC_STATUS_SUCCESS) #endif static void bc_parse_operator(BcParse *p, BcLexType type, size_t start, @@ -4151,7 +4151,7 @@ static BC_STATUS zbc_parse_if(BcParse *p) bc_vec_push(&p->exits, &ip); bc_vec_push(&p->func->labels, &ip.idx); - s = zbc_parse_stmt_fail_if_bare_NLINE(p, "if"); + s = zbc_parse_stmt_fail_if_bare_NLINE(p, false, "if"); if (s) RETURN_STATUS(s); dbg_lex("%s:%d in if after stmt: p->l.t.t:%d", __func__, __LINE__, p->l.t.t); @@ -4230,7 +4230,7 @@ static BC_STATUS zbc_parse_while(BcParse *p) bc_parse_push(p, BC_INST_JUMP_ZERO); bc_parse_pushIndex(p, ip.idx); - s = zbc_parse_stmt_fail_if_bare_NLINE(p, "while"); + s = zbc_parse_stmt_fail_if_bare_NLINE(p, false, "while"); if (s) RETURN_STATUS(s); n = *((size_t *) bc_vec_top(&p->conds)); @@ -4334,7 +4334,7 @@ static BC_STATUS zbc_parse_for(BcParse *p) s = zbc_lex_next_and_skip_NLINE(&p->l); if (s) RETURN_STATUS(s); - s = zbc_parse_stmt_fail_if_bare_NLINE(p, "for"); + s = zbc_parse_stmt_fail_if_bare_NLINE(p, false, "for"); if (s) RETURN_STATUS(s); n = *((size_t *) bc_vec_top(&p->conds)); @@ -4468,7 +4468,7 @@ static BC_STATUS zbc_parse_funcdef(BcParse *p) //TODO: GNU bc requires a {} block even if function body has single stmt, enforce this? p->in_funcdef++; // to determine whether "return" stmt is allowed, and such - s = zbc_parse_stmt_possibly_auto(p, true); + s = zbc_parse_stmt_fail_if_bare_NLINE(p, true, "define"); p->in_funcdef--; if (s) RETURN_STATUS(s); -- cgit v1.2.3-55-g6feb From 5d18f6be90a940f80c3b7238dc7a8b42a41f55bd Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 16 Dec 2018 21:08:30 +0100 Subject: bc: fix "print 1,2,3" parsing function old new delta zbc_parse_stmt_possibly_auto 2245 2180 -65 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-65) Total: -65 bytes text data bss dec hex filename 982237 485 7296 990018 f1b42 busybox_old 982152 485 7296 989933 f1aed busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 31 ++++++++----------------------- testsuite/bc.tests | 5 +++++ 2 files changed, 13 insertions(+), 23 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 2dc64dbc6..9f40a551e 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -4048,38 +4048,23 @@ static BC_STATUS zbc_parse_print(BcParse *p) { BcStatus s; BcLexType type; - bool comma; - s = zbc_lex_next(&p->l); - if (s) RETURN_STATUS(s); - - type = p->l.t.t; - - if (type == BC_LEX_SCOLON || type == BC_LEX_NLINE) - RETURN_STATUS(bc_error("bad print statement")); - - comma = false; - while (type != BC_LEX_SCOLON && type != BC_LEX_NLINE) { + for (;;) { + s = zbc_lex_next(&p->l); + if (s) RETURN_STATUS(s); + type = p->l.t.t; if (type == BC_LEX_STR) { s = zbc_parse_string(p, BC_INST_PRINT_POP); - if (s) RETURN_STATUS(s); } else { s = zbc_parse_expr(p, 0, bc_parse_next_print); - if (s) RETURN_STATUS(s); bc_parse_push(p, BC_INST_PRINT_POP); } - - comma = p->l.t.t == BC_LEX_COMMA; - if (comma) { - s = zbc_lex_next(&p->l); - if (s) RETURN_STATUS(s); - } - type = p->l.t.t; + if (s) RETURN_STATUS(s); + if (p->l.t.t != BC_LEX_COMMA) + break; } - if (comma) RETURN_STATUS(bc_error_bad_token()); - - RETURN_STATUS(zbc_lex_next(&p->l)); + RETURN_STATUS(s); } #if ERRORS_ARE_FATAL # define zbc_parse_print(...) (zbc_parse_print(__VA_ARGS__), BC_STATUS_SUCCESS) diff --git a/testsuite/bc.tests b/testsuite/bc.tests index 36baeea89..21b26008f 100755 --- a/testsuite/bc.tests +++ b/testsuite/bc.tests @@ -71,6 +71,11 @@ testing "bc while(cond)" \ "8\n7\n6\n5\n4\n3\n2\n1\n9\n" \ "" "i=9;while(--i)\ni\n9" +testing "bc print 1,2,3" \ + "bc" \ + "123" \ + "" "print 1,2,3" + tar xJf bc_large.tar.xz for f in bc*.bc; do -- cgit v1.2.3-55-g6feb From 741563312805fa99fc9588c3673eff4a219d5e9f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 16 Dec 2018 21:21:27 +0100 Subject: bc: preparation to stop using p->exits when parsing if() Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 9f40a551e..ad716fac3 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -4141,15 +4141,17 @@ static BC_STATUS zbc_parse_if(BcParse *p) dbg_lex("%s:%d in if after stmt: p->l.t.t:%d", __func__, __LINE__, p->l.t.t); if (p->l.t.t == BC_LEX_KEY_ELSE) { + BcInstPtr ip2; + s = zbc_lex_next_and_skip_NLINE(&p->l); if (s) RETURN_STATUS(s); - ip.idx = p->func->labels.len; - ip.func = ip.len = 0; + ip2.idx = p->func->labels.len; + ip2.func = ip.len = 0; dbg_lex("%s:%d after if() body: BC_INST_JUMP to %d", __func__, __LINE__, ip.idx); bc_parse_push(p, BC_INST_JUMP); - bc_parse_pushIndex(p, ip.idx); + bc_parse_pushIndex(p, ip2.idx); ipp = bc_vec_top(&p->exits); label = bc_vec_item(&p->func->labels, ipp->idx); @@ -4157,8 +4159,8 @@ static BC_STATUS zbc_parse_if(BcParse *p) *label = p->func->code.len; bc_vec_pop(&p->exits); - bc_vec_push(&p->exits, &ip); - bc_vec_push(&p->func->labels, &ip.idx); + bc_vec_push(&p->exits, &ip2); + bc_vec_push(&p->func->labels, &ip2.idx); s = zbc_parse_stmt(p); if (s) RETURN_STATUS(s); -- cgit v1.2.3-55-g6feb From 6b5b46f81744c72de8f63e45aa788303ab8df28b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 16 Dec 2018 21:29:08 +0100 Subject: bc: stop using p->exits when parsing if() function old new delta zbc_parse_stmt_possibly_auto 2180 2138 -42 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index ad716fac3..178cd7a24 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -4110,7 +4110,6 @@ static BC_STATUS zbc_parse_if(BcParse *p) { BcStatus s; BcInstPtr ip; - BcInstPtr *ipp; size_t *label; dbg_lex_enter("%s:%d entered", __func__, __LINE__); @@ -4132,8 +4131,6 @@ static BC_STATUS zbc_parse_if(BcParse *p) ip.idx = p->func->labels.len; ip.func = ip.len = 0; bc_parse_pushIndex(p, ip.idx); -//TODO: can get rid of p->exits stack? - bc_vec_push(&p->exits, &ip); bc_vec_push(&p->func->labels, &ip.idx); s = zbc_parse_stmt_fail_if_bare_NLINE(p, false, "if"); @@ -4147,32 +4144,27 @@ static BC_STATUS zbc_parse_if(BcParse *p) if (s) RETURN_STATUS(s); ip2.idx = p->func->labels.len; - ip2.func = ip.len = 0; + ip2.func = ip2.len = 0; dbg_lex("%s:%d after if() body: BC_INST_JUMP to %d", __func__, __LINE__, ip.idx); bc_parse_push(p, BC_INST_JUMP); bc_parse_pushIndex(p, ip2.idx); - ipp = bc_vec_top(&p->exits); - label = bc_vec_item(&p->func->labels, ipp->idx); + label = bc_vec_item(&p->func->labels, ip.idx); dbg_lex("%s:%d rewriting label: %d -> %d", __func__, __LINE__, *label, p->func->code.len); *label = p->func->code.len; - bc_vec_pop(&p->exits); - bc_vec_push(&p->exits, &ip2); bc_vec_push(&p->func->labels, &ip2.idx); + ip.idx = ip2.idx; - s = zbc_parse_stmt(p); + s = zbc_parse_stmt_fail_if_bare_NLINE(p, false, "else"); if (s) RETURN_STATUS(s); } - ipp = bc_vec_top(&p->exits); - label = bc_vec_item(&p->func->labels, ipp->idx); + label = bc_vec_item(&p->func->labels, ip.idx); dbg_lex("%s:%d rewriting label: %d -> %d", __func__, __LINE__, *label, p->func->code.len); *label = p->func->code.len; - bc_vec_pop(&p->exits); - dbg_lex_done("%s:%d done", __func__, __LINE__); RETURN_STATUS(s); } -- cgit v1.2.3-55-g6feb From 15850832be164b941aeef7c62aaed91fb5774f8a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 16 Dec 2018 21:40:54 +0100 Subject: bc: shrink zbc_parse_if() a bit more function old new delta zbc_parse_stmt_possibly_auto 2180 2106 -74 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-74) Total: -74 bytes text data bss dec hex filename 982152 485 7296 989933 f1aed busybox_old 982078 485 7296 989859 f1aa3 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 178cd7a24..2a9f3e2d3 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -4109,7 +4109,7 @@ static BC_STATUS zbc_parse_return(BcParse *p) static BC_STATUS zbc_parse_if(BcParse *p) { BcStatus s; - BcInstPtr ip; + size_t ip_idx; size_t *label; dbg_lex_enter("%s:%d entered", __func__, __LINE__); @@ -4128,41 +4128,39 @@ static BC_STATUS zbc_parse_if(BcParse *p) if (s) RETURN_STATUS(s); bc_parse_push(p, BC_INST_JUMP_ZERO); - ip.idx = p->func->labels.len; - ip.func = ip.len = 0; - bc_parse_pushIndex(p, ip.idx); - bc_vec_push(&p->func->labels, &ip.idx); + ip_idx = p->func->labels.len; + bc_parse_pushIndex(p, ip_idx); + bc_vec_push(&p->func->labels, &ip_idx); s = zbc_parse_stmt_fail_if_bare_NLINE(p, false, "if"); if (s) RETURN_STATUS(s); dbg_lex("%s:%d in if after stmt: p->l.t.t:%d", __func__, __LINE__, p->l.t.t); if (p->l.t.t == BC_LEX_KEY_ELSE) { - BcInstPtr ip2; + size_t ip2_idx; s = zbc_lex_next_and_skip_NLINE(&p->l); if (s) RETURN_STATUS(s); - ip2.idx = p->func->labels.len; - ip2.func = ip2.len = 0; + ip2_idx = p->func->labels.len; - dbg_lex("%s:%d after if() body: BC_INST_JUMP to %d", __func__, __LINE__, ip.idx); + dbg_lex("%s:%d after if() body: BC_INST_JUMP to %d", __func__, __LINE__, ip2_idx); bc_parse_push(p, BC_INST_JUMP); - bc_parse_pushIndex(p, ip2.idx); + bc_parse_pushIndex(p, ip2_idx); - label = bc_vec_item(&p->func->labels, ip.idx); - dbg_lex("%s:%d rewriting label: %d -> %d", __func__, __LINE__, *label, p->func->code.len); + label = bc_vec_item(&p->func->labels, ip_idx); + dbg_lex("%s:%d rewriting 'if_zero' label to jump to 'else': %d -> %d", __func__, __LINE__, *label, p->func->code.len); *label = p->func->code.len; - bc_vec_push(&p->func->labels, &ip2.idx); - ip.idx = ip2.idx; + bc_vec_push(&p->func->labels, &ip2_idx); + ip_idx = ip2_idx; s = zbc_parse_stmt_fail_if_bare_NLINE(p, false, "else"); if (s) RETURN_STATUS(s); } - label = bc_vec_item(&p->func->labels, ip.idx); - dbg_lex("%s:%d rewriting label: %d -> %d", __func__, __LINE__, *label, p->func->code.len); + label = bc_vec_item(&p->func->labels, ip_idx); + dbg_lex("%s:%d rewriting label to jump after 'if' body: %d -> %d", __func__, __LINE__, *label, p->func->code.len); *label = p->func->code.len; dbg_lex_done("%s:%d done", __func__, __LINE__); -- cgit v1.2.3-55-g6feb From 146a79d19c19465aa5a29c271341158b46cc5ade Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 16 Dec 2018 21:46:11 +0100 Subject: bc: shring bc_lib[] function old new delta bc_lib 1586 1584 -2 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 2a9f3e2d3..f85ab1aea 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -7115,7 +7115,7 @@ static const char bc_lib[] ALIGN1 = { "\n" "x=-x" "\n" "}" "\n" "s=scale" -"\n" "r=6+s+0.44*x" +"\n" "r=6+s+.44*x" "\n" "scale=scale(x)+1" "\n" "while(x>1){" "\n" "d+=1" @@ -7154,7 +7154,7 @@ static const char bc_lib[] ALIGN1 = { "\n" "p*=2" "\n" "x=sqrt(x)" "\n" "}" -"\n" "while(x<=0.5){" +"\n" "while(x<=.5){" "\n" "p*=2" "\n" "x=sqrt(x)" "\n" "}" -- cgit v1.2.3-55-g6feb From 06ade77002eaa28bb3f19480f68ad270b22bd48e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 16 Dec 2018 22:44:51 +0100 Subject: bc: simplify use of "ip" in loop parsing functions function old new delta zbc_parse_stmt_possibly_auto 2106 2065 -41 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-41) Total: -41 bytes text data bss dec hex filename 982076 485 7296 989857 f1aa1 busybox_old 982035 485 7296 989816 f1a78 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 8 ++------ testsuite/bc.tests | 31 +++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index f85ab1aea..925950d78 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -4174,7 +4174,6 @@ static BC_STATUS zbc_parse_while(BcParse *p) { BcStatus s; BcInstPtr ip; - BcInstPtr *ipp; size_t *label; size_t n; @@ -4214,14 +4213,13 @@ static BC_STATUS zbc_parse_while(BcParse *p) bc_parse_push(p, BC_INST_JUMP); bc_parse_pushIndex(p, n); - ipp = bc_vec_top(&p->exits); label = bc_vec_top(&p->conds); dbg_lex("%s:%d BC_INST_JUMP to %d", __func__, __LINE__, *label); bc_parse_push(p, BC_INST_JUMP); bc_parse_pushIndex(p, *label); - label = bc_vec_item(&p->func->labels, ipp->idx); + label = bc_vec_item(&p->func->labels, ip.idx); dbg_lex("%s:%d rewriting label: %d -> %d", __func__, __LINE__, *label, p->func->code.len); *label = p->func->code.len; @@ -4238,7 +4236,6 @@ static BC_STATUS zbc_parse_for(BcParse *p) { BcStatus s; BcInstPtr ip; - BcInstPtr *ipp; size_t *label; size_t cond_idx, exit_idx, body_idx, update_idx; size_t n; @@ -4318,7 +4315,6 @@ static BC_STATUS zbc_parse_for(BcParse *p) bc_parse_push(p, BC_INST_JUMP); bc_parse_pushIndex(p, n); - ipp = bc_vec_top(&p->exits); label = bc_vec_top(&p->conds); //TODO: commonalize? @@ -4326,7 +4322,7 @@ static BC_STATUS zbc_parse_for(BcParse *p) bc_parse_push(p, BC_INST_JUMP); bc_parse_pushIndex(p, *label); - label = bc_vec_item(&p->func->labels, ipp->idx); + label = bc_vec_item(&p->func->labels, ip.idx); dbg_lex("%s:%d rewriting label: %d -> %d", __func__, __LINE__, *label, p->func->code.len); *label = p->func->code.len; diff --git a/testsuite/bc.tests b/testsuite/bc.tests index 21b26008f..987461ebb 100755 --- a/testsuite/bc.tests +++ b/testsuite/bc.tests @@ -76,6 +76,37 @@ testing "bc print 1,2,3" \ "123" \ "" "print 1,2,3" +testing "bc nested loops and breaks" \ + "bc" \ + "\ +11 +21 +31 +22 +12 +99 +" \ + "" "\ +if(1) { + 11 + while(1) { + 21 + while(1) { + 31 + break + 32 + } + 22 + break + 23 + } + 12 +} else { + 88 +} +99 +" + tar xJf bc_large.tar.xz for f in bc*.bc; do -- cgit v1.2.3-55-g6feb From de24e9d3669e43a5419c7990ad13368ae51ced96 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 16 Dec 2018 23:02:22 +0100 Subject: bc: remove redundant JUMP generation when parsing 'while' function old new delta zbc_parse_stmt_possibly_auto 2065 2025 -40 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-40) Total: -40 bytes text data bss dec hex filename 982035 485 7296 989816 f1a78 busybox_old 981995 485 7296 989776 f1a50 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 16 +++++----------- testsuite/bc.tests | 27 +++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 925950d78..af57b3d6c 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -4175,7 +4175,7 @@ static BC_STATUS zbc_parse_while(BcParse *p) BcStatus s; BcInstPtr ip; size_t *label; - size_t n; + size_t cond_idx; s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); @@ -4183,10 +4183,10 @@ static BC_STATUS zbc_parse_while(BcParse *p) s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); - ip.idx = p->func->labels.len; + cond_idx = p->func->labels.len; bc_vec_push(&p->func->labels, &p->func->code.len); - bc_vec_push(&p->conds, &ip.idx); + bc_vec_push(&p->conds, &cond_idx); ip.idx = p->func->labels.len; ip.func = 1; @@ -4209,15 +4209,9 @@ static BC_STATUS zbc_parse_while(BcParse *p) s = zbc_parse_stmt_fail_if_bare_NLINE(p, false, "while"); if (s) RETURN_STATUS(s); - n = *((size_t *) bc_vec_top(&p->conds)); - bc_parse_push(p, BC_INST_JUMP); - bc_parse_pushIndex(p, n); - - label = bc_vec_top(&p->conds); - - dbg_lex("%s:%d BC_INST_JUMP to %d", __func__, __LINE__, *label); + dbg_lex("%s:%d BC_INST_JUMP to %d", __func__, __LINE__, cond_idx); bc_parse_push(p, BC_INST_JUMP); - bc_parse_pushIndex(p, *label); + bc_parse_pushIndex(p, cond_idx); label = bc_vec_item(&p->func->labels, ip.idx); dbg_lex("%s:%d rewriting label: %d -> %d", __func__, __LINE__, *label, p->func->code.len); diff --git a/testsuite/bc.tests b/testsuite/bc.tests index 987461ebb..0690e9c6f 100755 --- a/testsuite/bc.tests +++ b/testsuite/bc.tests @@ -107,6 +107,33 @@ if(1) { 99 " +testing "bc continue in if" \ + "bc" \ + "\ +11 +21 +11 +31 +99 +" \ + "" "\ +i=2 +while(i--) { + 11 + if(i) { + 21 + continue + 22 + } else { + 31 + continue + 32 + } + 12 +} +99 +" + tar xJf bc_large.tar.xz for f in bc*.bc; do -- cgit v1.2.3-55-g6feb From 8e7686e4577ac7b07845d16fd95a39a4ce0af3c1 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 16 Dec 2018 23:18:28 +0100 Subject: bc: p->exits.func is never zero, do not check for that function old new delta zbc_parse_stmt_possibly_auto 1978 1967 -11 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-11) Total: -11 bytes text data bss dec hex filename 981948 485 7296 989729 f1a21 busybox_old 981937 485 7296 989718 f1a16 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index af57b3d6c..ca14c1ba7 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -4232,7 +4232,6 @@ static BC_STATUS zbc_parse_for(BcParse *p) BcInstPtr ip; size_t *label; size_t cond_idx, exit_idx, body_idx, update_idx; - size_t n; dbg_lex("%s:%d p->l.t.t:%d", __func__, __LINE__, p->l.t.t); s = zbc_lex_next(&p->l); @@ -4305,16 +4304,10 @@ static BC_STATUS zbc_parse_for(BcParse *p) s = zbc_parse_stmt_fail_if_bare_NLINE(p, false, "for"); if (s) RETURN_STATUS(s); - n = *((size_t *) bc_vec_top(&p->conds)); - bc_parse_push(p, BC_INST_JUMP); - bc_parse_pushIndex(p, n); - - label = bc_vec_top(&p->conds); - //TODO: commonalize? - dbg_lex("%s:%d BC_INST_JUMP to %d", __func__, __LINE__, *label); + dbg_lex("%s:%d BC_INST_JUMP to %d", __func__, __LINE__, update_idx); bc_parse_push(p, BC_INST_JUMP); - bc_parse_pushIndex(p, *label); + bc_parse_pushIndex(p, update_idx); label = bc_vec_item(&p->func->labels, ip.idx); dbg_lex("%s:%d rewriting label: %d -> %d", __func__, __LINE__, *label, p->func->code.len); @@ -4337,18 +4330,13 @@ static BC_STATUS zbc_parse_break_or_continue(BcParse *p, BcLexType type) if (type == BC_LEX_KEY_BREAK) { BcInstPtr *ipp; - i = p->exits.len; - for (;;) { - if (i == 0) // none of the enclosing blocks is a loop - RETURN_STATUS(bc_error_bad_token()); - ipp = bc_vec_item(&p->exits, --i); - if (ipp->func != 0) - break; - } + if (p->exits.len == 0) // none of the enclosing blocks is a loop + RETURN_STATUS(bc_error_bad_token()); + ipp = bc_vec_top(&p->exits); i = ipp->idx; - } - else + } else { i = *((size_t *) bc_vec_top(&p->conds)); + } bc_parse_push(p, BC_INST_JUMP); bc_parse_pushIndex(p, i); -- cgit v1.2.3-55-g6feb From 266aa000126dcbb9e1c93306165f433a167bb50a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 16 Dec 2018 23:24:25 +0100 Subject: bc: store only index in p->exits, it's the only thing used there function old new delta zbc_parse_stmt_possibly_auto 1967 1964 -3 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-3) Total: -3 bytes text data bss dec hex filename 981937 485 7296 989718 f1a16 busybox_old 981934 485 7296 989715 f1a13 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 13 +++++-------- testsuite/bc.tests | 17 +++++++++++++++++ 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index ca14c1ba7..979d5113d 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -3642,7 +3642,7 @@ static void bc_parse_create(BcParse *p, size_t func) memset(p, 0, sizeof(BcParse)); bc_lex_init(&p->l); - bc_vec_init(&p->exits, sizeof(BcInstPtr), NULL); + bc_vec_init(&p->exits, sizeof(size_t), NULL); bc_vec_init(&p->conds, sizeof(size_t), NULL); bc_vec_init(&p->ops, sizeof(BcLexType), NULL); @@ -4192,7 +4192,7 @@ static BC_STATUS zbc_parse_while(BcParse *p) ip.func = 1; ip.len = 0; - bc_vec_push(&p->exits, &ip); + bc_vec_push(&p->exits, &ip.idx); bc_vec_push(&p->func->labels, &ip.idx); s = zbc_parse_expr(p, BC_PARSE_REL, bc_parse_next_rel); @@ -4294,7 +4294,7 @@ static BC_STATUS zbc_parse_for(BcParse *p) ip.func = 1; ip.len = 0; - bc_vec_push(&p->exits, &ip); + bc_vec_push(&p->exits, &ip.idx); bc_vec_push(&p->func->labels, &ip.idx); // for(...)stmt is accepted as well @@ -4328,14 +4328,11 @@ static BC_STATUS zbc_parse_break_or_continue(BcParse *p, BcLexType type) size_t i; if (type == BC_LEX_KEY_BREAK) { - BcInstPtr *ipp; - if (p->exits.len == 0) // none of the enclosing blocks is a loop RETURN_STATUS(bc_error_bad_token()); - ipp = bc_vec_top(&p->exits); - i = ipp->idx; + i = *(size_t*)bc_vec_top(&p->exits); } else { - i = *((size_t *) bc_vec_top(&p->conds)); + i = *(size_t*)bc_vec_top(&p->conds); } bc_parse_push(p, BC_INST_JUMP); diff --git a/testsuite/bc.tests b/testsuite/bc.tests index 0690e9c6f..d057bea17 100755 --- a/testsuite/bc.tests +++ b/testsuite/bc.tests @@ -134,6 +134,23 @@ while(i--) { 99 " +testing "bc continue in for" \ + "bc" \ + "\ +1 +77 +2 +99 +" \ + "" "\ +for(i=1; i<3; i++) { + i + if(i==2) continue + 77 +} +99 +" + tar xJf bc_large.tar.xz for f in bc*.bc; do -- cgit v1.2.3-55-g6feb From 5ebd2a612843821989f979b4277931d53b90671d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 16 Dec 2018 23:35:04 +0100 Subject: bc: remove use of "BcInstPtr ip" object from loop parsing function old new delta zbc_parse_stmt_possibly_auto 1964 1909 -55 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-55) Total: -55 bytes text data bss dec hex filename 981934 485 7296 989715 f1a13 busybox_old 981879 485 7296 989660 f19dc busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 979d5113d..56a2bca71 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -4173,9 +4173,9 @@ static BC_STATUS zbc_parse_if(BcParse *p) static BC_STATUS zbc_parse_while(BcParse *p) { BcStatus s; - BcInstPtr ip; size_t *label; size_t cond_idx; + size_t ip_idx; s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); @@ -4184,16 +4184,13 @@ static BC_STATUS zbc_parse_while(BcParse *p) if (s) RETURN_STATUS(s); cond_idx = p->func->labels.len; + ip_idx = cond_idx + 1; bc_vec_push(&p->func->labels, &p->func->code.len); bc_vec_push(&p->conds, &cond_idx); - ip.idx = p->func->labels.len; - ip.func = 1; - ip.len = 0; - - bc_vec_push(&p->exits, &ip.idx); - bc_vec_push(&p->func->labels, &ip.idx); + bc_vec_push(&p->exits, &ip_idx); + bc_vec_push(&p->func->labels, &ip_idx); s = zbc_parse_expr(p, BC_PARSE_REL, bc_parse_next_rel); if (s) RETURN_STATUS(s); @@ -4204,7 +4201,7 @@ static BC_STATUS zbc_parse_while(BcParse *p) if (s) RETURN_STATUS(s); bc_parse_push(p, BC_INST_JUMP_ZERO); - bc_parse_pushIndex(p, ip.idx); + bc_parse_pushIndex(p, ip_idx); s = zbc_parse_stmt_fail_if_bare_NLINE(p, false, "while"); if (s) RETURN_STATUS(s); @@ -4213,7 +4210,7 @@ static BC_STATUS zbc_parse_while(BcParse *p) bc_parse_push(p, BC_INST_JUMP); bc_parse_pushIndex(p, cond_idx); - label = bc_vec_item(&p->func->labels, ip.idx); + label = bc_vec_item(&p->func->labels, ip_idx); dbg_lex("%s:%d rewriting label: %d -> %d", __func__, __LINE__, *label, p->func->code.len); *label = p->func->code.len; @@ -4229,7 +4226,6 @@ static BC_STATUS zbc_parse_while(BcParse *p) static BC_STATUS zbc_parse_for(BcParse *p) { BcStatus s; - BcInstPtr ip; size_t *label; size_t cond_idx, exit_idx, body_idx, update_idx; @@ -4273,8 +4269,6 @@ static BC_STATUS zbc_parse_for(BcParse *p) bc_parse_push(p, BC_INST_JUMP); bc_parse_pushIndex(p, body_idx); - ip.idx = p->func->labels.len; - bc_vec_push(&p->conds, &update_idx); bc_vec_push(&p->func->labels, &p->func->code.len); @@ -4290,12 +4284,8 @@ static BC_STATUS zbc_parse_for(BcParse *p) bc_parse_pushIndex(p, cond_idx); bc_vec_push(&p->func->labels, &p->func->code.len); - ip.idx = exit_idx; - ip.func = 1; - ip.len = 0; - - bc_vec_push(&p->exits, &ip.idx); - bc_vec_push(&p->func->labels, &ip.idx); + bc_vec_push(&p->exits, &exit_idx); + bc_vec_push(&p->func->labels, &exit_idx); // for(...)stmt is accepted as well s = zbc_lex_next_and_skip_NLINE(&p->l); @@ -4309,7 +4299,7 @@ static BC_STATUS zbc_parse_for(BcParse *p) bc_parse_push(p, BC_INST_JUMP); bc_parse_pushIndex(p, update_idx); - label = bc_vec_item(&p->func->labels, ip.idx); + label = bc_vec_item(&p->func->labels, exit_idx); dbg_lex("%s:%d rewriting label: %d -> %d", __func__, __LINE__, *label, p->func->code.len); *label = p->func->code.len; -- cgit v1.2.3-55-g6feb From 94f72a387c13e4620635ee47ec7c5aa6bbbb473c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 17 Dec 2018 00:07:48 +0100 Subject: bc: factor out common code function old new delta zbc_parse_stmt_allow_NLINE_before - 59 +59 bc_parse_pushJUMP_ZERO - 27 +27 bc_parse_pushJUMP - 27 +27 rewrite_label_to_current - 19 +19 zbc_vm_process 594 599 +5 zbc_lex_next_and_skip_NLINE 22 - -22 zbc_parse_stmt_fail_if_bare_NLINE 28 - -28 zbc_parse_stmt_possibly_auto 1909 1678 -231 ------------------------------------------------------------------------------ (add/remove: 4/2 grow/shrink: 1/1 up/down: 137/-281) Total: -144 bytes text data bss dec hex filename 981879 485 7296 989660 f19dc busybox_old 981755 485 7296 989536 f1960 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 108 +++++++++++++++++++++++++++------------------------------ 1 file changed, 51 insertions(+), 57 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 56a2bca71..9f23a0601 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -3556,6 +3556,18 @@ static void bc_parse_pushIndex(BcParse *p, size_t idx) } } +static void bc_parse_pushJUMP(BcParse *p, size_t idx) +{ + bc_parse_push(p, BC_INST_JUMP); + bc_parse_pushIndex(p, idx); +} + +static void bc_parse_pushJUMP_ZERO(BcParse *p, size_t idx) +{ + bc_parse_push(p, BC_INST_JUMP_ZERO); + bc_parse_pushIndex(p, idx); +} + static void bc_parse_number(BcParse *p) { char *num = xstrdup(p->l.t.v.v); @@ -3677,14 +3689,19 @@ static BC_STATUS zbc_parse_stmt(BcParse *p) # define zbc_parse_stmt(...) (zbc_parse_stmt(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static BC_STATUS zbc_parse_stmt_fail_if_bare_NLINE(BcParse *p, bool auto_allowed, const char *after_X) +static BC_STATUS zbc_parse_stmt_allow_NLINE_before(BcParse *p, const char *after_X) { + // "if(cond)stmt" is accepted too, but not 2+ newlines. + // Same for "else", "while()", "for()". + BcStatus s = zbc_lex_next_and_skip_NLINE(&p->l); + if (s) RETURN_STATUS(s); if (p->l.t.t == BC_LEX_NLINE) RETURN_STATUS(bc_error_fmt("no statement after '%s'", after_X)); - RETURN_STATUS(zbc_parse_stmt_possibly_auto(p, auto_allowed)); + + RETURN_STATUS(zbc_parse_stmt(p)); } #if ERRORS_ARE_FATAL -# define zbc_parse_stmt_fail_if_bare_NLINE(...) (zbc_parse_stmt_fail_if_bare_NLINE(__VA_ARGS__), BC_STATUS_SUCCESS) +# define zbc_parse_stmt_allow_NLINE_before(...) (zbc_parse_stmt_allow_NLINE_before(__VA_ARGS__), BC_STATUS_SUCCESS) #endif static void bc_parse_operator(BcParse *p, BcLexType type, size_t start, @@ -4106,11 +4123,16 @@ static BC_STATUS zbc_parse_return(BcParse *p) # define zbc_parse_return(...) (zbc_parse_return(__VA_ARGS__), BC_STATUS_SUCCESS) #endif +static void rewrite_label_to_current(BcParse *p, size_t idx) +{ + size_t *label = bc_vec_item(&p->func->labels, idx); + *label = p->func->code.len; +} + static BC_STATUS zbc_parse_if(BcParse *p) { BcStatus s; size_t ip_idx; - size_t *label; dbg_lex_enter("%s:%d entered", __func__, __LINE__); s = zbc_lex_next(&p->l); @@ -4123,45 +4145,35 @@ static BC_STATUS zbc_parse_if(BcParse *p) if (s) RETURN_STATUS(s); if (p->l.t.t != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); - // if(cond)stmt is accepted too (but not 2+ newlines) - s = zbc_lex_next_and_skip_NLINE(&p->l); - if (s) RETURN_STATUS(s); - bc_parse_push(p, BC_INST_JUMP_ZERO); ip_idx = p->func->labels.len; - bc_parse_pushIndex(p, ip_idx); + bc_parse_pushJUMP_ZERO(p, ip_idx); bc_vec_push(&p->func->labels, &ip_idx); - s = zbc_parse_stmt_fail_if_bare_NLINE(p, false, "if"); + s = zbc_parse_stmt_allow_NLINE_before(p, "if"); if (s) RETURN_STATUS(s); dbg_lex("%s:%d in if after stmt: p->l.t.t:%d", __func__, __LINE__, p->l.t.t); if (p->l.t.t == BC_LEX_KEY_ELSE) { size_t ip2_idx; - s = zbc_lex_next_and_skip_NLINE(&p->l); - if (s) RETURN_STATUS(s); - ip2_idx = p->func->labels.len; dbg_lex("%s:%d after if() body: BC_INST_JUMP to %d", __func__, __LINE__, ip2_idx); - bc_parse_push(p, BC_INST_JUMP); - bc_parse_pushIndex(p, ip2_idx); + bc_parse_pushJUMP(p, ip2_idx); - label = bc_vec_item(&p->func->labels, ip_idx); - dbg_lex("%s:%d rewriting 'if_zero' label to jump to 'else': %d -> %d", __func__, __LINE__, *label, p->func->code.len); - *label = p->func->code.len; + dbg_lex("%s:%d rewriting 'if_zero' label to jump to 'else'-> %d", __func__, __LINE__, p->func->code.len); + rewrite_label_to_current(p, ip_idx); bc_vec_push(&p->func->labels, &ip2_idx); ip_idx = ip2_idx; - s = zbc_parse_stmt_fail_if_bare_NLINE(p, false, "else"); + s = zbc_parse_stmt_allow_NLINE_before(p, "else"); if (s) RETURN_STATUS(s); } - label = bc_vec_item(&p->func->labels, ip_idx); - dbg_lex("%s:%d rewriting label to jump after 'if' body: %d -> %d", __func__, __LINE__, *label, p->func->code.len); - *label = p->func->code.len; + dbg_lex("%s:%d rewriting label to jump after 'if' body-> %d", __func__, __LINE__, p->func->code.len); + rewrite_label_to_current(p, ip_idx); dbg_lex_done("%s:%d done", __func__, __LINE__); RETURN_STATUS(s); @@ -4173,7 +4185,6 @@ static BC_STATUS zbc_parse_if(BcParse *p) static BC_STATUS zbc_parse_while(BcParse *p) { BcStatus s; - size_t *label; size_t cond_idx; size_t ip_idx; @@ -4196,23 +4207,16 @@ static BC_STATUS zbc_parse_while(BcParse *p) if (s) RETURN_STATUS(s); if (p->l.t.t != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); - // while(cond)stmt is accepted too - s = zbc_lex_next_and_skip_NLINE(&p->l); - if (s) RETURN_STATUS(s); + bc_parse_pushJUMP_ZERO(p, ip_idx); - bc_parse_push(p, BC_INST_JUMP_ZERO); - bc_parse_pushIndex(p, ip_idx); - - s = zbc_parse_stmt_fail_if_bare_NLINE(p, false, "while"); + s = zbc_parse_stmt_allow_NLINE_before(p, "while"); if (s) RETURN_STATUS(s); dbg_lex("%s:%d BC_INST_JUMP to %d", __func__, __LINE__, cond_idx); - bc_parse_push(p, BC_INST_JUMP); - bc_parse_pushIndex(p, cond_idx); + bc_parse_pushJUMP(p, cond_idx); - label = bc_vec_item(&p->func->labels, ip_idx); - dbg_lex("%s:%d rewriting label: %d -> %d", __func__, __LINE__, *label, p->func->code.len); - *label = p->func->code.len; + dbg_lex("%s:%d rewriting label-> %d", __func__, __LINE__, p->func->code.len); + rewrite_label_to_current(p, ip_idx); bc_vec_pop(&p->exits); bc_vec_pop(&p->conds); @@ -4226,7 +4230,6 @@ static BC_STATUS zbc_parse_while(BcParse *p) static BC_STATUS zbc_parse_for(BcParse *p) { BcStatus s; - size_t *label; size_t cond_idx, exit_idx, body_idx, update_idx; dbg_lex("%s:%d p->l.t.t:%d", __func__, __LINE__, p->l.t.t); @@ -4264,10 +4267,8 @@ static BC_STATUS zbc_parse_for(BcParse *p) s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); - bc_parse_push(p, BC_INST_JUMP_ZERO); - bc_parse_pushIndex(p, exit_idx); - bc_parse_push(p, BC_INST_JUMP); - bc_parse_pushIndex(p, body_idx); + bc_parse_pushJUMP_ZERO(p, exit_idx); + bc_parse_pushJUMP(p, body_idx); bc_vec_push(&p->conds, &update_idx); bc_vec_push(&p->func->labels, &p->func->code.len); @@ -4280,28 +4281,20 @@ static BC_STATUS zbc_parse_for(BcParse *p) if (s) RETURN_STATUS(s); if (p->l.t.t != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); - bc_parse_push(p, BC_INST_JUMP); - bc_parse_pushIndex(p, cond_idx); + bc_parse_pushJUMP(p, cond_idx); bc_vec_push(&p->func->labels, &p->func->code.len); bc_vec_push(&p->exits, &exit_idx); bc_vec_push(&p->func->labels, &exit_idx); - // for(...)stmt is accepted as well - s = zbc_lex_next_and_skip_NLINE(&p->l); - if (s) RETURN_STATUS(s); - - s = zbc_parse_stmt_fail_if_bare_NLINE(p, false, "for"); + s = zbc_parse_stmt_allow_NLINE_before(p, "for"); if (s) RETURN_STATUS(s); -//TODO: commonalize? dbg_lex("%s:%d BC_INST_JUMP to %d", __func__, __LINE__, update_idx); - bc_parse_push(p, BC_INST_JUMP); - bc_parse_pushIndex(p, update_idx); + bc_parse_pushJUMP(p, update_idx); - label = bc_vec_item(&p->func->labels, exit_idx); - dbg_lex("%s:%d rewriting label: %d -> %d", __func__, __LINE__, *label, p->func->code.len); - *label = p->func->code.len; + dbg_lex("%s:%d rewriting label-> %d", __func__, __LINE__, p->func->code.len); + rewrite_label_to_current(p, exit_idx); bc_vec_pop(&p->exits); bc_vec_pop(&p->conds); @@ -4325,8 +4318,7 @@ static BC_STATUS zbc_parse_break_or_continue(BcParse *p, BcLexType type) i = *(size_t*)bc_vec_top(&p->conds); } - bc_parse_push(p, BC_INST_JUMP); - bc_parse_pushIndex(p, i); + bc_parse_pushJUMP(p, i); s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); @@ -4407,10 +4399,12 @@ static BC_STATUS zbc_parse_funcdef(BcParse *p) // Prevent "define z()" from being interpreted as function with empty stmt as body s = zbc_lex_skip_if_at_NLINE(&p->l); if (s) RETURN_STATUS(s); -//TODO: GNU bc requires a {} block even if function body has single stmt, enforce this? + //GNU bc requires a {} block even if function body has single stmt, enforce this? + if (p->l.t.t != BC_LEX_LBRACE) + RETURN_STATUS(bc_error("function { body } expected")); p->in_funcdef++; // to determine whether "return" stmt is allowed, and such - s = zbc_parse_stmt_fail_if_bare_NLINE(p, true, "define"); + s = zbc_parse_stmt_possibly_auto(p, true); p->in_funcdef--; if (s) RETURN_STATUS(s); -- cgit v1.2.3-55-g6feb From 51b22b1bce7c7bf656897ee38c409aa0abd64403 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 17 Dec 2018 00:15:35 +0100 Subject: bc: fix typo: defone -> define Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 9f23a0601..24d1ebba6 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -3678,7 +3678,7 @@ static BC_STATUS zbc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next); static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext next); #if ERRORS_ARE_FATAL # define zbc_parse_expr(...) (zbc_parse_expr(__VA_ARGS__), BC_STATUS_SUCCESS) -# defone zbc_parse_stmt_possibly_auto(...) (zbc_parse_stmt_possibly_auto(__VA_ARGS__), BC_STATUS_SUCCESS) +# define zbc_parse_stmt_possibly_auto(...) (zbc_parse_stmt_possibly_auto(__VA_ARGS__), BC_STATUS_SUCCESS) #endif static BC_STATUS zbc_parse_stmt(BcParse *p) -- cgit v1.2.3-55-g6feb From c5774a3458ab660e9f75526b3cd8e67da520e0ae Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 17 Dec 2018 01:22:53 +0100 Subject: bc: move fflush to the _actual_ execution loop Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 24d1ebba6..c92f6f813 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -6875,6 +6875,8 @@ static BC_STATUS zbc_program_exec(void) RETURN_STATUS(s); } + fflush_and_check(); + // If the stack has changed, pointers may be invalid. ip = bc_vec_top(&G.prog.stack); func = bc_program_func(ip->func); @@ -6920,7 +6922,6 @@ static BC_STATUS zbc_vm_process(const char *text) bc_program_reset(); break; } - fflush_and_check(); } dbg_lex_done("%s:%d done", __func__, __LINE__); -- cgit v1.2.3-55-g6feb From e4ba4c43716b6f550de3bf922e6f25e2dd9e983e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 17 Dec 2018 09:51:43 +0100 Subject: bc: parse file arguments piecemeal (do not read entire file) function old new delta bc_read_line 336 406 +70 zbc_vm_execute_FILE - 67 +67 zbc_lex_next 2309 2318 +9 zbc_program_exec 4002 4008 +6 bc_program_index 66 64 -2 bc_vm_run 139 124 -15 zbc_vm_file 208 32 -176 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 3/3 up/down: 152/-193) Total: -41 bytes text data bss dec hex filename 981736 485 7296 989517 f194d busybox_old 981667 485 7296 989448 f1908 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 183 ++++++++++++++++++++++++--------------------------------- 1 file changed, 78 insertions(+), 105 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index c92f6f813..2570e8313 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -694,7 +694,6 @@ struct globals { IF_FEATURE_BC_SIGNALS(smallint ttyin;) IF_FEATURE_CLEAN_UP(smallint exiting;) smallint in_read; - smallint use_stdin; BcParse prs; BcProgram prog; @@ -704,7 +703,8 @@ struct globals { unsigned err_line; BcVec files; - BcVec stdin_buffer; + BcVec input_buffer; + FILE *input_fp; char *env_args; @@ -1317,8 +1317,8 @@ static int bad_input_byte(char c) return 0; } -// Note: it _appends_ data from the stdin to vec. -static void bc_read_line(BcVec *vec) +// Note: it _appends_ data from fp to vec. +static void bc_read_line(BcVec *vec, FILE *fp) { again: fflush_and_check(); @@ -1326,6 +1326,17 @@ static void bc_read_line(BcVec *vec) #if ENABLE_FEATURE_BC_SIGNALS if (G_interrupt) { // ^C was pressed intr: + if (fp != stdin) { + // ^C while running a script (bc SCRIPT): die. + // We do not return to interactive prompt: + // user might be running us from a shell, + // and SCRIPT might be intended to terminate + // (e.g. contain a "halt" stmt). + // ^C dropping user into a bc prompt instead of + // the shell would be unexpected. + xfunc_die(); + } + // ^C while interactive input G_interrupt = 0; // GNU bc says "interrupted execution." // GNU dc says "Interrupt!" @@ -1333,14 +1344,14 @@ static void bc_read_line(BcVec *vec) } # if ENABLE_FEATURE_EDITING - if (G_ttyin) { + if (G_ttyin && fp == stdin) { int n, i; # define line_buf bb_common_bufsiz1 n = read_line_input(G.line_input_state, "", line_buf, COMMON_BUFSIZE); if (n <= 0) { // read errors or EOF, or ^D, or ^C if (n == 0) // ^C goto intr; - bc_vec_pushZeroByte(vec); + bc_vec_pushZeroByte(vec); // ^D or EOF (or error) return; } i = 0; @@ -1359,60 +1370,38 @@ static void bc_read_line(BcVec *vec) bool bad_chars = 0; size_t len = vec->len; - IF_FEATURE_BC_SIGNALS(errno = 0;) do { - c = fgetc(stdin); -#if ENABLE_FEATURE_BC_SIGNALS && !ENABLE_FEATURE_EDITING - // Both conditions appear simultaneously, check both just in case - if (errno == EINTR || G_interrupt) { - // ^C was pressed - clearerr(stdin); +#if ENABLE_FEATURE_BC_SIGNALS + if (G_interrupt) { + // ^C was pressed: ignore entire line, get another one + vec->len = len; goto intr; } #endif + c = fgetc(fp); if (c == EOF) { - if (ferror(stdin)) - quit(); // this emits error message - // Note: EOF does not append '\n', therefore: - // printf 'print 123\n' | bc - works - // printf 'print 123' | bc - fails (syntax error) + if (ferror(fp)) + bb_perror_msg_and_die("input error"); + // Note: EOF does not append '\n' break; } bad_chars |= bad_input_byte(c); bc_vec_pushByte(vec, (char)c); } while (c != '\n'); + if (bad_chars) { - // Bad chars on this line, ignore entire line - vec->len = len; - goto again; + // Bad chars on this line + if (!G.prog.file) { // stdin + // ignore entire line, get another one + vec->len = len; + goto again; + } + bb_perror_msg_and_die("file '%s' is not text", G.prog.file); } bc_vec_pushZeroByte(vec); } } -static char* bc_read_file(const char *path) -{ - char *buf; - size_t size = ((size_t) -1); - size_t i; - - // Never returns NULL (dies on errors) - buf = xmalloc_xopen_read_close(path, &size); - - for (i = 0; i < size; ++i) { - char c = buf[i]; - if ((c < ' ' && c != '\t' && c != '\r' && c != '\n') // also allow '\v' '\f'? - || c > 0x7e - ) { - free(buf); - buf = NULL; - break; - } - } - - return buf; -} - static void bc_num_setToZero(BcNum *n, size_t scale) { n->len = 0; @@ -2912,7 +2901,7 @@ static bool bc_lex_more_input(BcLex *l) size_t str; bool comment; - bc_vec_pop_all(&G.stdin_buffer); + bc_vec_pop_all(&G.input_buffer); // This loop is complex because the vm tries not to send any lines that end // with a backslash to the parser. The reason for that is because the parser @@ -2921,18 +2910,18 @@ static bool bc_lex_more_input(BcLex *l) comment = false; str = 0; for (;;) { - size_t prevlen = G.stdin_buffer.len; + size_t prevlen = G.input_buffer.len; char *string; - bc_read_line(&G.stdin_buffer); + bc_read_line(&G.input_buffer, G.input_fp); // No more input means EOF - if (G.stdin_buffer.len <= prevlen + 1) // (we expect +1 for NUL byte) + if (G.input_buffer.len <= prevlen + 1) // (we expect +1 for NUL byte) break; - string = G.stdin_buffer.v + prevlen; + string = G.input_buffer.v + prevlen; while (*string) { char c = *string; - if (string == G.stdin_buffer.v || string[-1] != '\\') { + if (string == G.input_buffer.v || string[-1] != '\\') { if (IS_BC) str ^= (c == '"'); else { @@ -2954,7 +2943,7 @@ static bool bc_lex_more_input(BcLex *l) } } if (str != 0 || comment) { - G.stdin_buffer.len--; // backstep over the trailing NUL byte + G.input_buffer.len--; // backstep over the trailing NUL byte continue; } @@ -2963,21 +2952,20 @@ static bool bc_lex_more_input(BcLex *l) // if it is not, then it's EOF, and looping back // to bc_read_line() will detect it: string -= 2; - if (string >= G.stdin_buffer.v && *string == '\\') { - G.stdin_buffer.len--; + if (string >= G.input_buffer.v && *string == '\\') { + G.input_buffer.len--; continue; } break; } - l->buf = G.stdin_buffer.v; + l->buf = G.input_buffer.v; l->i = 0; -//bb_error_msg("G.stdin_buffer.len:%d '%s'", G.stdin_buffer.len, G.stdin_buffer.v); - l->len = G.stdin_buffer.len - 1; // do not include NUL +// bb_error_msg("G.input_buffer.len:%d '%s'", G.input_buffer.len, G.input_buffer.v); + l->len = G.input_buffer.len - 1; // do not include NUL - G.use_stdin = (l->len != 0); - return G.use_stdin; + return l->len != 0; } static BC_STATUS zbc_lex_next(BcLex *l) @@ -2989,22 +2977,23 @@ static BC_STATUS zbc_lex_next(BcLex *l) l->line += l->newline; G.err_line = l->line; - - l->t.t = BC_LEX_EOF; -//this NL handling is bogus - l->newline = (l->i == l->len); - if (l->newline) { - if (!G.use_stdin || !bc_lex_more_input(l)) - RETURN_STATUS(BC_STATUS_SUCCESS); - // here it's guaranteed that l->i is below l->len - l->newline = false; - } + l->newline = false; // Loop until failure or we don't have whitespace. This // is so the parser doesn't get inundated with whitespace. // Comments are also BC_LEX_WHITESPACE tokens and eaten here. s = BC_STATUS_SUCCESS; do { + l->t.t = BC_LEX_EOF; + if (l->i == l->len) { + if (!G.input_fp) + RETURN_STATUS(BC_STATUS_SUCCESS); + if (!bc_lex_more_input(l)) { + G.input_fp = NULL; + RETURN_STATUS(BC_STATUS_SUCCESS); + } + // here it's guaranteed that l->i is below l->len + } dbg_lex("next string to parse:'%.*s'", (int)(strchrnul(l->buf + l->i, '\n') - (l->buf + l->i)), l->buf + l->i); @@ -5351,7 +5340,7 @@ static BC_STATUS zbc_program_read(void) G.in_read = 1; bc_char_vec_init(&buf); - bc_read_line(&buf); + bc_read_line(&buf, stdin); bc_parse_create(&parse, BC_PROG_READ); bc_lex_file(&parse.l); @@ -6931,60 +6920,44 @@ static BC_STATUS zbc_vm_process(const char *text) # define zbc_vm_process(...) (zbc_vm_process(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static BC_STATUS zbc_vm_file(const char *file) +static BC_STATUS zbc_vm_execute_FILE(FILE *fp, const char *filename) { // So far bc/dc have no way to include a file from another file, // therefore we know G.prog.file == NULL on entry //const char *sv_file; - char *data; BcStatus s; - BcFunc *main_func; - BcInstPtr *ip; - - data = bc_read_file(file); - if (!data) RETURN_STATUS(bc_error_fmt("file '%s' is not text", file)); - //sv_file = G.prog.file; - G.prog.file = file; + G.prog.file = filename; + G.input_fp = fp; bc_lex_file(&G.prs.l); - s = zbc_vm_process(data); - if (s) goto err; - - main_func = bc_program_func(BC_PROG_MAIN); - ip = bc_vec_item(&G.prog.stack, 0); - - if (main_func->code.len < ip->idx) - s = bc_error_fmt("file '%s' is not executable", file); -err: - //G.prog.file = sv_file; + do { + s = zbc_vm_process(""); + // We do not stop looping on errors here if reading stdin. + // Example: start interactive bc and enter "return". + // It should say "'return' not in a function" + // but should not exit. + } while (G.input_fp == stdin); G.prog.file = NULL; - free(data); RETURN_STATUS(s); } #if ERRORS_ARE_FATAL -# define zbc_vm_file(...) (zbc_vm_file(__VA_ARGS__), BC_STATUS_SUCCESS) +# define zbc_vm_execute_FILE(...) (zbc_vm_execute_FILE(__VA_ARGS__), BC_STATUS_SUCCESS) #endif -static BC_STATUS zbc_vm_stdin(void) +static BC_STATUS zbc_vm_file(const char *file) { BcStatus s; + FILE *fp; - //G.prog.file = NULL; - already is - bc_lex_file(&G.prs.l); + fp = xfopen_for_read(file); + s = zbc_vm_execute_FILE(fp, file); + fclose(fp); - G.use_stdin = 1; - do { - s = zbc_vm_process(""); - // We do not stop looping on errors here. - // Example: start interactive bc and enter "return". - // It should say "'return' not in a function" - // but should not exit. - } while (G.use_stdin); RETURN_STATUS(s); } #if ERRORS_ARE_FATAL -# define zbc_vm_stdin(...) (zbc_vm_stdin(__VA_ARGS__), BC_STATUS_SUCCESS) +# define zbc_vm_file(...) (zbc_vm_file(__VA_ARGS__), BC_STATUS_SUCCESS) #endif #if ENABLE_BC @@ -7257,7 +7230,7 @@ static BC_STATUS zbc_vm_exec(void) } if (IS_BC || (option_mask32 & BC_FLAG_I)) - s = zbc_vm_stdin(); + s = zbc_vm_execute_FILE(stdin, /*filename:*/ NULL); RETURN_STATUS(s); } @@ -7287,7 +7260,7 @@ static void bc_program_free(void) bc_num_free(&G.prog.last); bc_num_free(&G.prog.zero); bc_num_free(&G.prog.one); - bc_vec_free(&G.stdin_buffer); + bc_vec_free(&G.input_buffer); } static void bc_vm_free(void) @@ -7352,7 +7325,7 @@ static void bc_program_init(void) bc_vec_init(&G.prog.stack, sizeof(BcInstPtr), NULL); bc_vec_push(&G.prog.stack, &ip); - bc_char_vec_init(&G.stdin_buffer); + bc_char_vec_init(&G.input_buffer); } static int bc_vm_init(const char *env_len) -- cgit v1.2.3-55-g6feb From ec60318f15eae13621b632c1f72406f02bc47cc1 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 17 Dec 2018 10:34:02 +0100 Subject: bc: tidy up "z-function" macro machinery Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 449 +++++++++++++++++---------------------------------------- 1 file changed, 131 insertions(+), 318 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 2570e8313..ccc7cb4d1 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -551,12 +551,6 @@ enum { #define bc_lex_kws_POSIX(i) ((1 << (i)) & POSIX_KWORD_MASK) #endif -#if ENABLE_FEATURE_BC_SIGNALS || ENABLE_FEATURE_CLEAN_UP -# define BC_STATUS BcStatus -#else -# define BC_STATUS void -#endif - typedef struct BcLex { const char *buf; size_t i; @@ -890,15 +884,17 @@ dc_parse_insts[] = { #if ENABLE_FEATURE_BC_SIGNALS || ENABLE_FEATURE_CLEAN_UP # define ERRORS_ARE_FATAL 0 # define ERRORFUNC /*nothing*/ -# define ERROR_RETURN(a) a -//moved up: # define BC_STATUS BcStatus +# define IF_ERROR_RETURN_POSSIBLE(a) a +# define BC_STATUS BcStatus # define RETURN_STATUS(v) return (v) +# define COMMA_SUCCESS /*nothing*/ #else # define ERRORS_ARE_FATAL 1 # define ERRORFUNC NORETURN -# define ERROR_RETURN(a) /*nothing*/ -//moved up: # define BC_STATUS void +# define IF_ERROR_RETURN_POSSIBLE(a) /*nothing*/ +# define BC_STATUS void # define RETURN_STATUS(v) do { ((void)(v)); return; } while (0) +# define COMMA_SUCCESS ,BC_STATUS_SUCCESS #endif #define BC_NUM_NEG(n, neg) ((((ssize_t)(n)) ^ -((ssize_t)(neg))) + (neg)) @@ -968,14 +964,12 @@ static FAST_FUNC BC_STATUS zbc_num_pow(BcNum *a, BcNum *b, BcNum *c, size_t scal static const BcNumBinaryOp zbc_program_ops[] = { zbc_num_pow, zbc_num_mul, zbc_num_div, zbc_num_mod, zbc_num_add, zbc_num_sub, }; -#if ERRORS_ARE_FATAL -# define zbc_num_add(...) (zbc_num_add(__VA_ARGS__), BC_STATUS_SUCCESS) -# define zbc_num_sub(...) (zbc_num_sub(__VA_ARGS__), BC_STATUS_SUCCESS) -# define zbc_num_mul(...) (zbc_num_mul(__VA_ARGS__), BC_STATUS_SUCCESS) -# define zbc_num_div(...) (zbc_num_div(__VA_ARGS__), BC_STATUS_SUCCESS) -# define zbc_num_mod(...) (zbc_num_mod(__VA_ARGS__), BC_STATUS_SUCCESS) -# define zbc_num_pow(...) (zbc_num_pow(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_num_add(...) (zbc_num_add(__VA_ARGS__) COMMA_SUCCESS) +#define zbc_num_sub(...) (zbc_num_sub(__VA_ARGS__) COMMA_SUCCESS) +#define zbc_num_mul(...) (zbc_num_mul(__VA_ARGS__) COMMA_SUCCESS) +#define zbc_num_div(...) (zbc_num_div(__VA_ARGS__) COMMA_SUCCESS) +#define zbc_num_mod(...) (zbc_num_mod(__VA_ARGS__) COMMA_SUCCESS) +#define zbc_num_pow(...) (zbc_num_pow(__VA_ARGS__) COMMA_SUCCESS) static void fflush_and_check(void) { @@ -1027,9 +1021,9 @@ static NOINLINE ERRORFUNC int bc_error_fmt(const char *fmt, ...) bc_verror_msg(fmt, p); va_end(p); - if (!ENABLE_FEATURE_CLEAN_UP && !G_ttyin) - exit(1); - ERROR_RETURN(return BC_STATUS_FAILURE;) + if (ENABLE_FEATURE_CLEAN_UP || G_ttyin) + IF_ERROR_RETURN_POSSIBLE(return BC_STATUS_FAILURE); + exit(1); } #if ENABLE_BC @@ -1048,9 +1042,9 @@ static NOINLINE int bc_posix_error_fmt(const char *fmt, ...) // Do we treat non-POSIX constructs as errors? if (!(option_mask32 & BC_FLAG_S)) return BC_STATUS_SUCCESS; // no, it's a warning - if (!ENABLE_FEATURE_CLEAN_UP && !G_ttyin) - exit(1); - return BC_STATUS_FAILURE; + if (ENABLE_FEATURE_CLEAN_UP || G_ttyin) + return BC_STATUS_FAILURE; + exit(1); } #endif @@ -1061,31 +1055,31 @@ static NOINLINE int bc_posix_error_fmt(const char *fmt, ...) // Thus, use these shims for the cases when we have no vararg PARAMS: static ERRORFUNC int bc_error(const char *msg) { - ERROR_RETURN(return) bc_error_fmt("%s", msg); + IF_ERROR_RETURN_POSSIBLE(return) bc_error_fmt("%s", msg); } static ERRORFUNC int bc_error_bad_character(char c) { - ERROR_RETURN(return) bc_error_fmt("bad character '%c'", c); + IF_ERROR_RETURN_POSSIBLE(return) bc_error_fmt("bad character '%c'", c); } static ERRORFUNC int bc_error_bad_expression(void) { - ERROR_RETURN(return) bc_error("bad expression"); + IF_ERROR_RETURN_POSSIBLE(return) bc_error("bad expression"); } static ERRORFUNC int bc_error_bad_token(void) { - ERROR_RETURN(return) bc_error("bad token"); + IF_ERROR_RETURN_POSSIBLE(return) bc_error("bad token"); } static ERRORFUNC int bc_error_stack_has_too_few_elements(void) { - ERROR_RETURN(return) bc_error("stack has too few elements"); + IF_ERROR_RETURN_POSSIBLE(return) bc_error("stack has too few elements"); } static ERRORFUNC int bc_error_variable_is_wrong_type(void) { - ERROR_RETURN(return) bc_error("variable is wrong type"); + IF_ERROR_RETURN_POSSIBLE(return) bc_error("variable is wrong type"); } static ERRORFUNC int bc_error_nested_read_call(void) { - ERROR_RETURN(return) bc_error("read() call inside of a read() call"); + IF_ERROR_RETURN_POSSIBLE(return) bc_error("read() call inside of a read() call"); } #if ENABLE_BC static int bc_POSIX_requires(const char *msg) @@ -1494,9 +1488,7 @@ static BC_STATUS zbc_num_ulong(BcNum *n, unsigned long *result_p) RETURN_STATUS(BC_STATUS_SUCCESS); } -#if ERRORS_ARE_FATAL -# define zbc_num_ulong(...) (zbc_num_ulong(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_num_ulong(...) (zbc_num_ulong(__VA_ARGS__) COMMA_SUCCESS) static void bc_num_ulong2num(BcNum *n, unsigned long val) { @@ -1678,9 +1670,7 @@ static BC_STATUS zbc_num_shift(BcNum *n, size_t places) RETURN_STATUS(BC_STATUS_SUCCESS); } -#if ERRORS_ARE_FATAL -# define zbc_num_shift(...) (zbc_num_shift(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_num_shift(...) (zbc_num_shift(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_num_inv(BcNum *a, BcNum *b, size_t scale) { @@ -1693,9 +1683,7 @@ static BC_STATUS zbc_num_inv(BcNum *a, BcNum *b, size_t scale) RETURN_STATUS(zbc_num_div(&one, a, b, scale)); } -#if ERRORS_ARE_FATAL -# define zbc_num_inv(...) (zbc_num_inv(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_num_inv(...) (zbc_num_inv(__VA_ARGS__) COMMA_SUCCESS) static FAST_FUNC BC_STATUS zbc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) { @@ -1832,9 +1820,7 @@ static FAST_FUNC BC_STATUS zbc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size static FAST_FUNC BC_STATUS zbc_num_k(BcNum *restrict a, BcNum *restrict b, BcNum *restrict c) -#if ERRORS_ARE_FATAL -# define zbc_num_k(...) (zbc_num_k(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_num_k(...) (zbc_num_k(__VA_ARGS__) COMMA_SUCCESS) { BcStatus s; size_t max = BC_MAX(a->len, b->len), max2 = (max + 1) / 2; @@ -1982,9 +1968,7 @@ err: bc_num_free(&cpa); RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_num_m(...) (zbc_num_m(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_num_m(...) (zbc_num_m(__VA_ARGS__) COMMA_SUCCESS) static FAST_FUNC BC_STATUS zbc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) { @@ -2059,9 +2043,7 @@ static FAST_FUNC BC_STATUS zbc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_num_d(...) (zbc_num_d(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_num_d(...) (zbc_num_d(__VA_ARGS__) COMMA_SUCCESS) static FAST_FUNC BC_STATUS zbc_num_r(BcNum *a, BcNum *b, BcNum *restrict c, BcNum *restrict d, size_t scale, size_t ts) @@ -2099,9 +2081,7 @@ err: bc_num_free(&temp); RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_num_r(...) (zbc_num_r(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_num_r(...) (zbc_num_r(__VA_ARGS__) COMMA_SUCCESS) static FAST_FUNC BC_STATUS zbc_num_rem(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) { @@ -2115,9 +2095,7 @@ static FAST_FUNC BC_STATUS zbc_num_rem(BcNum *a, BcNum *b, BcNum *restrict c, si RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_num_rem(...) (zbc_num_rem(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_num_rem(...) (zbc_num_rem(__VA_ARGS__) COMMA_SUCCESS) static FAST_FUNC BC_STATUS zbc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) { @@ -2209,9 +2187,7 @@ err: bc_num_free(©); RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_num_p(...) (zbc_num_p(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_num_p(...) (zbc_num_p(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale, BcNumBinaryOp op, size_t req) @@ -2244,15 +2220,13 @@ static BC_STATUS zbc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale, bc_num_expand(c, req); s = BC_STATUS_SUCCESS; - ERROR_RETURN(s =) op(ptr_a, ptr_b, c, scale); + IF_ERROR_RETURN_POSSIBLE(s =) op(ptr_a, ptr_b, c, scale); if (init) bc_num_free(&num2); RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_num_binary(...) (zbc_num_binary(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_num_binary(...) (zbc_num_binary(__VA_ARGS__) COMMA_SUCCESS) static bool bc_num_strValid(const char *val, size_t base) { @@ -2400,9 +2374,7 @@ static BC_STATUS zbc_num_parse(BcNum *n, const char *val, BcNum *base, RETURN_STATUS(BC_STATUS_SUCCESS); } -#if ERRORS_ARE_FATAL -# define zbc_num_parse(...) (zbc_num_parse(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_num_parse(...) (zbc_num_parse(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale) { @@ -2505,9 +2477,7 @@ err: bc_num_free(&num1); RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_num_sqrt(...) (zbc_num_sqrt(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_num_sqrt(...) (zbc_num_sqrt(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d, size_t scale) @@ -2534,9 +2504,7 @@ static BC_STATUS zbc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d, RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_num_divmod(...) (zbc_num_divmod(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_num_divmod(...) (zbc_num_divmod(__VA_ARGS__) COMMA_SUCCESS) #if ENABLE_DC static BC_STATUS zbc_num_modexp(BcNum *a, BcNum *b, BcNum *c, BcNum *restrict d) @@ -2590,9 +2558,7 @@ err: bc_num_free(&base); RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_num_modexp(...) (zbc_num_modexp(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_num_modexp(...) (zbc_num_modexp(__VA_ARGS__) COMMA_SUCCESS) #endif // ENABLE_DC #if ENABLE_BC @@ -2613,9 +2579,7 @@ static BC_STATUS zbc_func_insert(BcFunc *f, char *name, bool var) RETURN_STATUS(BC_STATUS_SUCCESS); } -#if ERRORS_ARE_FATAL -# define zbc_func_insert(...) (zbc_func_insert(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_func_insert(...) (zbc_func_insert(__VA_ARGS__) COMMA_SUCCESS) #endif static void bc_func_init(BcFunc *f) @@ -2835,9 +2799,7 @@ static BC_STATUS zbc_lex_number(BcLex *l, char start) RETURN_STATUS(BC_STATUS_SUCCESS); } -#if ERRORS_ARE_FATAL -# define zbc_lex_number(...) (zbc_lex_number(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_lex_number(...) (zbc_lex_number(__VA_ARGS__) COMMA_SUCCESS) static void bc_lex_name(BcLex *l) { @@ -2895,6 +2857,7 @@ static BC_STATUS zcommon_lex_token(BcLex *l) } IF_DC(RETURN_STATUS(zdc_lex_token(l));) } +#define zcommon_lex_token(...) (zcommon_lex_token(__VA_ARGS__) COMMA_SUCCESS) static bool bc_lex_more_input(BcLex *l) { @@ -2997,15 +2960,13 @@ static BC_STATUS zbc_lex_next(BcLex *l) dbg_lex("next string to parse:'%.*s'", (int)(strchrnul(l->buf + l->i, '\n') - (l->buf + l->i)), l->buf + l->i); - ERROR_RETURN(s =) zcommon_lex_token(l); + s = zcommon_lex_token(l); } while (!s && l->t.t == BC_LEX_WHITESPACE); dbg_lex("l->t.t from string:%d", l->t.t); RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_lex_next(...) (zbc_lex_next(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_lex_next(...) (zbc_lex_next(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_lex_skip_if_at_NLINE(BcLex *l) { @@ -3013,9 +2974,7 @@ static BC_STATUS zbc_lex_skip_if_at_NLINE(BcLex *l) RETURN_STATUS(zbc_lex_next(l)); RETURN_STATUS(BC_STATUS_SUCCESS); } -#if ERRORS_ARE_FATAL -# define zbc_lex_skip_if_at_NLINE(...) (zbc_lex_skip_if_at_NLINE(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_lex_skip_if_at_NLINE(...) (zbc_lex_skip_if_at_NLINE(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_lex_next_and_skip_NLINE(BcLex *l) { @@ -3026,9 +2985,7 @@ static BC_STATUS zbc_lex_next_and_skip_NLINE(BcLex *l) s = zbc_lex_skip_if_at_NLINE(l); RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_lex_next_and_skip_NLINE(...) (zbc_lex_next_and_skip_NLINE(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_lex_next_and_skip_NLINE(...) (zbc_lex_next_and_skip_NLINE(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_lex_text_init(BcLex *l, const char *text) { @@ -3038,9 +2995,7 @@ static BC_STATUS zbc_lex_text_init(BcLex *l, const char *text) l->t.t = l->t.last = BC_LEX_INVALID; RETURN_STATUS(zbc_lex_next(l)); } -#if ERRORS_ARE_FATAL -# define zbc_lex_text_init(...) (zbc_lex_text_init(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_lex_text_init(...) (zbc_lex_text_init(__VA_ARGS__) COMMA_SUCCESS) #if ENABLE_BC static BC_STATUS zbc_lex_identifier(BcLex *l) @@ -3063,7 +3018,7 @@ static BC_STATUS zbc_lex_identifier(BcLex *l) l->t.t = BC_LEX_KEY_1st_keyword + i; if (!bc_lex_kws_POSIX(i)) { s = bc_posix_error_fmt("%sthe '%.8s' keyword", "POSIX does not allow ", bc_lex_kws[i].name8); - ERROR_RETURN(if (s) RETURN_STATUS(s);) + IF_ERROR_RETURN_POSSIBLE(if (s) RETURN_STATUS(s)); } // We minus 1 because the index has already been incremented. @@ -3084,9 +3039,7 @@ static BC_STATUS zbc_lex_identifier(BcLex *l) RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_lex_identifier(...) (zbc_lex_identifier(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_lex_identifier(...) (zbc_lex_identifier(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_lex_string(BcLex *l) { @@ -3117,9 +3070,7 @@ static BC_STATUS zbc_lex_string(BcLex *l) RETURN_STATUS(BC_STATUS_SUCCESS); } -#if ERRORS_ARE_FATAL -# define zbc_lex_string(...) (zbc_lex_string(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_lex_string(...) (zbc_lex_string(__VA_ARGS__) COMMA_SUCCESS) static void bc_lex_assign(BcLex *l, unsigned with_and_without) { @@ -3161,9 +3112,7 @@ static BC_STATUS zbc_lex_comment(BcLex *l) RETURN_STATUS(BC_STATUS_SUCCESS); } -#if ERRORS_ARE_FATAL -# define zbc_lex_comment(...) (zbc_lex_comment(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_lex_comment(...) (zbc_lex_comment(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_lex_token(BcLex *l) { @@ -3192,7 +3141,7 @@ static BC_STATUS zbc_lex_token(BcLex *l) bc_lex_assign(l, BC_LEX_OP_REL_NE, BC_LEX_OP_BOOL_NOT); if (l->t.t == BC_LEX_OP_BOOL_NOT) { s = bc_POSIX_does_not_allow_bool_ops_this_is_bad("!"); - ERROR_RETURN(if (s) RETURN_STATUS(s);) + IF_ERROR_RETURN_POSSIBLE(if (s) RETURN_STATUS(s)); } break; case '"': @@ -3200,7 +3149,7 @@ static BC_STATUS zbc_lex_token(BcLex *l) break; case '#': s = bc_POSIX_does_not_allow("'#' script comments"); - ERROR_RETURN(if (s) RETURN_STATUS(s);) + IF_ERROR_RETURN_POSSIBLE(if (s) RETURN_STATUS(s)); bc_lex_lineComment(l); break; case '%': @@ -3210,7 +3159,7 @@ static BC_STATUS zbc_lex_token(BcLex *l) c2 = l->buf[l->i]; if (c2 == '&') { s = bc_POSIX_does_not_allow_bool_ops_this_is_bad("&&"); - ERROR_RETURN(if (s) RETURN_STATUS(s);) + IF_ERROR_RETURN_POSSIBLE(if (s) RETURN_STATUS(s)); ++l->i; l->t.t = BC_LEX_OP_BOOL_AND; } else { @@ -3339,7 +3288,7 @@ static BC_STATUS zbc_lex_token(BcLex *l) c2 = l->buf[l->i]; if (c2 == '|') { s = bc_POSIX_does_not_allow_bool_ops_this_is_bad("||"); - ERROR_RETURN(if (s) RETURN_STATUS(s);) + IF_ERROR_RETURN_POSSIBLE(if (s) RETURN_STATUS(s)); ++l->i; l->t.t = BC_LEX_OP_BOOL_OR; } else { @@ -3376,9 +3325,7 @@ static BC_STATUS zdc_lex_register(BcLex *l) RETURN_STATUS(BC_STATUS_SUCCESS); } -#if ERRORS_ARE_FATAL -# define zdc_lex_register(...) (zdc_lex_register(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zdc_lex_register(...) (zdc_lex_register(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zdc_lex_string(BcLex *l) { @@ -3415,9 +3362,7 @@ static BC_STATUS zdc_lex_string(BcLex *l) RETURN_STATUS(BC_STATUS_SUCCESS); } -#if ERRORS_ARE_FATAL -# define zdc_lex_string(...) (zdc_lex_string(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zdc_lex_string(...) (zdc_lex_string(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zdc_lex_token(BcLex *l) { @@ -3578,6 +3523,7 @@ static BC_STATUS zcommon_parse(BcParse *p) } IF_DC(RETURN_STATUS(zdc_parse_parse(p));) } +#define zcommon_parse(...) (zcommon_parse(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_parse_text_init(BcParse *p, const char *text) { @@ -3585,9 +3531,7 @@ static BC_STATUS zbc_parse_text_init(BcParse *p, const char *text) RETURN_STATUS(zbc_lex_text_init(&p->l, text)); } -#if ERRORS_ARE_FATAL -# define zbc_parse_text_init(...) (zbc_parse_text_init(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_parse_text_init(...) (zbc_parse_text_init(__VA_ARGS__) COMMA_SUCCESS) // Called when parsing or execution detects a failure, // resets execution structures. @@ -3665,18 +3609,14 @@ static void bc_parse_create(BcParse *p, size_t func) static BC_STATUS zbc_parse_stmt_possibly_auto(BcParse *p, bool auto_allowed); static BC_STATUS zbc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next); static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext next); -#if ERRORS_ARE_FATAL -# define zbc_parse_expr(...) (zbc_parse_expr(__VA_ARGS__), BC_STATUS_SUCCESS) -# define zbc_parse_stmt_possibly_auto(...) (zbc_parse_stmt_possibly_auto(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_parse_expr(...) (zbc_parse_expr(__VA_ARGS__) COMMA_SUCCESS) +#define zbc_parse_stmt_possibly_auto(...) (zbc_parse_stmt_possibly_auto(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_parse_stmt(BcParse *p) { RETURN_STATUS(zbc_parse_stmt_possibly_auto(p, false)); } -#if ERRORS_ARE_FATAL -# define zbc_parse_stmt(...) (zbc_parse_stmt(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_parse_stmt(...) (zbc_parse_stmt(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_parse_stmt_allow_NLINE_before(BcParse *p, const char *after_X) { @@ -3689,9 +3629,7 @@ static BC_STATUS zbc_parse_stmt_allow_NLINE_before(BcParse *p, const char *after RETURN_STATUS(zbc_parse_stmt(p)); } -#if ERRORS_ARE_FATAL -# define zbc_parse_stmt_allow_NLINE_before(...) (zbc_parse_stmt_allow_NLINE_before(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_parse_stmt_allow_NLINE_before(...) (zbc_parse_stmt_allow_NLINE_before(__VA_ARGS__) COMMA_SUCCESS) static void bc_parse_operator(BcParse *p, BcLexType type, size_t start, size_t *nexprs) @@ -3737,9 +3675,7 @@ static BC_STATUS zbc_parse_rightParen(BcParse *p, size_t ops_bgn, size_t *nexs) RETURN_STATUS(zbc_lex_next(&p->l)); } -#if ERRORS_ARE_FATAL -# define zbc_parse_rightParen(...) (zbc_parse_rightParen(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_parse_rightParen(...) (zbc_parse_rightParen(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_parse_params(BcParse *p, uint8_t flags) { @@ -3769,9 +3705,7 @@ static BC_STATUS zbc_parse_params(BcParse *p, uint8_t flags) RETURN_STATUS(BC_STATUS_SUCCESS); } -#if ERRORS_ARE_FATAL -# define zbc_parse_params(...) (zbc_parse_params(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_parse_params(...) (zbc_parse_params(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_parse_call(BcParse *p, char *name, uint8_t flags) { @@ -3808,9 +3742,7 @@ err: free(name); RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_parse_call(...) (zbc_parse_call(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_parse_call(...) (zbc_parse_call(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_parse_name(BcParse *p, BcInst *type, uint8_t flags) { @@ -3863,9 +3795,7 @@ err: free(name); RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_parse_name(...) (zbc_parse_name(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_parse_name(...) (zbc_parse_name(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_parse_read(BcParse *p) { @@ -3883,9 +3813,7 @@ static BC_STATUS zbc_parse_read(BcParse *p) RETURN_STATUS(zbc_lex_next(&p->l)); } -#if ERRORS_ARE_FATAL -# define zbc_parse_read(...) (zbc_parse_read(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_parse_read(...) (zbc_parse_read(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_parse_builtin(BcParse *p, BcLexType type, uint8_t flags, BcInst *prev) @@ -3911,9 +3839,7 @@ static BC_STATUS zbc_parse_builtin(BcParse *p, BcLexType type, uint8_t flags, RETURN_STATUS(zbc_lex_next(&p->l)); } -#if ERRORS_ARE_FATAL -# define zbc_parse_builtin(...) (zbc_parse_builtin(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_parse_builtin(...) (zbc_parse_builtin(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_parse_scale(BcParse *p, BcInst *type, uint8_t flags) { @@ -3942,9 +3868,7 @@ static BC_STATUS zbc_parse_scale(BcParse *p, BcInst *type, uint8_t flags) RETURN_STATUS(zbc_lex_next(&p->l)); } -#if ERRORS_ARE_FATAL -# define zbc_parse_scale(...) (zbc_parse_scale(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_parse_scale(...) (zbc_parse_scale(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_parse_incdec(BcParse *p, BcInst *prev, bool *paren_expr, size_t *nexprs, uint8_t flags) @@ -4002,9 +3926,7 @@ static BC_STATUS zbc_parse_incdec(BcParse *p, BcInst *prev, bool *paren_expr, RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_parse_incdec(...) (zbc_parse_incdec(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_parse_incdec(...) (zbc_parse_incdec(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_parse_minus(BcParse *p, BcInst *prev, size_t ops_bgn, bool rparen, size_t *nexprs) @@ -4031,9 +3953,7 @@ static BC_STATUS zbc_parse_minus(BcParse *p, BcInst *prev, size_t ops_bgn, RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_parse_minus(...) (zbc_parse_minus(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_parse_minus(...) (zbc_parse_minus(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_parse_string(BcParse *p, char inst) { @@ -4046,9 +3966,7 @@ static BC_STATUS zbc_parse_string(BcParse *p, char inst) RETURN_STATUS(zbc_lex_next(&p->l)); } -#if ERRORS_ARE_FATAL -# define zbc_parse_string(...) (zbc_parse_string(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_parse_string(...) (zbc_parse_string(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_parse_print(BcParse *p) { @@ -4072,9 +3990,7 @@ static BC_STATUS zbc_parse_print(BcParse *p) RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_parse_print(...) (zbc_parse_print(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_parse_print(...) (zbc_parse_print(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_parse_return(BcParse *p) { @@ -4099,7 +4015,7 @@ static BC_STATUS zbc_parse_return(BcParse *p) if (!paren || p->l.t.last != BC_LEX_RPAREN) { s = bc_POSIX_requires("parentheses around return expressions"); - ERROR_RETURN(if (s) RETURN_STATUS(s);) + IF_ERROR_RETURN_POSSIBLE(if (s) RETURN_STATUS(s)); } bc_parse_push(p, BC_INST_RET); @@ -4108,9 +4024,7 @@ static BC_STATUS zbc_parse_return(BcParse *p) dbg_lex_done("%s:%d done", __func__, __LINE__); RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_parse_return(...) (zbc_parse_return(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_parse_return(...) (zbc_parse_return(__VA_ARGS__) COMMA_SUCCESS) static void rewrite_label_to_current(BcParse *p, size_t idx) { @@ -4167,9 +4081,7 @@ static BC_STATUS zbc_parse_if(BcParse *p) dbg_lex_done("%s:%d done", __func__, __LINE__); RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_parse_if(...) (zbc_parse_if(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_parse_if(...) (zbc_parse_if(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_parse_while(BcParse *p) { @@ -4212,9 +4124,7 @@ static BC_STATUS zbc_parse_while(BcParse *p) RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_parse_while(...) (zbc_parse_while(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_parse_while(...) (zbc_parse_while(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_parse_for(BcParse *p) { @@ -4290,9 +4200,7 @@ static BC_STATUS zbc_parse_for(BcParse *p) RETURN_STATUS(BC_STATUS_SUCCESS); } -#if ERRORS_ARE_FATAL -# define zbc_parse_for(...) (zbc_parse_for(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_parse_for(...) (zbc_parse_for(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_parse_break_or_continue(BcParse *p, BcLexType type) { @@ -4317,9 +4225,7 @@ static BC_STATUS zbc_parse_break_or_continue(BcParse *p, BcLexType type) RETURN_STATUS(zbc_lex_next(&p->l)); } -#if ERRORS_ARE_FATAL -# define zbc_parse_break_or_continue(...) (zbc_parse_break_or_continue(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_parse_break_or_continue(...) (zbc_parse_break_or_continue(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_parse_funcdef(BcParse *p) { @@ -4406,9 +4312,7 @@ err: free(name); RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_parse_funcdef(...) (zbc_parse_funcdef(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_parse_funcdef(...) (zbc_parse_funcdef(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_parse_auto(BcParse *p) { @@ -4466,9 +4370,7 @@ err: dbg_lex_done("%s:%d done (ERROR)", __func__, __LINE__); RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_parse_auto(...) (zbc_parse_auto(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_parse_auto(...) (zbc_parse_auto(__VA_ARGS__) COMMA_SUCCESS) #undef zbc_parse_stmt_possibly_auto static BC_STATUS zbc_parse_stmt_possibly_auto(BcParse *p, bool auto_allowed) @@ -4586,9 +4488,7 @@ static BC_STATUS zbc_parse_stmt_possibly_auto(BcParse *p, bool auto_allowed) dbg_lex_done("%s:%d done", __func__, __LINE__); RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_parse_stmt_possibly_auto(...) (zbc_parse_stmt_possibly_auto(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_parse_stmt_possibly_auto(...) (zbc_parse_stmt_possibly_auto(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_parse_stmt_or_funcdef(BcParse *p) { @@ -4608,9 +4508,7 @@ static BC_STATUS zbc_parse_stmt_or_funcdef(BcParse *p) dbg_lex_done("%s:%d done", __func__, __LINE__); RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_parse_stmt_or_funcdef(...) (zbc_parse_stmt_or_funcdef(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_parse_stmt_or_funcdef(...) (zbc_parse_stmt_or_funcdef(__VA_ARGS__) COMMA_SUCCESS) // This is not a "z" function: can also return BC_STATUS_PARSE_EMPTY_EXP static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext next) @@ -4864,11 +4762,11 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext ne if (!(flags & BC_PARSE_REL) && nrelops) { s = bc_POSIX_does_not_allow("comparison operators outside if or loops"); - ERROR_RETURN(if (s) return s;) + IF_ERROR_RETURN_POSSIBLE(if (s) return s); } else if ((flags & BC_PARSE_REL) && nrelops > 1) { s = bc_POSIX_requires("exactly one comparison operator per condition"); - ERROR_RETURN(if (s) return s;) + IF_ERROR_RETURN_POSSIBLE(if (s) return s); } if (flags & BC_PARSE_PRINT) { @@ -4890,9 +4788,7 @@ static BC_STATUS zbc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) RETURN_STATUS(bc_error("empty expression")); RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_parse_expr(...) (zbc_parse_expr(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_parse_expr(...) (zbc_parse_expr(__VA_ARGS__) COMMA_SUCCESS) #endif // ENABLE_BC @@ -4912,9 +4808,7 @@ static BC_STATUS zdc_parse_register(BcParse *p) RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zdc_parse_register(...) (zdc_parse_register(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zdc_parse_register(...) (zdc_parse_register(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zdc_parse_string(BcParse *p) { @@ -4932,9 +4826,7 @@ static BC_STATUS zdc_parse_string(BcParse *p) RETURN_STATUS(zbc_lex_next(&p->l)); } -#if ERRORS_ARE_FATAL -# define zdc_parse_string(...) (zdc_parse_string(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zdc_parse_string(...) (zdc_parse_string(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zdc_parse_mem(BcParse *p, uint8_t inst, bool name, bool store) { @@ -4954,9 +4846,7 @@ static BC_STATUS zdc_parse_mem(BcParse *p, uint8_t inst, bool name, bool store) RETURN_STATUS(zbc_lex_next(&p->l)); } -#if ERRORS_ARE_FATAL -# define zdc_parse_mem(...) (zdc_parse_mem(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zdc_parse_mem(...) (zdc_parse_mem(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zdc_parse_cond(BcParse *p, uint8_t inst) { @@ -4981,9 +4871,7 @@ static BC_STATUS zdc_parse_cond(BcParse *p, uint8_t inst) RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zdc_parse_cond(...) (zdc_parse_cond(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zdc_parse_cond(...) (zdc_parse_cond(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t, uint8_t flags) { @@ -5055,9 +4943,7 @@ static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t, uint8_t flags) RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zdc_parse_token(...) (zdc_parse_token(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zdc_parse_token(...) (zdc_parse_token(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zdc_parse_expr(BcParse *p, uint8_t flags) { @@ -5080,9 +4966,7 @@ static BC_STATUS zdc_parse_expr(BcParse *p, uint8_t flags) RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zdc_parse_expr(...) (zdc_parse_expr(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zdc_parse_expr(...) (zdc_parse_expr(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zdc_parse_parse(BcParse *p) { @@ -5100,9 +4984,7 @@ static BC_STATUS zdc_parse_parse(BcParse *p) RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zdc_parse_parse(...) (zdc_parse_parse(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zdc_parse_parse(...) (zdc_parse_parse(__VA_ARGS__) COMMA_SUCCESS) #endif // ENABLE_DC @@ -5114,9 +4996,7 @@ static BC_STATUS zcommon_parse_expr(BcParse *p, uint8_t flags) IF_DC(RETURN_STATUS(zdc_parse_expr(p, flags))); } } -#if ERRORS_ARE_FATAL -# define zcommon_parse_expr(...) (zcommon_parse_expr(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zcommon_parse_expr(...) (zcommon_parse_expr(__VA_ARGS__) COMMA_SUCCESS) static BcVec* bc_program_search(char *id, bool var) { @@ -5216,9 +5096,7 @@ static BC_STATUS zbc_program_num(BcResult *r, BcNum **num, bool hex) RETURN_STATUS(BC_STATUS_SUCCESS); } -#if ERRORS_ARE_FATAL -# define zbc_program_num(...) (zbc_program_num(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_program_num(...) (zbc_program_num(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_program_binOpPrep(BcResult **l, BcNum **ln, BcResult **r, BcNum **rn, bool assign) @@ -5256,9 +5134,7 @@ static BC_STATUS zbc_program_binOpPrep(BcResult **l, BcNum **ln, RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_program_binOpPrep(...) (zbc_program_binOpPrep(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_program_binOpPrep(...) (zbc_program_binOpPrep(__VA_ARGS__) COMMA_SUCCESS) static void bc_program_binOpRetire(BcResult *r) { @@ -5284,9 +5160,7 @@ static BC_STATUS zbc_program_prep(BcResult **r, BcNum **n) RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_program_prep(...) (zbc_program_prep(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_program_prep(...) (zbc_program_prep(__VA_ARGS__) COMMA_SUCCESS) static void bc_program_retire(BcResult *r, BcResultType t) { @@ -5306,7 +5180,7 @@ static BC_STATUS zbc_program_op(char inst) bc_num_init_DEF_SIZE(&res.d.n); s = BC_STATUS_SUCCESS; - ERROR_RETURN(s =) zbc_program_ops[inst - BC_INST_POWER](n1, n2, &res.d.n, G.prog.scale); + IF_ERROR_RETURN_POSSIBLE(s =) zbc_program_ops[inst - BC_INST_POWER](n1, n2, &res.d.n, G.prog.scale); if (s) goto err; bc_program_binOpRetire(&res); @@ -5316,9 +5190,7 @@ err: bc_num_free(&res.d.n); RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_program_op(...) (zbc_program_op(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_program_op(...) (zbc_program_op(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_program_read(void) { @@ -5367,15 +5239,12 @@ static BC_STATUS zbc_program_read(void) exec_err: bc_parse_free(&parse); -//io_err: G.in_read = 0; G.prog.file = sv_file; bc_vec_free(&buf); RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_program_read(...) (zbc_program_read(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_program_read(...) (zbc_program_read(__VA_ARGS__) COMMA_SUCCESS) static size_t bc_program_index(char *code, size_t *bgn) { @@ -5584,9 +5453,7 @@ err: bc_vec_free(&stack); RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_num_printNum(...) (zbc_num_printNum(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_num_printNum(...) (zbc_num_printNum(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_num_printBase(BcNum *n) { @@ -5617,18 +5484,14 @@ static BC_STATUS zbc_num_printBase(BcNum *n) RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_num_printBase(...) (zbc_num_printBase(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_num_printBase(...) (zbc_num_printBase(__VA_ARGS__) COMMA_SUCCESS) #if ENABLE_DC static BC_STATUS zbc_num_stream(BcNum *n, BcNum *base) { RETURN_STATUS(zbc_num_printNum(n, base, 1, bc_num_printChar)); } -#if ERRORS_ARE_FATAL -# define zbc_num_stream(...) (zbc_num_stream(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_num_stream(...) (zbc_num_stream(__VA_ARGS__) COMMA_SUCCESS) #endif static BC_STATUS zbc_num_print(BcNum *n, bool newline) @@ -5653,9 +5516,7 @@ static BC_STATUS zbc_num_print(BcNum *n, bool newline) RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_num_print(...) (zbc_num_print(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_num_print(...) (zbc_num_print(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_program_print(char inst, size_t idx) { @@ -5701,9 +5562,7 @@ static BC_STATUS zbc_program_print(char inst, size_t idx) RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_program_print(...) (zbc_program_print(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_program_print(...) (zbc_program_print(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_program_negate(void) { @@ -5722,9 +5581,7 @@ static BC_STATUS zbc_program_negate(void) RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_program_negate(...) (zbc_program_negate(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_program_negate(...) (zbc_program_negate(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_program_logical(char inst) { @@ -5773,9 +5630,7 @@ static BC_STATUS zbc_program_logical(char inst) RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_program_logical(...) (zbc_program_logical(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_program_logical(...) (zbc_program_logical(__VA_ARGS__) COMMA_SUCCESS) #if ENABLE_DC static BC_STATUS zbc_program_assignStr(BcResult *r, BcVec *v, @@ -5802,9 +5657,7 @@ static BC_STATUS zbc_program_assignStr(BcResult *r, BcVec *v, RETURN_STATUS(BC_STATUS_SUCCESS); } -#if ERRORS_ARE_FATAL -# define zbc_program_assignStr(...) (zbc_program_assignStr(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_program_assignStr(...) (zbc_program_assignStr(__VA_ARGS__) COMMA_SUCCESS) #endif // ENABLE_DC static BC_STATUS zbc_program_copyToVar(char *name, bool var) @@ -5849,9 +5702,7 @@ static BC_STATUS zbc_program_copyToVar(char *name, bool var) RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_program_copyToVar(...) (zbc_program_copyToVar(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_program_copyToVar(...) (zbc_program_copyToVar(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_program_assign(char inst) { @@ -5894,7 +5745,7 @@ static BC_STATUS zbc_program_assign(char inst) bc_num_copy(l, r); else { s = BC_STATUS_SUCCESS; - ERROR_RETURN(s =) zbc_program_ops[inst - BC_INST_ASSIGN_POWER](l, r, l, G.prog.scale); + IF_ERROR_RETURN_POSSIBLE(s =) zbc_program_ops[inst - BC_INST_ASSIGN_POWER](l, r, l, G.prog.scale); } if (s) RETURN_STATUS(s); #else @@ -5942,9 +5793,7 @@ static BC_STATUS zbc_program_assign(char inst) RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_program_assign(...) (zbc_program_assign(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_program_assign(...) (zbc_program_assign(__VA_ARGS__) COMMA_SUCCESS) #if !ENABLE_DC #define bc_program_pushVar(code, bgn, pop, copy) \ @@ -5996,11 +5845,7 @@ static BC_STATUS bc_program_pushVar(char *code, size_t *bgn, RETURN_STATUS(BC_STATUS_SUCCESS); } -#if ERRORS_ARE_FATAL -# define zbc_program_pushVar(...) (bc_program_pushVar(__VA_ARGS__), BC_STATUS_SUCCESS) -#else -# define zbc_program_pushVar(...) bc_program_pushVar(__VA_ARGS__) -#endif +#define zbc_program_pushVar(...) (bc_program_pushVar(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_program_pushArray(char *code, size_t *bgn, char inst) @@ -6038,9 +5883,7 @@ err: if (s) free(r.d.id.name); RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_program_pushArray(...) (zbc_program_pushArray(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_program_pushArray(...) (zbc_program_pushArray(__VA_ARGS__) COMMA_SUCCESS) #if ENABLE_BC static BC_STATUS zbc_program_incdec(char inst) @@ -6075,9 +5918,7 @@ static BC_STATUS zbc_program_incdec(char inst) RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_program_incdec(...) (zbc_program_incdec(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_program_incdec(...) (zbc_program_incdec(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_program_call(char *code, size_t *idx) { @@ -6133,9 +5974,7 @@ static BC_STATUS zbc_program_call(char *code, size_t *idx) RETURN_STATUS(BC_STATUS_SUCCESS); } -#if ERRORS_ARE_FATAL -# define zbc_program_call(...) (zbc_program_call(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_program_call(...) (zbc_program_call(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_program_return(char inst) { @@ -6180,9 +6019,7 @@ static BC_STATUS zbc_program_return(char inst) RETURN_STATUS(BC_STATUS_SUCCESS); } -#if ERRORS_ARE_FATAL -# define zbc_program_return(...) (zbc_program_return(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_program_return(...) (zbc_program_return(__VA_ARGS__) COMMA_SUCCESS) #endif // ENABLE_BC static unsigned long bc_program_scale(BcNum *n) @@ -6248,9 +6085,7 @@ static BC_STATUS zbc_program_builtin(char inst) RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_program_builtin(...) (zbc_program_builtin(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_program_builtin(...) (zbc_program_builtin(__VA_ARGS__) COMMA_SUCCESS) #if ENABLE_DC static BC_STATUS zbc_program_divmod(void) @@ -6279,9 +6114,7 @@ err: bc_num_free(&res.d.n); RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_program_divmod(...) (zbc_program_divmod(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_program_divmod(...) (zbc_program_divmod(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_program_modexp(void) { @@ -6327,9 +6160,7 @@ err: bc_num_free(&res.d.n); RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_program_modexp(...) (zbc_program_modexp(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_program_modexp(...) (zbc_program_modexp(__VA_ARGS__) COMMA_SUCCESS) static void bc_program_stackLen(void) { @@ -6412,9 +6243,7 @@ num_err: bc_num_free(&n); RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_program_asciify(...) (zbc_program_asciify(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_program_asciify(...) (zbc_program_asciify(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_program_printStream(void) { @@ -6441,9 +6270,7 @@ static BC_STATUS zbc_program_printStream(void) RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_program_printStream(...) (zbc_program_printStream(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_program_printStream(...) (zbc_program_printStream(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_program_nquit(void) { @@ -6469,9 +6296,7 @@ static BC_STATUS zbc_program_nquit(void) RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_program_nquit(...) (zbc_program_nquit(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_program_nquit(...) (zbc_program_nquit(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_program_execStr(char *code, size_t *bgn, bool cond) @@ -6573,9 +6398,7 @@ exit: bc_vec_pop(&G.prog.results); RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_program_execStr(...) (zbc_program_execStr(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_program_execStr(...) (zbc_program_execStr(__VA_ARGS__) COMMA_SUCCESS) #endif // ENABLE_DC static void bc_program_pushGlobal(char inst) @@ -6874,9 +6697,7 @@ static BC_STATUS zbc_program_exec(void) RETURN_STATUS(BC_STATUS_SUCCESS); } -#if ERRORS_ARE_FATAL -# define zbc_program_exec(...) (zbc_program_exec(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_program_exec(...) (zbc_program_exec(__VA_ARGS__) COMMA_SUCCESS) static unsigned bc_vm_envLen(const char *var) { @@ -6904,7 +6725,7 @@ static BC_STATUS zbc_vm_process(const char *text) while (G.prs.l.t.t != BC_LEX_EOF) { dbg_lex("%s:%d G.prs.l.t.t:%d", __func__, __LINE__, G.prs.l.t.t); - ERROR_RETURN(s =) zcommon_parse(&G.prs); + s = zcommon_parse(&G.prs); if (s) RETURN_STATUS(s); s = zbc_program_exec(); if (s) { @@ -6916,9 +6737,7 @@ static BC_STATUS zbc_vm_process(const char *text) dbg_lex_done("%s:%d done", __func__, __LINE__); RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_vm_process(...) (zbc_vm_process(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_vm_process(...) (zbc_vm_process(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_vm_execute_FILE(FILE *fp, const char *filename) { @@ -6941,9 +6760,7 @@ static BC_STATUS zbc_vm_execute_FILE(FILE *fp, const char *filename) G.prog.file = NULL; RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_vm_execute_FILE(...) (zbc_vm_execute_FILE(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_vm_execute_FILE(...) (zbc_vm_execute_FILE(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_vm_file(const char *file) { @@ -6956,9 +6773,7 @@ static BC_STATUS zbc_vm_file(const char *file) RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_vm_file(...) (zbc_vm_file(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_vm_file(...) (zbc_vm_file(__VA_ARGS__) COMMA_SUCCESS) #if ENABLE_BC static void bc_vm_info(void) @@ -7234,9 +7049,7 @@ static BC_STATUS zbc_vm_exec(void) RETURN_STATUS(s); } -#if ERRORS_ARE_FATAL -# define zbc_vm_exec(...) (zbc_vm_exec(__VA_ARGS__), BC_STATUS_SUCCESS) -#endif +#define zbc_vm_exec(...) (zbc_vm_exec(__VA_ARGS__) COMMA_SUCCESS) #if ENABLE_FEATURE_CLEAN_UP static void bc_program_free(void) -- cgit v1.2.3-55-g6feb From 59d4ce935ed8fa54e4b8197cc2c43ba1ad5e5d69 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 17 Dec 2018 10:42:31 +0100 Subject: bc: use common strings Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index ccc7cb4d1..58734cf9c 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -525,6 +525,10 @@ static const struct BcLexKeyword bc_lex_kws[20] = { BC_LEX_KW_ENTRY("while" , 1), // 19 }; #undef BC_LEX_KW_ENTRY +#define STRING_if (bc_lex_kws[8].name8) +#define STRING_else (bc_lex_kws[4].name8) +#define STRING_while (bc_lex_kws[19].name8) +#define STRING_for (bc_lex_kws[5].name8) enum { POSIX_KWORD_MASK = 0 | (1 << 0) // 0 @@ -4053,7 +4057,7 @@ static BC_STATUS zbc_parse_if(BcParse *p) bc_parse_pushJUMP_ZERO(p, ip_idx); bc_vec_push(&p->func->labels, &ip_idx); - s = zbc_parse_stmt_allow_NLINE_before(p, "if"); + s = zbc_parse_stmt_allow_NLINE_before(p, STRING_if); if (s) RETURN_STATUS(s); dbg_lex("%s:%d in if after stmt: p->l.t.t:%d", __func__, __LINE__, p->l.t.t); @@ -4071,7 +4075,7 @@ static BC_STATUS zbc_parse_if(BcParse *p) bc_vec_push(&p->func->labels, &ip2_idx); ip_idx = ip2_idx; - s = zbc_parse_stmt_allow_NLINE_before(p, "else"); + s = zbc_parse_stmt_allow_NLINE_before(p, STRING_else); if (s) RETURN_STATUS(s); } @@ -4110,7 +4114,7 @@ static BC_STATUS zbc_parse_while(BcParse *p) bc_parse_pushJUMP_ZERO(p, ip_idx); - s = zbc_parse_stmt_allow_NLINE_before(p, "while"); + s = zbc_parse_stmt_allow_NLINE_before(p, STRING_while); if (s) RETURN_STATUS(s); dbg_lex("%s:%d BC_INST_JUMP to %d", __func__, __LINE__, cond_idx); @@ -4186,7 +4190,7 @@ static BC_STATUS zbc_parse_for(BcParse *p) bc_vec_push(&p->exits, &exit_idx); bc_vec_push(&p->func->labels, &exit_idx); - s = zbc_parse_stmt_allow_NLINE_before(p, "for"); + s = zbc_parse_stmt_allow_NLINE_before(p, STRING_for); if (s) RETURN_STATUS(s); dbg_lex("%s:%d BC_INST_JUMP to %d", __func__, __LINE__, update_idx); -- cgit v1.2.3-55-g6feb From e42cc19b51febacba5e8f30f548bf294018d9e7c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 17 Dec 2018 11:02:26 +0100 Subject: bc: simplify zdc_parse_string() function old new delta bc_program_index 64 66 +2 zdc_parse_expr 671 656 -15 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/1 up/down: 2/-15) Total: -13 bytes text data bss dec hex filename 981667 485 7296 989448 f1908 busybox_old 981655 485 7296 989436 f18fc busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 58734cf9c..1fb1b00b3 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -4798,8 +4798,6 @@ static BC_STATUS zbc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) #if ENABLE_DC -#define DC_PARSE_BUF_LEN ((int) (sizeof(uint32_t) * CHAR_BIT)) - static BC_STATUS zdc_parse_register(BcParse *p) { BcStatus s; @@ -4816,11 +4814,11 @@ static BC_STATUS zdc_parse_register(BcParse *p) static BC_STATUS zdc_parse_string(BcParse *p) { - char *str, *name, b[DC_PARSE_BUF_LEN + 1]; + char *str, *name; size_t idx, len = G.prog.strs.len; - sprintf(b, "%0*zu", DC_PARSE_BUF_LEN, len); - name = xstrdup(b); +//why pad to 32 zeros?? + name = xasprintf("%032lu", (unsigned long)len); str = xstrdup(p->l.t.v.v); bc_parse_push(p, BC_INST_STR); -- cgit v1.2.3-55-g6feb From b44a7f1d6642e2da39e9f27e0b504f662ca443a2 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 17 Dec 2018 11:58:20 +0100 Subject: bc: tighten up input NUL handling function old new delta static.dc_lex_tokens - 90 +90 bc_error_bad_character 17 31 +14 static.dc_lex_regs - 13 +13 bc_read_line 406 410 +4 bc_program_index 64 66 +2 dc_lex_regs 13 - -13 zdc_parse_expr 671 656 -15 zbc_lex_next 2318 2230 -88 dc_lex_tokens 91 - -91 ------------------------------------------------------------------------------ (add/remove: 2/2 grow/shrink: 3/2 up/down: 123/-207) Total: -84 bytes text data bss dec hex filename 981667 485 7296 989448 f1908 busybox_old 981599 485 7296 989380 f18c4 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 113 ++++++++++++++++++++++++++++++++------------------------- 1 file changed, 64 insertions(+), 49 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 1fb1b00b3..214ea44ab 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -806,45 +806,6 @@ enum { #endif // ENABLE_BC #if ENABLE_DC -static const //BcLexType - should be this type, but narrower type saves size: -uint8_t -dc_lex_regs[] = { - BC_LEX_OP_REL_EQ, BC_LEX_OP_REL_LE, BC_LEX_OP_REL_GE, BC_LEX_OP_REL_NE, - BC_LEX_OP_REL_LT, BC_LEX_OP_REL_GT, BC_LEX_SCOLON, BC_LEX_COLON, - BC_LEX_ELSE, BC_LEX_LOAD, BC_LEX_LOAD_POP, BC_LEX_OP_ASSIGN, - BC_LEX_STORE_PUSH, -}; - -static const //BcLexType - should be this type -uint8_t -dc_lex_tokens[] = { - BC_LEX_OP_MODULUS, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_LPAREN, - BC_LEX_INVALID, BC_LEX_OP_MULTIPLY, BC_LEX_OP_PLUS, BC_LEX_INVALID, - BC_LEX_OP_MINUS, BC_LEX_INVALID, BC_LEX_OP_DIVIDE, - BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, - BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, - BC_LEX_INVALID, BC_LEX_INVALID, - BC_LEX_COLON, BC_LEX_SCOLON, BC_LEX_OP_REL_GT, BC_LEX_OP_REL_EQ, - BC_LEX_OP_REL_LT, BC_LEX_KEY_READ, BC_LEX_INVALID, - BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, - BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_EQ_NO_REG, BC_LEX_INVALID, - BC_LEX_KEY_IBASE, BC_LEX_INVALID, BC_LEX_KEY_SCALE, BC_LEX_LOAD_POP, - BC_LEX_INVALID, BC_LEX_OP_BOOL_NOT, BC_LEX_KEY_OBASE, BC_LEX_PRINT_STREAM, - BC_LEX_NQUIT, BC_LEX_POP, BC_LEX_STORE_PUSH, BC_LEX_INVALID, BC_LEX_INVALID, - BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_SCALE_FACTOR, BC_LEX_INVALID, - BC_LEX_KEY_LENGTH, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, - BC_LEX_OP_POWER, BC_LEX_NEG, BC_LEX_INVALID, - BC_LEX_ASCIIFY, BC_LEX_INVALID, BC_LEX_CLEAR_STACK, BC_LEX_DUPLICATE, - BC_LEX_ELSE, BC_LEX_PRINT_STACK, BC_LEX_INVALID, BC_LEX_INVALID, - BC_LEX_STORE_IBASE, BC_LEX_INVALID, BC_LEX_STORE_SCALE, BC_LEX_LOAD, - BC_LEX_INVALID, BC_LEX_PRINT_POP, BC_LEX_STORE_OBASE, BC_LEX_KEY_PRINT, - BC_LEX_KEY_QUIT, BC_LEX_SWAP, BC_LEX_OP_ASSIGN, BC_LEX_INVALID, - BC_LEX_INVALID, BC_LEX_KEY_SQRT, BC_LEX_INVALID, BC_LEX_EXECUTE, - BC_LEX_INVALID, BC_LEX_STACK_LEVEL, - BC_LEX_LBRACE, BC_LEX_OP_MODEXP, BC_LEX_INVALID, BC_LEX_OP_DIVMOD, - BC_LEX_INVALID -}; - static const //BcInst - should be this type. Using signed narrow type since BC_INST_INVALID is -1 int8_t dc_parse_insts[] = { @@ -1063,6 +1024,8 @@ static ERRORFUNC int bc_error(const char *msg) } static ERRORFUNC int bc_error_bad_character(char c) { + if (!c) + IF_ERROR_RETURN_POSSIBLE(return) bc_error("NUL character"); IF_ERROR_RETURN_POSSIBLE(return) bc_error_fmt("bad character '%c'", c); } static ERRORFUNC int bc_error_bad_expression(void) @@ -1376,7 +1339,7 @@ static void bc_read_line(BcVec *vec, FILE *fp) goto intr; } #endif - c = fgetc(fp); + do c = fgetc(fp); while (c == '\0'); if (c == EOF) { if (ferror(fp)) bb_perror_msg_and_die("input error"); @@ -3125,11 +3088,11 @@ static BC_STATUS zbc_lex_token(BcLex *l) // This is the workhorse of the lexer. switch (c) { - case '\0': // probably never reached - l->i--; - l->t.t = BC_LEX_EOF; - l->newline = true; - break; +// case '\0': // probably never reached +// l->i--; +// l->t.t = BC_LEX_EOF; +// l->newline = true; +// break; case '\n': l->t.t = BC_LEX_NLINE; l->newline = true; @@ -3370,6 +3333,58 @@ static BC_STATUS zdc_lex_string(BcLex *l) static BC_STATUS zdc_lex_token(BcLex *l) { + static const //BcLexType - should be this type, but narrower type saves size: + uint8_t + dc_lex_regs[] = { + BC_LEX_OP_REL_EQ, BC_LEX_OP_REL_LE, BC_LEX_OP_REL_GE, BC_LEX_OP_REL_NE, + BC_LEX_OP_REL_LT, BC_LEX_OP_REL_GT, BC_LEX_SCOLON, BC_LEX_COLON, + BC_LEX_ELSE, BC_LEX_LOAD, BC_LEX_LOAD_POP, BC_LEX_OP_ASSIGN, + BC_LEX_STORE_PUSH, + }; + static const //BcLexType - should be this type + uint8_t + dc_lex_tokens[] = { + /* %&'( */ + BC_LEX_OP_MODULUS, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_LPAREN, + /* )*+, */ + BC_LEX_INVALID, BC_LEX_OP_MULTIPLY, BC_LEX_OP_PLUS, BC_LEX_INVALID, + /* -./ */ + BC_LEX_OP_MINUS, BC_LEX_INVALID, BC_LEX_OP_DIVIDE, + /* 0123456789 */ + BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, + BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, + BC_LEX_INVALID, BC_LEX_INVALID, + /* :;<=>?@ */ + BC_LEX_COLON, BC_LEX_SCOLON, BC_LEX_OP_REL_GT, BC_LEX_OP_REL_EQ, + BC_LEX_OP_REL_LT, BC_LEX_KEY_READ, BC_LEX_INVALID, + /* ABCDEFGH */ + BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, + BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_EQ_NO_REG, BC_LEX_INVALID, + /* IJKLMNOP */ + BC_LEX_KEY_IBASE, BC_LEX_INVALID, BC_LEX_KEY_SCALE, BC_LEX_LOAD_POP, + BC_LEX_INVALID, BC_LEX_OP_BOOL_NOT, BC_LEX_KEY_OBASE, BC_LEX_PRINT_STREAM, + /* QRSTUVWXY */ + BC_LEX_NQUIT, BC_LEX_POP, BC_LEX_STORE_PUSH, BC_LEX_INVALID, BC_LEX_INVALID, + BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_SCALE_FACTOR, BC_LEX_INVALID, + /* Z[\] */ + BC_LEX_KEY_LENGTH, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, + /* ^_` */ + BC_LEX_OP_POWER, BC_LEX_NEG, BC_LEX_INVALID, + /* abcdefgh */ + BC_LEX_ASCIIFY, BC_LEX_INVALID, BC_LEX_CLEAR_STACK, BC_LEX_DUPLICATE, + BC_LEX_ELSE, BC_LEX_PRINT_STACK, BC_LEX_INVALID, BC_LEX_INVALID, + /* ijklmnop */ + BC_LEX_STORE_IBASE, BC_LEX_INVALID, BC_LEX_STORE_SCALE, BC_LEX_LOAD, + BC_LEX_INVALID, BC_LEX_PRINT_POP, BC_LEX_STORE_OBASE, BC_LEX_KEY_PRINT, + /* qrstuvwx */ + BC_LEX_KEY_QUIT, BC_LEX_SWAP, BC_LEX_OP_ASSIGN, BC_LEX_INVALID, + BC_LEX_INVALID, BC_LEX_KEY_SQRT, BC_LEX_INVALID, BC_LEX_EXECUTE, + /* yz */ + BC_LEX_INVALID, BC_LEX_STACK_LEVEL, + /* {|}~ */ + BC_LEX_LBRACE, BC_LEX_OP_MODEXP, BC_LEX_INVALID, BC_LEX_OP_DIVMOD, + }; + BcStatus s = BC_STATUS_SUCCESS; char c = l->buf[l->i++], c2; size_t i; @@ -3380,16 +3395,16 @@ static BC_STATUS zdc_lex_token(BcLex *l) } if (c >= '%' && c <= '~' - && (l->t.t = dc_lex_tokens[(c - '%')]) != BC_LEX_INVALID + && (l->t.t = dc_lex_tokens[c - '%']) != BC_LEX_INVALID ) { RETURN_STATUS(s); } // This is the workhorse of the lexer. switch (c) { - case '\0': - l->t.t = BC_LEX_EOF; - break; +// case '\0': // probably never reached +// l->t.t = BC_LEX_EOF; +// break; case '\n': case '\t': case '\v': -- cgit v1.2.3-55-g6feb From 4b72aebe80aaa50a765d5ff61d7d67ed731502d9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 17 Dec 2018 16:54:37 +0100 Subject: bc: remove "error after expression parsing" check It is misplaced: caller knows better what can or cannot follow the expression. Sometimes even caller's caller: "if (1) return a+b else..." - parser of "return" does not know that "else" after it is valid, parser of stmt does not know it either, - only parser of "if" knows it! The removed code balked on e.g. "{ print 1 }" statement. This does not break any valid programs, but starts accepting some invalid ones, e.g. "print 1 print 2" would work. function old new delta zcommon_parse_expr 40 32 -8 zbc_parse_name 509 494 -15 zbc_parse_stmt_possibly_auto 1678 1638 -40 bc_parse_expr_empty_ok 2025 1977 -48 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/4 up/down: 0/-111) Total: -111 bytes text data bss dec hex filename 981599 485 7296 989380 f18c4 busybox_old 981488 485 7296 989269 f1855 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 282 +++++++++++++++++++++++++---------------------------- testsuite/bc.tests | 5 + 2 files changed, 136 insertions(+), 151 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 214ea44ab..45d9eb8eb 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -390,7 +390,6 @@ typedef struct BcInstPtr { // BC_LEX_NEG is not used in lexing; it is only for parsing. typedef enum BcLexType { - BC_LEX_EOF, BC_LEX_INVALID, @@ -553,7 +552,93 @@ enum { | (1 << 19) // 19 }; #define bc_lex_kws_POSIX(i) ((1 << (i)) & POSIX_KWORD_MASK) + +// This is a bit array that corresponds to token types. An entry is +// true if the token is valid in an expression, false otherwise. +// Used to figure out when expr parsing should stop *without error message* +// - 0 element indicates this condition. 1 means "this token is to be eaten +// as part of the expression", token can them still be determined to be invalid +// by later processing. +enum { +#define EXBITS(a,b,c,d,e,f,g,h) \ + ((uint64_t)((a << 0)+(b << 1)+(c << 2)+(d << 3)+(e << 4)+(f << 5)+(g << 6)+(h << 7))) + BC_PARSE_EXPRS_BITS = 0 + + (EXBITS(0,0,1,1,1,1,1,1) << (0*8)) // 0: eof inval ++ -- - ^ * / + + (EXBITS(1,1,1,1,1,1,1,1) << (1*8)) // 8: % + - == <= >= != < + + (EXBITS(1,1,1,1,1,1,1,1) << (2*8)) // 16: > ! || && ^= *= /= %= + + (EXBITS(1,1,1,0,0,1,1,0) << (3*8)) // 24: += -= = NL WS ( ) [ + + (EXBITS(0,0,0,0,0,0,1,1) << (4*8)) // 32: , ] { ; } STR NAME NUM + + (EXBITS(0,0,0,0,0,0,0,1) << (5*8)) // 40: auto break cont define else for halt ibase + + (EXBITS(0,1,1,1,1,0,0,1) << (6*8)) // 48: if last len limits obase print quit read - bug, why "limits" is allowed? + + (EXBITS(0,1,1,0,0,0,0,0) << (7*8)) // 56: return scale sqrt while +#undef EXBITS +}; +static ALWAYS_INLINE long bc_parse_exprs(unsigned i) +{ +#if ULONG_MAX > 0xffffffff + // 64-bit version (will not work correctly for 32-bit longs!) + return BC_PARSE_EXPRS_BITS & (1UL << i); +#else + // 32-bit version + unsigned long m = (uint32_t)BC_PARSE_EXPRS_BITS; + if (i >= 32) { + m = (uint32_t)(BC_PARSE_EXPRS_BITS >> 32); + i &= 31; + } + return m & (1UL << i); #endif +} + +// This is an array of data for operators that correspond to +// [BC_LEX_OP_INC...BC_LEX_OP_ASSIGN] token types. +static const uint8_t bc_parse_ops[] = { +#define OP(p,l) ((int)(l) * 0x10 + (p)) + OP(0, false), OP( 0, false ), // inc dec + OP(1, false), // neg + OP(2, false), // pow + OP(3, true ), OP( 3, true ), OP( 3, true ), // mul div mod + OP(4, true ), OP( 4, true ), // + - + OP(6, true ), OP( 6, true ), OP( 6, true ), OP( 6, true ), OP( 6, true ), OP( 6, true ), // == <= >= != < > + OP(1, false), // not + OP(7, true ), OP( 7, true ), // or and + OP(5, false), OP( 5, false ), OP( 5, false ), OP( 5, false ), OP( 5, false ), // ^= *= /= %= += + OP(5, false), OP( 5, false ), // -= = +#undef OP +}; +#define bc_parse_op_PREC(i) (bc_parse_ops[i] & 0x0f) +#define bc_parse_op_LEFT(i) (bc_parse_ops[i] & 0x10) +#endif // ENABLE_BC + +#if ENABLE_DC +static const //BcInst - should be this type. Using signed narrow type since BC_INST_INVALID is -1 +int8_t +dc_parse_insts[] = { + BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_REL_GE, + BC_INST_INVALID, BC_INST_POWER, BC_INST_MULTIPLY, BC_INST_DIVIDE, + BC_INST_MODULUS, BC_INST_PLUS, BC_INST_MINUS, + BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, + BC_INST_INVALID, BC_INST_INVALID, + BC_INST_BOOL_NOT, BC_INST_INVALID, BC_INST_INVALID, + BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, + BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, + BC_INST_INVALID, BC_INST_INVALID, BC_INST_REL_GT, BC_INST_INVALID, + BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_REL_GE, + BC_INST_INVALID, BC_INST_INVALID, + BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, + BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, + BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_IBASE, + BC_INST_INVALID, BC_INST_INVALID, BC_INST_LENGTH, BC_INST_INVALID, + BC_INST_OBASE, BC_INST_PRINT, BC_INST_QUIT, BC_INST_INVALID, + BC_INST_INVALID, BC_INST_SCALE, BC_INST_SQRT, BC_INST_INVALID, + BC_INST_REL_EQ, BC_INST_MODEXP, BC_INST_DIVMOD, BC_INST_INVALID, + BC_INST_INVALID, BC_INST_EXECUTE, BC_INST_PRINT_STACK, BC_INST_CLEAR_STACK, + BC_INST_STACK_LEN, BC_INST_DUPLICATE, BC_INST_SWAP, BC_INST_POP, + BC_INST_ASCIIFY, BC_INST_PRINT_STREAM, BC_INST_INVALID, BC_INST_INVALID, + BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, + BC_INST_PRINT, BC_INST_NQUIT, BC_INST_SCALE_FUNC, +}; +#endif // ENABLE_DC + typedef struct BcLex { const char *buf; @@ -735,106 +820,6 @@ struct globals { #define IS_BC (ENABLE_BC && (!ENABLE_DC || applet_name[0] == 'b')) #define IS_DC (ENABLE_DC && (!ENABLE_BC || applet_name[0] != 'b')) -#if ENABLE_BC - -// This is a bit array that corresponds to token types. An entry is -// true if the token is valid in an expression, false otherwise. -enum { - BC_PARSE_EXPRS_BITS = 0 - + ((uint64_t)((0 << 0)+(0 << 1)+(1 << 2)+(1 << 3)+(1 << 4)+(1 << 5)+(1 << 6)+(1 << 7)) << (0*8)) - + ((uint64_t)((1 << 0)+(1 << 1)+(1 << 2)+(1 << 3)+(1 << 4)+(1 << 5)+(1 << 6)+(1 << 7)) << (1*8)) - + ((uint64_t)((1 << 0)+(1 << 1)+(1 << 2)+(1 << 3)+(1 << 4)+(1 << 5)+(1 << 6)+(1 << 7)) << (2*8)) - + ((uint64_t)((1 << 0)+(1 << 1)+(1 << 2)+(0 << 3)+(0 << 4)+(1 << 5)+(1 << 6)+(0 << 7)) << (3*8)) - + ((uint64_t)((0 << 0)+(0 << 1)+(0 << 2)+(0 << 3)+(0 << 4)+(0 << 5)+(1 << 6)+(1 << 7)) << (4*8)) - + ((uint64_t)((0 << 0)+(0 << 1)+(0 << 2)+(0 << 3)+(0 << 4)+(0 << 5)+(0 << 6)+(1 << 7)) << (5*8)) - + ((uint64_t)((0 << 0)+(1 << 1)+(1 << 2)+(1 << 3)+(1 << 4)+(0 << 5)+(0 << 6)+(1 << 7)) << (6*8)) - + ((uint64_t)((0 << 0)+(1 << 1)+(1 << 2)+(0 << 3) ) << (7*8)) -}; -static ALWAYS_INLINE long bc_parse_exprs(unsigned i) -{ -#if ULONG_MAX > 0xffffffff - // 64-bit version (will not work correctly for 32-bit longs!) - return BC_PARSE_EXPRS_BITS & (1UL << i); -#else - // 32-bit version - unsigned long m = (uint32_t)BC_PARSE_EXPRS_BITS; - if (i >= 32) { - m = (uint32_t)(BC_PARSE_EXPRS_BITS >> 32); - i &= 31; - } - return m & (1UL << i); -#endif -} - -// This is an array of data for operators that correspond to token types. -static const uint8_t bc_parse_ops[] = { -#define OP(p,l) ((int)(l) * 0x10 + (p)) - OP(0, false), OP( 0, false ), // inc dec - OP(1, false), // neg - OP(2, false), - OP(3, true ), OP( 3, true ), OP( 3, true ), // pow mul div - OP(4, true ), OP( 4, true ), // mod + - - OP(6, true ), OP( 6, true ), OP( 6, true ), OP( 6, true ), OP( 6, true ), OP( 6, true ), // == <= >= != < > - OP(1, false), // not - OP(7, true ), OP( 7, true ), // or and - OP(5, false), OP( 5, false ), OP( 5, false ), OP( 5, false ), OP( 5, false ), // ^= *= /= %= += - OP(5, false), OP( 5, false ), // -= = -#undef OP -}; -#define bc_parse_op_PREC(i) (bc_parse_ops[i] & 0x0f) -#define bc_parse_op_LEFT(i) (bc_parse_ops[i] & 0x10) - -// Byte array of up to 4 BC_LEX's, packed into 32-bit word -typedef uint32_t BcParseNext; - -// These identify what tokens can come after expressions in certain cases. -enum { -#define BC_PARSE_NEXT4(a,b,c,d) ( (a) | ((b)<<8) | ((c)<<16) | ((((d)|0x80)<<24)) ) -#define BC_PARSE_NEXT2(a,b) BC_PARSE_NEXT4(a,b,0xff,0xff) -#define BC_PARSE_NEXT1(a) BC_PARSE_NEXT4(a,0xff,0xff,0xff) - bc_parse_next_expr = BC_PARSE_NEXT4(BC_LEX_NLINE, BC_LEX_SCOLON, BC_LEX_RBRACE, BC_LEX_EOF), - bc_parse_next_param = BC_PARSE_NEXT2(BC_LEX_RPAREN, BC_LEX_COMMA), - bc_parse_next_print = BC_PARSE_NEXT4(BC_LEX_COMMA, BC_LEX_NLINE, BC_LEX_SCOLON, BC_LEX_EOF), - bc_parse_next_rel = BC_PARSE_NEXT1(BC_LEX_RPAREN), - bc_parse_next_elem = BC_PARSE_NEXT1(BC_LEX_RBRACKET), - bc_parse_next_for = BC_PARSE_NEXT1(BC_LEX_SCOLON), - bc_parse_next_read = BC_PARSE_NEXT2(BC_LEX_NLINE, BC_LEX_EOF), -#undef BC_PARSE_NEXT4 -#undef BC_PARSE_NEXT2 -#undef BC_PARSE_NEXT1 -}; -#endif // ENABLE_BC - -#if ENABLE_DC -static const //BcInst - should be this type. Using signed narrow type since BC_INST_INVALID is -1 -int8_t -dc_parse_insts[] = { - BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_REL_GE, - BC_INST_INVALID, BC_INST_POWER, BC_INST_MULTIPLY, BC_INST_DIVIDE, - BC_INST_MODULUS, BC_INST_PLUS, BC_INST_MINUS, - BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, - BC_INST_INVALID, BC_INST_INVALID, - BC_INST_BOOL_NOT, BC_INST_INVALID, BC_INST_INVALID, - BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, - BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, - BC_INST_INVALID, BC_INST_INVALID, BC_INST_REL_GT, BC_INST_INVALID, - BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_REL_GE, - BC_INST_INVALID, BC_INST_INVALID, - BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, - BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, - BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_IBASE, - BC_INST_INVALID, BC_INST_INVALID, BC_INST_LENGTH, BC_INST_INVALID, - BC_INST_OBASE, BC_INST_PRINT, BC_INST_QUIT, BC_INST_INVALID, - BC_INST_INVALID, BC_INST_SCALE, BC_INST_SQRT, BC_INST_INVALID, - BC_INST_REL_EQ, BC_INST_MODEXP, BC_INST_DIVMOD, BC_INST_INVALID, - BC_INST_INVALID, BC_INST_EXECUTE, BC_INST_PRINT_STACK, BC_INST_CLEAR_STACK, - BC_INST_STACK_LEN, BC_INST_DUPLICATE, BC_INST_SWAP, BC_INST_POP, - BC_INST_ASCIIFY, BC_INST_PRINT_STREAM, BC_INST_INVALID, BC_INST_INVALID, - BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, - BC_INST_PRINT, BC_INST_NQUIT, BC_INST_SCALE_FUNC, -}; -#endif // ENABLE_DC - // In configurations where errors abort instead of propagating error // return code up the call chain, functions returning BC_STATUS // actually don't return anything, they always succeed and return "void". @@ -3535,9 +3520,15 @@ static void bc_parse_number(BcParse *p) IF_BC(static BC_STATUS zbc_parse_stmt_or_funcdef(BcParse *p);) IF_DC(static BC_STATUS zdc_parse_parse(BcParse *p);) +// "Parse" half of "parse,execute,repeat" main loop static BC_STATUS zcommon_parse(BcParse *p) { if (IS_BC) { +// FIXME: "eating" of stmt delemiters is coded inconsistently +// (sometimes zbc_parse_stmt() eats the delimiter, sometimes don't), +// which causes bugs such as "print 1 print 2" erroneously accepted, +// or "print 1 else 2" detecting parse error only after executing +// "print 1" part. IF_BC(RETURN_STATUS(zbc_parse_stmt_or_funcdef(p));) } IF_DC(RETURN_STATUS(zdc_parse_parse(p));) @@ -3625,10 +3616,20 @@ static void bc_parse_create(BcParse *p, size_t func) // first in the expr enum. Note: This only works for binary operators. #define BC_TOKEN_2_INST(t) ((char) ((t) - BC_LEX_NEG + BC_INST_NEG)) -static BC_STATUS zbc_parse_stmt_possibly_auto(BcParse *p, bool auto_allowed); -static BC_STATUS zbc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next); -static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext next); +static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags); + +static BC_STATUS zbc_parse_expr(BcParse *p, uint8_t flags) +{ + BcStatus s; + + s = bc_parse_expr_empty_ok(p, flags); + if (s == BC_STATUS_PARSE_EMPTY_EXP) + RETURN_STATUS(bc_error("empty expression")); + RETURN_STATUS(s); +} #define zbc_parse_expr(...) (zbc_parse_expr(__VA_ARGS__) COMMA_SUCCESS) + +static BC_STATUS zbc_parse_stmt_possibly_auto(BcParse *p, bool auto_allowed); #define zbc_parse_stmt_possibly_auto(...) (zbc_parse_stmt_possibly_auto(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_parse_stmt(BcParse *p) @@ -3699,26 +3700,30 @@ static BC_STATUS zbc_parse_rightParen(BcParse *p, size_t ops_bgn, size_t *nexs) static BC_STATUS zbc_parse_params(BcParse *p, uint8_t flags) { BcStatus s; - bool comma = false; size_t nparams; dbg_lex("%s:%d p->l.t.t:%d", __func__, __LINE__, p->l.t.t); + flags = (flags & ~(BC_PARSE_PRINT | BC_PARSE_REL)) | BC_PARSE_ARRAY; + s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); - for (nparams = 0; p->l.t.t != BC_LEX_RPAREN; ++nparams) { - flags = (flags & ~(BC_PARSE_PRINT | BC_PARSE_REL)) | BC_PARSE_ARRAY; - s = zbc_parse_expr(p, flags, bc_parse_next_param); - if (s) RETURN_STATUS(s); - - comma = p->l.t.t == BC_LEX_COMMA; - if (comma) { + nparams = 0; + if (p->l.t.t != BC_LEX_RPAREN) { + for (;;) { + s = zbc_parse_expr(p, flags); + if (s) RETURN_STATUS(s); + nparams++; + if (p->l.t.t != BC_LEX_COMMA) { + if (p->l.t.t == BC_LEX_RPAREN) + break; + RETURN_STATUS(bc_error_bad_token()); + } s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); } } - if (comma) RETURN_STATUS(bc_error_bad_token()); bc_parse_push(p, BC_INST_CALL); bc_parse_pushIndex(p, nparams); @@ -3785,7 +3790,7 @@ static BC_STATUS zbc_parse_name(BcParse *p, BcInst *type, uint8_t flags) } else { *type = BC_INST_ARRAY_ELEM; flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL); - s = zbc_parse_expr(p, flags, bc_parse_next_elem); + s = zbc_parse_expr(p, flags); if (s) goto err; } s = zbc_lex_next(&p->l); @@ -3848,7 +3853,7 @@ static BC_STATUS zbc_parse_builtin(BcParse *p, BcLexType type, uint8_t flags, s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); - s = zbc_parse_expr(p, flags, bc_parse_next_rel); + s = zbc_parse_expr(p, flags); if (s) RETURN_STATUS(s); if (p->l.t.t != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); @@ -3879,7 +3884,7 @@ static BC_STATUS zbc_parse_scale(BcParse *p, BcInst *type, uint8_t flags) s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); - s = zbc_parse_expr(p, flags, bc_parse_next_rel); + s = zbc_parse_expr(p, flags); if (s) RETURN_STATUS(s); if (p->l.t.t != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); @@ -3999,7 +4004,7 @@ static BC_STATUS zbc_parse_print(BcParse *p) if (type == BC_LEX_STR) { s = zbc_parse_string(p, BC_INST_PRINT_POP); } else { - s = zbc_parse_expr(p, 0, bc_parse_next_print); + s = zbc_parse_expr(p, 0); bc_parse_push(p, BC_INST_PRINT_POP); } if (s) RETURN_STATUS(s); @@ -4025,7 +4030,7 @@ static BC_STATUS zbc_parse_return(BcParse *p) bc_parse_push(p, BC_INST_RET0); else { bool paren = (t == BC_LEX_LPAREN); - s = bc_parse_expr_empty_ok(p, 0, bc_parse_next_expr); + s = bc_parse_expr_empty_ok(p, 0); if (s == BC_STATUS_PARSE_EMPTY_EXP) { bc_parse_push(p, BC_INST_RET0); s = zbc_lex_next(&p->l); @@ -4063,7 +4068,7 @@ static BC_STATUS zbc_parse_if(BcParse *p) s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); - s = zbc_parse_expr(p, BC_PARSE_REL, bc_parse_next_rel); + s = zbc_parse_expr(p, BC_PARSE_REL); if (s) RETURN_STATUS(s); if (p->l.t.t != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); @@ -4123,7 +4128,7 @@ static BC_STATUS zbc_parse_while(BcParse *p) bc_vec_push(&p->exits, &ip_idx); bc_vec_push(&p->func->labels, &ip_idx); - s = zbc_parse_expr(p, BC_PARSE_REL, bc_parse_next_rel); + s = zbc_parse_expr(p, BC_PARSE_REL); if (s) RETURN_STATUS(s); if (p->l.t.t != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); @@ -4158,7 +4163,7 @@ static BC_STATUS zbc_parse_for(BcParse *p) if (s) RETURN_STATUS(s); if (p->l.t.t != BC_LEX_SCOLON) - s = zbc_parse_expr(p, 0, bc_parse_next_for); + s = zbc_parse_expr(p, 0); else s = bc_POSIX_does_not_allow_empty_X_expression_in_for("init"); @@ -4175,7 +4180,7 @@ static BC_STATUS zbc_parse_for(BcParse *p) bc_vec_push(&p->func->labels, &p->func->code.len); if (p->l.t.t != BC_LEX_SCOLON) - s = zbc_parse_expr(p, BC_PARSE_REL, bc_parse_next_for); + s = zbc_parse_expr(p, BC_PARSE_REL); else s = bc_POSIX_does_not_allow_empty_X_expression_in_for("condition"); @@ -4192,7 +4197,7 @@ static BC_STATUS zbc_parse_for(BcParse *p) bc_vec_push(&p->func->labels, &p->func->code.len); if (p->l.t.t != BC_LEX_RPAREN) - s = zbc_parse_expr(p, 0, bc_parse_next_rel); + s = zbc_parse_expr(p, 0); else s = bc_POSIX_does_not_allow_empty_X_expression_in_for("update"); @@ -4444,7 +4449,7 @@ static BC_STATUS zbc_parse_stmt_possibly_auto(BcParse *p, bool auto_allowed) case BC_LEX_KEY_READ: case BC_LEX_KEY_SCALE: case BC_LEX_KEY_SQRT: - s = zbc_parse_expr(p, BC_PARSE_PRINT, bc_parse_next_expr); + s = zbc_parse_expr(p, BC_PARSE_PRINT); break; case BC_LEX_STR: s = zbc_parse_string(p, BC_INST_PRINT_STR); @@ -4530,7 +4535,7 @@ static BC_STATUS zbc_parse_stmt_or_funcdef(BcParse *p) #define zbc_parse_stmt_or_funcdef(...) (zbc_parse_stmt_or_funcdef(__VA_ARGS__) COMMA_SUCCESS) // This is not a "z" function: can also return BC_STATUS_PARSE_EMPTY_EXP -static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext next) +static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) { BcStatus s = BC_STATUS_SUCCESS; BcInst prev = BC_INST_PRINT; @@ -4766,19 +4771,6 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext ne if (prev == BC_INST_BOOL_NOT || nexprs != 1) return bc_error_bad_expression(); -//TODO: why is this needed at all? - // next is BcParseNext, byte array of up to 4 BC_LEX's, packed into 32-bit word - for (;;) { - if (t == (next & 0x7f)) - goto ok; - if (next & 0x80) // last element? - break; - next >>= 8; - } - if (t != BC_LEX_KEY_ELSE) - return bc_error_bad_expression(); - ok: - if (!(flags & BC_PARSE_REL) && nrelops) { s = bc_POSIX_does_not_allow("comparison operators outside if or loops"); IF_ERROR_RETURN_POSSIBLE(if (s) return s); @@ -4797,18 +4789,6 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext ne return s; } -#undef zbc_parse_expr -static BC_STATUS zbc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) -{ - BcStatus s; - - s = bc_parse_expr_empty_ok(p, flags, next); - if (s == BC_STATUS_PARSE_EMPTY_EXP) - RETURN_STATUS(bc_error("empty expression")); - RETURN_STATUS(s); -} -#define zbc_parse_expr(...) (zbc_parse_expr(__VA_ARGS__) COMMA_SUCCESS) - #endif // ENABLE_BC #if ENABLE_DC @@ -5008,7 +4988,7 @@ static BC_STATUS zdc_parse_parse(BcParse *p) static BC_STATUS zcommon_parse_expr(BcParse *p, uint8_t flags) { if (IS_BC) { - IF_BC(RETURN_STATUS(zbc_parse_expr(p, flags, bc_parse_next_read))); + IF_BC(RETURN_STATUS(zbc_parse_expr(p, flags))); } else { IF_DC(RETURN_STATUS(zdc_parse_expr(p, flags))); } diff --git a/testsuite/bc.tests b/testsuite/bc.tests index d057bea17..e0a45a8bd 100755 --- a/testsuite/bc.tests +++ b/testsuite/bc.tests @@ -76,6 +76,11 @@ testing "bc print 1,2,3" \ "123" \ "" "print 1,2,3" +testing "bc { print 1 }" \ + "bc" \ + "1" \ + "" "{ print 1 }" + testing "bc nested loops and breaks" \ "bc" \ "\ -- cgit v1.2.3-55-g6feb From 6d3b4bb24da9a07c263f3c1acf8df85382ff562c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 17 Dec 2018 18:07:18 +0100 Subject: udhcpc: check that 4-byte options are indeed 4-byte, closes 11506 function old new delta udhcp_get_option32 - 27 +27 udhcp_get_option 231 248 +17 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 1/0 up/down: 44/0) Total: 44 bytes Signed-off-by: Denys Vlasenko --- networking/udhcp/common.c | 19 +++++++++++++++++++ networking/udhcp/common.h | 4 ++++ networking/udhcp/dhcpc.c | 6 +++--- networking/udhcp/dhcpd.c | 6 +++--- 4 files changed, 29 insertions(+), 6 deletions(-) diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c index e5fd74f91..41b05b855 100644 --- a/networking/udhcp/common.c +++ b/networking/udhcp/common.c @@ -272,6 +272,15 @@ uint8_t* FAST_FUNC udhcp_get_option(struct dhcp_packet *packet, int code) goto complain; /* complain and return NULL */ if (optionptr[OPT_CODE] == code) { + if (optionptr[OPT_LEN] == 0) { + /* So far no valid option with length 0 known. + * Having this check means that searching + * for DHCP_MESSAGE_TYPE need not worry + * that returned pointer might be unsafe + * to dereference. + */ + goto complain; /* complain and return NULL */ + } log_option("option found", optionptr); return optionptr + OPT_DATA; } @@ -289,6 +298,16 @@ uint8_t* FAST_FUNC udhcp_get_option(struct dhcp_packet *packet, int code) return NULL; } +uint8_t* FAST_FUNC udhcp_get_option32(struct dhcp_packet *packet, int code) +{ + uint8_t *r = udhcp_get_option(packet, code); + if (r) { + if (r[-1] != 4) + r = NULL; + } + return r; +} + /* Return the position of the 'end' option (no bounds checking) */ int FAST_FUNC udhcp_end_option(uint8_t *optionptr) { diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h index 7ad603d33..9511152ff 100644 --- a/networking/udhcp/common.h +++ b/networking/udhcp/common.h @@ -205,6 +205,10 @@ extern const uint8_t dhcp_option_lengths[] ALIGN1; unsigned FAST_FUNC udhcp_option_idx(const char *name, const char *option_strings); uint8_t *udhcp_get_option(struct dhcp_packet *packet, int code) FAST_FUNC; +/* Same as above + ensures that option length is 4 bytes + * (returns NULL if size is different) + */ +uint8_t *udhcp_get_option32(struct dhcp_packet *packet, int code) FAST_FUNC; int udhcp_end_option(uint8_t *optionptr) FAST_FUNC; void udhcp_add_binary_option(struct dhcp_packet *packet, uint8_t *addopt) FAST_FUNC; #if ENABLE_UDHCPC || ENABLE_UDHCPD diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index 4b23e4d39..5b3fd531c 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c @@ -1691,7 +1691,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) * They say ISC DHCP client supports this case. */ server_addr = 0; - temp = udhcp_get_option(&packet, DHCP_SERVER_ID); + temp = udhcp_get_option32(&packet, DHCP_SERVER_ID); if (!temp) { bb_error_msg("no server ID, using 0.0.0.0"); } else { @@ -1718,7 +1718,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) struct in_addr temp_addr; uint8_t *temp; - temp = udhcp_get_option(&packet, DHCP_LEASE_TIME); + temp = udhcp_get_option32(&packet, DHCP_LEASE_TIME); if (!temp) { bb_error_msg("no lease time with ACK, using 1 hour lease"); lease_seconds = 60 * 60; @@ -1813,7 +1813,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) uint32_t svid; uint8_t *temp; - temp = udhcp_get_option(&packet, DHCP_SERVER_ID); + temp = udhcp_get_option32(&packet, DHCP_SERVER_ID); if (!temp) { non_matching_svid: log1("received DHCP NAK with wrong" diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c index a8cd3f03b..477856d11 100644 --- a/networking/udhcp/dhcpd.c +++ b/networking/udhcp/dhcpd.c @@ -640,7 +640,7 @@ static void add_server_options(struct dhcp_packet *packet) static uint32_t select_lease_time(struct dhcp_packet *packet) { uint32_t lease_time_sec = server_config.max_lease_sec; - uint8_t *lease_time_opt = udhcp_get_option(packet, DHCP_LEASE_TIME); + uint8_t *lease_time_opt = udhcp_get_option32(packet, DHCP_LEASE_TIME); if (lease_time_opt) { move_from_unaligned32(lease_time_sec, lease_time_opt); lease_time_sec = ntohl(lease_time_sec); @@ -987,7 +987,7 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) } /* Get SERVER_ID if present */ - server_id_opt = udhcp_get_option(&packet, DHCP_SERVER_ID); + server_id_opt = udhcp_get_option32(&packet, DHCP_SERVER_ID); if (server_id_opt) { uint32_t server_id_network_order; move_from_unaligned32(server_id_network_order, server_id_opt); @@ -1011,7 +1011,7 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) } /* Get REQUESTED_IP if present */ - requested_ip_opt = udhcp_get_option(&packet, DHCP_REQUESTED_IP); + requested_ip_opt = udhcp_get_option32(&packet, DHCP_REQUESTED_IP); if (requested_ip_opt) { move_from_unaligned32(requested_nip, requested_ip_opt); } -- cgit v1.2.3-55-g6feb From f4f10720fe4f7a37685bf2d9a535d7bd59a64e86 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 18 Dec 2018 02:23:53 +0100 Subject: bc: fixed from 64-bit compile Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 45d9eb8eb..20ce497dd 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -3477,7 +3477,7 @@ static void bc_parse_pushIndex(BcParse *p, size_t idx) size_t mask; unsigned amt; - dbg_lex("%s:%d pushing index %d", __func__, __LINE__, idx); + dbg_lex("%s:%d pushing index %zd", __func__, __LINE__, idx); mask = ((size_t)0xff) << (sizeof(idx) * 8 - 8); amt = sizeof(idx); do { @@ -4086,10 +4086,10 @@ static BC_STATUS zbc_parse_if(BcParse *p) ip2_idx = p->func->labels.len; - dbg_lex("%s:%d after if() body: BC_INST_JUMP to %d", __func__, __LINE__, ip2_idx); + dbg_lex("%s:%d after if() body: BC_INST_JUMP to %zd", __func__, __LINE__, ip2_idx); bc_parse_pushJUMP(p, ip2_idx); - dbg_lex("%s:%d rewriting 'if_zero' label to jump to 'else'-> %d", __func__, __LINE__, p->func->code.len); + dbg_lex("%s:%d rewriting 'if_zero' label to jump to 'else'-> %zd", __func__, __LINE__, p->func->code.len); rewrite_label_to_current(p, ip_idx); bc_vec_push(&p->func->labels, &ip2_idx); @@ -4099,7 +4099,7 @@ static BC_STATUS zbc_parse_if(BcParse *p) if (s) RETURN_STATUS(s); } - dbg_lex("%s:%d rewriting label to jump after 'if' body-> %d", __func__, __LINE__, p->func->code.len); + dbg_lex("%s:%d rewriting label to jump after 'if' body-> %zd", __func__, __LINE__, p->func->code.len); rewrite_label_to_current(p, ip_idx); dbg_lex_done("%s:%d done", __func__, __LINE__); @@ -4137,10 +4137,10 @@ static BC_STATUS zbc_parse_while(BcParse *p) s = zbc_parse_stmt_allow_NLINE_before(p, STRING_while); if (s) RETURN_STATUS(s); - dbg_lex("%s:%d BC_INST_JUMP to %d", __func__, __LINE__, cond_idx); + dbg_lex("%s:%d BC_INST_JUMP to %zd", __func__, __LINE__, cond_idx); bc_parse_pushJUMP(p, cond_idx); - dbg_lex("%s:%d rewriting label-> %d", __func__, __LINE__, p->func->code.len); + dbg_lex("%s:%d rewriting label-> %zd", __func__, __LINE__, p->func->code.len); rewrite_label_to_current(p, ip_idx); bc_vec_pop(&p->exits); @@ -4213,10 +4213,10 @@ static BC_STATUS zbc_parse_for(BcParse *p) s = zbc_parse_stmt_allow_NLINE_before(p, STRING_for); if (s) RETURN_STATUS(s); - dbg_lex("%s:%d BC_INST_JUMP to %d", __func__, __LINE__, update_idx); + dbg_lex("%s:%d BC_INST_JUMP to %zd", __func__, __LINE__, update_idx); bc_parse_pushJUMP(p, update_idx); - dbg_lex("%s:%d rewriting label-> %d", __func__, __LINE__, p->func->code.len); + dbg_lex("%s:%d rewriting label-> %zd", __func__, __LINE__, p->func->code.len); rewrite_label_to_current(p, exit_idx); bc_vec_pop(&p->exits); @@ -4257,6 +4257,7 @@ static BC_STATUS zbc_parse_funcdef(BcParse *p) bool var, comma = false; char *name; + dbg_lex_enter("%s:%d entered", __func__, __LINE__); s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); if (p->l.t.t != BC_LEX_NAME) @@ -4330,9 +4331,11 @@ static BC_STATUS zbc_parse_funcdef(BcParse *p) bc_parse_push(p, BC_INST_RET0); bc_parse_updateFunc(p, BC_PROG_MAIN); + dbg_lex_done("%s:%d done", __func__, __LINE__); RETURN_STATUS(s); err: + dbg_lex_done("%s:%d done (error)", __func__, __LINE__); free(name); RETURN_STATUS(s); } @@ -4873,7 +4876,6 @@ static BC_STATUS zdc_parse_cond(BcParse *p, uint8_t inst) static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t, uint8_t flags) { BcStatus s = BC_STATUS_SUCCESS; - BcInst prev; uint8_t inst; bool assign, get_token = false; @@ -4902,7 +4904,6 @@ static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t, uint8_t flags) RETURN_STATUS(bc_error_bad_token()); } bc_parse_number(p); - prev = BC_INST_NUM; if (t == BC_LEX_NEG) bc_parse_push(p, BC_INST_NEG); get_token = true; break; -- cgit v1.2.3-55-g6feb From 0f31a5c79e8d4a35f790d9f7f2c0a63e3c0d6808 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 18 Dec 2018 03:16:48 +0100 Subject: bc: fixes to bugs found while testing 64-bit build Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 20ce497dd..57ae52ce7 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -2690,12 +2690,11 @@ static void bc_lex_whitespace(BcLex *l) static BC_STATUS zbc_lex_number(BcLex *l, char start) { const char *buf = l->buf + l->i; - size_t len, bslashes, i, ccnt; + size_t len, i, ccnt; bool pt; pt = (start == '.'); l->t.t = BC_LEX_NUMBER; - bslashes = 0; ccnt = i = 0; for (;;) { char c = buf[i]; @@ -2703,26 +2702,31 @@ static BC_STATUS zbc_lex_number(BcLex *l, char start) break; if (c == '\\' && buf[i + 1] == '\n') { i += 2; - bslashes++; + //number_of_backslashes++ - see comment below continue; } if (!isdigit(c) && (c < 'A' || c > 'F')) { if (c != '.') break; // if '.' was already seen, stop on second one: if (pt) break; - pt = 1; + pt = true; } // buf[i] is one of "0-9A-F." i++; if (c != '.') ccnt = i; } - //i is buf[i] index of the first not-yet-parsed char + //ccnt is the number of chars in the number string, excluding possible + //trailing "[\].[\]" (with any number of \ repetitions). + //i is buf[i] index of the first not-yet-parsed char after that. l->i += i; - //ccnt is the number of chars in the number string, excluding possible - //trailing "." and possible following trailing "\"(s). - len = ccnt - bslashes * 2 + 1; // +1 byte for NUL termination + // This might overestimate the size, if there are "\"'s + // in the number. Subtracting number_of_backslashes*2 correctly + // is not that easy: consider that in the case of "NNN.\" + // loop above will count "\" before it realizes it is not + // in fact *inside* the number: + len = ccnt + 1; // +1 byte for NUL termination // This check makes sense only if size_t is (much) larger than BC_MAX_NUM. if (SIZE_MAX > (BC_MAX_NUM | 0xff)) { @@ -2979,6 +2983,7 @@ static BC_STATUS zbc_lex_identifier(BcLex *l) } bc_lex_name(l); + s = BC_STATUS_SUCCESS; if (l->t.v.len > 2) { // Prevent this: -- cgit v1.2.3-55-g6feb From f6e3f8511e3257022302ad82a6dd6951ff1eae52 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 17 Dec 2018 21:05:09 +0100 Subject: bc: get rid of BcNum BcProgram::ib,hexb function old new delta zbc_program_num 907 943 +36 zbc_program_assign 485 474 -11 bc_vm_init 757 739 -18 bc_num_ten 30 - -30 ------------------------------------------------------------------------------ (add/remove: 0/1 grow/shrink: 1/2 up/down: 36/-59) Total: -23 bytes text data bss dec hex filename 981532 485 7296 989313 f1881 busybox_old 981509 485 7296 989290 f186a busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 60 +++++++++++++++++++++++----------------------------------- 1 file changed, 24 insertions(+), 36 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 57ae52ce7..c65555fe2 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -228,7 +228,6 @@ typedef struct BcNum { bool neg; } BcNum; -#define BC_NUM_MIN_BASE ((unsigned long) 2) #define BC_NUM_MAX_IBASE ((unsigned long) 16) // larger value might speed up BIGNUM calculations a bit: #define BC_NUM_DEF_SIZE (16) @@ -680,12 +679,9 @@ typedef struct BcProgram { size_t len; size_t scale; - BcNum ib; size_t ib_t; - BcNum ob; size_t ob_t; - - BcNum hexb; + BcNum ob; #if ENABLE_DC BcNum strmb; @@ -2240,10 +2236,11 @@ static void bc_num_parseDecimal(BcNum *n, const char *val) // Note: n is already "bc_num_zero()"ed, // leading zeroes in "val" are removed -static void bc_num_parseBase(BcNum *n, const char *val, BcNum *base) +static void bc_num_parseBase(BcNum *n, const char *val, unsigned base_t) { BcStatus s; BcNum temp, mult, result; + BcNum base; BcDig c = '\0'; unsigned long v; size_t i, digits; @@ -2257,6 +2254,8 @@ static void bc_num_parseBase(BcNum *n, const char *val, BcNum *base) bc_num_init_DEF_SIZE(&temp); bc_num_init_DEF_SIZE(&mult); + bc_num_init_DEF_SIZE(&base); + bc_num_ulong2num(&base, base_t); for (;;) { c = *val++; @@ -2265,14 +2264,14 @@ static void bc_num_parseBase(BcNum *n, const char *val, BcNum *base) v = (unsigned long) (c <= '9' ? c - '0' : c - 'A' + 10); - s = zbc_num_mul(n, base, &mult, 0); + s = zbc_num_mul(n, &base, &mult, 0); if (s) goto int_err; bc_num_ulong2num(&temp, v); s = zbc_num_add(&mult, &temp, n, 0); if (s) goto int_err; } - bc_num_init(&result, base->len); + bc_num_init(&result, base.len); //bc_num_zero(&result); - already is bc_num_one(&mult); @@ -2284,12 +2283,12 @@ static void bc_num_parseBase(BcNum *n, const char *val, BcNum *base) v = (unsigned long) (c <= '9' ? c - '0' : c - 'A' + 10); - s = zbc_num_mul(&result, base, &result, 0); + s = zbc_num_mul(&result, &base, &result, 0); if (s) goto err; bc_num_ulong2num(&temp, v); s = zbc_num_add(&result, &temp, &result, 0); if (s) goto err; - s = zbc_num_mul(&mult, base, &mult, 0); + s = zbc_num_mul(&mult, &base, &mult, 0); if (s) goto err; } @@ -2306,12 +2305,12 @@ static void bc_num_parseBase(BcNum *n, const char *val, BcNum *base) err: bc_num_free(&result); int_err: + bc_num_free(&base); bc_num_free(&mult); bc_num_free(&temp); } -static BC_STATUS zbc_num_parse(BcNum *n, const char *val, BcNum *base, - size_t base_t) +static BC_STATUS zbc_num_parse(BcNum *n, const char *val, unsigned base_t) { if (!bc_num_strValid(val, base_t)) RETURN_STATUS(bc_error("bad number string")); @@ -2322,7 +2321,7 @@ static BC_STATUS zbc_num_parse(BcNum *n, const char *val, BcNum *base, if (base_t == 10) bc_num_parseDecimal(n, val); else - bc_num_parseBase(n, val, base); + bc_num_parseBase(n, val, base_t); RETURN_STATUS(BC_STATUS_SUCCESS); } @@ -5044,15 +5043,14 @@ static BC_STATUS zbc_program_num(BcResult *r, BcNum **num, bool hex) { BcStatus s; char **str = bc_vec_item(&G.prog.consts, r->d.id.idx); - size_t base_t, len = strlen(*str); - BcNum *base; + unsigned base_t; + size_t len = strlen(*str); bc_num_init(&r->d.n, len); hex = hex && len == 1; - base = hex ? &G.prog.hexb : &G.prog.ib; - base_t = hex ? BC_NUM_MAX_IBASE : G.prog.ib_t; - s = zbc_num_parse(&r->d.n, *str, base, base_t); + base_t = hex ? 16 : G.prog.ib_t; + s = zbc_num_parse(&r->d.n, *str, base_t); if (s) { bc_num_free(&r->d.n); @@ -5475,8 +5473,7 @@ static BC_STATUS zbc_num_printBase(BcNum *n) if (G.prog.ob_t <= BC_NUM_MAX_IBASE) { width = 1; print = bc_num_printHex; - } - else { + } else { for (i = G.prog.ob_t - 1, width = 0; i != 0; i /= 10, ++width) continue; print = bc_num_printDigits; @@ -5506,8 +5503,7 @@ static BC_STATUS zbc_num_print(BcNum *n, bool newline) if (n->len == 0) { bb_putchar('0'); ++G.prog.nchars; - } - else if (G.prog.ob_t == 10) + } else if (G.prog.ob_t == 10) bc_num_printDecimal(n); else s = zbc_num_printBase(n); @@ -5765,7 +5761,8 @@ static BC_STATUS zbc_program_assign(char inst) "bad obase; must be [2,"BC_MAX_OBASE_STR"]", //BC_RESULT_OBASE }; size_t *ptr; - unsigned long val, max; + size_t max; + unsigned long val; s = zbc_num_ulong(l, &val); if (s) RETURN_STATUS(s); @@ -5773,9 +5770,8 @@ static BC_STATUS zbc_program_assign(char inst) if (sc) { max = BC_MAX_SCALE; ptr = &G.prog.scale; - } - else { - if (val < BC_NUM_MIN_BASE) + } else { + if (val < 2) RETURN_STATUS(bc_error(msg[s])); max = ib ? BC_NUM_MAX_IBASE : BC_MAX_OBASE; ptr = ib ? &G.prog.ib_t : &G.prog.ob_t; @@ -5783,8 +5779,8 @@ static BC_STATUS zbc_program_assign(char inst) if (val > max) RETURN_STATUS(bc_error(msg[s])); - if (!sc) - bc_num_copy(ib ? &G.prog.ib : &G.prog.ob, l); + if (!sc && !ib) + bc_num_copy(&G.prog.ob, l); *ptr = (size_t) val; s = BC_STATUS_SUCCESS; @@ -7057,9 +7053,7 @@ static BC_STATUS zbc_vm_exec(void) #if ENABLE_FEATURE_CLEAN_UP static void bc_program_free(void) { - bc_num_free(&G.prog.ib); bc_num_free(&G.prog.ob); - bc_num_free(&G.prog.hexb); # if ENABLE_DC bc_num_free(&G.prog.strmb); # endif @@ -7097,18 +7091,12 @@ static void bc_program_init(void) memset(&ip, 0, sizeof(BcInstPtr)); // G.prog.nchars = G.prog.scale = 0; - already is - bc_num_init_DEF_SIZE(&G.prog.ib); - bc_num_ten(&G.prog.ib); G.prog.ib_t = 10; bc_num_init_DEF_SIZE(&G.prog.ob); bc_num_ten(&G.prog.ob); G.prog.ob_t = 10; - bc_num_init_DEF_SIZE(&G.prog.hexb); - bc_num_ten(&G.prog.hexb); - G.prog.hexb.num[0] = 6; - #if ENABLE_DC bc_num_init_DEF_SIZE(&G.prog.strmb); bc_num_ulong2num(&G.prog.strmb, UCHAR_MAX + 1); -- cgit v1.2.3-55-g6feb From 57734c926bbfe69d1c3bb6096fbdf428628ed838 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 17 Dec 2018 21:14:05 +0100 Subject: bc: fold zbc_num_stream() into its single caller Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index c65555fe2..e5ad0ed86 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -5486,14 +5486,6 @@ static BC_STATUS zbc_num_printBase(BcNum *n) } #define zbc_num_printBase(...) (zbc_num_printBase(__VA_ARGS__) COMMA_SUCCESS) -#if ENABLE_DC -static BC_STATUS zbc_num_stream(BcNum *n, BcNum *base) -{ - RETURN_STATUS(zbc_num_printNum(n, base, 1, bc_num_printChar)); -} -#define zbc_num_stream(...) (zbc_num_stream(__VA_ARGS__) COMMA_SUCCESS) -#endif - static BC_STATUS zbc_num_print(BcNum *n, bool newline) { BcStatus s = BC_STATUS_SUCCESS; @@ -6259,9 +6251,9 @@ static BC_STATUS zbc_program_printStream(void) s = zbc_program_num(r, &n, false); if (s) RETURN_STATUS(s); - if (BC_PROG_NUM(r, n)) - s = zbc_num_stream(n, &G.prog.strmb); - else { + if (BC_PROG_NUM(r, n)) { + s = zbc_num_printNum(n, &G.prog.strmb, 1, bc_num_printChar); + } else { idx = (r->t == BC_RESULT_STR) ? r->d.id.idx : n->rdx; str = *bc_program_str(idx); printf("%s", str); -- cgit v1.2.3-55-g6feb From 4113e1f2cd2f45a95bcb0920bf2e3ee75b906281 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 18 Dec 2018 00:39:24 +0100 Subject: bc: rewrite bc_num_compare() to be readable function old new delta bc_num_compare 59 51 -8 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index e5ad0ed86..eaab6cee6 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1475,10 +1475,20 @@ static void bc_num_subArrays(BcDig *restrict a, BcDig *restrict b, static ssize_t bc_num_compare(BcDig *restrict a, BcDig *restrict b, size_t len) { - size_t i; - int c = 0; - for (i = len - 1; i < len && !(c = a[i] - b[i]); --i); - return BC_NUM_NEG(i + 1, c < 0); + size_t i = len; + for (;;) { + int c; + if (i == 0) + return 0; + i--; + c = a[i] - b[i]; + if (c != 0) { + i++; + if (c < 0) + return -i; + return i; + } + } } static ssize_t bc_num_cmp(BcNum *a, BcNum *b) -- cgit v1.2.3-55-g6feb From e2e6ffd3c5e229ef386ca22e467c6553e570c55a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 18 Dec 2018 12:23:16 +0100 Subject: bc: replace signed division / 10 by unsigned function old new delta zbc_num_a 443 441 -2 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 93 ++++++++++++++++++++-------------------------------------- 1 file changed, 32 insertions(+), 61 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index eaab6cee6..6c63c1703 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1466,9 +1466,10 @@ static void bc_num_subArrays(BcDig *restrict a, BcDig *restrict b, { size_t i, j; for (i = 0; i < len; ++i) { - for (a[i] -= b[i], j = 0; a[i + j] < 0;) { - a[i + j++] += 10; - a[i + j] -= 1; + a[i] -= b[i]; + for (j = i; a[j] < 0;) { + a[j++] += 10; + a[j] -= 1; } } } @@ -1647,7 +1648,7 @@ static FAST_FUNC BC_STATUS zbc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size { BcDig *ptr, *ptr_a, *ptr_b, *ptr_c; size_t i, max, min_rdx, min_int, diff, a_int, b_int; - int carry, in; + unsigned carry; // Because this function doesn't need to use scale (per the bc spec), // I am hijacking it to say whether it's doing an add or a subtract. @@ -1672,15 +1673,16 @@ static FAST_FUNC BC_STATUS zbc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size ptr = a->num; ptr_a = a->num + diff; ptr_b = b->num; - } - else { + } else { diff = b->rdx - a->rdx; ptr = b->num; ptr_a = a->num; ptr_b = b->num + diff; } - for (ptr_c = c->num, i = 0; i < diff; ++i, ++c->len) ptr_c[i] = ptr[i]; + ptr_c = c->num; + for (i = 0; i < diff; ++i, ++c->len) + ptr_c[i] = ptr[i]; ptr_c += diff; a_int = BC_NUM_INT(a); @@ -1690,24 +1692,24 @@ static FAST_FUNC BC_STATUS zbc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size min_int = b_int; max = a_int; ptr = ptr_a; - } - else { + } else { min_int = a_int; max = b_int; ptr = ptr_b; } - for (carry = 0, i = 0; i < min_rdx + min_int; ++i, ++c->len) { - in = ((int) ptr_a[i]) + ((int) ptr_b[i]) + carry; + carry = 0; + for (i = 0; i < min_rdx + min_int; ++i) { + unsigned in = (unsigned)ptr_a[i] + (unsigned)ptr_b[i] + carry; carry = in / 10; ptr_c[i] = (BcDig)(in % 10); } - - for (; i < max + min_rdx; ++i, ++c->len) { - in = ((int) ptr[i]) + carry; + for (; i < max + min_rdx; ++i) { + unsigned in = (unsigned)ptr[i] + carry; carry = in / 10; ptr_c[i] = (BcDig)(in % 10); } + c->len += i; if (carry != 0) c->num[c->len++] = (BcDig) carry; @@ -1751,8 +1753,7 @@ static FAST_FUNC BC_STATUS zbc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size neg = a->neg; minuend = a; subtrahend = b; - } - else { + } else { neg = b->neg; if (sub) neg = !neg; minuend = b; @@ -1765,8 +1766,7 @@ static FAST_FUNC BC_STATUS zbc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size if (c->rdx < subtrahend->rdx) { bc_num_extend(c, subtrahend->rdx - c->rdx); start = 0; - } - else + } else start = c->rdx - subtrahend->rdx; bc_num_subArrays(c->num + start, subtrahend->num, subtrahend->len); @@ -1795,11 +1795,11 @@ static FAST_FUNC BC_STATUS zbc_num_k(BcNum *restrict a, BcNum *restrict b, RETURN_STATUS(BC_STATUS_SUCCESS); } - if (a->len + b->len < BC_NUM_KARATSUBA_LEN || - a->len < BC_NUM_KARATSUBA_LEN || b->len < BC_NUM_KARATSUBA_LEN) - { + if (a->len + b->len < BC_NUM_KARATSUBA_LEN + || a->len < BC_NUM_KARATSUBA_LEN + || b->len < BC_NUM_KARATSUBA_LEN + ) { size_t i, j, len; - unsigned carry; bc_num_expand(c, a->len + b->len + 1); @@ -1807,11 +1807,10 @@ static FAST_FUNC BC_STATUS zbc_num_k(BcNum *restrict a, BcNum *restrict b, c->len = len = 0; for (i = 0; i < b->len; ++i) { - - carry = 0; + unsigned carry = 0; for (j = 0; j < a->len; ++j) { unsigned in = c->num[i + j]; - in += ((unsigned) a->num[j]) * ((unsigned) b->num[i]) + carry; + in += (unsigned)a->num[j] * (unsigned)b->num[i] + carry; // note: compilers prefer _unsigned_ div/const carry = in / 10; c->num[i + j] = (BcDig)(in % 10); @@ -2158,8 +2157,7 @@ static BC_STATUS zbc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale, ptr_a = &num2; memcpy(ptr_a, c, sizeof(BcNum)); init = true; - } - else + } else ptr_a = a; if (c == b) { @@ -2168,8 +2166,7 @@ static BC_STATUS zbc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale, memcpy(ptr_b, c, sizeof(BcNum)); init = true; } - } - else + } else ptr_b = b; if (init) @@ -2350,10 +2347,9 @@ static BC_STATUS zbc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale) if (a->len == 0) { bc_num_setToZero(b, scale); RETURN_STATUS(BC_STATUS_SUCCESS); - } - else if (a->neg) + } else if (a->neg) { RETURN_STATUS(bc_error("negative number")); - else if (BC_NUM_ONE(a)) { + } else if (BC_NUM_ONE(a)) { bc_num_one(b); bc_num_extend(b, scale); RETURN_STATUS(BC_STATUS_SUCCESS); @@ -2380,7 +2376,6 @@ static BC_STATUS zbc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale) pow = BC_NUM_INT(a); if (pow) { - if (pow & 1) x0->num[0] = 2; else @@ -2399,7 +2394,6 @@ static BC_STATUS zbc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale) len = BC_NUM_INT(x0) + resrdx - 1; while (cmp != 0 || digs < len) { - s = zbc_num_div(a, x0, &f, resrdx); if (s) goto err; s = zbc_num_add(x0, &f, &fprime, resrdx); @@ -2429,8 +2423,7 @@ static BC_STATUS zbc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale) bc_num_copy(b, x0); scale -= 1; if (b->rdx > scale) bc_num_truncate(b, b->rdx - scale); - -err: + err: bc_num_free(&fprime); bc_num_free(&f); bc_num_free(&half); @@ -2453,8 +2446,7 @@ static BC_STATUS zbc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d, ptr_a = &num2; bc_num_init(c, len); init = true; - } - else { + } else { ptr_a = a; bc_num_expand(c, len); } @@ -2495,7 +2487,6 @@ static BC_STATUS zbc_num_modexp(BcNum *a, BcNum *b, BcNum *c, BcNum *restrict d) bc_num_copy(&exp, b); while (exp.len != 0) { - s = zbc_num_divmod(&exp, &two, &exp, &temp, 0); if (s) goto err; @@ -2511,8 +2502,7 @@ static BC_STATUS zbc_num_modexp(BcNum *a, BcNum *b, BcNum *c, BcNum *restrict d) s = zbc_num_rem(&temp, c, &base, 0); if (s) goto err; } - -err: + err: bc_num_free(&temp); bc_num_free(&two); bc_num_free(&exp); @@ -2579,8 +2569,7 @@ static void bc_array_expand(BcVec *a, size_t len) bc_num_init_DEF_SIZE(&data.n); bc_vec_push(a, &data.n); } - } - else { + } else { while (len > a->len) { bc_array_init(&data.v, true); bc_vec_push(a, &data.v); @@ -2614,33 +2603,24 @@ static void bc_result_copy(BcResult *d, BcResult *src) d->t = src->t; switch (d->t) { - case BC_RESULT_TEMP: case BC_RESULT_IBASE: case BC_RESULT_SCALE: case BC_RESULT_OBASE: - { bc_num_init(&d->d.n, src->d.n.len); bc_num_copy(&d->d.n, &src->d.n); break; - } - case BC_RESULT_VAR: case BC_RESULT_ARRAY: case BC_RESULT_ARRAY_ELEM: - { d->d.id.name = xstrdup(src->d.id.name); break; - } - case BC_RESULT_CONSTANT: case BC_RESULT_LAST: case BC_RESULT_ONE: case BC_RESULT_STR: - { memcpy(&d->d.n, &src->d.n, sizeof(BcNum)); break; - } } } #endif // ENABLE_DC @@ -2650,29 +2630,20 @@ static FAST_FUNC void bc_result_free(void *result) BcResult *r = (BcResult *) result; switch (r->t) { - case BC_RESULT_TEMP: case BC_RESULT_IBASE: case BC_RESULT_SCALE: case BC_RESULT_OBASE: - { bc_num_free(&r->d.n); break; - } - case BC_RESULT_VAR: case BC_RESULT_ARRAY: case BC_RESULT_ARRAY_ELEM: - { free(r->d.id.name); break; - } - default: - { // Do nothing. break; - } } } -- cgit v1.2.3-55-g6feb From 71c82d1d8ca0617290600050728feda906878115 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 18 Dec 2018 12:43:21 +0100 Subject: bc: rewrite another for() loop function old new delta zbc_num_d 570 563 -7 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 6c63c1703..0cd8ba6b4 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1933,7 +1933,6 @@ static FAST_FUNC BC_STATUS zbc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size BcDig *n, *p, q; size_t len, end, i; BcNum cp; - bool zero = true; if (b->len == 0) RETURN_STATUS(bc_error("divide by zero")); @@ -1961,8 +1960,13 @@ static FAST_FUNC BC_STATUS zbc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size if (scale > cp.rdx) bc_num_extend(&cp, scale - cp.rdx); if (b->rdx == b->len) { - for (i = 0; zero && i < len; ++i) zero = !b->num[len - i - 1]; - len -= i - 1; + for (;;) { + if (len == 0) break; + len--; + if (b->num[len] != 0) + break; + } + len++; } if (cp.cap == cp.len) bc_num_expand(&cp, cp.len + 1); -- cgit v1.2.3-55-g6feb From 6b0fbd14fc0566a4f6cedf50f6301143e74adca5 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 18 Dec 2018 12:55:40 +0100 Subject: bc: rewrite more for() loops function old new delta bc_program_name 75 67 -8 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 0cd8ba6b4..927873d86 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -2064,7 +2064,7 @@ static FAST_FUNC BC_STATUS zbc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size BcNum copy; unsigned long pow; size_t i, powrdx, resrdx; - bool neg, zero; + bool neg; if (b->rdx) RETURN_STATUS(bc_error("non integer number")); @@ -2116,7 +2116,6 @@ static FAST_FUNC BC_STATUS zbc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size bc_num_copy(c, ©); for (resrdx = powrdx, pow >>= 1; pow != 0; pow >>= 1) { - powrdx <<= 1; s = zbc_num_mul(©, ©, ©, powrdx); if (s) goto err; @@ -2141,10 +2140,13 @@ static FAST_FUNC BC_STATUS zbc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size if (c->rdx > scale) bc_num_truncate(c, c->rdx - scale); // We can't use bc_num_clean() here. - for (zero = true, i = 0; zero && i < c->len; ++i) zero = !c->num[i]; - if (zero) bc_num_setToZero(c, scale); + for (i = 0; i < c->len; ++i) + if (c->num[i] != 0) + goto skip; + bc_num_setToZero(c, scale); + skip: -err: + err: bc_num_free(©); RETURN_STATUS(s); } @@ -2989,7 +2991,7 @@ static BC_STATUS zbc_lex_string(BcLex *l) l->t.t = BC_LEX_STR; - for (c = l->buf[i]; c != 0 && c != '"'; c = l->buf[++i]) + for (c = l->buf[i]; c != '\0' && c != '"'; c = l->buf[++i]) nls += (c == '\n'); if (c == '\0') { @@ -5246,14 +5248,16 @@ static size_t bc_program_index(char *code, size_t *bgn) static char *bc_program_name(char *code, size_t *bgn) { size_t i; - char c, *s, *str = code + *bgn, *ptr = strchr(str, BC_PARSE_STREND); + char *s, *str = code + *bgn, *ptr = strchr(str, BC_PARSE_STREND); s = xmalloc(ptr - str + 1); - c = code[(*bgn)++]; - - for (i = 0; c != 0 && c != BC_PARSE_STREND; c = code[(*bgn)++], ++i) - s[i] = c; - + i = 0; + for (;;) { + char c = code[(*bgn)++]; + if (c == '\0' || c == BC_PARSE_STREND) + break; + s[i++] = c; + } s[i] = '\0'; return s; -- cgit v1.2.3-55-g6feb From 5c0c5abba09c7bab423d1261920d8c73c5eac939 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 18 Dec 2018 13:15:55 +0100 Subject: bc: simplify another for() loop function old new delta zbc_num_d 563 557 -6 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 927873d86..4b5cac08a 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1929,8 +1929,7 @@ err: static FAST_FUNC BC_STATUS zbc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) { - BcStatus s = BC_STATUS_SUCCESS; - BcDig *n, *p, q; + BcStatus s; size_t len, end, i; BcNum cp; @@ -1981,12 +1980,13 @@ static FAST_FUNC BC_STATUS zbc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size memset(c->num + end, 0, (c->cap - end) * sizeof(BcDig)); c->rdx = cp.rdx; c->len = cp.len; - p = b->num; - for (i = end - 1; !s && i < end; --i) { + s = BC_STATUS_SUCCESS; + for (i = end - 1; i < end; --i) { + BcDig *n, q; n = cp.num + i; - for (q = 0; (!s && n[len] != 0) || bc_num_compare(n, p, len) >= 0; ++q) - bc_num_subArrays(n, p, len); + for (q = 0; n[len] != 0 || bc_num_compare(n, b->num, len) >= 0; ++q) + bc_num_subArrays(n, b->num, len); c->num[i] = q; #if ENABLE_FEATURE_BC_SIGNALS // a=2^100000 -- cgit v1.2.3-55-g6feb From d4258dd321dfdfd9586fb588f17f2a61fa7829d2 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 18 Dec 2018 13:22:23 +0100 Subject: bc: another for() loop simplified function old new delta zbc_program_print 688 686 -2 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 4b5cac08a..37c9012f9 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -5448,7 +5448,7 @@ err: static BC_STATUS zbc_num_printBase(BcNum *n) { BcStatus s; - size_t width, i; + size_t width; BcNumDigitOp print; bool neg = n->neg; @@ -5463,8 +5463,14 @@ static BC_STATUS zbc_num_printBase(BcNum *n) width = 1; print = bc_num_printHex; } else { - for (i = G.prog.ob_t - 1, width = 0; i != 0; i /= 10, ++width) - continue; + unsigned i = G.prog.ob_t - 1; + width = 0; + for (;;) { + width++; + i /= 10; + if (i == 0) + break; + } print = bc_num_printDigits; } -- cgit v1.2.3-55-g6feb From ef271da33f1423b3f14aab6448c3001132cd128e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 18 Dec 2018 13:48:37 +0100 Subject: bc: shrink zdc_lex_string() This actually fixes a rather obscure bug. This was failing to find end of the string: $ echo -n '[foo]' | dc dc: string end could not be found function old new delta zbc_lex_next 2230 2141 -89 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-89) Total: -89 bytes text data bss dec hex filename 981461 485 7296 989242 f183a busybox_old 981372 485 7296 989153 f17e1 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 37c9012f9..5d969c9d0 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -3272,25 +3272,31 @@ static BC_STATUS zdc_lex_register(BcLex *l) static BC_STATUS zdc_lex_string(BcLex *l) { - size_t depth = 1, nls = 0, i = l->i; - char c; + size_t depth, nls, i; l->t.t = BC_LEX_STR; bc_vec_pop_all(&l->t.v); - for (c = l->buf[i]; c != 0 && depth; c = l->buf[++i]) { - - depth += (c == '[' && (i == l->i || l->buf[i - 1] != '\\')); - depth -= (c == ']' && (i == l->i || l->buf[i - 1] != '\\')); + nls = 0; + depth = 1; + i = l->i; + for (;;) { + char c = l->buf[i]; + if (c == '\0') { + l->i = i; + RETURN_STATUS(bc_error("string end could not be found")); + } nls += (c == '\n'); - - if (depth) bc_vec_push(&l->t.v, &c); - } - - if (c == '\0') { - l->i = i; - RETURN_STATUS(bc_error("string end could not be found")); + if (i == l->i || l->buf[i - 1] != '\\') { + if (c == '[') depth++; + if (c == ']') + if (--depth == 0) + break; + } + bc_vec_push(&l->t.v, &l->buf[i]); + i++; } + i++; bc_vec_pushZeroByte(&l->t.v); // This check makes sense only if size_t is (much) larger than BC_MAX_STRING. -- cgit v1.2.3-55-g6feb From 07597cd35dfbdc7597d3b2b8ecf797016a996576 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 18 Dec 2018 14:03:20 +0100 Subject: bc: optimize zbc_lex_string() function old new delta zbc_lex_next 2359 2353 -6 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 5d969c9d0..be198a5fb 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -2986,17 +2986,22 @@ static BC_STATUS zbc_lex_identifier(BcLex *l) static BC_STATUS zbc_lex_string(BcLex *l) { - size_t len, nls = 0, i = l->i; - char c; + size_t len, nls, i; l->t.t = BC_LEX_STR; - for (c = l->buf[i]; c != '\0' && c != '"'; c = l->buf[++i]) + nls = 0; + i = l->i; + for (;;) { + char c = l->buf[i]; + if (c == '\0') { + l->i = i; + RETURN_STATUS(bc_error("string end could not be found")); + } + if (c == '"') + break; nls += (c == '\n'); - - if (c == '\0') { - l->i = i; - RETURN_STATUS(bc_error("string end could not be found")); + i++; } len = i - l->i; -- cgit v1.2.3-55-g6feb From a199cc95b726df7023c19fa5130a3b55287e43a2 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 18 Dec 2018 14:11:35 +0100 Subject: bc: shrink zdc_parse_expr() function old new delta zdc_parse_expr 656 653 -3 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index be198a5fb..a5fcaf3bc 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -4947,24 +4947,29 @@ static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t, uint8_t flags) static BC_STATUS zdc_parse_expr(BcParse *p, uint8_t flags) { - BcStatus s = BC_STATUS_SUCCESS; - BcInst inst; BcLexType t; - for (t = p->l.t.t; !s && t != BC_LEX_EOF; t = p->l.t.t) { - inst = dc_parse_insts[t]; + for (;;) { + BcInst inst; + BcStatus s; + + t = p->l.t.t; + if (t == BC_LEX_EOF) break; + inst = dc_parse_insts[t]; if (inst != BC_INST_INVALID) { bc_parse_push(p, inst); s = zbc_lex_next(&p->l); - } else + } else { s = zdc_parse_token(p, t, flags); + } + if (s) RETURN_STATUS(s); } - if (!s && p->l.t.t == BC_LEX_EOF && (flags & BC_PARSE_NOCALL)) + if (flags & BC_PARSE_NOCALL) bc_parse_push(p, BC_INST_POP_EXEC); - RETURN_STATUS(s); + RETURN_STATUS(BC_STATUS_SUCCESS); } #define zdc_parse_expr(...) (zdc_parse_expr(__VA_ARGS__) COMMA_SUCCESS) -- cgit v1.2.3-55-g6feb From 55f3cab7e9f61c1e9fc342f2d245d6b055a08b84 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 18 Dec 2018 14:37:16 +0100 Subject: bc: fix "echo -n '#foo' | bc" not eating last 'o' function old new delta zdc_parse_expr 656 653 -3 bc_lex_lineComment 39 36 -3 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-6) Total: -6 bytes text data bss dec hex filename 981424 485 7296 989205 f1815 busybox_old 981418 485 7296 989199 f180f busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 10 +++++++--- testsuite/bc.tests | 5 +++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index a5fcaf3bc..eaa28a94a 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -2655,9 +2655,13 @@ static FAST_FUNC void bc_result_free(void *result) static void bc_lex_lineComment(BcLex *l) { + // Try: echo -n '#foo' | bc + size_t i; l->t.t = BC_LEX_WHITESPACE; - while (l->i < l->len && l->buf[l->i++] != '\n'); - --l->i; + i = l->i; + while (i < l->len && l->buf[i] != '\n') + i++; + l->i = i; } static void bc_lex_whitespace(BcLex *l) @@ -2889,8 +2893,8 @@ static BC_STATUS zbc_lex_next(BcLex *l) // Comments are also BC_LEX_WHITESPACE tokens and eaten here. s = BC_STATUS_SUCCESS; do { - l->t.t = BC_LEX_EOF; if (l->i == l->len) { + l->t.t = BC_LEX_EOF; if (!G.input_fp) RETURN_STATUS(BC_STATUS_SUCCESS); if (!bc_lex_more_input(l)) { diff --git a/testsuite/bc.tests b/testsuite/bc.tests index e0a45a8bd..e303cf6ae 100755 --- a/testsuite/bc.tests +++ b/testsuite/bc.tests @@ -16,6 +16,11 @@ testing "bc comment 2: /*/ is not a closed comment" \ "4\n" \ "" "1 /*/ + 2 */ + 3" +testing "bc comment 3: unterminated #comment" \ + "bc" \ + "" \ + "" "#foo" # no trailing newline + testing "bc backslash 1" \ "bc" \ "3\n" \ -- cgit v1.2.3-55-g6feb From 3f940c9c707904df545c148065f720d33e805aed Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 18 Dec 2018 15:49:42 +0100 Subject: bc: shrink bc_program_index() function old new delta bc_program_index 66 47 -19 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-19) Total: -19 bytes text data bss dec hex filename 981418 485 7296 989199 f180f busybox_old 981399 485 7296 989180 f17fc busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index eaa28a94a..2da7c317c 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -5256,11 +5256,18 @@ exec_err: static size_t bc_program_index(char *code, size_t *bgn) { - char amt = code[(*bgn)++], i = 0; - size_t res = 0; + unsigned char *bytes = (void*)(code + *bgn); + unsigned amt; + unsigned i; + size_t res; + + amt = *bytes++; + *bgn += amt + 1; - for (; i < amt; ++i, ++(*bgn)) - res |= (((size_t)((int) code[*bgn]) & UCHAR_MAX) << (i * CHAR_BIT)); + amt *= 8; + res = 0; + for (i = 0; i < amt; i += 8) + res |= (size_t)(*bytes++) << i; return res; } -- cgit v1.2.3-55-g6feb From 7f2d59c38dcc56ea4e89c9ea64d56c349a51eaba Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 18 Dec 2018 16:24:07 +0100 Subject: bc: style edit, no code changes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 236 ++++++++++++++------------------------------------------- 1 file changed, 57 insertions(+), 179 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 2da7c317c..7ecddf014 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -236,7 +236,6 @@ typedef struct BcNum { #define BC_NUM_KARATSUBA_LEN (32) typedef enum BcInst { - #if ENABLE_BC BC_INST_INC_PRE, BC_INST_DEC_PRE, @@ -333,7 +332,6 @@ typedef enum BcInst { BC_INST_INVALID = -1, #endif - } BcInst; typedef struct BcId { @@ -349,7 +347,6 @@ typedef struct BcFunc { } BcFunc; typedef enum BcResultType { - BC_RESULT_TEMP, BC_RESULT_VAR, @@ -367,7 +364,6 @@ typedef enum BcResultType { BC_RESULT_ONE, BC_RESULT_OBASE, - } BcResultType; typedef union BcResultData { @@ -675,7 +671,6 @@ typedef struct BcParse { } BcParse; typedef struct BcProgram { - size_t len; size_t scale; @@ -709,7 +704,6 @@ typedef struct BcProgram { BcNum one; size_t nchars; - } BcProgram; #define BC_PROG_STACK(s, n) ((s)->len >= ((size_t) n)) @@ -1124,7 +1118,6 @@ static void bc_vec_pushAt(BcVec *v, const void *data, size_t idx) if (idx == v->len) bc_vec_push(v, data); else { - char *ptr; if (v->len == v->cap) bc_vec_grow(v, 1); @@ -1210,7 +1203,6 @@ static size_t bc_map_find(const BcVec *v, const void *ptr) size_t low = 0, high = v->len; while (low < high) { - size_t mid = (low + high) / 2; BcId *id = bc_vec_item(v, mid); int result = bc_id_cmp(ptr, id); @@ -1421,7 +1413,6 @@ static BC_STATUS zbc_num_ulong(BcNum *n, unsigned long *result_p) if (n->neg) RETURN_STATUS(bc_error("negative number")); for (result = 0, pow = 1, i = n->rdx; i < n->len; ++i) { - unsigned long prev = result, powprev = pow; result += ((unsigned long) n->num[i]) * pow; @@ -1461,8 +1452,7 @@ static void bc_num_ulong2num(BcNum *n, unsigned long val) } } -static void bc_num_subArrays(BcDig *restrict a, BcDig *restrict b, - size_t len) +static void bc_num_subArrays(BcDig *restrict a, BcDig *restrict b, size_t len) { size_t i, j; for (i = 0; i < len; ++i) { @@ -1556,7 +1546,6 @@ static void bc_num_extend(BcNum *n, size_t places) size_t len = n->len + places; if (places != 0) { - if (n->cap < len) bc_num_expand(n, len); memmove(n->num + places, n->num, sizeof(BcDig) * n->len); @@ -1591,15 +1580,13 @@ static void bc_num_split(BcNum *restrict n, size_t idx, BcNum *restrict a, BcNum *restrict b) { if (idx < n->len) { - b->len = n->len - idx; a->len = idx; a->rdx = b->rdx = 0; memcpy(b->num, n->num + idx, b->len * sizeof(BcDig)); memcpy(a->num, n->num, idx * sizeof(BcDig)); - } - else { + } else { bc_num_zero(b); bc_num_copy(a, n); } @@ -1869,8 +1856,7 @@ static FAST_FUNC BC_STATUS zbc_num_k(BcNum *restrict a, BcNum *restrict b, s = zbc_num_add(&z0, &z1, &temp, 0); if (s) goto err; s = zbc_num_add(&temp, &z2, c, 0); - -err: + err: bc_num_free(&temp); bc_num_free(&z2); bc_num_free(&z1); @@ -1919,8 +1905,7 @@ static FAST_FUNC BC_STATUS zbc_num_m(BcNum *a, BcNum *b, BcNum *restrict c, size c->rdx = maxrdx; bc_num_retireMul(c, scale, a->neg, b->neg); - -err: + err: bc_num_free(&cpb); bc_num_free(&cpa); RETURN_STATUS(s); @@ -2037,8 +2022,7 @@ static FAST_FUNC BC_STATUS zbc_num_r(BcNum *a, BcNum *b, BcNum *restrict c, neg = d->neg; bc_num_retireMul(d, ts, a->neg, b->neg); d->neg = neg; - -err: + err: bc_num_free(&temp); RETURN_STATUS(s); } @@ -2311,13 +2295,13 @@ static void bc_num_parseBase(BcNum *n, const char *val, unsigned base_t) if (s) goto err; if (n->len != 0) { - if (n->rdx < digits) bc_num_extend(n, digits - n->rdx); + if (n->rdx < digits) + bc_num_extend(n, digits - n->rdx); } else bc_num_zero(n); - -err: + err: bc_num_free(&result); -int_err: + int_err: bc_num_free(&base); bc_num_free(&mult); bc_num_free(&temp); @@ -2353,9 +2337,11 @@ static BC_STATUS zbc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale) if (a->len == 0) { bc_num_setToZero(b, scale); RETURN_STATUS(BC_STATUS_SUCCESS); - } else if (a->neg) { + } + if (a->neg) { RETURN_STATUS(bc_error("negative number")); - } else if (BC_NUM_ONE(a)) { + } + if (BC_NUM_ONE(a)) { bc_num_one(b); bc_num_extend(b, scale); RETURN_STATUS(BC_STATUS_SUCCESS); @@ -3767,8 +3753,7 @@ static BC_STATUS zbc_parse_call(BcParse *p, char *name, uint8_t flags) bc_parse_pushIndex(p, entry_ptr->idx); RETURN_STATUS(zbc_lex_next(&p->l)); - -err: + err: free(name); RETURN_STATUS(s); } @@ -3804,8 +3789,7 @@ static BC_STATUS zbc_parse_name(BcParse *p, BcInst *type, uint8_t flags) bc_parse_push(p, *type); bc_parse_pushName(p, name); free(name); - } - else if (p->l.t.t == BC_LEX_LPAREN) { + } else if (p->l.t.t == BC_LEX_LPAREN) { if (flags & BC_PARSE_NOCALL) { s = bc_error_bad_token(); goto err; @@ -3820,8 +3804,7 @@ static BC_STATUS zbc_parse_name(BcParse *p, BcInst *type, uint8_t flags) } RETURN_STATUS(s); - -err: + err: free(name); RETURN_STATUS(s); } @@ -3908,15 +3891,14 @@ static BC_STATUS zbc_parse_incdec(BcParse *p, BcInst *prev, bool *paren_expr, char inst; BcInst etype = *prev; - if (etype == BC_INST_VAR || etype == BC_INST_ARRAY_ELEM || - etype == BC_INST_SCALE || etype == BC_INST_LAST || - etype == BC_INST_IBASE || etype == BC_INST_OBASE) - { + if (etype == BC_INST_VAR || etype == BC_INST_ARRAY_ELEM + || etype == BC_INST_SCALE || etype == BC_INST_LAST + || etype == BC_INST_IBASE || etype == BC_INST_OBASE + ) { *prev = inst = BC_INST_INC_POST + (p->l.t.t != BC_LEX_OP_INC); bc_parse_push(p, inst); s = zbc_lex_next(&p->l); - } - else { + } else { *prev = inst = BC_INST_INC_PRE + (p->l.t.t != BC_LEX_OP_INC); *paren_expr = true; @@ -4339,8 +4321,7 @@ static BC_STATUS zbc_parse_funcdef(BcParse *p) dbg_lex_done("%s:%d done", __func__, __LINE__); RETURN_STATUS(s); - -err: + err: dbg_lex_done("%s:%d done (error)", __func__, __LINE__); free(name); RETURN_STATUS(s); @@ -4397,8 +4378,7 @@ static BC_STATUS zbc_parse_auto(BcParse *p) dbg_lex_done("%s:%d done", __func__, __LINE__); RETURN_STATUS(zbc_lex_next(&p->l)); - -err: + err: free(name); dbg_lex_done("%s:%d done (ERROR)", __func__, __LINE__); RETURN_STATUS(s); @@ -4561,23 +4541,16 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) for (; !G_interrupt && !s && !done && bc_parse_exprs(t); t = p->l.t.t) { switch (t) { - case BC_LEX_OP_INC: case BC_LEX_OP_DEC: - { s = zbc_parse_incdec(p, &prev, &paren_expr, &nexprs, flags); rprn = get_token = bin_last = false; break; - } - case BC_LEX_OP_MINUS: - { s = zbc_parse_minus(p, &prev, ops_bgn, rprn, &nexprs); rprn = get_token = false; bin_last = prev == BC_INST_MINUS; break; - } - case BC_LEX_OP_ASSIGN_POWER: case BC_LEX_OP_ASSIGN_MULTIPLY: case BC_LEX_OP_ASSIGN_DIVIDE: @@ -4585,18 +4558,16 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) case BC_LEX_OP_ASSIGN_PLUS: case BC_LEX_OP_ASSIGN_MINUS: case BC_LEX_OP_ASSIGN: - { - if (prev != BC_INST_VAR && prev != BC_INST_ARRAY_ELEM && - prev != BC_INST_SCALE && prev != BC_INST_IBASE && - prev != BC_INST_OBASE && prev != BC_INST_LAST) - { + if (prev != BC_INST_VAR && prev != BC_INST_ARRAY_ELEM + && prev != BC_INST_SCALE && prev != BC_INST_IBASE + && prev != BC_INST_OBASE && prev != BC_INST_LAST + ) { s = bc_error("bad assignment:" " left side must be variable" " or array element" ); // note: shared string break; } - } // Fallthrough. case BC_LEX_OP_POWER: case BC_LEX_OP_MULTIPLY: @@ -4612,74 +4583,53 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) case BC_LEX_OP_BOOL_NOT: case BC_LEX_OP_BOOL_OR: case BC_LEX_OP_BOOL_AND: - { if (((t == BC_LEX_OP_BOOL_NOT) != bin_last) || (t != BC_LEX_OP_BOOL_NOT && prev == BC_INST_BOOL_NOT) ) { return bc_error_bad_expression(); } - nrelops += t >= BC_LEX_OP_REL_EQ && t <= BC_LEX_OP_REL_GT; prev = BC_TOKEN_2_INST(t); bc_parse_operator(p, t, ops_bgn, &nexprs); s = zbc_lex_next(&p->l); rprn = get_token = false; bin_last = t != BC_LEX_OP_BOOL_NOT; - break; - } - case BC_LEX_LPAREN: - { if (BC_PARSE_LEAF(prev, rprn)) return bc_error_bad_expression(); ++nparens; paren_expr = rprn = bin_last = false; get_token = true; bc_vec_push(&p->ops, &t); - break; - } - case BC_LEX_RPAREN: - { if (bin_last || prev == BC_INST_BOOL_NOT) return bc_error_bad_expression(); - if (nparens == 0) { s = BC_STATUS_SUCCESS; done = true; get_token = false; break; } - else if (!paren_expr) { + if (!paren_expr) { dbg_lex_done("%s:%d done (returning EMPTY_EXP)", __func__, __LINE__); return BC_STATUS_PARSE_EMPTY_EXP; } - --nparens; paren_expr = rprn = true; get_token = bin_last = false; - s = zbc_parse_rightParen(p, ops_bgn, &nexprs); - break; - } - case BC_LEX_NAME: - { if (BC_PARSE_LEAF(prev, rprn)) return bc_error_bad_expression(); paren_expr = true; rprn = get_token = bin_last = false; s = zbc_parse_name(p, &prev, flags & ~BC_PARSE_NOCALL); ++nexprs; - break; - } - case BC_LEX_NUMBER: - { if (BC_PARSE_LEAF(prev, rprn)) return bc_error_bad_expression(); bc_parse_number(p); @@ -4687,58 +4637,40 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) prev = BC_INST_NUM; paren_expr = get_token = true; rprn = bin_last = false; - break; - } - case BC_LEX_KEY_IBASE: case BC_LEX_KEY_LAST: case BC_LEX_KEY_OBASE: - { if (BC_PARSE_LEAF(prev, rprn)) return bc_error_bad_expression(); prev = (char) (t - BC_LEX_KEY_IBASE + BC_INST_IBASE); bc_parse_push(p, (char) prev); - paren_expr = get_token = true; rprn = bin_last = false; ++nexprs; - break; - } - case BC_LEX_KEY_LENGTH: case BC_LEX_KEY_SQRT: - { if (BC_PARSE_LEAF(prev, rprn)) return bc_error_bad_expression(); s = zbc_parse_builtin(p, t, flags, &prev); paren_expr = true; rprn = get_token = bin_last = false; ++nexprs; - break; - } - case BC_LEX_KEY_READ: - { if (BC_PARSE_LEAF(prev, rprn)) return bc_error_bad_expression(); else if (flags & BC_PARSE_NOREAD) s = bc_error_nested_read_call(); else s = zbc_parse_read(p); - paren_expr = true; rprn = get_token = bin_last = false; ++nexprs; prev = BC_INST_READ; - break; - } - case BC_LEX_KEY_SCALE: - { if (BC_PARSE_LEAF(prev, rprn)) return bc_error_bad_expression(); s = zbc_parse_scale(p, &prev, flags); @@ -4746,15 +4678,10 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) rprn = get_token = bin_last = false; ++nexprs; prev = BC_INST_SCALE; - break; - } - default: - { s = bc_error_bad_token(); break; - } } if (!s && get_token) s = zbc_lex_next(&p->l); @@ -4764,7 +4691,6 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) if (G_interrupt) return BC_STATUS_FAILURE; // ^C: stop parsing while (p->ops.len > ops_bgn) { - top = BC_PARSE_TOP_OP(p); assign = top >= BC_LEX_OP_ASSIGN_POWER && top <= BC_LEX_OP_ASSIGN; @@ -4783,8 +4709,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) if (!(flags & BC_PARSE_REL) && nrelops) { s = bc_POSIX_does_not_allow("comparison operators outside if or loops"); IF_ERROR_RETURN_POSSIBLE(if (s) return s); - } - else if ((flags & BC_PARSE_REL) && nrelops > 1) { + } else if ((flags & BC_PARSE_REL) && nrelops > 1) { s = bc_POSIX_requires("exactly one comparison operator per condition"); IF_ERROR_RETURN_POSSIBLE(if (s) return s); } @@ -4871,8 +4796,7 @@ static BC_STATUS zdc_parse_cond(BcParse *p, uint8_t inst) s = zdc_parse_register(p); if (s) RETURN_STATUS(s); s = zbc_lex_next(&p->l); - } - else + } else bc_parse_push(p, BC_PARSE_STREND); RETURN_STATUS(s); @@ -5035,19 +4959,14 @@ static BcVec* bc_program_search(char *id, bool var) static BC_STATUS zbc_program_num(BcResult *r, BcNum **num, bool hex) { switch (r->t) { - case BC_RESULT_STR: case BC_RESULT_TEMP: case BC_RESULT_IBASE: case BC_RESULT_SCALE: case BC_RESULT_OBASE: - { *num = &r->d.n; break; - } - - case BC_RESULT_CONSTANT: - { + case BC_RESULT_CONSTANT: { BcStatus s; char **str = bc_vec_item(&G.prog.consts, r->d.id.idx); unsigned base_t; @@ -5066,14 +4985,11 @@ static BC_STATUS zbc_program_num(BcResult *r, BcNum **num, bool hex) *num = &r->d.n; r->t = BC_RESULT_TEMP; - break; } - case BC_RESULT_VAR: case BC_RESULT_ARRAY: - case BC_RESULT_ARRAY_ELEM: - { + case BC_RESULT_ARRAY_ELEM: { BcVec *v; v = bc_program_search(r->d.id.name, r->t == BC_RESULT_VAR); @@ -5082,24 +4998,16 @@ static BC_STATUS zbc_program_num(BcResult *r, BcNum **num, bool hex) v = bc_vec_top(v); if (v->len <= r->d.id.idx) bc_array_expand(v, r->d.id.idx + 1); *num = bc_vec_item(v, r->d.id.idx); - } - else + } else *num = bc_vec_top(v); - break; } - case BC_RESULT_LAST: - { *num = &G.prog.last; break; - } - case BC_RESULT_ONE: - { *num = &G.prog.one; break; - } } RETURN_STATUS(BC_STATUS_SUCCESS); @@ -5193,8 +5101,7 @@ static BC_STATUS zbc_program_op(char inst) bc_program_binOpRetire(&res); RETURN_STATUS(s); - -err: + err: bc_num_free(&res.d.n); RETURN_STATUS(s); } @@ -5244,8 +5151,7 @@ static BC_STATUS zbc_program_read(void) bc_vec_pushByte(&f->code, BC_INST_POP_EXEC); bc_vec_push(&G.prog.stack, &ip); - -exec_err: + exec_err: bc_parse_free(&parse); G.in_read = 0; G.prog.file = sv_file; @@ -5461,8 +5367,7 @@ static BC_STATUS zbc_num_printNum(BcNum *n, BcNum *base, size_t width, BcNumDigi s = zbc_num_mul(&frac_len, base, &frac_len, 0); if (s) goto err; } - -err: + err: bc_num_free(&frac_len); bc_num_free(&digit); bc_num_free(&fracp); @@ -5549,8 +5454,7 @@ static BC_STATUS zbc_program_print(char inst, size_t idx) if (BC_PROG_NUM(r, num)) { s = zbc_num_print(num, !pop); if (!s) bc_num_copy(&G.prog.last, num); - } - else { + } else { char *str; idx = (r->t == BC_RESULT_STR) ? r->d.id.idx : num->rdx; @@ -5564,8 +5468,7 @@ static BC_STATUS zbc_program_print(char inst, size_t idx) ++G.prog.nchars; if (c == '\n') G.prog.nchars = 0; } - } - else { + } else { bc_program_printString(str); if (inst == BC_INST_PRINT) bb_putchar('\n'); } @@ -5646,8 +5549,7 @@ static BC_STATUS zbc_program_logical(char inst) #define zbc_program_logical(...) (zbc_program_logical(__VA_ARGS__) COMMA_SUCCESS) #if ENABLE_DC -static BC_STATUS zbc_program_assignStr(BcResult *r, BcVec *v, - bool push) +static BC_STATUS zbc_program_assignStr(BcResult *r, BcVec *v, bool push) { BcNum n2; BcResult res; @@ -5704,8 +5606,7 @@ static BC_STATUS zbc_program_copyToVar(char *name, bool var) if (var) { bc_num_init_DEF_SIZE(&r.d.n); bc_num_copy(&r.d.n, n); - } - else { + } else { bc_array_init(&r.d.v, true); bc_array_copy(&r.d.v, (BcVec *) n); } @@ -5731,9 +5632,7 @@ static BC_STATUS zbc_program_assign(char inst) sc = left->t == BC_RESULT_SCALE; #if ENABLE_DC - if (right->t == BC_RESULT_STR) { - BcVec *v; if (left->t != BC_RESULT_VAR) @@ -5828,7 +5727,6 @@ static BC_STATUS bc_program_pushVar(char *code, size_t *bgn, BcNum *num = bc_vec_top(v); if (pop || copy) { - if (!BC_PROG_STACK(v, 2 - copy)) { free(name); RETURN_STATUS(bc_error_stack_has_too_few_elements()); @@ -5838,13 +5736,11 @@ static BC_STATUS bc_program_pushVar(char *code, size_t *bgn, name = NULL; if (!BC_PROG_STR(num)) { - r.t = BC_RESULT_TEMP; bc_num_init_DEF_SIZE(&r.d.n); bc_num_copy(&r.d.n, num); - } - else { + } else { r.t = BC_RESULT_STR; r.d.id.idx = num->rdx; } @@ -5860,8 +5756,7 @@ static BC_STATUS bc_program_pushVar(char *code, size_t *bgn, } #define zbc_program_pushVar(...) (bc_program_pushVar(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zbc_program_pushArray(char *code, size_t *bgn, - char inst) +static BC_STATUS zbc_program_pushArray(char *code, size_t *bgn, char inst) { BcStatus s = BC_STATUS_SUCCESS; BcResult r; @@ -5872,9 +5767,7 @@ static BC_STATUS zbc_program_pushArray(char *code, size_t *bgn, if (inst == BC_INST_ARRAY) { r.t = BC_RESULT_ARRAY; bc_vec_push(&G.prog.results, &r); - } - else { - + } else { BcResult *operand; unsigned long temp; @@ -5891,8 +5784,7 @@ static BC_STATUS zbc_program_pushArray(char *code, size_t *bgn, r.d.id.idx = (size_t) temp; bc_program_retire(&r, BC_RESULT_ARRAY_ELEM); } - -err: + err: if (s) free(r.d.id.name); RETURN_STATUS(s); } @@ -5976,8 +5868,7 @@ static BC_STATUS zbc_program_call(char *code, size_t *idx) if (a->idx) { bc_num_init_DEF_SIZE(¶m.n); bc_vec_push(v, ¶m.n); - } - else { + } else { bc_array_init(¶m.v, true); bc_vec_push(v, ¶m.v); } @@ -6011,8 +5902,7 @@ static BC_STATUS zbc_program_return(char inst) if (s) RETURN_STATUS(s); bc_num_init(&res.d.n, num->len); bc_num_copy(&res.d.n, num); - } - else { + } else { bc_num_init_DEF_SIZE(&res.d.n); //bc_num_zero(&res.d.n); - already is } @@ -6075,7 +5965,8 @@ static BC_STATUS zbc_program_builtin(char inst) bc_num_init_DEF_SIZE(&res.d.n); - if (inst == BC_INST_SQRT) s = zbc_num_sqrt(num, &res.d.n, G.prog.scale); + if (inst == BC_INST_SQRT) + s = zbc_num_sqrt(num, &res.d.n, G.prog.scale); #if ENABLE_BC else if (len != 0 && opnd->t == BC_RESULT_ARRAY) { bc_num_ulong2num(&res.d.n, (unsigned long) ((BcVec *) num)->len); @@ -6121,8 +6012,7 @@ static BC_STATUS zbc_program_divmod(void) bc_vec_push(&G.prog.results, &res); RETURN_STATUS(s); - -err: + err: bc_num_free(&res2.d.n); bc_num_free(&res.d.n); RETURN_STATUS(s); @@ -6148,12 +6038,10 @@ static BC_STATUS zbc_program_modexp(void) // Make sure that the values have their pointers updated, if necessary. if (r1->t == BC_RESULT_VAR || r1->t == BC_RESULT_ARRAY_ELEM) { - if (r1->t == r2->t) { s = zbc_program_num(r2, &n2, false); if (s) RETURN_STATUS(s); } - if (r1->t == r3->t) { s = zbc_program_num(r3, &n3, false); if (s) RETURN_STATUS(s); @@ -6168,8 +6056,7 @@ static BC_STATUS zbc_program_modexp(void) bc_program_binOpRetire(&res); RETURN_STATUS(s); - -err: + err: bc_num_free(&res.d.n); RETURN_STATUS(s); } @@ -6205,7 +6092,6 @@ static BC_STATUS zbc_program_asciify(void) if (s) RETURN_STATUS(s); if (BC_PROG_NUM(r, num)) { - bc_num_init_DEF_SIZE(&n); bc_num_copy(&n, num); bc_num_truncate(&n, n.rdx); @@ -6218,8 +6104,7 @@ static BC_STATUS zbc_program_asciify(void) c = (char) val; bc_num_free(&n); - } - else { + } else { idx = (r->t == BC_RESULT_STR) ? r->d.id.idx : num->rdx; str2 = *bc_program_str(idx); c = str2[0]; @@ -6239,10 +6124,8 @@ static BC_STATUS zbc_program_asciify(void) break; } } - free(str); - } - else + } else bc_vec_push(&G.prog.strs, &str); res.t = BC_RESULT_STR; @@ -6251,8 +6134,7 @@ static BC_STATUS zbc_program_asciify(void) bc_vec_push(&G.prog.results, &res); RETURN_STATUS(BC_STATUS_SUCCESS); - -num_err: + num_err: bc_num_free(&n); RETURN_STATUS(s); } @@ -6311,8 +6193,7 @@ static BC_STATUS zbc_program_nquit(void) } #define zbc_program_nquit(...) (zbc_program_nquit(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zbc_program_execStr(char *code, size_t *bgn, - bool cond) +static BC_STATUS zbc_program_execStr(char *code, size_t *bgn, bool cond) { BcStatus s = BC_STATUS_SUCCESS; BcResult *r; @@ -6402,12 +6283,11 @@ static BC_STATUS zbc_program_execStr(char *code, size_t *bgn, bc_vec_push(&G.prog.stack, &ip); RETURN_STATUS(BC_STATUS_SUCCESS); - -err: + err: bc_parse_free(&prs); f = bc_program_func(fidx); bc_vec_pop_all(&f->code); -exit: + exit: bc_vec_pop(&G.prog.results); RETURN_STATUS(s); } @@ -6448,7 +6328,6 @@ static void bc_program_addFunc(char *name, size_t *idx) *idx = entry_ptr->idx; if (!inserted) { - BcFunc *func = bc_program_func(entry_ptr->idx); // We need to reset these, so the function can be repopulated. @@ -6456,8 +6335,7 @@ static void bc_program_addFunc(char *name, size_t *idx) bc_vec_pop_all(&func->autos); bc_vec_pop_all(&func->code); bc_vec_pop_all(&func->labels); - } - else { + } else { bc_func_init(&f); bc_vec_push(&G.prog.fns, &f); } -- cgit v1.2.3-55-g6feb From 09fe0aaefac905287fc4b533714ec961ec8c6968 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 18 Dec 2018 16:32:25 +0100 Subject: bc: do not show -i in --help, it's a NOP (for now) Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 7ecddf014..0b891d88a 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -110,7 +110,7 @@ //See www.gnu.org/software/bc/manual/bc.html //usage:#define bc_trivial_usage -//usage: "[-sqliw] FILE..." +//usage: "[-sqlw] FILE..." //usage: //usage:#define bc_full_usage "\n" //usage: "\nArbitrary precision calculator" -- cgit v1.2.3-55-g6feb From d340143247f9b3aff486a2a6a4dc1e11ab8c8f86 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 18 Dec 2018 17:00:35 +0100 Subject: bc: get rid of G.prog.ob, G.prog.strmb function old new delta zbc_num_printNum 489 540 +51 zbc_program_asciify 426 473 +47 zbc_program_print 686 684 -2 zbc_program_exec 4008 3995 -13 zbc_program_assign 474 440 -34 bc_vm_init 739 663 -76 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/4 up/down: 98/-125) Total: -27 bytes text data bss dec hex filename 981404 485 7296 989185 f1801 busybox_old 981377 485 7296 989158 f17e6 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 49 ++++++++++++++++++++----------------------------- 1 file changed, 20 insertions(+), 29 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 0b891d88a..566808e92 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1355,14 +1355,6 @@ static void bc_num_one(BcNum *n) n->num[0] = 1; } -static void bc_num_ten(BcNum *n) -{ - bc_num_setToZero(n, 0); - n->len = 2; - n->num[0] = 0; - n->num[1] = 1; -} - // Note: this also sets BcNum to zero static void bc_num_init(BcNum *n, size_t req) { @@ -2251,6 +2243,7 @@ static void bc_num_parseBase(BcNum *n, const char *val, unsigned base_t) bc_num_init_DEF_SIZE(&temp); bc_num_init_DEF_SIZE(&mult); +//TODO: have BcNumSmall type, with static buffer bc_num_init_DEF_SIZE(&base); bc_num_ulong2num(&base, base_t); @@ -5314,10 +5307,11 @@ static void bc_num_printDecimal(BcNum *n) bc_num_printHex((size_t) n->num[i], 1, i == rdx); } -static BC_STATUS zbc_num_printNum(BcNum *n, BcNum *base, size_t width, BcNumDigitOp print) +static BC_STATUS zbc_num_printNum(BcNum *n, unsigned base_t, size_t width, BcNumDigitOp print) { BcStatus s; BcVec stack; + BcNum base; BcNum intp, fracp, digit, frac_len; unsigned long dig, *ptr; size_t i; @@ -5335,13 +5329,16 @@ static BC_STATUS zbc_num_printNum(BcNum *n, BcNum *base, size_t width, BcNumDigi bc_num_init(&frac_len, BC_NUM_INT(n)); bc_num_copy(&intp, n); bc_num_one(&frac_len); +//TODO: have BcNumSmall type, with static buffer + bc_num_init_DEF_SIZE(&base); + bc_num_ulong2num(&base, base_t); bc_num_truncate(&intp, intp.rdx); s = zbc_num_sub(n, &intp, &fracp, 0); if (s) goto err; while (intp.len != 0) { - s = zbc_num_divmod(&intp, base, &intp, &digit, 0); + s = zbc_num_divmod(&intp, &base, &intp, &digit, 0); if (s) goto err; s = zbc_num_ulong(&digit, &dig); if (s) goto err; @@ -5356,7 +5353,7 @@ static BC_STATUS zbc_num_printNum(BcNum *n, BcNum *base, size_t width, BcNumDigi if (!n->rdx) goto err; for (radix = true; frac_len.len <= n->rdx; radix = false) { - s = zbc_num_mul(&fracp, base, &fracp, n->rdx); + s = zbc_num_mul(&fracp, &base, &fracp, n->rdx); if (s) goto err; s = zbc_num_ulong(&fracp, &dig); if (s) goto err; @@ -5364,10 +5361,11 @@ static BC_STATUS zbc_num_printNum(BcNum *n, BcNum *base, size_t width, BcNumDigi s = zbc_num_sub(&fracp, &intp, &fracp, 0); if (s) goto err; print(dig, width, radix); - s = zbc_num_mul(&frac_len, base, &frac_len, 0); + s = zbc_num_mul(&frac_len, &base, &frac_len, 0); if (s) goto err; } err: + bc_num_free(&base); bc_num_free(&frac_len); bc_num_free(&digit); bc_num_free(&fracp); @@ -5406,7 +5404,7 @@ static BC_STATUS zbc_num_printBase(BcNum *n) print = bc_num_printDigits; } - s = zbc_num_printNum(n, &G.prog.ob, width, print); + s = zbc_num_printNum(n, G.prog.ob_t, width, print); n->neg = neg; RETURN_STATUS(s); @@ -5692,8 +5690,6 @@ static BC_STATUS zbc_program_assign(char inst) if (val > max) RETURN_STATUS(bc_error(msg[s])); - if (!sc && !ib) - bc_num_copy(&G.prog.ob, l); *ptr = (size_t) val; s = BC_STATUS_SUCCESS; @@ -6092,11 +6088,18 @@ static BC_STATUS zbc_program_asciify(void) if (s) RETURN_STATUS(s); if (BC_PROG_NUM(r, num)) { + BcNum strmb; + bc_num_init_DEF_SIZE(&n); bc_num_copy(&n, num); bc_num_truncate(&n, n.rdx); - s = zbc_num_mod(&n, &G.prog.strmb, &n, 0); +//TODO: have BcNumSmall type, with static buffer + bc_num_init_DEF_SIZE(&strmb); + bc_num_ulong2num(&strmb, 0x100); + s = zbc_num_mod(&n, &strmb, &n, 0); + bc_num_free(&strmb); + if (s) goto num_err; s = zbc_num_ulong(&n, &val); if (s) goto num_err; @@ -6156,7 +6159,7 @@ static BC_STATUS zbc_program_printStream(void) if (s) RETURN_STATUS(s); if (BC_PROG_NUM(r, n)) { - s = zbc_num_printNum(n, &G.prog.strmb, 1, bc_num_printChar); + s = zbc_num_printNum(n, 0x100, 1, bc_num_printChar); } else { idx = (r->t == BC_RESULT_STR) ? r->d.id.idx : n->rdx; str = *bc_program_str(idx); @@ -6945,10 +6948,6 @@ static BC_STATUS zbc_vm_exec(void) #if ENABLE_FEATURE_CLEAN_UP static void bc_program_free(void) { - bc_num_free(&G.prog.ob); -# if ENABLE_DC - bc_num_free(&G.prog.strmb); -# endif bc_vec_free(&G.prog.fns); bc_vec_free(&G.prog.fn_map); bc_vec_free(&G.prog.vars); @@ -6984,16 +6983,8 @@ static void bc_program_init(void) // G.prog.nchars = G.prog.scale = 0; - already is G.prog.ib_t = 10; - - bc_num_init_DEF_SIZE(&G.prog.ob); - bc_num_ten(&G.prog.ob); G.prog.ob_t = 10; -#if ENABLE_DC - bc_num_init_DEF_SIZE(&G.prog.strmb); - bc_num_ulong2num(&G.prog.strmb, UCHAR_MAX + 1); -#endif - bc_num_init_DEF_SIZE(&G.prog.last); //bc_num_zero(&G.prog.last); - already is -- cgit v1.2.3-55-g6feb From 7b30bc0222fa5f4e539a36a15ceb7b6e413cafd2 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 18 Dec 2018 17:14:34 +0100 Subject: bc: shrink bc_program_pushVar() function old new delta bc_program_pushVar 203 198 -5 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 566808e92..40bb29942 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -5718,31 +5718,25 @@ static BC_STATUS bc_program_pushVar(char *code, size_t *bgn, r.d.id.name = name; #if ENABLE_DC - { + if (pop || copy) { BcVec *v = bc_program_search(name, true); BcNum *num = bc_vec_top(v); - if (pop || copy) { - if (!BC_PROG_STACK(v, 2 - copy)) { - free(name); - RETURN_STATUS(bc_error_stack_has_too_few_elements()); - } - - free(name); - name = NULL; - - if (!BC_PROG_STR(num)) { - r.t = BC_RESULT_TEMP; - - bc_num_init_DEF_SIZE(&r.d.n); - bc_num_copy(&r.d.n, num); - } else { - r.t = BC_RESULT_STR; - r.d.id.idx = num->rdx; - } + free(name); + if (!BC_PROG_STACK(v, 2 - copy)) { + RETURN_STATUS(bc_error_stack_has_too_few_elements()); + } - if (!copy) bc_vec_pop(v); + if (!BC_PROG_STR(num)) { + r.t = BC_RESULT_TEMP; + bc_num_init_DEF_SIZE(&r.d.n); + bc_num_copy(&r.d.n, num); + } else { + r.t = BC_RESULT_STR; + r.d.id.idx = num->rdx; } + + if (!copy) bc_vec_pop(v); } #endif // ENABLE_DC -- cgit v1.2.3-55-g6feb From 694d2982e5cc73edfc870e26647e85a558d71bbe Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 18 Dec 2018 19:17:11 +0100 Subject: bc: code shrink function old new delta bc_program_name 67 63 -4 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-4) Total: -4 bytes text data bss dec hex filename 981372 485 7296 989153 f17e1 busybox_old 981368 485 7296 989149 f17dd busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 40bb29942..eba8aa272 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -5174,17 +5174,19 @@ static size_t bc_program_index(char *code, size_t *bgn) static char *bc_program_name(char *code, size_t *bgn) { size_t i; - char *s, *str = code + *bgn, *ptr = strchr(str, BC_PARSE_STREND); + char *s; - s = xmalloc(ptr - str + 1); + code += *bgn; + s = xmalloc(strchr(code, BC_PARSE_STREND) - code + 1); i = 0; for (;;) { - char c = code[(*bgn)++]; - if (c == '\0' || c == BC_PARSE_STREND) + char c = *code++; + if (c == BC_PARSE_STREND) break; s[i++] = c; } s[i] = '\0'; + *bgn += i + 1; return s; } -- cgit v1.2.3-55-g6feb From 30a8e0c2f9006db75840724ce89883595dfc7379 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 18 Dec 2018 19:20:04 +0100 Subject: bc: code shrink function old new delta zbc_program_print 684 680 -4 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-4) Total: -4 bytes text data bss dec hex filename 981368 485 7296 989149 f17dd busybox_old 981364 485 7296 989145 f17d9 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index eba8aa272..e62ca0f69 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -5290,7 +5290,7 @@ static FAST_FUNC void bc_num_printHex(size_t num, size_t width, bool radix) if (radix) { bc_num_printNewline(); bb_putchar('.'); - G.prog.nchars += 1; + G.prog.nchars++; } bc_num_printNewline(); @@ -5302,8 +5302,10 @@ static void bc_num_printDecimal(BcNum *n) { size_t i, rdx = n->rdx - 1; - if (n->neg) bb_putchar('-'); - G.prog.nchars += n->neg; + if (n->neg) { + bb_putchar('-'); + G.prog.nchars++; + } for (i = n->len - 1; i < n->len; --i) bc_num_printHex((size_t) n->num[i], 1, i == rdx); -- cgit v1.2.3-55-g6feb From d6e24bd795d5d1d00c2414efe2e5d9e1152c5f5b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 18 Dec 2018 20:10:48 +0100 Subject: bc: simplify bc_array_expand() Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index e62ca0f69..7ddae341f 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -2547,17 +2547,19 @@ static void bc_array_init(BcVec *a, bool nums) static void bc_array_expand(BcVec *a, size_t len) { - BcResultData data; - - if (a->size == sizeof(BcNum) && a->dtor == bc_num_free) { + if (a->dtor == bc_num_free + // && a->size == sizeof(BcNum) - always true + ) { + BcNum n; while (len > a->len) { - bc_num_init_DEF_SIZE(&data.n); - bc_vec_push(a, &data.n); + bc_num_init_DEF_SIZE(&n); + bc_vec_push(a, &n); } } else { + BcVec v; while (len > a->len) { - bc_array_init(&data.v, true); - bc_vec_push(a, &data.v); + bc_array_init(&v, true); + bc_vec_push(a, &v); } } } -- cgit v1.2.3-55-g6feb From b80d7aad1b001479942c314690e6979d8290bdfb Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 19 Dec 2018 12:35:27 +0100 Subject: bc: in execution loop, reload stack only after insts which can change it Only these functions affect G.prog.exestack: zbc_program_read zbc_program_call zbc_program_return zbc_program_nquit zbc_program_execStr function old new delta zbc_program_exec 3995 4093 +98 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/0 up/down: 98/0) Total: 98 bytes text data bss dec hex filename 981364 485 7296 989145 f17d9 busybox_old 981462 485 7296 989243 f183b busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 77 +++++++++++++++++++++++++++++++++------------------------- 1 file changed, 44 insertions(+), 33 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 7ddae341f..92bf1df57 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -167,8 +167,9 @@ # include "dc.c" #else -#define DEBUG_LEXER 0 -#define DEBUG_EXEC 0 +#define DEBUG_LEXER 0 +#define DEBUG_COMPILE 0 +#define DEBUG_EXEC 0 #if DEBUG_LEXER static uint8_t lex_indent; @@ -193,6 +194,12 @@ static uint8_t lex_indent; # define dbg_lex_done(...) ((void)0) #endif +#if DEBUG_COMPILE +# define dbg_compile(...) bb_error_msg(__VA_ARGS__) +#else +# define dbg_compile(...) ((void)0) +#endif + #if DEBUG_EXEC # define dbg_exec(...) bb_error_msg(__VA_ARGS__) #else @@ -683,7 +690,7 @@ typedef struct BcProgram { #endif BcVec results; - BcVec stack; + BcVec exestack; BcVec fns; BcVec fn_map; @@ -3448,7 +3455,7 @@ static void bc_parse_addFunc(BcParse *p, char *name, size_t *idx) static void bc_parse_push(BcParse *p, char i) { - dbg_lex("%s:%d pushing opcode %d", __func__, __LINE__, i); + dbg_compile("%s:%d pushing bytecode %zd:%d", __func__, __LINE__, p->func->code.len, i); bc_vec_pushByte(&p->func->code, i); } @@ -3537,11 +3544,11 @@ static void bc_program_reset(void) BcFunc *f; BcInstPtr *ip; - bc_vec_npop(&G.prog.stack, G.prog.stack.len - 1); + bc_vec_npop(&G.prog.exestack, G.prog.exestack.len - 1); bc_vec_pop_all(&G.prog.results); f = bc_program_func(0); - ip = bc_vec_top(&G.prog.stack); + ip = bc_vec_top(&G.prog.exestack); ip->idx = f->code.len; } @@ -5145,7 +5152,7 @@ static BC_STATUS zbc_program_read(void) f = bc_program_func(BC_PROG_READ); bc_vec_pushByte(&f->code, BC_INST_POP_EXEC); - bc_vec_push(&G.prog.stack, &ip); + bc_vec_push(&G.prog.exestack, &ip); exec_err: bc_parse_free(&parse); G.in_read = 0; @@ -5824,12 +5831,13 @@ static BC_STATUS zbc_program_incdec(char inst) static BC_STATUS zbc_program_call(char *code, size_t *idx) { BcInstPtr ip; - size_t i, nparams = bc_program_index(code, idx); + size_t i, nparams; BcFunc *func; BcId *a; BcResultData param; BcResult *arg; + nparams = bc_program_index(code, idx); ip.idx = 0; ip.func = bc_program_index(code, idx); func = bc_program_func(ip.func); @@ -5870,7 +5878,7 @@ static BC_STATUS zbc_program_call(char *code, size_t *idx) } } - bc_vec_push(&G.prog.stack, &ip); + bc_vec_push(&G.prog.exestack, &ip); RETURN_STATUS(BC_STATUS_SUCCESS); } @@ -5881,7 +5889,7 @@ static BC_STATUS zbc_program_return(char inst) BcResult res; BcFunc *f; size_t i; - BcInstPtr *ip = bc_vec_top(&G.prog.stack); + BcInstPtr *ip = bc_vec_top(&G.prog.exestack); if (!BC_PROG_STACK(&G.prog.results, ip->len + inst == BC_INST_RET)) RETURN_STATUS(bc_error_stack_has_too_few_elements()); @@ -5914,7 +5922,7 @@ static BC_STATUS zbc_program_return(char inst) bc_vec_npop(&G.prog.results, G.prog.results.len - ip->len); bc_vec_push(&G.prog.results, &res); - bc_vec_pop(&G.prog.stack); + bc_vec_pop(&G.prog.exestack); RETURN_STATUS(BC_STATUS_SUCCESS); } @@ -6184,13 +6192,13 @@ static BC_STATUS zbc_program_nquit(void) bc_vec_pop(&G.prog.results); - if (G.prog.stack.len < val) + if (G.prog.exestack.len < val) RETURN_STATUS(bc_error_stack_has_too_few_elements()); - if (G.prog.stack.len == val) { + if (G.prog.exestack.len == val) { QUIT_OR_RETURN_TO_MAIN; } - bc_vec_npop(&G.prog.stack, val); + bc_vec_npop(&G.prog.exestack, val); RETURN_STATUS(s); } @@ -6283,7 +6291,7 @@ static BC_STATUS zbc_program_execStr(char *code, size_t *bgn, bool cond) ip.func = fidx; bc_vec_pop(&G.prog.results); - bc_vec_push(&G.prog.stack, &ip); + bc_vec_push(&G.prog.exestack, &ip); RETURN_STATUS(BC_STATUS_SUCCESS); err: @@ -6348,15 +6356,16 @@ static BC_STATUS zbc_program_exec(void) { BcResult r, *ptr; BcNum *num; - BcInstPtr *ip = bc_vec_top(&G.prog.stack); + BcInstPtr *ip = bc_vec_top(&G.prog.exestack); BcFunc *func = bc_program_func(ip->func); char *code = func->code.v; + dbg_exec("func:%zd bytes:%zd ip:%zd", ip->func, func->code.len, ip->idx); while (ip->idx < func->code.len) { BcStatus s = BC_STATUS_SUCCESS; - char inst = code[(ip->idx)++]; + char inst = code[ip->idx++]; - dbg_exec("inst:%d", inst); + dbg_exec("inst at %zd:%d", ip->idx - 1, inst); switch (inst) { #if ENABLE_BC case BC_INST_JUMP_ZERO: { @@ -6382,7 +6391,7 @@ static BC_STATUS zbc_program_exec(void) case BC_INST_CALL: dbg_exec("BC_INST_CALL:"); s = zbc_program_call(code, &ip->idx); - break; + goto read_updated_ip; case BC_INST_INC_PRE: case BC_INST_DEC_PRE: case BC_INST_INC_POST: @@ -6398,7 +6407,7 @@ static BC_STATUS zbc_program_exec(void) case BC_INST_RET0: dbg_exec("BC_INST_RET[0]:"); s = zbc_program_return(inst); - break; + goto read_updated_ip; case BC_INST_BOOL_OR: case BC_INST_BOOL_AND: #endif // ENABLE_BC @@ -6414,7 +6423,7 @@ static BC_STATUS zbc_program_exec(void) case BC_INST_READ: dbg_exec("BC_INST_READ:"); s = zbc_program_read(); - break; + goto read_updated_ip; case BC_INST_VAR: dbg_exec("BC_INST_VAR:"); s = zbc_program_pushVar(code, &ip->idx, false, false); @@ -6454,7 +6463,7 @@ static BC_STATUS zbc_program_exec(void) break; case BC_INST_POP_EXEC: dbg_exec("BC_INST_POP_EXEC:"); - bc_vec_pop(&G.prog.stack); + bc_vec_pop(&G.prog.exestack); break; case BC_INST_PRINT: case BC_INST_PRINT_POP: @@ -6513,7 +6522,7 @@ static BC_STATUS zbc_program_exec(void) case BC_INST_EXECUTE: case BC_INST_EXEC_COND: s = zbc_program_execStr(code, &ip->idx, inst == BC_INST_EXEC_COND); - break; + goto read_updated_ip; case BC_INST_PRINT_STACK: { size_t idx; for (idx = 0; idx < G.prog.results.len; ++idx) { @@ -6566,14 +6575,20 @@ static BC_STATUS zbc_program_exec(void) } case BC_INST_QUIT: dbg_exec("BC_INST_NEG:"); - if (G.prog.stack.len <= 2) + if (G.prog.exestack.len <= 2) QUIT_OR_RETURN_TO_MAIN; - bc_vec_npop(&G.prog.stack, 2); + bc_vec_npop(&G.prog.exestack, 2); break; case BC_INST_NQUIT: s = zbc_program_nquit(); - break; + //goto read_updated_ip; - just fall through to it #endif // ENABLE_DC + read_updated_ip: + // Instruction stack has changed, read new pointers + ip = bc_vec_top(&G.prog.exestack); + func = bc_program_func(ip->func); + code = func->code.v; + dbg_exec("func:%zd bytes:%zd ip:%zd", ip->func, func->code.len, ip->idx); } if (s || G_interrupt) { @@ -6583,10 +6598,6 @@ static BC_STATUS zbc_program_exec(void) fflush_and_check(); - // If the stack has changed, pointers may be invalid. - ip = bc_vec_top(&G.prog.stack); - func = bc_program_func(ip->func); - code = func->code.v; } RETURN_STATUS(BC_STATUS_SUCCESS); @@ -6957,7 +6968,7 @@ static void bc_program_free(void) bc_vec_free(&G.prog.strs); bc_vec_free(&G.prog.consts); bc_vec_free(&G.prog.results); - bc_vec_free(&G.prog.stack); + bc_vec_free(&G.prog.exestack); bc_num_free(&G.prog.last); bc_num_free(&G.prog.zero); bc_num_free(&G.prog.one); @@ -7009,8 +7020,8 @@ static void bc_program_init(void) bc_vec_init(&G.prog.strs, sizeof(char *), bc_string_free); bc_vec_init(&G.prog.consts, sizeof(char *), bc_string_free); bc_vec_init(&G.prog.results, sizeof(BcResult), bc_result_free); - bc_vec_init(&G.prog.stack, sizeof(BcInstPtr), NULL); - bc_vec_push(&G.prog.stack, &ip); + bc_vec_init(&G.prog.exestack, sizeof(BcInstPtr), NULL); + bc_vec_push(&G.prog.exestack, &ip); bc_char_vec_init(&G.input_buffer); } -- cgit v1.2.3-55-g6feb From 4796a1d5375aac790564a38289d5b238a81e8efb Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 19 Dec 2018 12:47:45 +0100 Subject: bc: delete G.prog.strmb for real Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 36 +++++++++++++++--------------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 92bf1df57..8ddedf337 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -362,15 +362,13 @@ typedef enum BcResultType { BC_RESULT_STR, - BC_RESULT_IBASE, - BC_RESULT_SCALE, - BC_RESULT_LAST, - - // These are between to calculate ibase, obase, and last from instructions. + //code uses "inst - BC_INST_IBASE + BC_RESULT_IBASE" construct, + BC_RESULT_IBASE, // relative order should match for: BC_INST_IBASE + BC_RESULT_SCALE, // relative order should match for: BC_INST_SCALE + BC_RESULT_LAST, // relative order should match for: BC_INST_LAST BC_RESULT_CONSTANT, BC_RESULT_ONE, - - BC_RESULT_OBASE, + BC_RESULT_OBASE, // relative order should match for: BC_INST_OBASE } BcResultType; typedef union BcResultData { @@ -485,12 +483,13 @@ typedef enum BcLexType { BC_LEX_ASCIIFY, BC_LEX_PRINT_STREAM, - BC_LEX_STORE_IBASE, - BC_LEX_STORE_SCALE, + // code uses "t - BC_LEX_STORE_IBASE + BC_INST_IBASE" construct, + BC_LEX_STORE_IBASE, // relative order should match for: BC_INST_IBASE + BC_LEX_STORE_SCALE, // relative order should match for: BC_INST_SCALE BC_LEX_LOAD, BC_LEX_LOAD_POP, BC_LEX_STORE_PUSH, - BC_LEX_STORE_OBASE, + BC_LEX_STORE_OBASE, // relative order should match for: BC_INST_OBASE BC_LEX_PRINT_POP, BC_LEX_NQUIT, BC_LEX_SCALE_FACTOR, @@ -641,7 +640,6 @@ dc_parse_insts[] = { }; #endif // ENABLE_DC - typedef struct BcLex { const char *buf; size_t i; @@ -655,13 +653,13 @@ typedef struct BcLex { } t; } BcLex; -#define BC_PARSE_STREND ((char) UCHAR_MAX) +#define BC_PARSE_STREND (0xff) -#define BC_PARSE_REL (1 << 0) -#define BC_PARSE_PRINT (1 << 1) -#define BC_PARSE_NOCALL (1 << 2) -#define BC_PARSE_NOREAD (1 << 3) -#define BC_PARSE_ARRAY (1 << 4) +#define BC_PARSE_REL (1 << 0) +#define BC_PARSE_PRINT (1 << 1) +#define BC_PARSE_NOCALL (1 << 2) +#define BC_PARSE_NOREAD (1 << 3) +#define BC_PARSE_ARRAY (1 << 4) typedef struct BcParse { BcLex l; @@ -685,10 +683,6 @@ typedef struct BcProgram { size_t ob_t; BcNum ob; -#if ENABLE_DC - BcNum strmb; -#endif - BcVec results; BcVec exestack; -- cgit v1.2.3-55-g6feb From e3d3d2067dd535224e7a6f713107a38c3c7e18cd Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 19 Dec 2018 13:19:44 +0100 Subject: bc: remove redundant strdup+free in zbc_parse_call() function old new delta zbc_parse_name 527 482 -45 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-45) Total: -45 bytes text data bss dec hex filename 981541 485 7296 989322 f188a busybox_old 981486 485 7296 989267 f1853 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 8ddedf337..afc09a30b 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1210,7 +1210,7 @@ static size_t bc_map_find(const BcVec *v, const void *ptr) if (result == 0) return mid; - else if (result < 0) + if (result < 0) high = mid; else low = mid + 1; @@ -3441,6 +3441,7 @@ static BC_STATUS zdc_lex_token(BcLex *l) static void bc_program_addFunc(char *name, size_t *idx); +// Note: takes ownership of 'name' (must be malloced) static void bc_parse_addFunc(BcParse *p, char *name, size_t *idx) { bc_program_addFunc(name, idx); @@ -3494,7 +3495,7 @@ static void bc_parse_pushJUMP_ZERO(BcParse *p, size_t idx) bc_parse_pushIndex(p, idx); } -static void bc_parse_number(BcParse *p) +static void bc_parse_pushNUM(BcParse *p) { char *num = xstrdup(p->l.t.v.v); size_t idx = G.prog.consts.len; @@ -3719,6 +3720,7 @@ static BC_STATUS zbc_parse_params(BcParse *p, uint8_t flags) } #define zbc_parse_params(...) (zbc_parse_params(__VA_ARGS__) COMMA_SUCCESS) +// Note: takes ownership of 'name' (must be malloced) static BC_STATUS zbc_parse_call(BcParse *p, char *name, uint8_t flags) { BcStatus s; @@ -3738,10 +3740,9 @@ static BC_STATUS zbc_parse_call(BcParse *p, char *name, uint8_t flags) idx = bc_map_index(&G.prog.fn_map, &entry); if (idx == BC_VEC_INVALID_IDX) { - name = xstrdup(entry.name); + // No such function exist, create an empty one bc_parse_addFunc(p, name, &idx); idx = bc_map_index(&G.prog.fn_map, &entry); - free(entry.name); } else free(name); @@ -4628,7 +4629,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) case BC_LEX_NUMBER: if (BC_PARSE_LEAF(prev, rprn)) return bc_error_bad_expression(); - bc_parse_number(p); + bc_parse_pushNUM(p); nexprs++; prev = BC_INST_NUM; paren_expr = get_token = true; @@ -4829,7 +4830,7 @@ static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t, uint8_t flags) if (p->l.t.t != BC_LEX_NUMBER) RETURN_STATUS(bc_error_bad_token()); } - bc_parse_number(p); + bc_parse_pushNUM(p); if (t == BC_LEX_NEG) bc_parse_push(p, BC_INST_NEG); get_token = true; break; @@ -4964,15 +4965,15 @@ static BC_STATUS zbc_program_num(BcResult *r, BcNum **num, bool hex) break; case BC_RESULT_CONSTANT: { BcStatus s; - char **str = bc_vec_item(&G.prog.consts, r->d.id.idx); + char *str = *(char**)bc_vec_item(&G.prog.consts, r->d.id.idx); unsigned base_t; - size_t len = strlen(*str); + size_t len = strlen(str); bc_num_init(&r->d.n, len); hex = hex && len == 1; base_t = hex ? 16 : G.prog.ib_t; - s = zbc_num_parse(&r->d.n, *str, base_t); + s = zbc_num_parse(&r->d.n, str, base_t); if (s) { bc_num_free(&r->d.n); @@ -6317,6 +6318,7 @@ static void bc_program_pushGlobal(char inst) bc_vec_push(&G.prog.results, &res); } +// Note: takes ownership of 'name' (must be malloced) static void bc_program_addFunc(char *name, size_t *idx) { BcId entry, *entry_ptr; -- cgit v1.2.3-55-g6feb From 5aa54830bf31ccd85d4ffa9be36a56adc64589f9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 19 Dec 2018 13:55:53 +0100 Subject: bc: rename a few functions function old new delta bc_map_find_ge - 71 +71 bc_map_find_exact - 50 +50 bc_map_index 50 - -50 bc_map_find 71 - -71 ------------------------------------------------------------------------------ (add/remove: 2/2 grow/shrink: 0/0 up/down: 121/-121) Total: 0 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index afc09a30b..dde5c354e 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1199,7 +1199,7 @@ static FAST_FUNC void bc_id_free(void *id) free(((BcId *) id)->name); } -static size_t bc_map_find(const BcVec *v, const void *ptr) +static size_t bc_map_find_ge(const BcVec *v, const void *ptr) { size_t low = 0, high = v->len; @@ -1221,7 +1221,7 @@ static size_t bc_map_find(const BcVec *v, const void *ptr) static int bc_map_insert(BcVec *v, const void *ptr, size_t *i) { - size_t n = *i = bc_map_find(v, ptr); + size_t n = *i = bc_map_find_ge(v, ptr); if (n == v->len) bc_vec_push(v, ptr); @@ -1233,9 +1233,9 @@ static int bc_map_insert(BcVec *v, const void *ptr, size_t *i) } #if ENABLE_BC -static size_t bc_map_index(const BcVec *v, const void *ptr) +static size_t bc_map_find_exact(const BcVec *v, const void *ptr) { - size_t i = bc_map_find(v, ptr); + size_t i = bc_map_find_ge(v, ptr); if (i >= v->len) return BC_VEC_INVALID_IDX; return bc_id_cmp(ptr, bc_vec_item(v, i)) ? BC_VEC_INVALID_IDX : i; } @@ -3737,12 +3737,12 @@ static BC_STATUS zbc_parse_call(BcParse *p, char *name, uint8_t flags) goto err; } - idx = bc_map_index(&G.prog.fn_map, &entry); + idx = bc_map_find_exact(&G.prog.fn_map, &entry); if (idx == BC_VEC_INVALID_IDX) { - // No such function exist, create an empty one + // No such function exists, create an empty one bc_parse_addFunc(p, name, &idx); - idx = bc_map_index(&G.prog.fn_map, &entry); + idx = bc_map_find_exact(&G.prog.fn_map, &entry); } else free(name); -- cgit v1.2.3-55-g6feb From 085b4202209c7cf9fe12b8823c939e8e028ed775 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 19 Dec 2018 14:02:59 +0100 Subject: bc: "reload stack only after insts" change missed a few places Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index dde5c354e..ec7a0838b 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -6460,7 +6460,7 @@ static BC_STATUS zbc_program_exec(void) case BC_INST_POP_EXEC: dbg_exec("BC_INST_POP_EXEC:"); bc_vec_pop(&G.prog.exestack); - break; + goto read_updated_ip; case BC_INST_PRINT: case BC_INST_PRINT_POP: case BC_INST_PRINT_STR: @@ -6574,7 +6574,7 @@ static BC_STATUS zbc_program_exec(void) if (G.prog.exestack.len <= 2) QUIT_OR_RETURN_TO_MAIN; bc_vec_npop(&G.prog.exestack, 2); - break; + goto read_updated_ip; case BC_INST_NQUIT: s = zbc_program_nquit(); //goto read_updated_ip; - just fall through to it -- cgit v1.2.3-55-g6feb From 684d441f5c8c4eac5962ad0e0b59e8999284fe6a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 19 Dec 2018 14:57:23 +0100 Subject: bc: make bc_program_addFunc() return new idx, untangle &p->fidx interaction In: bc_program_addFunc(name, idx); p->func = bc_program_func(p->fidx); in some cases p->fidx was updated by _first_ statement - because passed idx was pointing at it. This was very obscure. function old new delta zdc_parse_expr 653 658 +5 bc_program_addFunc 204 201 -3 zbc_vm_process 594 586 -8 bc_vm_init 663 655 -8 zbc_parse_name 482 472 -10 bc_parse_addFunc 25 - -25 zbc_program_asciify 473 447 -26 ------------------------------------------------------------------------------ (add/remove: 0/1 grow/shrink: 1/5 up/down: 5/-80) Total: -75 bytes text data bss dec hex filename 981482 485 7296 989263 f184f busybox_old 981401 485 7296 989182 f17fe busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 90 ++++++++++++++++++++++++++++------------------------------ 1 file changed, 43 insertions(+), 47 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index ec7a0838b..d03d38aa9 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -3439,15 +3439,6 @@ static BC_STATUS zdc_lex_token(BcLex *l) } #endif // ENABLE_DC -static void bc_program_addFunc(char *name, size_t *idx); - -// Note: takes ownership of 'name' (must be malloced) -static void bc_parse_addFunc(BcParse *p, char *name, size_t *idx) -{ - bc_program_addFunc(name, idx); - p->func = bc_program_func(p->fidx); -} - static void bc_parse_push(BcParse *p, char i) { dbg_compile("%s:%d pushing bytecode %zd:%d", __func__, __LINE__, p->func->code.len, i); @@ -3720,6 +3711,39 @@ static BC_STATUS zbc_parse_params(BcParse *p, uint8_t flags) } #define zbc_parse_params(...) (zbc_parse_params(__VA_ARGS__) COMMA_SUCCESS) +// Note: takes ownership of 'name' (must be malloced) +static size_t bc_program_addFunc(char *name) +{ + size_t idx; + BcId entry, *entry_ptr; + BcFunc f; + int inserted; + + entry.name = name; + entry.idx = G.prog.fns.len; + + inserted = bc_map_insert(&G.prog.fn_map, &entry, &idx); + if (!inserted) free(name); + + entry_ptr = bc_vec_item(&G.prog.fn_map, idx); + idx = entry_ptr->idx; + + if (!inserted) { + BcFunc *func = bc_program_func(entry_ptr->idx); + + // We need to reset these, so the function can be repopulated. + func->nparams = 0; + bc_vec_pop_all(&func->autos); + bc_vec_pop_all(&func->code); + bc_vec_pop_all(&func->labels); + } else { + bc_func_init(&f); + bc_vec_push(&G.prog.fns, &f); + } + + return idx; +} + // Note: takes ownership of 'name' (must be malloced) static BC_STATUS zbc_parse_call(BcParse *p, char *name, uint8_t flags) { @@ -3741,7 +3765,7 @@ static BC_STATUS zbc_parse_call(BcParse *p, char *name, uint8_t flags) if (idx == BC_VEC_INVALID_IDX) { // No such function exists, create an empty one - bc_parse_addFunc(p, name, &idx); + bc_program_addFunc(name); idx = bc_map_find_exact(&G.prog.fn_map, &entry); } else free(name); @@ -4249,7 +4273,8 @@ static BC_STATUS zbc_parse_funcdef(BcParse *p) RETURN_STATUS(bc_error("bad function definition")); name = xstrdup(p->l.t.v.v); - bc_parse_addFunc(p, name, &p->fidx); + p->fidx = bc_program_addFunc(name); + p->func = bc_program_func(p->fidx); s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); @@ -4741,7 +4766,7 @@ static BC_STATUS zdc_parse_register(BcParse *p) static BC_STATUS zdc_parse_string(BcParse *p) { char *str, *name; - size_t idx, len = G.prog.strs.len; + size_t len = G.prog.strs.len; //why pad to 32 zeros?? name = xasprintf("%032lu", (unsigned long)len); @@ -4750,7 +4775,8 @@ static BC_STATUS zdc_parse_string(BcParse *p) bc_parse_push(p, BC_INST_STR); bc_parse_pushIndex(p, len); bc_vec_push(&G.prog.strs, &str); - bc_parse_addFunc(p, name, &idx); + bc_program_addFunc(name); + p->func = bc_program_func(p->fidx); RETURN_STATUS(zbc_lex_next(&p->l)); } @@ -6121,7 +6147,7 @@ static BC_STATUS zbc_program_asciify(void) //str[1] = '\0'; - already is str2 = xstrdup(str); - bc_program_addFunc(str2, &idx); + idx = bc_program_addFunc(str2); if (idx != len + BC_PROG_REQ_FUNCS) { for (idx = 0; idx < G.prog.strs.len; ++idx) { @@ -6318,36 +6344,6 @@ static void bc_program_pushGlobal(char inst) bc_vec_push(&G.prog.results, &res); } -// Note: takes ownership of 'name' (must be malloced) -static void bc_program_addFunc(char *name, size_t *idx) -{ - BcId entry, *entry_ptr; - BcFunc f; - int inserted; - - entry.name = name; - entry.idx = G.prog.fns.len; - - inserted = bc_map_insert(&G.prog.fn_map, &entry, idx); - if (!inserted) free(name); - - entry_ptr = bc_vec_item(&G.prog.fn_map, *idx); - *idx = entry_ptr->idx; - - if (!inserted) { - BcFunc *func = bc_program_func(entry_ptr->idx); - - // We need to reset these, so the function can be repopulated. - func->nparams = 0; - bc_vec_pop_all(&func->autos); - bc_vec_pop_all(&func->code); - bc_vec_pop_all(&func->labels); - } else { - bc_func_init(&f); - bc_vec_push(&G.prog.fns, &f); - } -} - static BC_STATUS zbc_program_exec(void) { BcResult r, *ptr; @@ -6982,7 +6978,6 @@ static void bc_vm_free(void) static void bc_program_init(void) { - size_t idx; BcInstPtr ip; // memset(&G.prog, 0, sizeof(G.prog)); - already is @@ -7004,8 +6999,9 @@ static void bc_program_init(void) bc_vec_init(&G.prog.fns, sizeof(BcFunc), bc_func_free); bc_vec_init(&G.prog.fn_map, sizeof(BcId), bc_id_free); - bc_program_addFunc(xstrdup("(main)"), &idx); - bc_program_addFunc(xstrdup("(read)"), &idx); +//TODO: with "", dc_strings.dc enters infinite loop, ??! + bc_program_addFunc(xstrdup("(m)")); // func #0: main + bc_program_addFunc(xstrdup("(r)")); // func #1: for read() bc_vec_init(&G.prog.vars, sizeof(BcVec), bc_vec_free); bc_vec_init(&G.prog.var_map, sizeof(BcId), bc_id_free); -- cgit v1.2.3-55-g6feb From 65e1046abf28a3b73e56e6b17ae936e7b2f314c3 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 19 Dec 2018 15:13:14 +0100 Subject: bc: open-code bc_parse_updateFunc() macro This clearly shows one place which would need changing for nested funcdefs to work. function old new delta bc_parse_reset 106 110 +4 zbc_vm_process 586 585 -1 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/1 up/down: 4/-1) Total: 3 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index d03d38aa9..8d2c2705b 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1171,6 +1171,8 @@ static BcFunc* bc_program_func(size_t idx) { return bc_vec_item(&G.prog.fns, idx); } +// BC_PROG_MAIN is zeroth element, so: +#define bc_program_func_BC_PROG_MAIN() ((BcFunc*)(G.prog.fns.v)) static void *bc_vec_item_rev(const BcVec *v, size_t idx) { @@ -3538,9 +3540,6 @@ static void bc_program_reset(void) ip->idx = f->code.len; } -#define bc_parse_updateFunc(p, f) \ - ((p)->func = bc_program_func((p)->fidx = (f))) - // Called when zbc/zdc_parse_parse() detects a failure, // resets parsing structures. static void bc_parse_reset(BcParse *p) @@ -3551,7 +3550,8 @@ static void bc_parse_reset(BcParse *p) bc_vec_pop_all(&p->func->autos); bc_vec_pop_all(&p->func->labels); - bc_parse_updateFunc(p, BC_PROG_MAIN); + p->fidx = BC_PROG_MAIN; + p->func = bc_program_func_BC_PROG_MAIN(); } p->l.i = p->l.len; @@ -3581,7 +3581,8 @@ static void bc_parse_create(BcParse *p, size_t func) bc_vec_init(&p->conds, sizeof(size_t), NULL); bc_vec_init(&p->ops, sizeof(BcLexType), NULL); - bc_parse_updateFunc(p, func); + p->fidx = func; + p->func = bc_program_func(func); } #if ENABLE_BC @@ -4339,7 +4340,10 @@ static BC_STATUS zbc_parse_funcdef(BcParse *p) if (s) RETURN_STATUS(s); bc_parse_push(p, BC_INST_RET0); - bc_parse_updateFunc(p, BC_PROG_MAIN); + + // Subsequent code generation is into main program + p->fidx = BC_PROG_MAIN; + p->func = bc_program_func_BC_PROG_MAIN(); dbg_lex_done("%s:%d done", __func__, __LINE__); RETURN_STATUS(s); -- cgit v1.2.3-55-g6feb From dfe1dd20318e79423634593725e2d0229fb19fd3 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 19 Dec 2018 17:09:01 +0100 Subject: bc: "unsigned_n > 0" is shorter code than "unsigned_n >= 1" function old new delta zbc_program_print 680 677 -3 zbc_program_exec 4089 4085 -4 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-7) Total: -7 bytes text data bss dec hex filename 981404 485 7296 989185 f1801 busybox_old 981397 485 7296 989178 f17fa busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 8d2c2705b..d62a852d5 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -707,8 +707,6 @@ typedef struct BcProgram { size_t nchars; } BcProgram; -#define BC_PROG_STACK(s, n) ((s)->len >= ((size_t) n)) - #define BC_PROG_MAIN (0) #define BC_PROG_READ (1) #if ENABLE_DC @@ -838,6 +836,9 @@ struct globals { # define COMMA_SUCCESS ,BC_STATUS_SUCCESS #endif +#define STACK_HAS_MORE_THAN(s, n) ((s)->len > ((size_t)(n))) +#define STACK_HAS_EQUAL_OR_MORE_THAN(s, n) ((s)->len >= ((size_t)(n))) + #define BC_NUM_NEG(n, neg) ((((ssize_t)(n)) ^ -((ssize_t)(neg))) + (neg)) #define BC_NUM_ONE(n) ((n)->len == 1 && (n)->rdx == 0 && (n)->num[0] == 1) #define BC_NUM_INT(n) ((n)->len - (n)->rdx) @@ -5048,7 +5049,7 @@ static BC_STATUS zbc_program_binOpPrep(BcResult **l, BcNum **ln, bool hex; BcResultType lt, rt; - if (!BC_PROG_STACK(&G.prog.results, 2)) + if (!STACK_HAS_MORE_THAN(&G.prog.results, 1)) RETURN_STATUS(bc_error_stack_has_too_few_elements()); *r = bc_vec_item_rev(&G.prog.results, 0); @@ -5091,7 +5092,7 @@ static BC_STATUS zbc_program_prep(BcResult **r, BcNum **n) { BcStatus s; - if (!BC_PROG_STACK(&G.prog.results, 1)) + if (!STACK_HAS_MORE_THAN(&G.prog.results, 0)) RETURN_STATUS(bc_error_stack_has_too_few_elements()); *r = bc_vec_top(&G.prog.results); @@ -5479,7 +5480,7 @@ static BC_STATUS zbc_program_print(char inst, size_t idx) BcNum *num; bool pop = inst != BC_INST_PRINT; - if (!BC_PROG_STACK(&G.prog.results, idx + 1)) + if (!STACK_HAS_MORE_THAN(&G.prog.results, idx)) RETURN_STATUS(bc_error_stack_has_too_few_elements()); r = bc_vec_item_rev(&G.prog.results, idx); @@ -5595,7 +5596,7 @@ static BC_STATUS zbc_program_assignStr(BcResult *r, BcVec *v, bool push) res.t = BC_RESULT_STR; if (!push) { - if (!BC_PROG_STACK(&G.prog.results, 2)) + if (!STACK_HAS_MORE_THAN(&G.prog.results, 1)) RETURN_STATUS(bc_error_stack_has_too_few_elements()); bc_vec_pop(v); bc_vec_pop(&G.prog.results); @@ -5618,7 +5619,7 @@ static BC_STATUS zbc_program_copyToVar(char *name, bool var) BcVec *v; BcNum *n; - if (!BC_PROG_STACK(&G.prog.results, 1)) + if (!STACK_HAS_MORE_THAN(&G.prog.results, 0)) RETURN_STATUS(bc_error_stack_has_too_few_elements()); ptr = bc_vec_top(&G.prog.results); @@ -5761,7 +5762,7 @@ static BC_STATUS bc_program_pushVar(char *code, size_t *bgn, BcNum *num = bc_vec_top(v); free(name); - if (!BC_PROG_STACK(v, 2 - copy)) { + if (!STACK_HAS_MORE_THAN(v, 1 - copy)) { RETURN_STATUS(bc_error_stack_has_too_few_elements()); } @@ -5916,7 +5917,7 @@ static BC_STATUS zbc_program_return(char inst) size_t i; BcInstPtr *ip = bc_vec_top(&G.prog.exestack); - if (!BC_PROG_STACK(&G.prog.results, ip->len + inst == BC_INST_RET)) + if (!STACK_HAS_EQUAL_OR_MORE_THAN(&G.prog.results, ip->len + (inst == BC_INST_RET))) RETURN_STATUS(bc_error_stack_has_too_few_elements()); f = bc_program_func(ip->func); @@ -5980,7 +5981,7 @@ static BC_STATUS zbc_program_builtin(char inst) BcResult res; bool len = inst == BC_INST_LENGTH; - if (!BC_PROG_STACK(&G.prog.results, 1)) + if (!STACK_HAS_MORE_THAN(&G.prog.results, 0)) RETURN_STATUS(bc_error_stack_has_too_few_elements()); opnd = bc_vec_top(&G.prog.results); @@ -6054,7 +6055,7 @@ static BC_STATUS zbc_program_modexp(void) BcResult *r1, *r2, *r3, res; BcNum *n1, *n2, *n3; - if (!BC_PROG_STACK(&G.prog.results, 3)) + if (!STACK_HAS_MORE_THAN(&G.prog.results, 2)) RETURN_STATUS(bc_error_stack_has_too_few_elements()); s = zbc_program_binOpPrep(&r2, &n2, &r3, &n3, false); if (s) RETURN_STATUS(s); @@ -6112,7 +6113,7 @@ static BC_STATUS zbc_program_asciify(void) size_t len = G.prog.strs.len, idx; unsigned long val; - if (!BC_PROG_STACK(&G.prog.results, 1)) + if (!STACK_HAS_MORE_THAN(&G.prog.results, 0)) RETURN_STATUS(bc_error_stack_has_too_few_elements()); r = bc_vec_top(&G.prog.results); @@ -6184,7 +6185,7 @@ static BC_STATUS zbc_program_printStream(void) size_t idx; char *str; - if (!BC_PROG_STACK(&G.prog.results, 1)) + if (!STACK_HAS_MORE_THAN(&G.prog.results, 0)) RETURN_STATUS(bc_error_stack_has_too_few_elements()); r = bc_vec_top(&G.prog.results); @@ -6239,7 +6240,7 @@ static BC_STATUS zbc_program_execStr(char *code, size_t *bgn, bool cond) BcInstPtr ip; size_t fidx, sidx; - if (!BC_PROG_STACK(&G.prog.results, 1)) + if (!STACK_HAS_MORE_THAN(&G.prog.results, 0)) RETURN_STATUS(bc_error_stack_has_too_few_elements()); r = bc_vec_top(&G.prog.results); @@ -6452,7 +6453,7 @@ static BC_STATUS zbc_program_exec(void) break; case BC_INST_POP: dbg_exec("BC_INST_POP:"); - if (!BC_PROG_STACK(&G.prog.results, 1)) + if (!STACK_HAS_MORE_THAN(&G.prog.results, 0)) s = bc_error_stack_has_too_few_elements(); else bc_vec_pop(&G.prog.results); @@ -6534,7 +6535,7 @@ static BC_STATUS zbc_program_exec(void) bc_program_stackLen(); break; case BC_INST_DUPLICATE: - if (!BC_PROG_STACK(&G.prog.results, 1)) + if (!STACK_HAS_MORE_THAN(&G.prog.results, 0)) RETURN_STATUS(bc_error_stack_has_too_few_elements()); ptr = bc_vec_top(&G.prog.results); bc_result_copy(&r, ptr); @@ -6542,7 +6543,7 @@ static BC_STATUS zbc_program_exec(void) break; case BC_INST_SWAP: { BcResult *ptr2; - if (!BC_PROG_STACK(&G.prog.results, 2)) + if (!STACK_HAS_MORE_THAN(&G.prog.results, 1)) RETURN_STATUS(bc_error_stack_has_too_few_elements()); ptr = bc_vec_item_rev(&G.prog.results, 0); ptr2 = bc_vec_item_rev(&G.prog.results, 1); @@ -6570,7 +6571,7 @@ static BC_STATUS zbc_program_exec(void) break; } case BC_INST_QUIT: - dbg_exec("BC_INST_NEG:"); + dbg_exec("BC_INST_QUIT:"); if (G.prog.exestack.len <= 2) QUIT_OR_RETURN_TO_MAIN; bc_vec_npop(&G.prog.exestack, 2); -- cgit v1.2.3-55-g6feb From f36a0adf8b1d2720880d84dcbcb800b904aedad5 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 19 Dec 2018 17:15:04 +0100 Subject: bc: remove unnecessary union use Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index d62a852d5..12e3079f1 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -4964,7 +4964,6 @@ static BcVec* bc_program_search(char *id, bool var) BcId e, *ptr; BcVec *v, *map; size_t i; - BcResultData data; int new; v = var ? &G.prog.vars : &G.prog.arrs; @@ -4975,8 +4974,9 @@ static BcVec* bc_program_search(char *id, bool var) new = bc_map_insert(map, &e, &i); // 1 if insertion was successful if (new) { - bc_array_init(&data.v, var); - bc_vec_push(v, &data.v); + BcVec v2; + bc_array_init(&v2, var); + bc_vec_push(v, &v2); } ptr = bc_vec_item(map, i); @@ -5860,7 +5860,6 @@ static BC_STATUS zbc_program_call(char *code, size_t *idx) size_t i, nparams; BcFunc *func; BcId *a; - BcResultData param; BcResult *arg; nparams = bc_program_index(code, idx); @@ -5896,11 +5895,13 @@ static BC_STATUS zbc_program_call(char *code, size_t *idx) v = bc_program_search(a->name, a->idx); if (a->idx) { - bc_num_init_DEF_SIZE(¶m.n); - bc_vec_push(v, ¶m.n); + BcNum n2; + bc_num_init_DEF_SIZE(&n2); + bc_vec_push(v, &n2); } else { - bc_array_init(¶m.v, true); - bc_vec_push(v, ¶m.v); + BcVec v2; + bc_array_init(&v2, true); + bc_vec_push(v, &v2); } } -- cgit v1.2.3-55-g6feb From 87888ce4d826a117bac89fe3475a8ae859a6e42a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 19 Dec 2018 17:55:23 +0100 Subject: bc: avoid successive bc_vec_item(&func->autos, i) function old new delta zbc_func_insert 97 100 +3 zbc_program_call 353 354 +1 zbc_program_exec 4085 4078 -7 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/1 up/down: 4/-7) Total: -3 bytes text data bss dec hex filename 981403 485 7296 989184 f1800 busybox_old 981400 485 7296 989181 f17fd busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 12e3079f1..8316933f6 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -2504,11 +2504,13 @@ static BC_STATUS zbc_num_modexp(BcNum *a, BcNum *b, BcNum *c, BcNum *restrict d) #if ENABLE_BC static BC_STATUS zbc_func_insert(BcFunc *f, char *name, bool var) { + BcId *autoid; BcId a; size_t i; - for (i = 0; i < f->autos.len; ++i) { - if (strcmp(name, ((BcId *) bc_vec_item(&f->autos, i))->name) == 0) + autoid = (void*)f->autos.v; + for (i = 0; i < f->autos.len; i++, autoid++) { + if (strcmp(name, autoid->name) == 0) RETURN_STATUS(bc_error("function parameter or auto var has the same name as another")); } @@ -5888,12 +5890,11 @@ static BC_STATUS zbc_program_call(char *code, size_t *idx) if (s) RETURN_STATUS(s); } - for (; i < func->autos.len; ++i) { + a = bc_vec_item(&func->autos, i); + for (; i < func->autos.len; i++, a++) { BcVec *v; - a = bc_vec_item(&func->autos, i); v = bc_program_search(a->name, a->idx); - if (a->idx) { BcNum n2; bc_num_init_DEF_SIZE(&n2); @@ -5915,6 +5916,7 @@ static BC_STATUS zbc_program_return(char inst) { BcResult res; BcFunc *f; + BcId *a; size_t i; BcInstPtr *ip = bc_vec_top(&G.prog.exestack); @@ -5939,10 +5941,9 @@ static BC_STATUS zbc_program_return(char inst) } // We need to pop arguments as well, so this takes that into account. - for (i = 0; i < f->autos.len; ++i) { + a = (void*)f->autos.v; + for (i = 0; i < f->autos.len; i++, a++) { BcVec *v; - BcId *a = bc_vec_item(&f->autos, i); - v = bc_program_search(a->name, a->idx); bc_vec_pop(v); } -- cgit v1.2.3-55-g6feb From eac0de55d69a4eea87689c1d4800eb8e80824aca Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 19 Dec 2018 17:59:30 +0100 Subject: bc: avoid bc_vec_item() calls in bc_array_copy() function old new delta zbc_program_copyToVar 311 300 -11 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 8316933f6..01442c33b 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -2572,14 +2572,16 @@ static void bc_array_expand(BcVec *a, size_t len) static void bc_array_copy(BcVec *d, const BcVec *s) { + BcNum *dnum, *snum; size_t i; bc_vec_pop_all(d); bc_vec_expand(d, s->cap); d->len = s->len; - for (i = 0; i < s->len; ++i) { - BcNum *dnum = bc_vec_item(d, i), *snum = bc_vec_item(s, i); + dnum = (void*)d->v; + snum = (void*)s->v; + for (i = 0; i < s->len; i++, dnum++, snum++) { bc_num_init(dnum, snum->len); bc_num_copy(dnum, snum); } -- cgit v1.2.3-55-g6feb From ea5cad2a0dc7ebbb7de0d1d49ae2b72e6fbd163a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 19 Dec 2018 18:09:31 +0100 Subject: bc: avoid bc_vec_item() calls in bc_vm_run() function old new delta bc_vm_run 124 112 -12 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 01442c33b..c1601a3e4 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -6926,6 +6926,7 @@ static const char bc_lib[] ALIGN1 = { static BC_STATUS zbc_vm_exec(void) { + char **fname; BcStatus s; size_t i; @@ -6941,13 +6942,16 @@ static BC_STATUS zbc_vm_exec(void) #endif s = BC_STATUS_SUCCESS; - for (i = 0; !s && i < G.files.len; ++i) - s = zbc_vm_file(*((char **) bc_vec_item(&G.files, i))); - if (ENABLE_FEATURE_CLEAN_UP && s && !G_ttyin) { - // Debug config, non-interactive mode: - // return all the way back to main. - // Non-debug builds do not come here, they exit. - RETURN_STATUS(s); + fname = (void*)G.files.v; + for (i = 0; i < G.files.len; i++) { + s = zbc_vm_file(*fname++); + if (ENABLE_FEATURE_CLEAN_UP && !G_ttyin && s) { + // Debug config, non-interactive mode: + // return all the way back to main. + // Non-debug builds do not come here + // in non-interactive mode, they exit. + RETURN_STATUS(s); + } } if (IS_BC || (option_mask32 & BC_FLAG_I)) -- cgit v1.2.3-55-g6feb From 44dbe675ddbcffb37e98358599610b5b81ea0644 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 19 Dec 2018 19:10:40 +0100 Subject: bc: rename zbc_parse_string->bc_parse_pushSTR, do not emit next opcode in it function old new delta bc_parse_pushSTR - 73 +73 zbc_parse_stmt_possibly_auto 1638 1640 +2 zbc_parse_string 89 - -89 ------------------------------------------------------------------------------ (add/remove: 1/1 grow/shrink: 1/0 up/down: 75/-89) Total: -14 bytes text data bss dec hex filename 981377 485 7296 989158 f17e6 busybox_old 981363 485 7296 989144 f17d8 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index c1601a3e4..6e15a8c26 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -3504,6 +3504,18 @@ static void bc_parse_pushNUM(BcParse *p) bc_parse_pushIndex(p, idx); } +static BC_STATUS bc_parse_pushSTR(BcParse *p) +{ + char *str = xstrdup(p->l.t.v.v); + + bc_parse_push(p, BC_INST_STR); + bc_parse_pushIndex(p, G.prog.strs.len); + bc_vec_push(&G.prog.strs, &str); + + RETURN_STATUS(zbc_lex_next(&p->l)); +} +#define bc_parse_pushSTR(...) (bc_parse_pushSTR(__VA_ARGS__) COMMA_SUCCESS) + IF_BC(static BC_STATUS zbc_parse_stmt_or_funcdef(BcParse *p);) IF_DC(static BC_STATUS zdc_parse_parse(BcParse *p);) @@ -3994,19 +4006,6 @@ static BC_STATUS zbc_parse_minus(BcParse *p, BcInst *prev, size_t ops_bgn, } #define zbc_parse_minus(...) (zbc_parse_minus(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zbc_parse_string(BcParse *p, char inst) -{ - char *str = xstrdup(p->l.t.v.v); - - bc_parse_push(p, BC_INST_STR); - bc_parse_pushIndex(p, G.prog.strs.len); - bc_vec_push(&G.prog.strs, &str); - bc_parse_push(p, inst); - - RETURN_STATUS(zbc_lex_next(&p->l)); -} -#define zbc_parse_string(...) (zbc_parse_string(__VA_ARGS__) COMMA_SUCCESS) - static BC_STATUS zbc_parse_print(BcParse *p) { BcStatus s; @@ -4017,12 +4016,12 @@ static BC_STATUS zbc_parse_print(BcParse *p) if (s) RETURN_STATUS(s); type = p->l.t.t; if (type == BC_LEX_STR) { - s = zbc_parse_string(p, BC_INST_PRINT_POP); + s = bc_parse_pushSTR(p); } else { s = zbc_parse_expr(p, 0); - bc_parse_push(p, BC_INST_PRINT_POP); } if (s) RETURN_STATUS(s); + bc_parse_push(p, BC_INST_PRINT_POP); if (p->l.t.t != BC_LEX_COMMA) break; } @@ -4472,7 +4471,8 @@ static BC_STATUS zbc_parse_stmt_possibly_auto(BcParse *p, bool auto_allowed) s = zbc_parse_expr(p, BC_PARSE_PRINT); break; case BC_LEX_STR: - s = zbc_parse_string(p, BC_INST_PRINT_STR); + s = bc_parse_pushSTR(p); + bc_parse_push(p, BC_INST_PRINT_STR); break; case BC_LEX_KEY_BREAK: case BC_LEX_KEY_CONTINUE: -- cgit v1.2.3-55-g6feb From fa2107918386d8262356120f86b846c2c7493b73 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 19 Dec 2018 19:35:40 +0100 Subject: bc: rename dc-specific functions, simplify zdc_program_execStr() a bit function old new delta zbc_program_execStr 496 - -496 zdc_program_execStr - 491 +491 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 95 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 47 insertions(+), 48 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 6e15a8c26..fa24f0c9f 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -2449,7 +2449,7 @@ static BC_STATUS zbc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d, #define zbc_num_divmod(...) (zbc_num_divmod(__VA_ARGS__) COMMA_SUCCESS) #if ENABLE_DC -static BC_STATUS zbc_num_modexp(BcNum *a, BcNum *b, BcNum *c, BcNum *restrict d) +static BC_STATUS zdc_num_modexp(BcNum *a, BcNum *b, BcNum *c, BcNum *restrict d) { BcStatus s; BcNum base, exp, two, temp; @@ -2498,7 +2498,7 @@ static BC_STATUS zbc_num_modexp(BcNum *a, BcNum *b, BcNum *c, BcNum *restrict d) bc_num_free(&base); RETURN_STATUS(s); } -#define zbc_num_modexp(...) (zbc_num_modexp(__VA_ARGS__) COMMA_SUCCESS) +#define zdc_num_modexp(...) (zdc_num_modexp(__VA_ARGS__) COMMA_SUCCESS) #endif // ENABLE_DC #if ENABLE_BC @@ -2593,7 +2593,7 @@ static FAST_FUNC void bc_string_free(void *string) } #if ENABLE_DC -static void bc_result_copy(BcResult *d, BcResult *src) +static void dc_result_copy(BcResult *d, BcResult *src) { d->t = src->t; @@ -3589,7 +3589,7 @@ static void bc_parse_free(BcParse *p) bc_lex_free(&p->l); } -static void bc_parse_create(BcParse *p, size_t func) +static void bc_parse_create(BcParse *p, size_t fidx) { memset(p, 0, sizeof(BcParse)); @@ -3598,8 +3598,8 @@ static void bc_parse_create(BcParse *p, size_t func) bc_vec_init(&p->conds, sizeof(size_t), NULL); bc_vec_init(&p->ops, sizeof(BcLexType), NULL); - p->fidx = func; - p->func = bc_program_func(func); + p->fidx = fidx; + p->func = bc_program_func(fidx); } #if ENABLE_BC @@ -5295,7 +5295,7 @@ static void bc_num_printNewline(void) } #if ENABLE_DC -static FAST_FUNC void bc_num_printChar(size_t num, size_t width, bool radix) +static FAST_FUNC void dc_num_printChar(size_t num, size_t width, bool radix) { (void) radix; bb_putchar((char) num); @@ -5590,7 +5590,7 @@ static BC_STATUS zbc_program_logical(char inst) #define zbc_program_logical(...) (zbc_program_logical(__VA_ARGS__) COMMA_SUCCESS) #if ENABLE_DC -static BC_STATUS zbc_program_assignStr(BcResult *r, BcVec *v, bool push) +static BC_STATUS zdc_program_assignStr(BcResult *r, BcVec *v, bool push) { BcNum n2; BcResult res; @@ -5613,7 +5613,7 @@ static BC_STATUS zbc_program_assignStr(BcResult *r, BcVec *v, bool push) RETURN_STATUS(BC_STATUS_SUCCESS); } -#define zbc_program_assignStr(...) (zbc_program_assignStr(__VA_ARGS__) COMMA_SUCCESS) +#define zdc_program_assignStr(...) (zdc_program_assignStr(__VA_ARGS__) COMMA_SUCCESS) #endif // ENABLE_DC static BC_STATUS zbc_program_copyToVar(char *name, bool var) @@ -5635,7 +5635,7 @@ static BC_STATUS zbc_program_copyToVar(char *name, bool var) if (ptr->t == BC_RESULT_STR && !var) RETURN_STATUS(bc_error_variable_is_wrong_type()); if (ptr->t == BC_RESULT_STR) - RETURN_STATUS(zbc_program_assignStr(ptr, v, true)); + RETURN_STATUS(zdc_program_assignStr(ptr, v, true)); #endif s = zbc_program_num(ptr, &n, false); @@ -5680,7 +5680,7 @@ static BC_STATUS zbc_program_assign(char inst) RETURN_STATUS(bc_error_variable_is_wrong_type()); v = bc_program_search(left->d.id.name, true); - RETURN_STATUS(zbc_program_assignStr(right, v, false)); + RETURN_STATUS(zdc_program_assignStr(right, v, false)); } #endif @@ -6026,7 +6026,7 @@ static BC_STATUS zbc_program_builtin(char inst) #define zbc_program_builtin(...) (zbc_program_builtin(__VA_ARGS__) COMMA_SUCCESS) #if ENABLE_DC -static BC_STATUS zbc_program_divmod(void) +static BC_STATUS zdc_program_divmod(void) { BcStatus s; BcResult *opd1, *opd2, res, res2; @@ -6051,9 +6051,9 @@ static BC_STATUS zbc_program_divmod(void) bc_num_free(&res.d.n); RETURN_STATUS(s); } -#define zbc_program_divmod(...) (zbc_program_divmod(__VA_ARGS__) COMMA_SUCCESS) +#define zdc_program_divmod(...) (zdc_program_divmod(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zbc_program_modexp(void) +static BC_STATUS zdc_program_modexp(void) { BcStatus s; BcResult *r1, *r2, *r3, res; @@ -6083,7 +6083,7 @@ static BC_STATUS zbc_program_modexp(void) } bc_num_init(&res.d.n, n3->len); - s = zbc_num_modexp(n1, n2, n3, &res.d.n); + s = zdc_num_modexp(n1, n2, n3, &res.d.n); if (s) goto err; bc_vec_pop(&G.prog.results); @@ -6094,9 +6094,9 @@ static BC_STATUS zbc_program_modexp(void) bc_num_free(&res.d.n); RETURN_STATUS(s); } -#define zbc_program_modexp(...) (zbc_program_modexp(__VA_ARGS__) COMMA_SUCCESS) +#define zdc_program_modexp(...) (zdc_program_modexp(__VA_ARGS__) COMMA_SUCCESS) -static void bc_program_stackLen(void) +static void dc_program_stackLen(void) { BcResult res; size_t len = G.prog.results.len; @@ -6108,7 +6108,7 @@ static void bc_program_stackLen(void) bc_vec_push(&G.prog.results, &res); } -static BC_STATUS zbc_program_asciify(void) +static BC_STATUS zdc_program_asciify(void) { BcStatus s; BcResult *r, res; @@ -6179,36 +6179,37 @@ static BC_STATUS zbc_program_asciify(void) bc_num_free(&n); RETURN_STATUS(s); } -#define zbc_program_asciify(...) (zbc_program_asciify(__VA_ARGS__) COMMA_SUCCESS) +#define zdc_program_asciify(...) (zdc_program_asciify(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zbc_program_printStream(void) +static BC_STATUS zdc_program_printStream(void) { BcStatus s; BcResult *r; - BcNum *n = NULL; + BcNum *n; size_t idx; - char *str; if (!STACK_HAS_MORE_THAN(&G.prog.results, 0)) RETURN_STATUS(bc_error_stack_has_too_few_elements()); r = bc_vec_top(&G.prog.results); + n = NULL; // is this needed? s = zbc_program_num(r, &n, false); if (s) RETURN_STATUS(s); if (BC_PROG_NUM(r, n)) { - s = zbc_num_printNum(n, 0x100, 1, bc_num_printChar); + s = zbc_num_printNum(n, 0x100, 1, dc_num_printChar); } else { + char *str; idx = (r->t == BC_RESULT_STR) ? r->d.id.idx : n->rdx; str = *bc_program_str(idx); - printf("%s", str); + fputs(str, stdout); } RETURN_STATUS(s); } -#define zbc_program_printStream(...) (zbc_program_printStream(__VA_ARGS__) COMMA_SUCCESS) +#define zdc_program_printStream(...) (zdc_program_printStream(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zbc_program_nquit(void) +static BC_STATUS zdc_program_nquit(void) { BcStatus s; BcResult *opnd; @@ -6232,15 +6233,13 @@ static BC_STATUS zbc_program_nquit(void) RETURN_STATUS(s); } -#define zbc_program_nquit(...) (zbc_program_nquit(__VA_ARGS__) COMMA_SUCCESS) +#define zdc_program_nquit(...) (zdc_program_nquit(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zbc_program_execStr(char *code, size_t *bgn, bool cond) +static BC_STATUS zdc_program_execStr(char *code, size_t *bgn, bool cond) { BcStatus s = BC_STATUS_SUCCESS; BcResult *r; - char **str; BcFunc *f; - BcParse prs; BcInstPtr ip; size_t fidx, sidx; @@ -6298,21 +6297,25 @@ static BC_STATUS zbc_program_execStr(char *code, size_t *bgn, bool cond) fidx = sidx + BC_PROG_REQ_FUNCS; - str = bc_program_str(sidx); f = bc_program_func(fidx); if (f->code.len == 0) { + BcParse prs; + char *str; + bc_parse_create(&prs, fidx); - s = zbc_parse_text_init(&prs, *str); + str = *bc_program_str(sidx); + s = zbc_parse_text_init(&prs, str); if (s) goto err; s = zcommon_parse_expr(&prs, BC_PARSE_NOCALL); if (s) goto err; - if (prs.l.t.t != BC_LEX_EOF) { s = bc_error_bad_expression(); - goto err; + err: + bc_parse_free(&prs); + bc_vec_pop_all(&f->code); + goto exit; } - bc_parse_free(&prs); } @@ -6324,15 +6327,11 @@ static BC_STATUS zbc_program_execStr(char *code, size_t *bgn, bool cond) bc_vec_push(&G.prog.exestack, &ip); RETURN_STATUS(BC_STATUS_SUCCESS); - err: - bc_parse_free(&prs); - f = bc_program_func(fidx); - bc_vec_pop_all(&f->code); exit: bc_vec_pop(&G.prog.results); RETURN_STATUS(s); } -#define zbc_program_execStr(...) (zbc_program_execStr(__VA_ARGS__) COMMA_SUCCESS) +#define zdc_program_execStr(...) (zdc_program_execStr(__VA_ARGS__) COMMA_SUCCESS) #endif // ENABLE_DC static void bc_program_pushGlobal(char inst) @@ -6515,14 +6514,14 @@ static BC_STATUS zbc_program_exec(void) break; #if ENABLE_DC case BC_INST_MODEXP: - s = zbc_program_modexp(); + s = zdc_program_modexp(); break; case BC_INST_DIVMOD: - s = zbc_program_divmod(); + s = zdc_program_divmod(); break; case BC_INST_EXECUTE: case BC_INST_EXEC_COND: - s = zbc_program_execStr(code, &ip->idx, inst == BC_INST_EXEC_COND); + s = zdc_program_execStr(code, &ip->idx, inst == BC_INST_EXEC_COND); goto read_updated_ip; case BC_INST_PRINT_STACK: { size_t idx; @@ -6536,13 +6535,13 @@ static BC_STATUS zbc_program_exec(void) bc_vec_pop_all(&G.prog.results); break; case BC_INST_STACK_LEN: - bc_program_stackLen(); + dc_program_stackLen(); break; case BC_INST_DUPLICATE: if (!STACK_HAS_MORE_THAN(&G.prog.results, 0)) RETURN_STATUS(bc_error_stack_has_too_few_elements()); ptr = bc_vec_top(&G.prog.results); - bc_result_copy(&r, ptr); + dc_result_copy(&r, ptr); bc_vec_push(&G.prog.results, &r); break; case BC_INST_SWAP: { @@ -6557,10 +6556,10 @@ static BC_STATUS zbc_program_exec(void) break; } case BC_INST_ASCIIFY: - s = zbc_program_asciify(); + s = zdc_program_asciify(); break; case BC_INST_PRINT_STREAM: - s = zbc_program_printStream(); + s = zdc_program_printStream(); break; case BC_INST_LOAD: case BC_INST_PUSH_VAR: { @@ -6581,7 +6580,7 @@ static BC_STATUS zbc_program_exec(void) bc_vec_npop(&G.prog.exestack, 2); goto read_updated_ip; case BC_INST_NQUIT: - s = zbc_program_nquit(); + s = zdc_program_nquit(); //goto read_updated_ip; - just fall through to it #endif // ENABLE_DC read_updated_ip: -- cgit v1.2.3-55-g6feb From 408b7d45f638dd163fc38d12d08ef94403412c90 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 19 Dec 2018 19:43:03 +0100 Subject: bc: fix "dc only" and "bc only" configs Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 92 ++++++++++++++++++++++++++++++---------------------------- 1 file changed, 48 insertions(+), 44 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index fa24f0c9f..7fcf00aa9 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -2903,6 +2903,7 @@ static BC_STATUS zbc_lex_next(BcLex *l) } #define zbc_lex_next(...) (zbc_lex_next(__VA_ARGS__) COMMA_SUCCESS) +#if ENABLE_BC static BC_STATUS zbc_lex_skip_if_at_NLINE(BcLex *l) { if (l->t.t == BC_LEX_NLINE) @@ -2921,6 +2922,7 @@ static BC_STATUS zbc_lex_next_and_skip_NLINE(BcLex *l) RETURN_STATUS(s); } #define zbc_lex_next_and_skip_NLINE(...) (zbc_lex_next_and_skip_NLINE(__VA_ARGS__) COMMA_SUCCESS) +#endif static BC_STATUS zbc_lex_text_init(BcLex *l, const char *text) { @@ -3481,6 +3483,7 @@ static void bc_parse_pushIndex(BcParse *p, size_t idx) } } +#if ENABLE_BC static void bc_parse_pushJUMP(BcParse *p, size_t idx) { bc_parse_push(p, BC_INST_JUMP); @@ -3493,17 +3496,6 @@ static void bc_parse_pushJUMP_ZERO(BcParse *p, size_t idx) bc_parse_pushIndex(p, idx); } -static void bc_parse_pushNUM(BcParse *p) -{ - char *num = xstrdup(p->l.t.v.v); - size_t idx = G.prog.consts.len; - - bc_vec_push(&G.prog.consts, &num); - - bc_parse_push(p, BC_INST_NUM); - bc_parse_pushIndex(p, idx); -} - static BC_STATUS bc_parse_pushSTR(BcParse *p) { char *str = xstrdup(p->l.t.v.v); @@ -3515,6 +3507,18 @@ static BC_STATUS bc_parse_pushSTR(BcParse *p) RETURN_STATUS(zbc_lex_next(&p->l)); } #define bc_parse_pushSTR(...) (bc_parse_pushSTR(__VA_ARGS__) COMMA_SUCCESS) +#endif + +static void bc_parse_pushNUM(BcParse *p) +{ + char *num = xstrdup(p->l.t.v.v); + size_t idx = G.prog.consts.len; + + bc_vec_push(&G.prog.consts, &num); + + bc_parse_push(p, BC_INST_NUM); + bc_parse_pushIndex(p, idx); +} IF_BC(static BC_STATUS zbc_parse_stmt_or_funcdef(BcParse *p);) IF_DC(static BC_STATUS zdc_parse_parse(BcParse *p);) @@ -3602,6 +3606,39 @@ static void bc_parse_create(BcParse *p, size_t fidx) p->func = bc_program_func(fidx); } +// Note: takes ownership of 'name' (must be malloced) +static size_t bc_program_addFunc(char *name) +{ + size_t idx; + BcId entry, *entry_ptr; + BcFunc f; + int inserted; + + entry.name = name; + entry.idx = G.prog.fns.len; + + inserted = bc_map_insert(&G.prog.fn_map, &entry, &idx); + if (!inserted) free(name); + + entry_ptr = bc_vec_item(&G.prog.fn_map, idx); + idx = entry_ptr->idx; + + if (!inserted) { + BcFunc *func = bc_program_func(entry_ptr->idx); + + // We need to reset these, so the function can be repopulated. + func->nparams = 0; + bc_vec_pop_all(&func->autos); + bc_vec_pop_all(&func->code); + bc_vec_pop_all(&func->labels); + } else { + bc_func_init(&f); + bc_vec_push(&G.prog.fns, &f); + } + + return idx; +} + #if ENABLE_BC #define BC_PARSE_TOP_OP(p) (*((BcLexType *) bc_vec_top(&(p)->ops))) @@ -3729,39 +3766,6 @@ static BC_STATUS zbc_parse_params(BcParse *p, uint8_t flags) } #define zbc_parse_params(...) (zbc_parse_params(__VA_ARGS__) COMMA_SUCCESS) -// Note: takes ownership of 'name' (must be malloced) -static size_t bc_program_addFunc(char *name) -{ - size_t idx; - BcId entry, *entry_ptr; - BcFunc f; - int inserted; - - entry.name = name; - entry.idx = G.prog.fns.len; - - inserted = bc_map_insert(&G.prog.fn_map, &entry, &idx); - if (!inserted) free(name); - - entry_ptr = bc_vec_item(&G.prog.fn_map, idx); - idx = entry_ptr->idx; - - if (!inserted) { - BcFunc *func = bc_program_func(entry_ptr->idx); - - // We need to reset these, so the function can be repopulated. - func->nparams = 0; - bc_vec_pop_all(&func->autos); - bc_vec_pop_all(&func->code); - bc_vec_pop_all(&func->labels); - } else { - bc_func_init(&f); - bc_vec_push(&G.prog.fns, &f); - } - - return idx; -} - // Note: takes ownership of 'name' (must be malloced) static BC_STATUS zbc_parse_call(BcParse *p, char *name, uint8_t flags) { -- cgit v1.2.3-55-g6feb From eaa3b00002e23e2ecccade3e06790dd524e7b662 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 19 Dec 2018 20:05:50 +0100 Subject: bc: shorten bc_program_addFunc() function old new delta bc_func_init - 50 +50 bc_program_addFunc 201 138 -63 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 0/1 up/down: 50/-63) Total: -13 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 7fcf00aa9..c59d5a2b5 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -3624,13 +3624,11 @@ static size_t bc_program_addFunc(char *name) idx = entry_ptr->idx; if (!inserted) { + // There is already a function with this name. + // It'll be redefined now, clear old definition. BcFunc *func = bc_program_func(entry_ptr->idx); - - // We need to reset these, so the function can be repopulated. - func->nparams = 0; - bc_vec_pop_all(&func->autos); - bc_vec_pop_all(&func->code); - bc_vec_pop_all(&func->labels); + bc_func_free(func); + bc_func_init(func); } else { bc_func_init(&f); bc_vec_push(&G.prog.fns, &f); -- cgit v1.2.3-55-g6feb From 503faf9d5331b70d93836d221ff12f97d769499b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 20 Dec 2018 16:24:18 +0100 Subject: bc: shrink "dc only" code by dropping unused structure members function old new delta zbc_program_num 979 981 +2 zbc_program_pushArray 147 145 -2 bc_program_pushVar 198 196 -2 bc_program_func 17 15 -2 dc_num_printChar 24 21 -3 bc_program_retire 35 32 -3 bc_program_binOpRetire 46 43 -3 zdc_program_printStream 153 148 -5 zbc_program_prep 91 86 -5 zbc_program_copyToVar 300 295 -5 zdc_program_modexp 721 715 -6 zbc_program_binOpPrep 311 305 -6 bc_program_addFunc 138 132 -6 bc_num_printNewline 51 45 -6 bc_num_printHex 67 61 -6 bc_num_printDigits 137 131 -6 zdc_program_assignStr 146 137 -9 bc_program_reset 64 55 -9 bc_func_free 27 5 -22 bc_parse_free 38 8 -30 bc_parse_create 92 47 -45 bc_func_init 50 5 -45 dc_main 691 645 -46 zdc_program_execStr 496 442 -54 zbc_program_print 677 623 -54 zbc_vm_process 204 137 -67 zbc_program_exec 4132 4057 -75 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/26 up/down: 2/-522) Total: -520 bytes text data bss dec hex filename 969767 485 7296 977548 eea8c busybox_old 969210 485 7296 976991 ee85f busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 87 +++++++++++++++++++++++++++++++--------------------------- 1 file changed, 46 insertions(+), 41 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index c59d5a2b5..c5288102d 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -348,9 +348,9 @@ typedef struct BcId { typedef struct BcFunc { BcVec code; - BcVec labels; - size_t nparams; - BcVec autos; + IF_BC(BcVec labels;) + IF_BC(BcVec autos;) + IF_BC(size_t nparams;) } BcFunc; typedef enum BcResultType { @@ -385,7 +385,7 @@ typedef struct BcResult { typedef struct BcInstPtr { size_t func; size_t idx; - size_t len; + IF_BC(size_t len;) } BcInstPtr; // BC_LEX_NEG is not used in lexing; it is only for parsing. @@ -664,30 +664,29 @@ typedef struct BcLex { typedef struct BcParse { BcLex l; - BcVec exits; - BcVec conds; - - BcVec ops; + IF_BC(BcVec exits;) + IF_BC(BcVec conds;) + IF_BC(BcVec ops;) BcFunc *func; size_t fidx; - size_t in_funcdef; + IF_BC(size_t in_funcdef;) } BcParse; typedef struct BcProgram { size_t len; - size_t scale; + size_t nchars; + size_t scale; size_t ib_t; size_t ob_t; - BcNum ob; BcVec results; BcVec exestack; BcVec fns; - BcVec fn_map; + BcVec fn_map; //TODO: dc does not need this, its 'functions' are anonynomous (have no names) BcVec vars; BcVec var_map; @@ -700,11 +699,9 @@ typedef struct BcProgram { const char *file; - BcNum last; BcNum zero; - BcNum one; - - size_t nchars; + IF_BC(BcNum one;) + IF_BC(BcNum last;) } BcProgram; #define BC_PROG_MAIN (0) @@ -1616,6 +1613,7 @@ static BC_STATUS zbc_num_shift(BcNum *n, size_t places) static BC_STATUS zbc_num_inv(BcNum *a, BcNum *b, size_t scale) { +//TODO: nice example of non-allocated BcNum, use in other places as well! BcNum one; BcDig num[2]; @@ -2527,17 +2525,17 @@ static BC_STATUS zbc_func_insert(BcFunc *f, char *name, bool var) static void bc_func_init(BcFunc *f) { bc_char_vec_init(&f->code); - bc_vec_init(&f->autos, sizeof(BcId), bc_id_free); - bc_vec_init(&f->labels, sizeof(size_t), NULL); - f->nparams = 0; + IF_BC(bc_vec_init(&f->labels, sizeof(size_t), NULL);) + IF_BC(bc_vec_init(&f->autos, sizeof(BcId), bc_id_free);) + IF_BC(f->nparams = 0;) } static FAST_FUNC void bc_func_free(void *func) { BcFunc *f = (BcFunc *) func; bc_vec_free(&f->code); - bc_vec_free(&f->autos); - bc_vec_free(&f->labels); + IF_BC(bc_vec_free(&f->labels);) + IF_BC(bc_vec_free(&f->autos);) } static void bc_array_expand(BcVec *a, size_t len); @@ -3566,10 +3564,10 @@ static void bc_program_reset(void) static void bc_parse_reset(BcParse *p) { if (p->fidx != BC_PROG_MAIN) { - p->func->nparams = 0; bc_vec_pop_all(&p->func->code); - bc_vec_pop_all(&p->func->autos); - bc_vec_pop_all(&p->func->labels); + IF_BC(bc_vec_pop_all(&p->func->labels);) + IF_BC(bc_vec_pop_all(&p->func->autos);) + IF_BC(p->func->nparams = 0;) p->fidx = BC_PROG_MAIN; p->func = bc_program_func_BC_PROG_MAIN(); @@ -3578,18 +3576,18 @@ static void bc_parse_reset(BcParse *p) p->l.i = p->l.len; p->l.t.t = BC_LEX_EOF; - bc_vec_pop_all(&p->exits); - bc_vec_pop_all(&p->conds); - bc_vec_pop_all(&p->ops); + IF_BC(bc_vec_pop_all(&p->exits);) + IF_BC(bc_vec_pop_all(&p->conds);) + IF_BC(bc_vec_pop_all(&p->ops);) bc_program_reset(); } static void bc_parse_free(BcParse *p) { - bc_vec_free(&p->exits); - bc_vec_free(&p->conds); - bc_vec_free(&p->ops); + IF_BC(bc_vec_free(&p->exits);) + IF_BC(bc_vec_free(&p->conds);) + IF_BC(bc_vec_free(&p->ops);) bc_lex_free(&p->l); } @@ -3598,9 +3596,9 @@ static void bc_parse_create(BcParse *p, size_t fidx) memset(p, 0, sizeof(BcParse)); bc_lex_init(&p->l); - bc_vec_init(&p->exits, sizeof(size_t), NULL); - bc_vec_init(&p->conds, sizeof(size_t), NULL); - bc_vec_init(&p->ops, sizeof(BcLexType), NULL); + IF_BC(bc_vec_init(&p->exits, sizeof(size_t), NULL);) + IF_BC(bc_vec_init(&p->conds, sizeof(size_t), NULL);) + IF_BC(bc_vec_init(&p->ops, sizeof(BcLexType), NULL);) p->fidx = fidx; p->func = bc_program_func(fidx); @@ -5036,12 +5034,17 @@ static BC_STATUS zbc_program_num(BcResult *r, BcNum **num, bool hex) *num = bc_vec_top(v); break; } +#if ENABLE_BC case BC_RESULT_LAST: *num = &G.prog.last; break; case BC_RESULT_ONE: *num = &G.prog.one; break; +#endif + default: + // Testing the theory that dc does not reach LAST/ONE + bb_error_msg_and_die("BUG:%d", r->t); } RETURN_STATUS(BC_STATUS_SUCCESS); @@ -5178,7 +5181,7 @@ static BC_STATUS zbc_program_read(void) ip.func = BC_PROG_READ; ip.idx = 0; - ip.len = G.prog.results.len; + IF_BC(ip.len = G.prog.results.len;) // Update this pointer, just in case. f = bc_program_func(BC_PROG_READ); @@ -5496,7 +5499,9 @@ static BC_STATUS zbc_program_print(char inst, size_t idx) if (BC_PROG_NUM(r, num)) { s = zbc_num_print(num, !pop); - if (!s) bc_num_copy(&G.prog.last, num); +#if ENABLE_BC + if (!s && IS_BC) bc_num_copy(&G.prog.last, num); +#endif } else { char *str; @@ -6322,7 +6327,7 @@ static BC_STATUS zdc_program_execStr(char *code, size_t *bgn, bool cond) } ip.idx = 0; - ip.len = G.prog.results.len; + IF_BC(ip.len = G.prog.results.len;) ip.func = fidx; bc_vec_pop(&G.prog.results); @@ -6977,7 +6982,7 @@ static void bc_program_free(void) bc_vec_free(&G.prog.exestack); bc_num_free(&G.prog.last); bc_num_free(&G.prog.zero); - bc_num_free(&G.prog.one); + IF_BC(bc_num_free(&G.prog.one);) bc_vec_free(&G.input_buffer); } @@ -7001,14 +7006,14 @@ static void bc_program_init(void) G.prog.ib_t = 10; G.prog.ob_t = 10; - bc_num_init_DEF_SIZE(&G.prog.last); - //bc_num_zero(&G.prog.last); - already is + IF_BC(bc_num_init_DEF_SIZE(&G.prog.last);) + //IF_BC(bc_num_zero(&G.prog.last);) - already is bc_num_init_DEF_SIZE(&G.prog.zero); //bc_num_zero(&G.prog.zero); - already is - bc_num_init_DEF_SIZE(&G.prog.one); - bc_num_one(&G.prog.one); + IF_BC(bc_num_init_DEF_SIZE(&G.prog.one);) + IF_BC(bc_num_one(&G.prog.one);) bc_vec_init(&G.prog.fns, sizeof(BcFunc), bc_func_free); bc_vec_init(&G.prog.fn_map, sizeof(BcId), bc_id_free); -- cgit v1.2.3-55-g6feb From 5acd14ba5b911aff28cb259cabdb84c5f8233e55 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 20 Dec 2018 16:48:50 +0100 Subject: bc: fix keyword matching to not think "ifz" is the "if" keyword function old new delta zbc_lex_next 2224 2225 +1 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 2 ++ testsuite/bc.tests | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/miscutils/bc.c b/miscutils/bc.c index c5288102d..1e2ca8b83 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -2950,6 +2950,8 @@ static BC_STATUS zbc_lex_identifier(BcLex *l) continue; match: // buf starts with keyword bc_lex_kws[i] + if (isalnum(buf[j]) || buf[j]=='_') + continue; // "ifz" does not match "if" keyword, "if." does l->t.t = BC_LEX_KEY_1st_keyword + i; if (!bc_lex_kws_POSIX(i)) { s = bc_posix_error_fmt("%sthe '%.8s' keyword", "POSIX does not allow ", bc_lex_kws[i].name8); diff --git a/testsuite/bc.tests b/testsuite/bc.tests index e303cf6ae..d33f8c90a 100755 --- a/testsuite/bc.tests +++ b/testsuite/bc.tests @@ -76,6 +76,11 @@ testing "bc while(cond)" \ "8\n7\n6\n5\n4\n3\n2\n1\n9\n" \ "" "i=9;while(--i)\ni\n9" +testing "bc ifz does not match if keyword" \ + "bc" \ + "1\n2\n2\n3\n" \ + "" "ifz=1;ifz\n++ifz;ifz++\nifz" + testing "bc print 1,2,3" \ "bc" \ "123" \ -- cgit v1.2.3-55-g6feb From 44a99ca61716f9846756c3d0cd434bfe8192339e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 20 Dec 2018 20:34:09 +0100 Subject: bc: "dc only" config does not need G.prog.fn_map function old new delta bc_program_add_fn - 43 +43 bc_vm_init 655 675 +20 bc_program_addFunc 138 118 -20 zdc_parse_expr 658 635 -23 zdc_program_asciify 447 407 -40 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 1/3 up/down: 63/-83) Total: -20 bytes text data bss dec hex filename 984739 489 7312 992540 f251c busybox_old 984712 489 7312 992513 f2501 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 92 +++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 56 insertions(+), 36 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 1e2ca8b83..e05191717 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -686,7 +686,7 @@ typedef struct BcProgram { BcVec exestack; BcVec fns; - BcVec fn_map; //TODO: dc does not need this, its 'functions' are anonynomous (have no names) + IF_BC(BcVec fn_map;) BcVec vars; BcVec var_map; @@ -3606,12 +3606,23 @@ static void bc_parse_create(BcParse *p, size_t fidx) p->func = bc_program_func(fidx); } +static size_t bc_program_add_fn(void) +{ + size_t idx; + BcFunc f; + bc_func_init(&f); + idx = G.prog.fns.len; + bc_vec_push(&G.prog.fns, &f); + return idx; +} + +#if ENABLE_BC + // Note: takes ownership of 'name' (must be malloced) static size_t bc_program_addFunc(char *name) { size_t idx; BcId entry, *entry_ptr; - BcFunc f; int inserted; entry.name = name; @@ -3630,15 +3641,12 @@ static size_t bc_program_addFunc(char *name) bc_func_free(func); bc_func_init(func); } else { - bc_func_init(&f); - bc_vec_push(&G.prog.fns, &f); + bc_program_add_fn(); } return idx; } -#if ENABLE_BC - #define BC_PARSE_TOP_OP(p) (*((BcLexType *) bc_vec_top(&(p)->ops))) #define BC_PARSE_LEAF(p, rparen) \ (((p) >= BC_INST_NUM && (p) <= BC_INST_SQRT) || (rparen) || \ @@ -4776,19 +4784,22 @@ static BC_STATUS zdc_parse_register(BcParse *p) static BC_STATUS zdc_parse_string(BcParse *p) { - char *str, *name; + char *str; size_t len = G.prog.strs.len; -//why pad to 32 zeros?? - name = xasprintf("%032lu", (unsigned long)len); + dbg_lex_enter("%s:%d entered", __func__, __LINE__); str = xstrdup(p->l.t.v.v); bc_parse_push(p, BC_INST_STR); bc_parse_pushIndex(p, len); bc_vec_push(&G.prog.strs, &str); - bc_program_addFunc(name); + + // Explanation needed here + bc_program_add_fn(); p->func = bc_program_func(p->fidx); + dbg_lex_done("%s:%d done", __func__, __LINE__); + RETURN_STATUS(zbc_lex_next(&p->l)); } #define zdc_parse_string(...) (zdc_parse_string(__VA_ARGS__) COMMA_SUCCESS) @@ -4843,6 +4854,7 @@ static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t, uint8_t flags) uint8_t inst; bool assign, get_token = false; + dbg_lex_enter("%s:%d entered", __func__, __LINE__); switch (t) { case BC_LEX_OP_REL_EQ: case BC_LEX_OP_REL_LE: @@ -4857,10 +4869,12 @@ static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t, uint8_t flags) s = zdc_parse_mem(p, BC_INST_ARRAY_ELEM, true, t == BC_LEX_COLON); break; case BC_LEX_STR: + dbg_lex("%s:%d LEX_STR", __func__, __LINE__); s = zdc_parse_string(p); break; case BC_LEX_NEG: case BC_LEX_NUMBER: + dbg_lex("%s:%d LEX_NEG/NUMBER", __func__, __LINE__); if (t == BC_LEX_NEG) { s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); @@ -4903,6 +4917,7 @@ static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t, uint8_t flags) if (!s && get_token) s = zbc_lex_next(&p->l); + dbg_lex_done("%s:%d done", __func__, __LINE__); RETURN_STATUS(s); } #define zdc_parse_token(...) (zdc_parse_token(__VA_ARGS__) COMMA_SUCCESS) @@ -4911,6 +4926,7 @@ static BC_STATUS zdc_parse_expr(BcParse *p, uint8_t flags) { BcLexType t; + dbg_lex_enter("%s:%d entered G.prs.l.t.t:%d", __func__, __LINE__, G.prs.l.t.t); for (;;) { BcInst inst; BcStatus s; @@ -4920,9 +4936,11 @@ static BC_STATUS zdc_parse_expr(BcParse *p, uint8_t flags) inst = dc_parse_insts[t]; if (inst != BC_INST_INVALID) { + dbg_lex("%s:%d", __func__, __LINE__); bc_parse_push(p, inst); s = zbc_lex_next(&p->l); } else { + dbg_lex("%s:%d", __func__, __LINE__); s = zdc_parse_token(p, t, flags); } if (s) RETURN_STATUS(s); @@ -4931,6 +4949,7 @@ static BC_STATUS zdc_parse_expr(BcParse *p, uint8_t flags) if (flags & BC_PARSE_NOCALL) bc_parse_push(p, BC_INST_POP_EXEC); + dbg_lex_done("%s:%d done", __func__, __LINE__); RETURN_STATUS(BC_STATUS_SUCCESS); } #define zdc_parse_expr(...) (zdc_parse_expr(__VA_ARGS__) COMMA_SUCCESS) @@ -6122,8 +6141,10 @@ static BC_STATUS zdc_program_asciify(void) BcStatus s; BcResult *r, res; BcNum *num, n; - char *str, *str2, c; - size_t len = G.prog.strs.len, idx; + char **strs; + char *str; + char c; + size_t idx; unsigned long val; if (!STACK_HAS_MORE_THAN(&G.prog.results, 0)) @@ -6155,31 +6176,25 @@ static BC_STATUS zdc_program_asciify(void) bc_num_free(&n); } else { + char *sp; idx = (r->t == BC_RESULT_STR) ? r->d.id.idx : num->rdx; - str2 = *bc_program_str(idx); - c = str2[0]; + sp = *bc_program_str(idx); + c = sp[0]; } + strs = (void*)G.prog.strs.v; + for (idx = 0; idx < G.prog.strs.len; idx++) { + if (strs[idx][0] == c && strs[idx][1] == '\0') { + goto dup; + } + } str = xzalloc(2); str[0] = c; //str[1] = '\0'; - already is - - str2 = xstrdup(str); - idx = bc_program_addFunc(str2); - - if (idx != len + BC_PROG_REQ_FUNCS) { - for (idx = 0; idx < G.prog.strs.len; ++idx) { - if (strcmp(*bc_program_str(idx), str) == 0) { - len = idx; - break; - } - } - free(str); - } else - bc_vec_push(&G.prog.strs, &str); - + bc_vec_push(&G.prog.strs, &str); + dup: res.t = BC_RESULT_STR; - res.d.id.idx = len; + res.d.id.idx = idx; bc_vec_pop(&G.prog.results); bc_vec_push(&G.prog.results, &res); @@ -6973,7 +6988,7 @@ static BC_STATUS zbc_vm_exec(void) static void bc_program_free(void) { bc_vec_free(&G.prog.fns); - bc_vec_free(&G.prog.fn_map); + IF_BC(bc_vec_free(&G.prog.fn_map);) bc_vec_free(&G.prog.vars); bc_vec_free(&G.prog.var_map); bc_vec_free(&G.prog.arrs); @@ -6982,8 +6997,8 @@ static void bc_program_free(void) bc_vec_free(&G.prog.consts); bc_vec_free(&G.prog.results); bc_vec_free(&G.prog.exestack); - bc_num_free(&G.prog.last); - bc_num_free(&G.prog.zero); + IF_BC(bc_num_free(&G.prog.last);) + IF_BC(bc_num_free(&G.prog.zero);) IF_BC(bc_num_free(&G.prog.one);) bc_vec_free(&G.input_buffer); } @@ -7018,11 +7033,16 @@ static void bc_program_init(void) IF_BC(bc_num_one(&G.prog.one);) bc_vec_init(&G.prog.fns, sizeof(BcFunc), bc_func_free); - bc_vec_init(&G.prog.fn_map, sizeof(BcId), bc_id_free); + IF_BC(bc_vec_init(&G.prog.fn_map, sizeof(BcId), bc_id_free);) //TODO: with "", dc_strings.dc enters infinite loop, ??! - bc_program_addFunc(xstrdup("(m)")); // func #0: main - bc_program_addFunc(xstrdup("(r)")); // func #1: for read() + if (IS_BC) { + IF_BC(bc_program_addFunc(xstrdup("(m)"))); // func #0: main + IF_BC(bc_program_addFunc(xstrdup("(r)"))); // func #1: for read() + } else { + bc_program_add_fn(); + bc_program_add_fn(); + } bc_vec_init(&G.prog.vars, sizeof(BcVec), bc_vec_free); bc_vec_init(&G.prog.var_map, sizeof(BcId), bc_id_free); -- cgit v1.2.3-55-g6feb From 047154472ac41ddf45ed57d9bc294fbf9057cbad Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 21 Dec 2018 00:10:26 +0100 Subject: bc: shrink bc_program_add_fn() Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index e05191717..d37417f11 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -3606,14 +3606,14 @@ static void bc_parse_create(BcParse *p, size_t fidx) p->func = bc_program_func(fidx); } -static size_t bc_program_add_fn(void) +static void bc_program_add_fn(void) { - size_t idx; + //size_t idx; BcFunc f; bc_func_init(&f); - idx = G.prog.fns.len; + //idx = G.prog.fns.len; bc_vec_push(&G.prog.fns, &f); - return idx; + //return idx; } #if ENABLE_BC @@ -7035,10 +7035,11 @@ static void bc_program_init(void) bc_vec_init(&G.prog.fns, sizeof(BcFunc), bc_func_free); IF_BC(bc_vec_init(&G.prog.fn_map, sizeof(BcId), bc_id_free);) -//TODO: with "", dc_strings.dc enters infinite loop, ??! if (IS_BC) { - IF_BC(bc_program_addFunc(xstrdup("(m)"))); // func #0: main - IF_BC(bc_program_addFunc(xstrdup("(r)"))); // func #1: for read() + // Names are chosen simply to never match + // a valid function name (and be short) + IF_BC(bc_program_addFunc(xstrdup(""))); // func #0: main + IF_BC(bc_program_addFunc(xstrdup(""))); // func #1: for read() } else { bc_program_add_fn(); bc_program_add_fn(); -- cgit v1.2.3-55-g6feb From 52caa007e3f32225b6cd9f899480362c4563b023 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 21 Dec 2018 00:35:22 +0100 Subject: bc: for(;;) fix from upstream Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 8 +++++++- testsuite/bc.tests | 5 +++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index d37417f11..e7983f38d 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -4205,8 +4205,14 @@ static BC_STATUS zbc_parse_for(BcParse *p) if (p->l.t.t != BC_LEX_SCOLON) s = zbc_parse_expr(p, BC_PARSE_REL); - else + else { + // Set this for the next call to bc_parse_number. + // This is safe to set because the current token is a semicolon, + // which has no string requirement. + bc_vec_string(&p->l.t.v, 1, "1"); + bc_parse_pushNUM(p); s = bc_POSIX_does_not_allow_empty_X_expression_in_for("condition"); + } if (s) RETURN_STATUS(s); if (p->l.t.t != BC_LEX_SCOLON) RETURN_STATUS(bc_error_bad_token()); diff --git a/testsuite/bc.tests b/testsuite/bc.tests index d33f8c90a..edff209bb 100755 --- a/testsuite/bc.tests +++ b/testsuite/bc.tests @@ -51,6 +51,11 @@ testing "bc if 0 else if 1" \ "2\n9\n" \ "" "if (0) 1 else if (1) 2; 9" +testing "bc for(;;)" \ + "bc" \ + "2\n3\n2\n9\n" \ + "" "i=2; for (;;) { 2; if(--i==0) break; 3; }; 9" + testing "bc define auto" \ "bc" \ "8\n9\n" \ -- cgit v1.2.3-55-g6feb From 447dc02c2759e8c965dfcb3280b335b49a8c3a61 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 21 Dec 2018 00:39:02 +0100 Subject: bc: fix comment Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index e7983f38d..05dbd62f6 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -4206,7 +4206,7 @@ static BC_STATUS zbc_parse_for(BcParse *p) if (p->l.t.t != BC_LEX_SCOLON) s = zbc_parse_expr(p, BC_PARSE_REL); else { - // Set this for the next call to bc_parse_number. + // Set this for the next call to bc_parse_pushNUM(). // This is safe to set because the current token is a semicolon, // which has no string requirement. bc_vec_string(&p->l.t.v, 1, "1"); -- cgit v1.2.3-55-g6feb From 5d57bc442dfebefdd7db37c04fe2c9f1343bd08d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 21 Dec 2018 16:22:26 +0100 Subject: bc: fix infinite state growth for "yes 1 | bc" case function old new delta zbc_vm_process 585 672 +87 bc_func_init 50 86 +36 zbc_program_num 990 1022 +32 bc_program_str 17 47 +30 bc_program_current_func - 22 +22 bc_parse_pushNUM 66 87 +21 bc_func_free 27 43 +16 zbc_num_binary 145 147 +2 bc_program_reset 64 61 -3 bc_parse_pushSTR 73 65 -8 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 7/2 up/down: 246/-11) Total: 235 bytes text data bss dec hex filename 981393 485 7296 989174 f17f6 busybox_old 981656 485 7296 989437 f18fd busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 137 +++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 109 insertions(+), 28 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 05dbd62f6..50e5457b9 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -350,6 +350,8 @@ typedef struct BcFunc { BcVec code; IF_BC(BcVec labels;) IF_BC(BcVec autos;) + IF_BC(BcVec strs;) + IF_BC(BcVec consts;) IF_BC(size_t nparams;) } BcFunc; @@ -694,8 +696,8 @@ typedef struct BcProgram { BcVec arrs; BcVec arr_map; - BcVec strs; - BcVec consts; + IF_DC(BcVec strs;) + IF_DC(BcVec consts;) const char *file; @@ -1093,6 +1095,7 @@ static void bc_vec_pop_all(BcVec *v) bc_vec_npop(v, v->len); } +//TODO: return index of pushed data - many callers can use that static void bc_vec_push(BcVec *v, const void *data) { if (v->len + 1 > v->cap) bc_vec_grow(v, 1); @@ -1160,9 +1163,21 @@ static void *bc_vec_item(const BcVec *v, size_t idx) return v->v + v->size * idx; } -static char** bc_program_str(size_t idx) +static void *bc_vec_item_rev(const BcVec *v, size_t idx) +{ + return v->v + v->size * (v->len - idx - 1); +} + +static void *bc_vec_top(const BcVec *v) { - return bc_vec_item(&G.prog.strs, idx); + return v->v + v->size * (v->len - 1); +} + +static FAST_FUNC void bc_vec_free(void *vec) +{ + BcVec *v = (BcVec *) vec; + bc_vec_pop_all(v); + free(v->v); } static BcFunc* bc_program_func(size_t idx) @@ -1172,23 +1187,39 @@ static BcFunc* bc_program_func(size_t idx) // BC_PROG_MAIN is zeroth element, so: #define bc_program_func_BC_PROG_MAIN() ((BcFunc*)(G.prog.fns.v)) -static void *bc_vec_item_rev(const BcVec *v, size_t idx) +#if ENABLE_BC +static BcFunc* bc_program_current_func(void) { - return v->v + v->size * (v->len - idx - 1); + BcInstPtr *ip = bc_vec_top(&G.prog.exestack); + BcFunc *func = bc_program_func(ip->func); + return func; } +#endif -static void *bc_vec_top(const BcVec *v) +static char** bc_program_str(size_t idx) { - return v->v + v->size * (v->len - 1); +#if ENABLE_BC + if (IS_BC) { + BcFunc *func = bc_program_current_func(); + return bc_vec_item(&func->strs, idx); + } +#endif + IF_DC(return bc_vec_item(&G.prog.strs, idx);) } -static FAST_FUNC void bc_vec_free(void *vec) +static char** bc_program_const(size_t idx) { - BcVec *v = (BcVec *) vec; - bc_vec_pop_all(v); - free(v->v); +#if ENABLE_BC + if (IS_BC) { + BcFunc *func = bc_program_current_func(); + return bc_vec_item(&func->consts, idx); + } +#endif + IF_DC(return bc_vec_item(&G.prog.consts, idx);) } + + static int bc_id_cmp(const void *e1, const void *e2) { return strcmp(((const BcId *) e1)->name, ((const BcId *) e2)->name); @@ -2522,11 +2553,18 @@ static BC_STATUS zbc_func_insert(BcFunc *f, char *name, bool var) #define zbc_func_insert(...) (zbc_func_insert(__VA_ARGS__) COMMA_SUCCESS) #endif +static FAST_FUNC void bc_string_free(void *string) +{ + free(*(char**)string); +} + static void bc_func_init(BcFunc *f) { bc_char_vec_init(&f->code); IF_BC(bc_vec_init(&f->labels, sizeof(size_t), NULL);) IF_BC(bc_vec_init(&f->autos, sizeof(BcId), bc_id_free);) + IF_BC(bc_vec_init(&f->strs, sizeof(char *), bc_string_free);) + IF_BC(bc_vec_init(&f->consts, sizeof(char *), bc_string_free);) IF_BC(f->nparams = 0;) } @@ -2536,6 +2574,8 @@ static FAST_FUNC void bc_func_free(void *func) bc_vec_free(&f->code); IF_BC(bc_vec_free(&f->labels);) IF_BC(bc_vec_free(&f->autos);) + IF_BC(bc_vec_free(&f->strs);) + IF_BC(bc_vec_free(&f->consts);) } static void bc_array_expand(BcVec *a, size_t len); @@ -2585,11 +2625,6 @@ static void bc_array_copy(BcVec *d, const BcVec *s) } } -static FAST_FUNC void bc_string_free(void *string) -{ - free(*((char **) string)); -} - #if ENABLE_DC static void dc_result_copy(BcResult *d, BcResult *src) { @@ -3501,8 +3536,8 @@ static BC_STATUS bc_parse_pushSTR(BcParse *p) char *str = xstrdup(p->l.t.v.v); bc_parse_push(p, BC_INST_STR); - bc_parse_pushIndex(p, G.prog.strs.len); - bc_vec_push(&G.prog.strs, &str); + bc_parse_pushIndex(p, p->func->strs.len); + bc_vec_push(&p->func->strs, &str); RETURN_STATUS(zbc_lex_next(&p->l)); } @@ -3512,10 +3547,16 @@ static BC_STATUS bc_parse_pushSTR(BcParse *p) static void bc_parse_pushNUM(BcParse *p) { char *num = xstrdup(p->l.t.v.v); +#if ENABLE_BC && ENABLE_DC + size_t idx = IS_BC ? p->func->consts.len : G.prog.consts.len; + bc_vec_push(IS_BC ? &p->func->consts : &G.prog.consts, &num); +#elif ENABLE_BC + size_t idx = p->func->consts.len; + bc_vec_push(&p->func->consts, &num); +#else // DC size_t idx = G.prog.consts.len; - bc_vec_push(&G.prog.consts, &num); - +#endif bc_parse_push(p, BC_INST_NUM); bc_parse_pushIndex(p, idx); } @@ -3556,7 +3597,7 @@ static void bc_program_reset(void) bc_vec_npop(&G.prog.exestack, G.prog.exestack.len - 1); bc_vec_pop_all(&G.prog.results); - f = bc_program_func(0); + f = bc_program_func_BC_PROG_MAIN(); ip = bc_vec_top(&G.prog.exestack); ip->idx = f->code.len; } @@ -5027,9 +5068,12 @@ static BC_STATUS zbc_program_num(BcResult *r, BcNum **num, bool hex) break; case BC_RESULT_CONSTANT: { BcStatus s; - char *str = *(char**)bc_vec_item(&G.prog.consts, r->d.id.idx); + char *str; unsigned base_t; - size_t len = strlen(str); + size_t len; + + str = *bc_program_const(r->d.id.idx); + len = strlen(str); bc_num_init(&r->d.n, len); @@ -6667,6 +6711,43 @@ static BC_STATUS zbc_vm_process(const char *text) bc_program_reset(); break; } + // bc discards strings, constants and code after each + // top-level statement in the "main program". + // This prevents "yes 1 | bc" from growing its memory + // without bound. This can be done because data stack + // is empty and thus can't hold any references to + // strings or constants, there is no generated code + // which can hold references (after we discard one + // we just executed). Code of functions can have references, + // but bc stores function strings/constants in per-function + // storage. + if (IS_BC) { + BcFunc *f; + BcInstPtr *ip; + + //FIXME: this does not clear up the stack + //for(i=1; i<3; i++) { + // i + // if(i==2) continue + // 77 + //} +// if (G.prog.results.len != 0) +// bb_error_msg_and_die("data stack not empty: %d slots", G.prog.results.len); + + if (G.prog.exestack.len != 1) // should be empty + bb_error_msg_and_die("BUG:call stack"); + + ip = (void*)G.prog.exestack.v; + if (ip->func != BC_PROG_MAIN) + bb_error_msg_and_die("BUG:not MAIN"); +//bb_error_msg("ip->func:%d >idx:%d >len:%d", ip->func, ip->idx, ip->len); + f = bc_program_func_BC_PROG_MAIN(); +//bb_error_msg("MAIN->code.len:%d >strs.len:%d >consts.len:%d", f->code.len, f->strs.len, f->consts.len); // labels, autos, nparams + bc_vec_pop_all(&f->code); + ip->idx = 0; + IF_BC(bc_vec_pop_all(&f->strs);) + IF_BC(bc_vec_pop_all(&f->consts);) + } } dbg_lex_done("%s:%d done", __func__, __LINE__); @@ -6999,8 +7080,8 @@ static void bc_program_free(void) bc_vec_free(&G.prog.var_map); bc_vec_free(&G.prog.arrs); bc_vec_free(&G.prog.arr_map); - bc_vec_free(&G.prog.strs); - bc_vec_free(&G.prog.consts); + IF_DC(bc_vec_free(&G.prog.strs);) + IF_DC(bc_vec_free(&G.prog.consts);) bc_vec_free(&G.prog.results); bc_vec_free(&G.prog.exestack); IF_BC(bc_num_free(&G.prog.last);) @@ -7057,8 +7138,8 @@ static void bc_program_init(void) bc_vec_init(&G.prog.arrs, sizeof(BcVec), bc_vec_free); bc_vec_init(&G.prog.arr_map, sizeof(BcId), bc_id_free); - bc_vec_init(&G.prog.strs, sizeof(char *), bc_string_free); - bc_vec_init(&G.prog.consts, sizeof(char *), bc_string_free); + IF_DC(bc_vec_init(&G.prog.strs, sizeof(char *), bc_string_free);) + IF_DC(bc_vec_init(&G.prog.consts, sizeof(char *), bc_string_free);) bc_vec_init(&G.prog.results, sizeof(BcResult), bc_result_free); bc_vec_init(&G.prog.exestack, sizeof(BcInstPtr), NULL); bc_vec_push(&G.prog.exestack, &ip); -- cgit v1.2.3-55-g6feb From 19eee8ed7cf32de37afa53ce56c62376c880a5a8 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 21 Dec 2018 20:29:34 +0100 Subject: bc: fix for() to not leave data on stack function old new delta zbc_parse_stmt_possibly_auto 1665 1697 +32 zbc_vm_process 672 701 +29 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 61/0) Total: 61 bytes text data bss dec hex filename 981656 485 7296 989437 f18fd busybox_old 981748 485 7296 989529 f1959 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 48 +++++++++++++++++++++++------------------------- testsuite/bc.tests | 15 +++++++++++++++ 2 files changed, 38 insertions(+), 25 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 50e5457b9..441cb0467 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -170,6 +170,8 @@ #define DEBUG_LEXER 0 #define DEBUG_COMPILE 0 #define DEBUG_EXEC 0 +// This can be left enabled for production as well: +#define SANITY_CHECKS 1 #if DEBUG_LEXER static uint8_t lex_indent; @@ -1218,8 +1220,6 @@ static char** bc_program_const(size_t idx) IF_DC(return bc_vec_item(&G.prog.consts, idx);) } - - static int bc_id_cmp(const void *e1, const void *e2) { return strcmp(((const BcId *) e1)->name, ((const BcId *) e2)->name); @@ -4227,12 +4227,15 @@ static BC_STATUS zbc_parse_for(BcParse *p) s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); - if (p->l.t.t != BC_LEX_SCOLON) + if (p->l.t.t != BC_LEX_SCOLON) { s = zbc_parse_expr(p, 0); - else + bc_parse_push(p, BC_INST_POP); + if (s) RETURN_STATUS(s); + } else { s = bc_POSIX_does_not_allow_empty_X_expression_in_for("init"); + IF_ERROR_RETURN_POSSIBLE(if (s) RETURN_STATUS(s);) + } - if (s) RETURN_STATUS(s); if (p->l.t.t != BC_LEX_SCOLON) RETURN_STATUS(bc_error_bad_token()); s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); @@ -4254,8 +4257,8 @@ static BC_STATUS zbc_parse_for(BcParse *p) bc_parse_pushNUM(p); s = bc_POSIX_does_not_allow_empty_X_expression_in_for("condition"); } - if (s) RETURN_STATUS(s); + if (p->l.t.t != BC_LEX_SCOLON) RETURN_STATUS(bc_error_bad_token()); s = zbc_lex_next(&p->l); @@ -4267,12 +4270,14 @@ static BC_STATUS zbc_parse_for(BcParse *p) bc_vec_push(&p->conds, &update_idx); bc_vec_push(&p->func->labels, &p->func->code.len); - if (p->l.t.t != BC_LEX_RPAREN) + if (p->l.t.t != BC_LEX_RPAREN) { s = zbc_parse_expr(p, 0); - else + bc_parse_push(p, BC_INST_POP); + if (s) RETURN_STATUS(s); + } else { s = bc_POSIX_does_not_allow_empty_X_expression_in_for("update"); - - if (s) RETURN_STATUS(s); + IF_ERROR_RETURN_POSSIBLE(if (s) RETURN_STATUS(s);) + } if (p->l.t.t != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); bc_parse_pushJUMP(p, cond_idx); @@ -6434,12 +6439,13 @@ static BC_STATUS zbc_program_exec(void) BcFunc *func = bc_program_func(ip->func); char *code = func->code.v; - dbg_exec("func:%zd bytes:%zd ip:%zd", ip->func, func->code.len, ip->idx); + dbg_exec("func:%zd bytes:%zd ip:%zd results.len:%d", + ip->func, func->code.len, ip->idx, G.prog.results.len); while (ip->idx < func->code.len) { BcStatus s = BC_STATUS_SUCCESS; char inst = code[ip->idx++]; - dbg_exec("inst at %zd:%d", ip->idx - 1, inst); + dbg_exec("inst at %zd:%d results.len:%d", ip->idx - 1, inst, G.prog.results.len); switch (inst) { #if ENABLE_BC case BC_INST_JUMP_ZERO: { @@ -6671,7 +6677,6 @@ static BC_STATUS zbc_program_exec(void) } fflush_and_check(); - } RETURN_STATUS(BC_STATUS_SUCCESS); @@ -6723,23 +6728,16 @@ static BC_STATUS zbc_vm_process(const char *text) // storage. if (IS_BC) { BcFunc *f; - BcInstPtr *ip; - - //FIXME: this does not clear up the stack - //for(i=1; i<3; i++) { - // i - // if(i==2) continue - // 77 - //} -// if (G.prog.results.len != 0) -// bb_error_msg_and_die("data stack not empty: %d slots", G.prog.results.len); + BcInstPtr *ip = (void*)G.prog.exestack.v; +#if SANITY_CHECKS + if (G.prog.results.len != 0) + bb_error_msg_and_die("data stack not empty: %d slots", G.prog.results.len); if (G.prog.exestack.len != 1) // should be empty bb_error_msg_and_die("BUG:call stack"); - - ip = (void*)G.prog.exestack.v; if (ip->func != BC_PROG_MAIN) bb_error_msg_and_die("BUG:not MAIN"); +#endif //bb_error_msg("ip->func:%d >idx:%d >len:%d", ip->func, ip->idx, ip->len); f = bc_program_func_BC_PROG_MAIN(); //bb_error_msg("MAIN->code.len:%d >strs.len:%d >consts.len:%d", f->code.len, f->strs.len, f->consts.len); // labels, autos, nparams diff --git a/testsuite/bc.tests b/testsuite/bc.tests index edff209bb..b3ce894ee 100755 --- a/testsuite/bc.tests +++ b/testsuite/bc.tests @@ -56,6 +56,21 @@ testing "bc for(;;)" \ "2\n3\n2\n9\n" \ "" "i=2; for (;;) { 2; if(--i==0) break; 3; }; 9" +testing "bc for (;cond;)" \ + "bc" \ + "1\n2\n3\n9\n" \ + "" "i=0; for(;i<3;)++i; 9" + +testing "bc for (;cond;upd)" \ + "bc" \ + "1\n2\n3\n9\n" \ + "" "i=1; for(;i<4;i++)i; 9" + +testing "bc for (init;cond;upd)" \ + "bc" \ + "1\n2\n3\n9\n" \ + "" "for(i=1;i<4;i++)i; 9" + testing "bc define auto" \ "bc" \ "8\n9\n" \ -- cgit v1.2.3-55-g6feb From 6ed7fb0a877d550428cb289feb3695dcd2812ab8 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 21 Dec 2018 22:16:17 +0100 Subject: bc: optimize bc_vec_push() usage function old new delta bc_parse_pushNUM 87 80 -7 zbc_parse_stmt_possibly_auto 1697 1689 -8 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-15) Total: -15 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 58 ++++++++++++++++++++++++++-------------------------------- 1 file changed, 26 insertions(+), 32 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 441cb0467..abedbdf0b 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1097,24 +1097,25 @@ static void bc_vec_pop_all(BcVec *v) bc_vec_npop(v, v->len); } -//TODO: return index of pushed data - many callers can use that -static void bc_vec_push(BcVec *v, const void *data) +static size_t bc_vec_push(BcVec *v, const void *data) { - if (v->len + 1 > v->cap) bc_vec_grow(v, 1); - memmove(v->v + (v->size * v->len), data, v->size); - v->len += 1; + size_t len = v->len; + if (len >= v->cap) bc_vec_grow(v, 1); + memmove(v->v + (v->size * len), data, v->size); + v->len++; + return len; } -static void bc_vec_pushByte(BcVec *v, char data) +static size_t bc_vec_pushByte(BcVec *v, char data) { - bc_vec_push(v, &data); + return bc_vec_push(v, &data); } -static void bc_vec_pushZeroByte(BcVec *v) +static size_t bc_vec_pushZeroByte(BcVec *v) { - //bc_vec_pushByte(v, '\0'); + //return bc_vec_pushByte(v, '\0'); // better: - bc_vec_push(v, &const_int_0); + return bc_vec_push(v, &const_int_0); } static void bc_vec_pushAt(BcVec *v, const void *data, size_t idx) @@ -3548,14 +3549,11 @@ static void bc_parse_pushNUM(BcParse *p) { char *num = xstrdup(p->l.t.v.v); #if ENABLE_BC && ENABLE_DC - size_t idx = IS_BC ? p->func->consts.len : G.prog.consts.len; - bc_vec_push(IS_BC ? &p->func->consts : &G.prog.consts, &num); + size_t idx = bc_vec_push(IS_BC ? &p->func->consts : &G.prog.consts, &num); #elif ENABLE_BC - size_t idx = p->func->consts.len; - bc_vec_push(&p->func->consts, &num); + size_t idx = bc_vec_push(&p->func->consts, &num); #else // DC - size_t idx = G.prog.consts.len; - bc_vec_push(&G.prog.consts, &num); + size_t idx = bc_vec_push(&G.prog.consts, &num); #endif bc_parse_push(p, BC_INST_NUM); bc_parse_pushIndex(p, idx); @@ -3652,7 +3650,7 @@ static void bc_program_add_fn(void) //size_t idx; BcFunc f; bc_func_init(&f); - //idx = G.prog.fns.len; + //idx = bc_vec_push(&G.prog.fns, &f); //return idx; } @@ -4135,12 +4133,13 @@ static BC_STATUS zbc_parse_if(BcParse *p) if (s) RETURN_STATUS(s); s = zbc_parse_expr(p, BC_PARSE_REL); if (s) RETURN_STATUS(s); - if (p->l.t.t != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); - ip_idx = p->func->labels.len; + // Encode "if zero, jump to ..." + // Pushed value (destination of the jump) is uninitialized, + // will be rewritten to be address of "end of if()" or of "else". + ip_idx = bc_vec_push(&p->func->labels, &ip_idx); bc_parse_pushJUMP_ZERO(p, ip_idx); - bc_vec_push(&p->func->labels, &ip_idx); s = zbc_parse_stmt_allow_NLINE_before(p, STRING_if); if (s) RETURN_STATUS(s); @@ -4149,15 +4148,14 @@ static BC_STATUS zbc_parse_if(BcParse *p) if (p->l.t.t == BC_LEX_KEY_ELSE) { size_t ip2_idx; - ip2_idx = p->func->labels.len; - - dbg_lex("%s:%d after if() body: BC_INST_JUMP to %zd", __func__, __LINE__, ip2_idx); + // Encode "after then_stmt, jump to end of if()" + ip2_idx = bc_vec_push(&p->func->labels, &ip2_idx); + dbg_lex("%s:%d after if() then_stmt: BC_INST_JUMP to %zd", __func__, __LINE__, ip2_idx); bc_parse_pushJUMP(p, ip2_idx); dbg_lex("%s:%d rewriting 'if_zero' label to jump to 'else'-> %zd", __func__, __LINE__, p->func->code.len); rewrite_label_to_current(p, ip_idx); - bc_vec_push(&p->func->labels, &ip2_idx); ip_idx = ip2_idx; s = zbc_parse_stmt_allow_NLINE_before(p, STRING_else); @@ -4184,10 +4182,8 @@ static BC_STATUS zbc_parse_while(BcParse *p) s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); - cond_idx = p->func->labels.len; + cond_idx = bc_vec_push(&p->func->labels, &p->func->code.len); ip_idx = cond_idx + 1; - - bc_vec_push(&p->func->labels, &p->func->code.len); bc_vec_push(&p->conds, &cond_idx); bc_vec_push(&p->exits, &ip_idx); @@ -4240,13 +4236,11 @@ static BC_STATUS zbc_parse_for(BcParse *p) s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); - cond_idx = p->func->labels.len; + cond_idx = bc_vec_push(&p->func->labels, &p->func->code.len); update_idx = cond_idx + 1; body_idx = update_idx + 1; exit_idx = body_idx + 1; - bc_vec_push(&p->func->labels, &p->func->code.len); - if (p->l.t.t != BC_LEX_SCOLON) s = zbc_parse_expr(p, BC_PARSE_REL); else { @@ -4272,14 +4266,14 @@ static BC_STATUS zbc_parse_for(BcParse *p) if (p->l.t.t != BC_LEX_RPAREN) { s = zbc_parse_expr(p, 0); - bc_parse_push(p, BC_INST_POP); if (s) RETURN_STATUS(s); + if (p->l.t.t != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); + bc_parse_push(p, BC_INST_POP); } else { s = bc_POSIX_does_not_allow_empty_X_expression_in_for("update"); IF_ERROR_RETURN_POSSIBLE(if (s) RETURN_STATUS(s);) } - if (p->l.t.t != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); bc_parse_pushJUMP(p, cond_idx); bc_vec_push(&p->func->labels, &p->func->code.len); -- cgit v1.2.3-55-g6feb From e8e7bda63aeefb17b59718baca592246e24d04df Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 21 Dec 2018 22:36:04 +0100 Subject: bc: use non-allocated BcNum's where appropriate function old new delta zbc_num_printNum 540 543 +3 zdc_program_asciify 407 403 -4 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/1 up/down: 3/-4) Total: -1 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index abedbdf0b..58e3bcb52 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1454,6 +1454,14 @@ static BC_STATUS zbc_num_ulong(BcNum *n, unsigned long *result_p) } #define zbc_num_ulong(...) (zbc_num_ulong(__VA_ARGS__) COMMA_SUCCESS) +#if ULONG_MAX == 0xffffffffUL // 10 digits: 4294967295 +# define ULONG_NUM_BUFSIZE (10 > BC_NUM_DEF_SIZE ? 10 : BC_NUM_DEF_SIZE) +#elif ULONG_MAX == 0xffffffffffffffffULL // 20 digits: 18446744073709551615 +# define ULONG_NUM_BUFSIZE (20 > BC_NUM_DEF_SIZE ? 20 : BC_NUM_DEF_SIZE) +#endif +// minimum BC_NUM_DEF_SIZE, so that bc_num_expand() in bc_num_ulong2num() +// would not hit realloc() code path - not good if num[] is not malloced + static void bc_num_ulong2num(BcNum *n, unsigned long val) { BcDig *ptr; @@ -1462,11 +1470,7 @@ static void bc_num_ulong2num(BcNum *n, unsigned long val) if (val == 0) return; - if (ULONG_MAX == 0xffffffffUL) - bc_num_expand(n, 10); // 10 digits: 4294967295 - if (ULONG_MAX == 0xffffffffffffffffULL) - bc_num_expand(n, 20); // 20 digits: 18446744073709551615 - BUILD_BUG_ON(ULONG_MAX > 0xffffffffffffffffULL); + bc_num_expand(n, ULONG_NUM_BUFSIZE); ptr = n->num; for (;;) { @@ -1645,7 +1649,6 @@ static BC_STATUS zbc_num_shift(BcNum *n, size_t places) static BC_STATUS zbc_num_inv(BcNum *a, BcNum *b, size_t scale) { -//TODO: nice example of non-allocated BcNum, use in other places as well! BcNum one; BcDig num[2]; @@ -2264,6 +2267,7 @@ static void bc_num_parseBase(BcNum *n, const char *val, unsigned base_t) BcStatus s; BcNum temp, mult, result; BcNum base; + BcDig base_digs[ULONG_NUM_BUFSIZE]; BcDig c = '\0'; unsigned long v; size_t i, digits; @@ -2277,8 +2281,8 @@ static void bc_num_parseBase(BcNum *n, const char *val, unsigned base_t) bc_num_init_DEF_SIZE(&temp); bc_num_init_DEF_SIZE(&mult); -//TODO: have BcNumSmall type, with static buffer - bc_num_init_DEF_SIZE(&base); + base.cap = ARRAY_SIZE(base_digs); + base.num = base_digs; bc_num_ulong2num(&base, base_t); for (;;) { @@ -2329,7 +2333,6 @@ static void bc_num_parseBase(BcNum *n, const char *val, unsigned base_t) err: bc_num_free(&result); int_err: - bc_num_free(&base); bc_num_free(&mult); bc_num_free(&temp); } @@ -5430,6 +5433,7 @@ static BC_STATUS zbc_num_printNum(BcNum *n, unsigned base_t, size_t width, BcNum BcStatus s; BcVec stack; BcNum base; + BcDig base_digs[ULONG_NUM_BUFSIZE]; BcNum intp, fracp, digit, frac_len; unsigned long dig, *ptr; size_t i; @@ -5447,8 +5451,8 @@ static BC_STATUS zbc_num_printNum(BcNum *n, unsigned base_t, size_t width, BcNum bc_num_init(&frac_len, BC_NUM_INT(n)); bc_num_copy(&intp, n); bc_num_one(&frac_len); -//TODO: have BcNumSmall type, with static buffer - bc_num_init_DEF_SIZE(&base); + base.cap = ARRAY_SIZE(base_digs); + base.num = base_digs; bc_num_ulong2num(&base, base_t); bc_num_truncate(&intp, intp.rdx); @@ -5483,7 +5487,6 @@ static BC_STATUS zbc_num_printNum(BcNum *n, unsigned base_t, size_t width, BcNum if (s) goto err; } err: - bc_num_free(&base); bc_num_free(&frac_len); bc_num_free(&digit); bc_num_free(&fracp); @@ -6206,16 +6209,16 @@ static BC_STATUS zdc_program_asciify(void) if (BC_PROG_NUM(r, num)) { BcNum strmb; + BcDig strmb_digs[ULONG_NUM_BUFSIZE]; bc_num_init_DEF_SIZE(&n); bc_num_copy(&n, num); bc_num_truncate(&n, n.rdx); -//TODO: have BcNumSmall type, with static buffer - bc_num_init_DEF_SIZE(&strmb); + strmb.cap = ARRAY_SIZE(strmb_digs); + strmb.num = strmb_digs; bc_num_ulong2num(&strmb, 0x100); s = zbc_num_mod(&n, &strmb, &n, 0); - bc_num_free(&strmb); if (s) goto num_err; s = zbc_num_ulong(&n, &val); -- cgit v1.2.3-55-g6feb From 8287b1c869564ad90c0b8fac64551bfef4f6eee0 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 21 Dec 2018 22:43:53 +0100 Subject: bc: remove unnecessary initializations function old new delta zdc_program_asciify 403 395 -8 zbc_program_print 691 683 -8 zbc_program_exec 4079 4068 -11 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/3 up/down: 0/-27) Total: -27 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 58e3bcb52..cf620f8ec 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -5058,6 +5058,7 @@ static BcVec* bc_program_search(char *id, bool var) return bc_vec_item(v, ptr->idx); } +// 'num' need not be initialized on entry static BC_STATUS zbc_program_num(BcResult *r, BcNum **num, bool hex) { switch (r->t) { @@ -5082,12 +5083,10 @@ static BC_STATUS zbc_program_num(BcResult *r, BcNum **num, bool hex) hex = hex && len == 1; base_t = hex ? 16 : G.prog.ib_t; s = zbc_num_parse(&r->d.n, str, base_t); - if (s) { bc_num_free(&r->d.n); RETURN_STATUS(s); } - *num = &r->d.n; r->t = BC_RESULT_TEMP; break; @@ -5566,7 +5565,6 @@ static BC_STATUS zbc_program_print(char inst, size_t idx) RETURN_STATUS(bc_error_stack_has_too_few_elements()); r = bc_vec_item_rev(&G.prog.results, idx); - num = NULL; // is this NULL necessary? s = zbc_program_num(r, &num, false); if (s) RETURN_STATUS(s); @@ -6203,7 +6201,6 @@ static BC_STATUS zdc_program_asciify(void) RETURN_STATUS(bc_error_stack_has_too_few_elements()); r = bc_vec_top(&G.prog.results); - num = NULL; // TODO: is this NULL needed? s = zbc_program_num(r, &num, false); if (s) RETURN_STATUS(s); @@ -6268,7 +6265,6 @@ static BC_STATUS zdc_program_printStream(void) RETURN_STATUS(bc_error_stack_has_too_few_elements()); r = bc_vec_top(&G.prog.results); - n = NULL; // is this needed? s = zbc_program_num(r, &n, false); if (s) RETURN_STATUS(s); -- cgit v1.2.3-55-g6feb From 24e41946355a77b97b43bc64a2a9861c0185f88a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 21 Dec 2018 23:01:26 +0100 Subject: bc: rename BcInstPtr::idx and ::len Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 57 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 28 insertions(+), 29 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index cf620f8ec..2ba530d43 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -388,8 +388,8 @@ typedef struct BcResult { typedef struct BcInstPtr { size_t func; - size_t idx; - IF_BC(size_t len;) + size_t inst_idx; + IF_BC(size_t results_len_before_call;) } BcInstPtr; // BC_LEX_NEG is not used in lexing; it is only for parsing. @@ -3600,7 +3600,7 @@ static void bc_program_reset(void) f = bc_program_func_BC_PROG_MAIN(); ip = bc_vec_top(&G.prog.exestack); - ip->idx = f->code.len; + ip->inst_idx = f->code.len; } // Called when zbc/zdc_parse_parse() detects a failure, @@ -5252,8 +5252,8 @@ static BC_STATUS zbc_program_read(void) } ip.func = BC_PROG_READ; - ip.idx = 0; - IF_BC(ip.len = G.prog.results.len;) + ip.inst_idx = 0; + IF_BC(ip.results_len_before_call = G.prog.results.len;) // Update this pointer, just in case. f = bc_program_func(BC_PROG_READ); @@ -5945,7 +5945,7 @@ static BC_STATUS zbc_program_call(char *code, size_t *idx) BcResult *arg; nparams = bc_program_index(code, idx); - ip.idx = 0; + ip.inst_idx = 0; ip.func = bc_program_index(code, idx); func = bc_program_func(ip.func); @@ -5955,7 +5955,7 @@ static BC_STATUS zbc_program_call(char *code, size_t *idx) if (nparams != func->nparams) { RETURN_STATUS(bc_error_fmt("function has %u parameters, but called with %u", func->nparams, nparams)); } - ip.len = G.prog.results.len - nparams; + ip.results_len_before_call = G.prog.results.len - nparams; for (i = 0; i < nparams; ++i) { BcStatus s; @@ -6000,7 +6000,7 @@ static BC_STATUS zbc_program_return(char inst) size_t i; BcInstPtr *ip = bc_vec_top(&G.prog.exestack); - if (!STACK_HAS_EQUAL_OR_MORE_THAN(&G.prog.results, ip->len + (inst == BC_INST_RET))) + if (!STACK_HAS_EQUAL_OR_MORE_THAN(&G.prog.results, ip->results_len_before_call + (inst == BC_INST_RET))) RETURN_STATUS(bc_error_stack_has_too_few_elements()); f = bc_program_func(ip->func); @@ -6028,7 +6028,7 @@ static BC_STATUS zbc_program_return(char inst) bc_vec_pop(v); } - bc_vec_npop(&G.prog.results, G.prog.results.len - ip->len); + bc_vec_npop(&G.prog.results, G.prog.results.len - ip->results_len_before_call); bc_vec_push(&G.prog.results, &res); bc_vec_pop(&G.prog.exestack); @@ -6391,8 +6391,7 @@ static BC_STATUS zdc_program_execStr(char *code, size_t *bgn, bool cond) bc_parse_free(&prs); } - ip.idx = 0; - IF_BC(ip.len = G.prog.results.len;) + ip.inst_idx = 0; ip.func = fidx; bc_vec_pop(&G.prog.results); @@ -6433,12 +6432,12 @@ static BC_STATUS zbc_program_exec(void) char *code = func->code.v; dbg_exec("func:%zd bytes:%zd ip:%zd results.len:%d", - ip->func, func->code.len, ip->idx, G.prog.results.len); - while (ip->idx < func->code.len) { + ip->func, func->code.len, ip->inst_idx, G.prog.results.len); + while (ip->inst_idx < func->code.len) { BcStatus s = BC_STATUS_SUCCESS; - char inst = code[ip->idx++]; + char inst = code[ip->inst_idx++]; - dbg_exec("inst at %zd:%d results.len:%d", ip->idx - 1, inst, G.prog.results.len); + dbg_exec("inst at %zd:%d results.len:%d", ip->inst_idx - 1, inst, G.prog.results.len); switch (inst) { #if ENABLE_BC case BC_INST_JUMP_ZERO: { @@ -6449,21 +6448,21 @@ static BC_STATUS zbc_program_exec(void) zero = (bc_num_cmp(num, &G.prog.zero) == 0); bc_vec_pop(&G.prog.results); if (!zero) { - bc_program_index(code, &ip->idx); + bc_program_index(code, &ip->inst_idx); break; } // else: fall through } case BC_INST_JUMP: { - size_t idx = bc_program_index(code, &ip->idx); + size_t idx = bc_program_index(code, &ip->inst_idx); size_t *addr = bc_vec_item(&func->labels, idx); dbg_exec("BC_INST_JUMP: to %ld", (long)*addr); - ip->idx = *addr; + ip->inst_idx = *addr; break; } case BC_INST_CALL: dbg_exec("BC_INST_CALL:"); - s = zbc_program_call(code, &ip->idx); + s = zbc_program_call(code, &ip->inst_idx); goto read_updated_ip; case BC_INST_INC_PRE: case BC_INST_DEC_PRE: @@ -6499,12 +6498,12 @@ static BC_STATUS zbc_program_exec(void) goto read_updated_ip; case BC_INST_VAR: dbg_exec("BC_INST_VAR:"); - s = zbc_program_pushVar(code, &ip->idx, false, false); + s = zbc_program_pushVar(code, &ip->inst_idx, false, false); break; case BC_INST_ARRAY_ELEM: case BC_INST_ARRAY: dbg_exec("BC_INST_ARRAY[_ELEM]:"); - s = zbc_program_pushArray(code, &ip->idx, inst); + s = zbc_program_pushArray(code, &ip->inst_idx, inst); break; case BC_INST_LAST: r.t = BC_RESULT_LAST; @@ -6524,7 +6523,7 @@ static BC_STATUS zbc_program_exec(void) case BC_INST_NUM: dbg_exec("BC_INST_NUM:"); r.t = BC_RESULT_CONSTANT; - r.d.id.idx = bc_program_index(code, &ip->idx); + r.d.id.idx = bc_program_index(code, &ip->inst_idx); bc_vec_push(&G.prog.results, &r); break; case BC_INST_POP: @@ -6547,7 +6546,7 @@ static BC_STATUS zbc_program_exec(void) case BC_INST_STR: dbg_exec("BC_INST_STR:"); r.t = BC_RESULT_STR; - r.d.id.idx = bc_program_index(code, &ip->idx); + r.d.id.idx = bc_program_index(code, &ip->inst_idx); bc_vec_push(&G.prog.results, &r); break; case BC_INST_POWER: @@ -6594,7 +6593,7 @@ static BC_STATUS zbc_program_exec(void) break; case BC_INST_EXECUTE: case BC_INST_EXEC_COND: - s = zdc_program_execStr(code, &ip->idx, inst == BC_INST_EXEC_COND); + s = zdc_program_execStr(code, &ip->inst_idx, inst == BC_INST_EXEC_COND); goto read_updated_ip; case BC_INST_PRINT_STACK: { size_t idx; @@ -6637,11 +6636,11 @@ static BC_STATUS zbc_program_exec(void) case BC_INST_LOAD: case BC_INST_PUSH_VAR: { bool copy = inst == BC_INST_LOAD; - s = zbc_program_pushVar(code, &ip->idx, true, copy); + s = zbc_program_pushVar(code, &ip->inst_idx, true, copy); break; } case BC_INST_PUSH_TO_VAR: { - char *name = bc_program_name(code, &ip->idx); + char *name = bc_program_name(code, &ip->inst_idx); s = zbc_program_copyToVar(name, true); free(name); break; @@ -6661,7 +6660,7 @@ static BC_STATUS zbc_program_exec(void) ip = bc_vec_top(&G.prog.exestack); func = bc_program_func(ip->func); code = func->code.v; - dbg_exec("func:%zd bytes:%zd ip:%zd", ip->func, func->code.len, ip->idx); + dbg_exec("func:%zd bytes:%zd ip:%zd", ip->func, func->code.len, ip->inst_idx); } if (s || G_interrupt) { @@ -6731,11 +6730,11 @@ static BC_STATUS zbc_vm_process(const char *text) if (ip->func != BC_PROG_MAIN) bb_error_msg_and_die("BUG:not MAIN"); #endif -//bb_error_msg("ip->func:%d >idx:%d >len:%d", ip->func, ip->idx, ip->len); +//bb_error_msg("ip->func:%d >idx:%d >len:%d", ip->func, ip->inst_idx, ip->len); f = bc_program_func_BC_PROG_MAIN(); //bb_error_msg("MAIN->code.len:%d >strs.len:%d >consts.len:%d", f->code.len, f->strs.len, f->consts.len); // labels, autos, nparams bc_vec_pop_all(&f->code); - ip->idx = 0; + ip->inst_idx = 0; IF_BC(bc_vec_pop_all(&f->strs);) IF_BC(bc_vec_pop_all(&f->consts);) } -- cgit v1.2.3-55-g6feb From 1dc4de9d9bbdf3f60b76cecf94d756ef9394e25f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 21 Dec 2018 23:13:48 +0100 Subject: bc: code shrink function old new delta bc_result_pop_and_push - 73 +73 zbc_program_exec 4068 4064 -4 bc_program_binOpRetire 46 32 -14 zdc_program_assignStr 146 126 -20 zdc_program_asciify 395 370 -25 bc_program_retire 35 7 -28 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 0/5 up/down: 73/-91) Total: -18 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 2ba530d43..cac3cb734 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1106,6 +1106,21 @@ static size_t bc_vec_push(BcVec *v, const void *data) return len; } +// G.prog.results often needs "pop old operand, push result" idiom. +// Can do this without a few extra ops +static size_t bc_result_pop_and_push(const void *data) +{ + BcVec *v = &G.prog.results; + char *last; + size_t len = v->len - 1; + + last = v->v + (v->size * len); + if (v->dtor) + v->dtor(last); + memmove(last, data, v->size); + return len; +} + static size_t bc_vec_pushByte(BcVec *v, char data) { return bc_vec_push(v, &data); @@ -5165,8 +5180,7 @@ static void bc_program_binOpRetire(BcResult *r) { r->t = BC_RESULT_TEMP; bc_vec_pop(&G.prog.results); - bc_vec_pop(&G.prog.results); - bc_vec_push(&G.prog.results, r); + bc_result_pop_and_push(r); } static BC_STATUS zbc_program_prep(BcResult **r, BcNum **n) @@ -5190,8 +5204,7 @@ static BC_STATUS zbc_program_prep(BcResult **r, BcNum **n) static void bc_program_retire(BcResult *r, BcResultType t) { r->t = t; - bc_vec_pop(&G.prog.results); - bc_vec_push(&G.prog.results, r); + bc_result_pop_and_push(r); } static BC_STATUS zbc_program_op(char inst) @@ -5684,9 +5697,7 @@ static BC_STATUS zdc_program_assignStr(BcResult *r, BcVec *v, bool push) bc_vec_pop(&G.prog.results); } - bc_vec_pop(&G.prog.results); - - bc_vec_push(&G.prog.results, &res); + bc_result_pop_and_push(&res); bc_vec_push(v, &n2); RETURN_STATUS(BC_STATUS_SUCCESS); @@ -5928,8 +5939,7 @@ static BC_STATUS zbc_program_incdec(char inst) if (s) RETURN_STATUS(s); if (inst2 == BC_INST_INC_POST || inst2 == BC_INST_DEC_POST) { - bc_vec_pop(&G.prog.results); - bc_vec_push(&G.prog.results, ©); + bc_result_pop_and_push(©); } RETURN_STATUS(s); @@ -6244,8 +6254,7 @@ static BC_STATUS zdc_program_asciify(void) dup: res.t = BC_RESULT_STR; res.d.id.idx = idx; - bc_vec_pop(&G.prog.results); - bc_vec_push(&G.prog.results, &res); + bc_result_pop_and_push(&res); RETURN_STATUS(BC_STATUS_SUCCESS); num_err: -- cgit v1.2.3-55-g6feb From 8c1e72359626789b1b98aeac0225d73d1336bb59 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 22 Dec 2018 01:34:10 +0100 Subject: bc: unbreak read(), remove checks for nested read() function old new delta zbc_parse_pushSTR - 65 +65 common_parse_expr - 32 +32 bc_error_nested_read_call 10 - -10 bc_parse_expr_empty_ok 1977 1963 -14 zdc_parse_expr 635 615 -20 zcommon_parse_expr 32 - -32 zbc_program_exec 4064 4023 -41 bc_parse_pushSTR 65 - -65 ------------------------------------------------------------------------------ (add/remove: 2/3 grow/shrink: 0/3 up/down: 97/-182) Total: -85 bytes text data bss dec hex filename 981661 485 7296 989442 f1902 busybox_old 981540 485 7296 989321 f1889 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 64 ++++++++++++++++++++++-------------------------------- testsuite/bc.tests | 15 +++++++++++++ 2 files changed, 41 insertions(+), 38 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index cac3cb734..1ba8427da 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -314,9 +314,9 @@ typedef enum BcInst { #endif BC_INST_POP, +#if ENABLE_DC BC_INST_POP_EXEC, -#if ENABLE_DC BC_INST_MODEXP, BC_INST_DIVMOD, @@ -662,8 +662,7 @@ typedef struct BcLex { #define BC_PARSE_REL (1 << 0) #define BC_PARSE_PRINT (1 << 1) #define BC_PARSE_NOCALL (1 << 2) -#define BC_PARSE_NOREAD (1 << 3) -#define BC_PARSE_ARRAY (1 << 4) +#define BC_PARSE_ARRAY (1 << 3) typedef struct BcParse { BcLex l; @@ -766,7 +765,6 @@ typedef struct BcProgram { struct globals { IF_FEATURE_BC_SIGNALS(smallint ttyin;) IF_FEATURE_CLEAN_UP(smallint exiting;) - smallint in_read; BcParse prs; BcProgram prog; @@ -1022,10 +1020,6 @@ static ERRORFUNC int bc_error_variable_is_wrong_type(void) { IF_ERROR_RETURN_POSSIBLE(return) bc_error("variable is wrong type"); } -static ERRORFUNC int bc_error_nested_read_call(void) -{ - IF_ERROR_RETURN_POSSIBLE(return) bc_error("read() call inside of a read() call"); -} #if ENABLE_BC static int bc_POSIX_requires(const char *msg) { @@ -3550,7 +3544,7 @@ static void bc_parse_pushJUMP_ZERO(BcParse *p, size_t idx) bc_parse_pushIndex(p, idx); } -static BC_STATUS bc_parse_pushSTR(BcParse *p) +static BC_STATUS zbc_parse_pushSTR(BcParse *p) { char *str = xstrdup(p->l.t.v.v); @@ -3560,7 +3554,7 @@ static BC_STATUS bc_parse_pushSTR(BcParse *p) RETURN_STATUS(zbc_lex_next(&p->l)); } -#define bc_parse_pushSTR(...) (bc_parse_pushSTR(__VA_ARGS__) COMMA_SUCCESS) +#define zbc_parse_pushSTR(...) (zbc_parse_pushSTR(__VA_ARGS__) COMMA_SUCCESS) #endif static void bc_parse_pushNUM(BcParse *p) @@ -4083,7 +4077,7 @@ static BC_STATUS zbc_parse_print(BcParse *p) if (s) RETURN_STATUS(s); type = p->l.t.t; if (type == BC_LEX_STR) { - s = bc_parse_pushSTR(p); + s = zbc_parse_pushSTR(p); } else { s = zbc_parse_expr(p, 0); } @@ -4545,7 +4539,7 @@ static BC_STATUS zbc_parse_stmt_possibly_auto(BcParse *p, bool auto_allowed) s = zbc_parse_expr(p, BC_PARSE_PRINT); break; case BC_LEX_STR: - s = bc_parse_pushSTR(p); + s = zbc_parse_pushSTR(p); bc_parse_push(p, BC_INST_PRINT_STR); break; case BC_LEX_KEY_BREAK: @@ -4645,6 +4639,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) bin_last = true; for (; !G_interrupt && !s && !done && bc_parse_exprs(t); t = p->l.t.t) { + dbg_lex("%s:%d t:%d", __func__, __LINE__, t); switch (t) { case BC_LEX_OP_INC: case BC_LEX_OP_DEC: @@ -4766,8 +4761,6 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) case BC_LEX_KEY_READ: if (BC_PARSE_LEAF(prev, rprn)) return bc_error_bad_expression(); - else if (flags & BC_PARSE_NOREAD) - s = bc_error_nested_read_call(); else s = zbc_parse_read(p); paren_expr = true; @@ -4912,7 +4905,7 @@ static BC_STATUS zdc_parse_cond(BcParse *p, uint8_t inst) } #define zdc_parse_cond(...) (zdc_parse_cond(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t, uint8_t flags) +static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t) { BcStatus s = BC_STATUS_SUCCESS; uint8_t inst; @@ -4950,10 +4943,7 @@ static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t, uint8_t flags) get_token = true; break; case BC_LEX_KEY_READ: - if (flags & BC_PARSE_NOREAD) - s = bc_error_nested_read_call(); - else - bc_parse_push(p, BC_INST_READ); + bc_parse_push(p, BC_INST_READ); get_token = true; break; case BC_LEX_OP_ASSIGN: @@ -5005,7 +4995,7 @@ static BC_STATUS zdc_parse_expr(BcParse *p, uint8_t flags) s = zbc_lex_next(&p->l); } else { dbg_lex("%s:%d", __func__, __LINE__); - s = zdc_parse_token(p, t, flags); + s = zdc_parse_token(p, t); } if (s) RETURN_STATUS(s); } @@ -5038,7 +5028,12 @@ static BC_STATUS zdc_parse_parse(BcParse *p) #endif // ENABLE_DC -static BC_STATUS zcommon_parse_expr(BcParse *p, uint8_t flags) +#if !ENABLE_DC +#define common_parse_expr(p,flags) \ + common_parse_expr(p) +#define flags 0 +#endif +static BC_STATUS common_parse_expr(BcParse *p, uint8_t flags) { if (IS_BC) { IF_BC(RETURN_STATUS(zbc_parse_expr(p, flags))); @@ -5046,7 +5041,7 @@ static BC_STATUS zcommon_parse_expr(BcParse *p, uint8_t flags) IF_DC(RETURN_STATUS(zdc_parse_expr(p, flags))); } } -#define zcommon_parse_expr(...) (zcommon_parse_expr(__VA_ARGS__) COMMA_SUCCESS) +#define zcommon_parse_expr(...) (common_parse_expr(__VA_ARGS__) COMMA_SUCCESS) static BcVec* bc_program_search(char *id, bool var) { @@ -5238,15 +5233,11 @@ static BC_STATUS zbc_program_read(void) BcInstPtr ip; BcFunc *f; - if (G.in_read) - RETURN_STATUS(bc_error_nested_read_call()); - f = bc_program_func(BC_PROG_READ); bc_vec_pop_all(&f->code); sv_file = G.prog.file; G.prog.file = NULL; - G.in_read = 1; bc_char_vec_init(&buf); bc_read_line(&buf, stdin); @@ -5256,7 +5247,7 @@ static BC_STATUS zbc_program_read(void) s = zbc_parse_text_init(&parse, buf.v); if (s) goto exec_err; - s = zcommon_parse_expr(&parse, BC_PARSE_NOREAD); + s = zcommon_parse_expr(&parse, 0); if (s) goto exec_err; if (parse.l.t.t != BC_LEX_NLINE && parse.l.t.t != BC_LEX_EOF) { @@ -5268,14 +5259,10 @@ static BC_STATUS zbc_program_read(void) ip.inst_idx = 0; IF_BC(ip.results_len_before_call = G.prog.results.len;) - // Update this pointer, just in case. - f = bc_program_func(BC_PROG_READ); - - bc_vec_pushByte(&f->code, BC_INST_POP_EXEC); + bc_parse_push(&parse, BC_INST_RET); bc_vec_push(&G.prog.exestack, &ip); exec_err: bc_parse_free(&parse); - G.in_read = 0; G.prog.file = sv_file; bc_vec_free(&buf); RETURN_STATUS(s); @@ -6542,10 +6529,6 @@ static BC_STATUS zbc_program_exec(void) else bc_vec_pop(&G.prog.results); break; - case BC_INST_POP_EXEC: - dbg_exec("BC_INST_POP_EXEC:"); - bc_vec_pop(&G.prog.exestack); - goto read_updated_ip; case BC_INST_PRINT: case BC_INST_PRINT_POP: case BC_INST_PRINT_STR: @@ -6594,6 +6577,10 @@ static BC_STATUS zbc_program_exec(void) s = zbc_program_assign(inst); break; #if ENABLE_DC + case BC_INST_POP_EXEC: + dbg_exec("BC_INST_POP_EXEC:"); + bc_vec_pop(&G.prog.exestack); + goto read_updated_ip; case BC_INST_MODEXP: s = zdc_program_modexp(); break; @@ -7122,11 +7109,12 @@ static void bc_program_init(void) IF_BC(bc_vec_init(&G.prog.fn_map, sizeof(BcId), bc_id_free);) if (IS_BC) { - // Names are chosen simply to never match + // Names are chosen simply to be distinct and never match // a valid function name (and be short) IF_BC(bc_program_addFunc(xstrdup(""))); // func #0: main - IF_BC(bc_program_addFunc(xstrdup(""))); // func #1: for read() + IF_BC(bc_program_addFunc(xstrdup("1"))); // func #1: for read() } else { + // in dc, functions have no names bc_program_add_fn(); bc_program_add_fn(); } diff --git a/testsuite/bc.tests b/testsuite/bc.tests index b3ce894ee..c84a2987c 100755 --- a/testsuite/bc.tests +++ b/testsuite/bc.tests @@ -31,6 +31,21 @@ testing "bc string 1" \ "STR\n" \ "" "\"STR\n\"" +testing "bc read() 4" \ + "bc input" \ + "4\n" \ + "read();halt" "4" + +testing "bc read()^2" \ + "bc input" \ + "16\n" \ + "read()^2;halt" "4\n" + +testing "bc read()*read()" \ + "bc input" \ + "20\n" \ + "read()*read();halt" "4\n5" + testing "bc if 0 else" \ "bc" \ "2\n9\n" \ -- cgit v1.2.3-55-g6feb From 39287e0d0225db167baa34db59a0ae63eecf5a6c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 22 Dec 2018 02:23:08 +0100 Subject: bc: stop using BC_PARSE_NOCALL in dc code function old new delta zdc_program_execStr 465 474 +9 zbc_vm_process 701 699 -2 common_parse_expr 32 29 -3 zdc_parse_expr 615 586 -29 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/3 up/down: 9/-34) Total: -25 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 1ba8427da..65f98afc2 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -302,16 +302,14 @@ typedef enum BcInst { BC_INST_PRINT_STR, #if ENABLE_BC + BC_INST_HALT, BC_INST_JUMP, BC_INST_JUMP_ZERO, BC_INST_CALL, - - BC_INST_RET, BC_INST_RET0, - - BC_INST_HALT, #endif + BC_INST_RET, BC_INST_POP, #if ENABLE_DC @@ -659,10 +657,12 @@ typedef struct BcLex { #define BC_PARSE_STREND (0xff) -#define BC_PARSE_REL (1 << 0) -#define BC_PARSE_PRINT (1 << 1) -#define BC_PARSE_NOCALL (1 << 2) -#define BC_PARSE_ARRAY (1 << 3) +#if ENABLE_BC +# define BC_PARSE_REL (1 << 0) +# define BC_PARSE_PRINT (1 << 1) +# define BC_PARSE_ARRAY (1 << 2) +# define BC_PARSE_NOCALL (1 << 3) +#endif typedef struct BcParse { BcLex l; @@ -4976,7 +4976,7 @@ static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t) } #define zdc_parse_token(...) (zdc_parse_token(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zdc_parse_expr(BcParse *p, uint8_t flags) +static BC_STATUS zdc_parse_expr(BcParse *p) { BcLexType t; @@ -5000,9 +5000,6 @@ static BC_STATUS zdc_parse_expr(BcParse *p, uint8_t flags) if (s) RETURN_STATUS(s); } - if (flags & BC_PARSE_NOCALL) - bc_parse_push(p, BC_INST_POP_EXEC); - dbg_lex_done("%s:%d done", __func__, __LINE__); RETURN_STATUS(BC_STATUS_SUCCESS); } @@ -5015,7 +5012,7 @@ static BC_STATUS zdc_parse_parse(BcParse *p) if (p->l.t.t == BC_LEX_EOF) s = bc_error("end of file"); else - s = zdc_parse_expr(p, 0); + s = zdc_parse_expr(p); if (s || G_interrupt) { bc_parse_reset(p); @@ -5028,8 +5025,8 @@ static BC_STATUS zdc_parse_parse(BcParse *p) #endif // ENABLE_DC -#if !ENABLE_DC -#define common_parse_expr(p,flags) \ +#if !ENABLE_BC +#define common_parse_expr(p, flags) \ common_parse_expr(p) #define flags 0 #endif @@ -5038,8 +5035,9 @@ static BC_STATUS common_parse_expr(BcParse *p, uint8_t flags) if (IS_BC) { IF_BC(RETURN_STATUS(zbc_parse_expr(p, flags))); } else { - IF_DC(RETURN_STATUS(zdc_parse_expr(p, flags))); + IF_DC(RETURN_STATUS(zdc_parse_expr(p))); } +#undef flags } #define zcommon_parse_expr(...) (common_parse_expr(__VA_ARGS__) COMMA_SUCCESS) @@ -6375,7 +6373,7 @@ static BC_STATUS zdc_program_execStr(char *code, size_t *bgn, bool cond) str = *bc_program_str(sidx); s = zbc_parse_text_init(&prs, str); if (s) goto err; - s = zcommon_parse_expr(&prs, BC_PARSE_NOCALL); + s = zcommon_parse_expr(&prs, 0); if (s) goto err; if (prs.l.t.t != BC_LEX_EOF) { s = bc_error_bad_expression(); @@ -6384,6 +6382,7 @@ static BC_STATUS zdc_program_execStr(char *code, size_t *bgn, bool cond) bc_vec_pop_all(&f->code); goto exit; } + bc_parse_push(&prs, BC_INST_POP_EXEC); bc_parse_free(&prs); } @@ -6696,9 +6695,10 @@ static BC_STATUS zbc_vm_process(const char *text) if (s) RETURN_STATUS(s); while (G.prs.l.t.t != BC_LEX_EOF) { - dbg_lex("%s:%d G.prs.l.t.t:%d", __func__, __LINE__, G.prs.l.t.t); + dbg_lex("%s:%d G.prs.l.t.t:%d, parsing...", __func__, __LINE__, G.prs.l.t.t); s = zcommon_parse(&G.prs); if (s) RETURN_STATUS(s); + dbg_lex("%s:%d executing...", __func__, __LINE__); s = zbc_program_exec(); if (s) { bc_program_reset(); -- cgit v1.2.3-55-g6feb From f093e3df2df46f026d5c3f053a6095b5c72387ac Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 22 Dec 2018 02:30:18 +0100 Subject: bc: zcommon_parse_expr() lost its flags argument function old new delta zcommon_parse_expr - 28 +28 zdc_program_execStr 474 472 -2 zbc_program_exec 4023 4021 -2 common_parse_expr 29 - -29 ------------------------------------------------------------------------------ (add/remove: 1/1 grow/shrink: 0/2 up/down: 28/-33) Total: -5 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 65f98afc2..1c47fba1d 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -5025,21 +5025,15 @@ static BC_STATUS zdc_parse_parse(BcParse *p) #endif // ENABLE_DC -#if !ENABLE_BC -#define common_parse_expr(p, flags) \ - common_parse_expr(p) -#define flags 0 -#endif -static BC_STATUS common_parse_expr(BcParse *p, uint8_t flags) +static BC_STATUS zcommon_parse_expr(BcParse *p) { if (IS_BC) { - IF_BC(RETURN_STATUS(zbc_parse_expr(p, flags))); + IF_BC(RETURN_STATUS(zbc_parse_expr(p, 0))); } else { IF_DC(RETURN_STATUS(zdc_parse_expr(p))); } -#undef flags } -#define zcommon_parse_expr(...) (common_parse_expr(__VA_ARGS__) COMMA_SUCCESS) +#define zcommon_parse_expr(...) (zcommon_parse_expr(__VA_ARGS__) COMMA_SUCCESS) static BcVec* bc_program_search(char *id, bool var) { @@ -5245,7 +5239,7 @@ static BC_STATUS zbc_program_read(void) s = zbc_parse_text_init(&parse, buf.v); if (s) goto exec_err; - s = zcommon_parse_expr(&parse, 0); + s = zcommon_parse_expr(&parse); if (s) goto exec_err; if (parse.l.t.t != BC_LEX_NLINE && parse.l.t.t != BC_LEX_EOF) { @@ -6373,7 +6367,7 @@ static BC_STATUS zdc_program_execStr(char *code, size_t *bgn, bool cond) str = *bc_program_str(sidx); s = zbc_parse_text_init(&prs, str); if (s) goto err; - s = zcommon_parse_expr(&prs, 0); + s = zcommon_parse_expr(&prs); if (s) goto err; if (prs.l.t.t != BC_LEX_EOF) { s = bc_error_bad_expression(); -- cgit v1.2.3-55-g6feb From 514967df5e5ef21873dc2f8a303e892e3f200ea4 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 22 Dec 2018 03:38:52 +0100 Subject: bc: zcommon_parse_expr() has only one user, fold it in function old new delta zbc_program_exec 4021 4046 +25 zdc_parse_expr 589 586 -3 zcommon_parse_expr 28 - -28 ------------------------------------------------------------------------------ (add/remove: 0/1 grow/shrink: 1/1 up/down: 25/-31) Total: -6 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 1c47fba1d..4d252cc97 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -4986,6 +4986,7 @@ static BC_STATUS zdc_parse_expr(BcParse *p) BcStatus s; t = p->l.t.t; + dbg_lex("%s:%d G.prs.l.t.t:%d", __func__, __LINE__, G.prs.l.t.t); if (t == BC_LEX_EOF) break; inst = dc_parse_insts[t]; @@ -5009,6 +5010,7 @@ static BC_STATUS zdc_parse_parse(BcParse *p) { BcStatus s; + dbg_lex_enter("%s:%d entered", __func__, __LINE__); if (p->l.t.t == BC_LEX_EOF) s = bc_error("end of file"); else @@ -5019,22 +5021,13 @@ static BC_STATUS zdc_parse_parse(BcParse *p) s = BC_STATUS_FAILURE; } + dbg_lex_done("%s:%d done", __func__, __LINE__); RETURN_STATUS(s); } #define zdc_parse_parse(...) (zdc_parse_parse(__VA_ARGS__) COMMA_SUCCESS) #endif // ENABLE_DC -static BC_STATUS zcommon_parse_expr(BcParse *p) -{ - if (IS_BC) { - IF_BC(RETURN_STATUS(zbc_parse_expr(p, 0))); - } else { - IF_DC(RETURN_STATUS(zdc_parse_expr(p))); - } -} -#define zcommon_parse_expr(...) (zcommon_parse_expr(__VA_ARGS__) COMMA_SUCCESS) - static BcVec* bc_program_search(char *id, bool var) { BcId e, *ptr; @@ -5239,7 +5232,11 @@ static BC_STATUS zbc_program_read(void) s = zbc_parse_text_init(&parse, buf.v); if (s) goto exec_err; - s = zcommon_parse_expr(&parse); + if (IS_BC) { + IF_BC(s = zbc_parse_expr(&parse, 0)); + } else { + IF_DC(s = zdc_parse_expr(&parse)); + } if (s) goto exec_err; if (parse.l.t.t != BC_LEX_NLINE && parse.l.t.t != BC_LEX_EOF) { @@ -6367,7 +6364,7 @@ static BC_STATUS zdc_program_execStr(char *code, size_t *bgn, bool cond) str = *bc_program_str(sidx); s = zbc_parse_text_init(&prs, str); if (s) goto err; - s = zcommon_parse_expr(&prs); + s = zdc_parse_expr(&prs); if (s) goto err; if (prs.l.t.t != BC_LEX_EOF) { s = bc_error_bad_expression(); -- cgit v1.2.3-55-g6feb From 88fcd5cc6c9b64daf200860a53783d03c8dfe225 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 22 Dec 2018 06:00:25 +0100 Subject: bc: fold single-callsite functions into callers, commonalize code function old new delta zbc_vm_process 699 745 +46 zbc_parse_stmt_possibly_auto 1689 1682 -7 bc_parse_reset 113 - -113 ------------------------------------------------------------------------------ (add/remove: 0/1 grow/shrink: 1/1 up/down: 46/-120) Total: -74 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 98 ++++++++++++++++++++-------------------------------------- 1 file changed, 33 insertions(+), 65 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 4d252cc97..29007d828 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -2828,18 +2828,6 @@ static void bc_lex_file(BcLex *l) l->newline = false; } -IF_BC(static BC_STATUS zbc_lex_token(BcLex *l);) -IF_DC(static BC_STATUS zdc_lex_token(BcLex *l);) - -static BC_STATUS zcommon_lex_token(BcLex *l) -{ - if (IS_BC) { - IF_BC(RETURN_STATUS(zbc_lex_token(l));) - } - IF_DC(RETURN_STATUS(zdc_lex_token(l));) -} -#define zcommon_lex_token(...) (zcommon_lex_token(__VA_ARGS__) COMMA_SUCCESS) - static bool bc_lex_more_input(BcLex *l) { size_t str; @@ -2912,6 +2900,9 @@ static bool bc_lex_more_input(BcLex *l) return l->len != 0; } +IF_BC(static BC_STATUS zbc_lex_token(BcLex *l);) +IF_DC(static BC_STATUS zdc_lex_token(BcLex *l);) + static BC_STATUS zbc_lex_next(BcLex *l) { BcStatus s; @@ -2941,7 +2932,11 @@ static BC_STATUS zbc_lex_next(BcLex *l) dbg_lex("next string to parse:'%.*s'", (int)(strchrnul(l->buf + l->i, '\n') - (l->buf + l->i)), l->buf + l->i); - s = zcommon_lex_token(l); + if (IS_BC) { + IF_BC(s = zbc_lex_token(l)); + } else { + IF_DC(s = zdc_lex_token(l)); + } } while (!s && l->t.t == BC_LEX_WHITESPACE); dbg_lex("l->t.t from string:%d", l->t.t); @@ -3571,24 +3566,6 @@ static void bc_parse_pushNUM(BcParse *p) bc_parse_pushIndex(p, idx); } -IF_BC(static BC_STATUS zbc_parse_stmt_or_funcdef(BcParse *p);) -IF_DC(static BC_STATUS zdc_parse_parse(BcParse *p);) - -// "Parse" half of "parse,execute,repeat" main loop -static BC_STATUS zcommon_parse(BcParse *p) -{ - if (IS_BC) { -// FIXME: "eating" of stmt delemiters is coded inconsistently -// (sometimes zbc_parse_stmt() eats the delimiter, sometimes don't), -// which causes bugs such as "print 1 print 2" erroneously accepted, -// or "print 1 else 2" detecting parse error only after executing -// "print 1" part. - IF_BC(RETURN_STATUS(zbc_parse_stmt_or_funcdef(p));) - } - IF_DC(RETURN_STATUS(zdc_parse_parse(p));) -} -#define zcommon_parse(...) (zcommon_parse(__VA_ARGS__) COMMA_SUCCESS) - static BC_STATUS zbc_parse_text_init(BcParse *p, const char *text) { p->func = bc_program_func(p->fidx); @@ -3612,15 +3589,13 @@ static void bc_program_reset(void) ip->inst_idx = f->code.len; } -// Called when zbc/zdc_parse_parse() detects a failure, +// Called when parsing code detects a failure, // resets parsing structures. static void bc_parse_reset(BcParse *p) { if (p->fidx != BC_PROG_MAIN) { - bc_vec_pop_all(&p->func->code); - IF_BC(bc_vec_pop_all(&p->func->labels);) - IF_BC(bc_vec_pop_all(&p->func->autos);) - IF_BC(p->func->nparams = 0;) + bc_func_free(p->func); + bc_func_init(p->func); p->fidx = BC_PROG_MAIN; p->func = bc_program_func_BC_PROG_MAIN(); @@ -4592,11 +4567,6 @@ static BC_STATUS zbc_parse_stmt_possibly_auto(BcParse *p, bool auto_allowed) break; } - if (s || G_interrupt) { - bc_parse_reset(p); - s = BC_STATUS_FAILURE; - } - dbg_lex_done("%s:%d done", __func__, __LINE__); RETURN_STATUS(s); } @@ -4980,13 +4950,13 @@ static BC_STATUS zdc_parse_expr(BcParse *p) { BcLexType t; - dbg_lex_enter("%s:%d entered G.prs.l.t.t:%d", __func__, __LINE__, G.prs.l.t.t); + dbg_lex_enter("%s:%d entered, p->l.t.t:%d", __func__, __LINE__, p->l.t.t); for (;;) { BcInst inst; BcStatus s; t = p->l.t.t; - dbg_lex("%s:%d G.prs.l.t.t:%d", __func__, __LINE__, G.prs.l.t.t); + dbg_lex("%s:%d p->l.t.t:%d", __func__, __LINE__, p->l.t.t); if (t == BC_LEX_EOF) break; inst = dc_parse_insts[t]; @@ -5006,26 +4976,6 @@ static BC_STATUS zdc_parse_expr(BcParse *p) } #define zdc_parse_expr(...) (zdc_parse_expr(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zdc_parse_parse(BcParse *p) -{ - BcStatus s; - - dbg_lex_enter("%s:%d entered", __func__, __LINE__); - if (p->l.t.t == BC_LEX_EOF) - s = bc_error("end of file"); - else - s = zdc_parse_expr(p); - - if (s || G_interrupt) { - bc_parse_reset(p); - s = BC_STATUS_FAILURE; - } - - dbg_lex_done("%s:%d done", __func__, __LINE__); - RETURN_STATUS(s); -} -#define zdc_parse_parse(...) (zdc_parse_parse(__VA_ARGS__) COMMA_SUCCESS) - #endif // ENABLE_DC static BcVec* bc_program_search(char *id, bool var) @@ -6687,8 +6637,26 @@ static BC_STATUS zbc_vm_process(const char *text) while (G.prs.l.t.t != BC_LEX_EOF) { dbg_lex("%s:%d G.prs.l.t.t:%d, parsing...", __func__, __LINE__, G.prs.l.t.t); - s = zcommon_parse(&G.prs); - if (s) RETURN_STATUS(s); + if (IS_BC) { +// FIXME: "eating" of stmt delemiters is coded inconsistently +// (sometimes zbc_parse_stmt() eats the delimiter, sometimes don't), +// which causes bugs such as "print 1 print 2" erroneously accepted, +// or "print 1 else 2" detecting parse error only after executing +// "print 1" part. + IF_BC(s = zbc_parse_stmt_or_funcdef(&G.prs)); + } else { +#if ENABLE_DC + if (G.prs.l.t.t == BC_LEX_EOF) + s = bc_error("end of file"); + else + s = zdc_parse_expr(&G.prs); +#endif + } + if (s || G_interrupt) { + bc_parse_reset(&G.prs); // includes bc_program_reset() + RETURN_STATUS(BC_STATUS_FAILURE); + } + dbg_lex("%s:%d executing...", __func__, __LINE__); s = zbc_program_exec(); if (s) { -- cgit v1.2.3-55-g6feb From 7c1c9dc86bf7d7bc91e906473c0f81a666113402 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 22 Dec 2018 14:18:47 +0100 Subject: bc: shorten sanity-check code function old new delta zbc_vm_process 745 740 -5 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 29007d828..bb83e0a14 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -6678,9 +6678,9 @@ static BC_STATUS zbc_vm_process(const char *text) BcInstPtr *ip = (void*)G.prog.exestack.v; #if SANITY_CHECKS - if (G.prog.results.len != 0) - bb_error_msg_and_die("data stack not empty: %d slots", G.prog.results.len); - if (G.prog.exestack.len != 1) // should be empty + if (G.prog.results.len != 0) // should be empty + bb_error_msg_and_die("BUG:data stack"); + if (G.prog.exestack.len != 1) // should have only main's IP bb_error_msg_and_die("BUG:call stack"); if (ip->func != BC_PROG_MAIN) bb_error_msg_and_die("BUG:not MAIN"); -- cgit v1.2.3-55-g6feb From 5daa1a0adfe08bae588e5293686a84ab3649a2aa Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 22 Dec 2018 16:40:38 +0100 Subject: bc: move zbc_lex_next() out of zdc_parse_string() and zdc_parse_mem() function old new delta zdc_parse_mem 99 93 -6 zdc_parse_expr 586 569 -17 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-23) Total: -23 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index bb83e0a14..5d5449efa 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -4809,7 +4809,7 @@ static BC_STATUS zdc_parse_register(BcParse *p) } #define zdc_parse_register(...) (zdc_parse_register(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zdc_parse_string(BcParse *p) +static void dc_parse_string(BcParse *p) { char *str; size_t len = G.prog.strs.len; @@ -4826,10 +4826,7 @@ static BC_STATUS zdc_parse_string(BcParse *p) p->func = bc_program_func(p->fidx); dbg_lex_done("%s:%d done", __func__, __LINE__); - - RETURN_STATUS(zbc_lex_next(&p->l)); } -#define zdc_parse_string(...) (zdc_parse_string(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zdc_parse_mem(BcParse *p, uint8_t inst, bool name, bool store) { @@ -4847,7 +4844,7 @@ static BC_STATUS zdc_parse_mem(BcParse *p, uint8_t inst, bool name, bool store) bc_parse_push(p, BC_INST_POP); } - RETURN_STATUS(zbc_lex_next(&p->l)); + RETURN_STATUS(BC_STATUS_SUCCESS); } #define zdc_parse_mem(...) (zdc_parse_mem(__VA_ARGS__) COMMA_SUCCESS) @@ -4877,11 +4874,13 @@ static BC_STATUS zdc_parse_cond(BcParse *p, uint8_t inst) static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t) { - BcStatus s = BC_STATUS_SUCCESS; + BcStatus s; uint8_t inst; - bool assign, get_token = false; + bool assign, get_token; dbg_lex_enter("%s:%d entered", __func__, __LINE__); + s = BC_STATUS_SUCCESS; + get_token = true; switch (t) { case BC_LEX_OP_REL_EQ: case BC_LEX_OP_REL_LE: @@ -4890,6 +4889,7 @@ static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t) case BC_LEX_OP_REL_LT: case BC_LEX_OP_REL_GT: s = zdc_parse_cond(p, t - BC_LEX_OP_REL_EQ + BC_INST_REL_EQ); + get_token = false; break; case BC_LEX_SCOLON: case BC_LEX_COLON: @@ -4897,7 +4897,7 @@ static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t) break; case BC_LEX_STR: dbg_lex("%s:%d LEX_STR", __func__, __LINE__); - s = zdc_parse_string(p); + dc_parse_string(p); break; case BC_LEX_NEG: case BC_LEX_NUMBER: @@ -4910,11 +4910,9 @@ static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t) } bc_parse_pushNUM(p); if (t == BC_LEX_NEG) bc_parse_push(p, BC_INST_NEG); - get_token = true; break; case BC_LEX_KEY_READ: bc_parse_push(p, BC_INST_READ); - get_token = true; break; case BC_LEX_OP_ASSIGN: case BC_LEX_STORE_PUSH: @@ -4934,9 +4932,8 @@ static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t) s = zdc_parse_mem(p, inst, false, true); break; default: - s = bc_error_bad_token(); - get_token = true; - break; + dbg_lex_done("%s:%d done (bad token)", __func__, __LINE__); + RETURN_STATUS(bc_error_bad_token()); } if (!s && get_token) s = zbc_lex_next(&p->l); -- cgit v1.2.3-55-g6feb From badf683b0aa693de9b1a7c1634ad20665463c503 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 22 Dec 2018 18:04:08 +0100 Subject: dc: unbreak interactive mode - was trying to get next tokens instead of executing function old new delta zbc_program_read - 268 +268 zdc_program_printStream - 146 +146 zbc_program_exec 4046 4182 +136 zdc_program_execStr 472 512 +40 zdc_parse_exprs_until_eof - 26 +26 zbc_vm_process 740 765 +25 zbc_lex_next 2225 2240 +15 zdc_parse_expr 569 535 -34 zbc_program_pushArray 147 - -147 zdc_program_asciify 370 - -370 ------------------------------------------------------------------------------ (add/remove: 3/2 grow/shrink: 4/1 up/down: 656/-551) Total: 105 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 96 +++++++++++++++++++++++++++++++++++++----------------- testsuite/dc.tests | 15 +++++++++ 2 files changed, 81 insertions(+), 30 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 5d5449efa..d8fbb6ed7 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -3431,6 +3431,17 @@ static BC_STATUS zdc_lex_token(BcLex *l) // l->t.t = BC_LEX_EOF; // break; case '\n': + // '\n' is BC_LEX_NLINE, not BC_LEX_WHITESPACE + // (and "case '\n'" is not just empty here) + // only to allow interactive dc have a way to exit + // "parse" stage of "parse,execute" loop + // on '\n', not on _next_ token (which would mean + // command are not executed on pressing ). + // IOW: typing "1p" should print "1" _at once_, + // not after some more input. + l->t.t = BC_LEX_NLINE; + l->newline = true; + break; case '\t': case '\v': case '\f': @@ -4861,12 +4872,16 @@ static BC_STATUS zdc_parse_cond(BcParse *p, uint8_t inst) s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); + // Note that 'else' part can not be on the next line: + // echo -e '[1p]sa [2p]sb 2 1>a eb' | dc - OK, prints "2" + // echo -e '[1p]sa [2p]sb 2 1>a\neb' | dc - parse error if (p->l.t.t == BC_LEX_ELSE) { s = zdc_parse_register(p); if (s) RETURN_STATUS(s); s = zbc_lex_next(&p->l); - } else + } else { bc_parse_push(p, BC_PARSE_STREND); + } RETURN_STATUS(s); } @@ -4945,33 +4960,32 @@ static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t) static BC_STATUS zdc_parse_expr(BcParse *p) { - BcLexType t; - - dbg_lex_enter("%s:%d entered, p->l.t.t:%d", __func__, __LINE__, p->l.t.t); - for (;;) { - BcInst inst; - BcStatus s; + BcInst inst; + BcStatus s; - t = p->l.t.t; - dbg_lex("%s:%d p->l.t.t:%d", __func__, __LINE__, p->l.t.t); - if (t == BC_LEX_EOF) break; + inst = dc_parse_insts[p->l.t.t]; + if (inst != BC_INST_INVALID) { + bc_parse_push(p, inst); + s = zbc_lex_next(&p->l); + } else { + s = zdc_parse_token(p, p->l.t.t); + } + RETURN_STATUS(s); +} +#define zdc_parse_expr(...) (zdc_parse_expr(__VA_ARGS__) COMMA_SUCCESS) - inst = dc_parse_insts[t]; - if (inst != BC_INST_INVALID) { - dbg_lex("%s:%d", __func__, __LINE__); - bc_parse_push(p, inst); - s = zbc_lex_next(&p->l); - } else { - dbg_lex("%s:%d", __func__, __LINE__); - s = zdc_parse_token(p, t); - } +static BC_STATUS zdc_parse_exprs_until_eof(BcParse *p) +{ + dbg_lex_enter("%s:%d entered, p->l.t.t:%d", __func__, __LINE__, p->l.t.t); + while (p->l.t.t != BC_LEX_EOF) { + BcStatus s = zdc_parse_expr(p); if (s) RETURN_STATUS(s); } dbg_lex_done("%s:%d done", __func__, __LINE__); RETURN_STATUS(BC_STATUS_SUCCESS); } -#define zdc_parse_expr(...) (zdc_parse_expr(__VA_ARGS__) COMMA_SUCCESS) +#define zdc_parse_exprs_until_eof(...) (zdc_parse_exprs_until_eof(__VA_ARGS__) COMMA_SUCCESS) #endif // ENABLE_DC @@ -5182,7 +5196,7 @@ static BC_STATUS zbc_program_read(void) if (IS_BC) { IF_BC(s = zbc_parse_expr(&parse, 0)); } else { - IF_DC(s = zdc_parse_expr(&parse)); + IF_DC(s = zdc_parse_exprs_until_eof(&parse)); } if (s) goto exec_err; @@ -6304,6 +6318,7 @@ static BC_STATUS zdc_program_execStr(char *code, size_t *bgn, bool cond) f = bc_program_func(fidx); if (f->code.len == 0) { + FILE *sv_input_fp; BcParse prs; char *str; @@ -6311,7 +6326,12 @@ static BC_STATUS zdc_program_execStr(char *code, size_t *bgn, bool cond) str = *bc_program_str(sidx); s = zbc_parse_text_init(&prs, str); if (s) goto err; - s = zdc_parse_expr(&prs); + + sv_input_fp = G.input_fp; + G.input_fp = NULL; // "do not read from input file when reached" + s = zdc_parse_exprs_until_eof(&prs); + G.input_fp = sv_input_fp; + if (s) goto err; if (prs.l.t.t != BC_LEX_EOF) { s = bc_error_bad_expression(); @@ -6439,12 +6459,15 @@ static BC_STATUS zbc_program_exec(void) s = zbc_program_pushArray(code, &ip->inst_idx, inst); break; case BC_INST_LAST: +//TODO: this can't happen on dc, right? + dbg_exec("BC_INST_LAST:"); r.t = BC_RESULT_LAST; bc_vec_push(&G.prog.results, &r); break; case BC_INST_IBASE: case BC_INST_SCALE: case BC_INST_OBASE: + dbg_exec("BC_INST_internalvar:"); bc_program_pushGlobal(inst); break; case BC_INST_SCALE_FUNC: @@ -6519,17 +6542,21 @@ static BC_STATUS zbc_program_exec(void) bc_vec_pop(&G.prog.exestack); goto read_updated_ip; case BC_INST_MODEXP: + dbg_exec("BC_INST_MODEXP:"); s = zdc_program_modexp(); break; case BC_INST_DIVMOD: + dbg_exec("BC_INST_DIVMOD:"); s = zdc_program_divmod(); break; case BC_INST_EXECUTE: case BC_INST_EXEC_COND: + dbg_exec("BC_INST_EXEC[_COND]:"); s = zdc_program_execStr(code, &ip->inst_idx, inst == BC_INST_EXEC_COND); goto read_updated_ip; case BC_INST_PRINT_STACK: { size_t idx; + dbg_exec("BC_INST_PRINT_STACK:"); for (idx = 0; idx < G.prog.results.len; ++idx) { s = zbc_program_print(BC_INST_PRINT, idx); if (s) break; @@ -6537,12 +6564,15 @@ static BC_STATUS zbc_program_exec(void) break; } case BC_INST_CLEAR_STACK: + dbg_exec("BC_INST_CLEAR_STACK:"); bc_vec_pop_all(&G.prog.results); break; case BC_INST_STACK_LEN: + dbg_exec("BC_INST_STACK_LEN:"); dc_program_stackLen(); break; case BC_INST_DUPLICATE: + dbg_exec("BC_INST_DUPLICATE:"); if (!STACK_HAS_MORE_THAN(&G.prog.results, 0)) RETURN_STATUS(bc_error_stack_has_too_few_elements()); ptr = bc_vec_top(&G.prog.results); @@ -6551,6 +6581,7 @@ static BC_STATUS zbc_program_exec(void) break; case BC_INST_SWAP: { BcResult *ptr2; + dbg_exec("BC_INST_SWAP:"); if (!STACK_HAS_MORE_THAN(&G.prog.results, 1)) RETURN_STATUS(bc_error_stack_has_too_few_elements()); ptr = bc_vec_item_rev(&G.prog.results, 0); @@ -6561,9 +6592,11 @@ static BC_STATUS zbc_program_exec(void) break; } case BC_INST_ASCIIFY: + dbg_exec("BC_INST_ASCIIFY:"); s = zdc_program_asciify(); break; case BC_INST_PRINT_STREAM: + dbg_exec("BC_INST_STREAM:"); s = zdc_program_printStream(); break; case BC_INST_LOAD: @@ -6585,6 +6618,7 @@ static BC_STATUS zbc_program_exec(void) bc_vec_npop(&G.prog.exestack, 2); goto read_updated_ip; case BC_INST_NQUIT: + dbg_exec("BC_INST_NQUIT:"); s = zdc_program_nquit(); //goto read_updated_ip; - just fall through to it #endif // ENABLE_DC @@ -6629,25 +6663,20 @@ static BC_STATUS zbc_vm_process(const char *text) BcStatus s; dbg_lex_enter("%s:%d entered", __func__, __LINE__); - s = zbc_parse_text_init(&G.prs, text); + s = zbc_parse_text_init(&G.prs, text); // does the first zbc_lex_next() if (s) RETURN_STATUS(s); while (G.prs.l.t.t != BC_LEX_EOF) { dbg_lex("%s:%d G.prs.l.t.t:%d, parsing...", __func__, __LINE__, G.prs.l.t.t); if (IS_BC) { -// FIXME: "eating" of stmt delemiters is coded inconsistently +// FIXME: "eating" of stmt delimiters is coded inconsistently // (sometimes zbc_parse_stmt() eats the delimiter, sometimes don't), // which causes bugs such as "print 1 print 2" erroneously accepted, // or "print 1 else 2" detecting parse error only after executing // "print 1" part. IF_BC(s = zbc_parse_stmt_or_funcdef(&G.prs)); } else { -#if ENABLE_DC - if (G.prs.l.t.t == BC_LEX_EOF) - s = bc_error("end of file"); - else - s = zdc_parse_expr(&G.prs); -#endif + IF_DC(s = zdc_parse_expr(&G.prs)); } if (s || G_interrupt) { bc_parse_reset(&G.prs); // includes bc_program_reset() @@ -6689,6 +6718,13 @@ static BC_STATUS zbc_vm_process(const char *text) ip->inst_idx = 0; IF_BC(bc_vec_pop_all(&f->strs);) IF_BC(bc_vec_pop_all(&f->consts);) + } else { + // Most of dc parsing assumes all whitespace, + // including '\n', is eaten. + if (G.prs.l.t.t == BC_LEX_NLINE) { + s = zbc_lex_next(&G.prs.l); + if (s) RETURN_STATUS(s); + } } } diff --git a/testsuite/dc.tests b/testsuite/dc.tests index 8edfa07ca..cb2dcbc23 100755 --- a/testsuite/dc.tests +++ b/testsuite/dc.tests @@ -41,6 +41,21 @@ testing "dc complex without spaces (multiple args)" \ "16\n" \ "" "" +testing "dc '>a' (conditional execute string) 1" \ + "dc" \ + "1\n9\n" \ + "" "[1p]sa [2p]sb 1 2>a\n9p" + +testing "dc '>a' (conditional execute string) 2" \ + "dc" \ + "9\n" \ + "" "[1p]sa [2p]sb 2 1>a\n9p" + +testing "dc '>aeb' (conditional execute string with else)" \ + "dc" \ + "2\n9\n" \ + "" "[1p]sa [2p]sb 2 1>aeb\n9p" + for f in dc_*.dc; do r="`basename "$f" .dc`_results.txt" test -f "$r" || continue -- cgit v1.2.3-55-g6feb From 5cf0b2d46617cdc52009da526c127ead57ab554f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 22 Dec 2018 18:24:19 +0100 Subject: bc: unbreak "z function" macro machinery Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/miscutils/bc.c b/miscutils/bc.c index d8fbb6ed7..bdee14de4 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -2902,6 +2902,8 @@ static bool bc_lex_more_input(BcLex *l) IF_BC(static BC_STATUS zbc_lex_token(BcLex *l);) IF_DC(static BC_STATUS zdc_lex_token(BcLex *l);) +#define zbc_lex_token(...) (zbc_lex_token(__VA_ARGS__) COMMA_SUCCESS) +#define zdc_lex_token(...) (zdc_lex_token(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_lex_next(BcLex *l) { @@ -3100,6 +3102,7 @@ static BC_STATUS zbc_lex_comment(BcLex *l) } #define zbc_lex_comment(...) (zbc_lex_comment(__VA_ARGS__) COMMA_SUCCESS) +#undef zbc_lex_token static BC_STATUS zbc_lex_token(BcLex *l) { BcStatus s = BC_STATUS_SUCCESS; @@ -3290,6 +3293,7 @@ static BC_STATUS zbc_lex_token(BcLex *l) RETURN_STATUS(s); } +#define zbc_lex_token(...) (zbc_lex_token(__VA_ARGS__) COMMA_SUCCESS) #endif // ENABLE_BC #if ENABLE_DC @@ -3356,6 +3360,7 @@ static BC_STATUS zdc_lex_string(BcLex *l) } #define zdc_lex_string(...) (zdc_lex_string(__VA_ARGS__) COMMA_SUCCESS) +#undef zdc_lex_token static BC_STATUS zdc_lex_token(BcLex *l) { static const //BcLexType - should be this type, but narrower type saves size: @@ -3500,6 +3505,7 @@ static BC_STATUS zdc_lex_token(BcLex *l) RETURN_STATUS(s); } +#define zdc_lex_token(...) (zdc_lex_token(__VA_ARGS__) COMMA_SUCCESS) #endif // ENABLE_DC static void bc_parse_push(BcParse *p, char i) -- cgit v1.2.3-55-g6feb From ec74a9c14572f17ad4a5ff94813a743bc6e6222d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 22 Dec 2018 19:23:46 +0100 Subject: bc: make long-running dc drop data it does not need (when it can) function old new delta zbc_vm_process 765 824 +59 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 49 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index bdee14de4..7be2d0b9b 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -3437,11 +3437,11 @@ static BC_STATUS zdc_lex_token(BcLex *l) // break; case '\n': // '\n' is BC_LEX_NLINE, not BC_LEX_WHITESPACE - // (and "case '\n'" is not just empty here) + // (and "case '\n':" is not just empty here) // only to allow interactive dc have a way to exit // "parse" stage of "parse,execute" loop - // on '\n', not on _next_ token (which would mean - // command are not executed on pressing ). + // on , not on _next_ token (which would mean + // commands are not executed on pressing ). // IOW: typing "1p" should print "1" _at once_, // not after some more input. l->t.t = BC_LEX_NLINE; @@ -6673,6 +6673,9 @@ static BC_STATUS zbc_vm_process(const char *text) if (s) RETURN_STATUS(s); while (G.prs.l.t.t != BC_LEX_EOF) { + BcInstPtr *ip; + BcFunc *f; + dbg_lex("%s:%d G.prs.l.t.t:%d, parsing...", __func__, __LINE__, G.prs.l.t.t); if (IS_BC) { // FIXME: "eating" of stmt delimiters is coded inconsistently @@ -6695,6 +6698,15 @@ static BC_STATUS zbc_vm_process(const char *text) bc_program_reset(); break; } + + ip = (void*)G.prog.exestack.v; +#if SANITY_CHECKS + if (G.prog.exestack.len != 1) // should have only main's IP + bb_error_msg_and_die("BUG:call stack"); + if (ip->func != BC_PROG_MAIN) + bb_error_msg_and_die("BUG:not MAIN"); +#endif + f = bc_program_func_BC_PROG_MAIN(); // bc discards strings, constants and code after each // top-level statement in the "main program". // This prevents "yes 1 | bc" from growing its memory @@ -6706,22 +6718,10 @@ static BC_STATUS zbc_vm_process(const char *text) // but bc stores function strings/constants in per-function // storage. if (IS_BC) { - BcFunc *f; - BcInstPtr *ip = (void*)G.prog.exestack.v; - #if SANITY_CHECKS if (G.prog.results.len != 0) // should be empty bb_error_msg_and_die("BUG:data stack"); - if (G.prog.exestack.len != 1) // should have only main's IP - bb_error_msg_and_die("BUG:call stack"); - if (ip->func != BC_PROG_MAIN) - bb_error_msg_and_die("BUG:not MAIN"); #endif -//bb_error_msg("ip->func:%d >idx:%d >len:%d", ip->func, ip->inst_idx, ip->len); - f = bc_program_func_BC_PROG_MAIN(); -//bb_error_msg("MAIN->code.len:%d >strs.len:%d >consts.len:%d", f->code.len, f->strs.len, f->consts.len); // labels, autos, nparams - bc_vec_pop_all(&f->code); - ip->inst_idx = 0; IF_BC(bc_vec_pop_all(&f->strs);) IF_BC(bc_vec_pop_all(&f->consts);) } else { @@ -6731,7 +6731,26 @@ static BC_STATUS zbc_vm_process(const char *text) s = zbc_lex_next(&G.prs.l); if (s) RETURN_STATUS(s); } + + if (G.prog.results.len == 0 + && G.prog.vars.len == 0 + ) { + // If stack is empty and no registers exist (TODO: or they are all empty), + // we can get rid of accumulated strings and constants. + // In this example dc process should not grow + // its memory consumption with time: + // yes 1pc | dc + IF_DC(bc_vec_pop_all(&G.prog.strs);) + IF_DC(bc_vec_pop_all(&G.prog.consts);) + } + // The code is discarded always (below), thus this example + // should also not grow its memory consumption with time, + // even though its data stack is not empty: + // { echo 1; yes dk; } | dc } + // We drop generated and executed code for both bc and dc: + bc_vec_pop_all(&f->code); + ip->inst_idx = 0; } dbg_lex_done("%s:%d done", __func__, __LINE__); -- cgit v1.2.3-55-g6feb From 1557b76edde8bc810f82ac67e3b83b2d6ccce51c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 22 Dec 2018 21:37:46 +0100 Subject: bc: shrink zbc_num_ulong() Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 7be2d0b9b..876244b34 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1442,20 +1442,21 @@ static void bc_num_copy(BcNum *d, BcNum *s) static BC_STATUS zbc_num_ulong(BcNum *n, unsigned long *result_p) { size_t i; - unsigned long pow, result; + unsigned long result; if (n->neg) RETURN_STATUS(bc_error("negative number")); - for (result = 0, pow = 1, i = n->rdx; i < n->len; ++i) { - unsigned long prev = result, powprev = pow; - - result += ((unsigned long) n->num[i]) * pow; - pow *= 10; - - if (result < prev || pow < powprev) + result = 0; + i = n->len; + while (i > n->rdx) { + unsigned long prev = result; + result = result * 10 + n->num[--i]; + // Even overflowed N*10 can still satisfy N*10>=N. For example, + // 0x1ff00000 * 10 is 0x13f600000, + // or 0x3f600000 truncated to 32 bits. Which is larger. + // However, (N*10)/8 < N check is always correct. + if ((result / 8) < prev) RETURN_STATUS(bc_error("overflow")); - prev = result; - powprev = pow; } *result_p = result; -- cgit v1.2.3-55-g6feb From 2ea8ddf8c245dd160eacf35409572c28345506f7 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 22 Dec 2018 21:45:18 +0100 Subject: bc: do not disallow powers to N.0000 degree - it's even shorter code function old new delta zbc_num_p 440 424 -16 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 876244b34..d7595ce8e 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -2089,7 +2089,8 @@ static FAST_FUNC BC_STATUS zbc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size size_t i, powrdx, resrdx; bool neg; - if (b->rdx) RETURN_STATUS(bc_error("non integer number")); +// GNU bc does not allow 2^2.0. We do. +// if (b->rdx) RETURN_STATUS(bc_error("non integer number")); if (b->len == 0) { bc_num_one(c); @@ -2109,9 +2110,10 @@ static FAST_FUNC BC_STATUS zbc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size neg = b->neg; b->neg = false; - s = zbc_num_ulong(b, &pow); + b->neg = neg; if (s) RETURN_STATUS(s); + // b is not used beyond this point bc_num_init(©, a->len); bc_num_copy(©, a); @@ -2123,7 +2125,6 @@ static FAST_FUNC BC_STATUS zbc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size scale = a->rdx * pow; } - b->neg = neg; for (powrdx = a->rdx; !(pow & 1); pow >>= 1) { powrdx <<= 1; -- cgit v1.2.3-55-g6feb From a9f59db809d45847779b9c631d663a25b6115d7d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 22 Dec 2018 21:52:30 +0100 Subject: bc: avoid having to twiddle b->neg in zbc_num_p() function old new delta zbc_num_ulong_abs - 70 +70 zbc_num_p 424 413 -11 zbc_num_ulong 81 21 -60 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 0/2 up/down: 70/-71) Total: -1 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index d7595ce8e..ae5105b01 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1439,13 +1439,11 @@ static void bc_num_copy(BcNum *d, BcNum *s) } } -static BC_STATUS zbc_num_ulong(BcNum *n, unsigned long *result_p) +static BC_STATUS zbc_num_ulong_abs(BcNum *n, unsigned long *result_p) { size_t i; unsigned long result; - if (n->neg) RETURN_STATUS(bc_error("negative number")); - result = 0; i = n->len; while (i > n->rdx) { @@ -1462,6 +1460,14 @@ static BC_STATUS zbc_num_ulong(BcNum *n, unsigned long *result_p) RETURN_STATUS(BC_STATUS_SUCCESS); } +#define zbc_num_ulong_abs(...) (zbc_num_ulong_abs(__VA_ARGS__) COMMA_SUCCESS) + +static BC_STATUS zbc_num_ulong(BcNum *n, unsigned long *result_p) +{ + if (n->neg) RETURN_STATUS(bc_error("negative number")); + + RETURN_STATUS(zbc_num_ulong_abs(n, result_p)); +} #define zbc_num_ulong(...) (zbc_num_ulong(__VA_ARGS__) COMMA_SUCCESS) #if ULONG_MAX == 0xffffffffUL // 10 digits: 4294967295 @@ -2109,9 +2115,7 @@ static FAST_FUNC BC_STATUS zbc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size } neg = b->neg; - b->neg = false; - s = zbc_num_ulong(b, &pow); - b->neg = neg; + s = zbc_num_ulong_abs(b, &pow); if (s) RETURN_STATUS(s); // b is not used beyond this point @@ -6150,7 +6154,6 @@ static BC_STATUS zdc_program_asciify(void) char *str; char c; size_t idx; - unsigned long val; if (!STACK_HAS_MORE_THAN(&G.prog.results, 0)) RETURN_STATUS(bc_error_stack_has_too_few_elements()); @@ -6160,6 +6163,7 @@ static BC_STATUS zdc_program_asciify(void) if (s) RETURN_STATUS(s); if (BC_PROG_NUM(r, num)) { + unsigned long val; BcNum strmb; BcDig strmb_digs[ULONG_NUM_BUFSIZE]; -- cgit v1.2.3-55-g6feb From 1acac7f9c596cd447d197039216f7b55c9ee3ab3 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 22 Dec 2018 23:14:48 +0100 Subject: bc: do not yet allow 2^2.1 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index ae5105b01..8cd67b0f5 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -2095,8 +2095,10 @@ static FAST_FUNC BC_STATUS zbc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size size_t i, powrdx, resrdx; bool neg; -// GNU bc does not allow 2^2.0. We do. -// if (b->rdx) RETURN_STATUS(bc_error("non integer number")); + // GNU bc does not allow 2^2.0 - we do + for (i = 0; i < b->rdx; i++) + if (b->num[i] != 0) + RETURN_STATUS(bc_error("not an integer")); if (b->len == 0) { bc_num_one(c); @@ -2505,7 +2507,7 @@ static BC_STATUS zdc_num_modexp(BcNum *a, BcNum *b, BcNum *c, BcNum *restrict d) if (c->len == 0) RETURN_STATUS(bc_error("divide by zero")); if (a->rdx || b->rdx || c->rdx) - RETURN_STATUS(bc_error("non integer number")); + RETURN_STATUS(bc_error("not an integer")); if (b->neg) RETURN_STATUS(bc_error("negative number")); -- cgit v1.2.3-55-g6feb From 01eb5e9da1546f5410831d3a5a8d268d630d2653 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 22 Dec 2018 23:59:21 +0100 Subject: bc: shrink modular exponentiation code function old new delta zdc_program_modexp 721 694 -27 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 8cd67b0f5..25150a9eb 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -2503,6 +2503,7 @@ static BC_STATUS zdc_num_modexp(BcNum *a, BcNum *b, BcNum *c, BcNum *restrict d) { BcStatus s; BcNum base, exp, two, temp; + BcDig two_digs[2]; if (c->len == 0) RETURN_STATUS(bc_error("divide by zero")); @@ -2514,11 +2515,13 @@ static BC_STATUS zdc_num_modexp(BcNum *a, BcNum *b, BcNum *c, BcNum *restrict d) bc_num_expand(d, c->len); bc_num_init(&base, c->len); bc_num_init(&exp, b->len); - bc_num_init_DEF_SIZE(&two); bc_num_init(&temp, b->len); + two.cap = ARRAY_SIZE(two_digs); + two.num = two_digs; bc_num_one(&two); - two.num[0] = 2; + two_digs[0] = 2; + bc_num_one(d); s = zbc_num_rem(a, c, &base, 0); @@ -2543,7 +2546,6 @@ static BC_STATUS zdc_num_modexp(BcNum *a, BcNum *b, BcNum *c, BcNum *restrict d) } err: bc_num_free(&temp); - bc_num_free(&two); bc_num_free(&exp); bc_num_free(&base); RETURN_STATUS(s); -- cgit v1.2.3-55-g6feb From 9471bd46603d9f61c76d672b0a679c2b9446c3cf Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 23 Dec 2018 00:13:15 +0100 Subject: bc: fix empty lines in dc generating "bad token" message function old new delta zdc_program_asciify - 370 +370 zbc_program_pushArray - 147 +147 zbc_vm_process 824 828 +4 zbc_program_exec 4182 4046 -136 zdc_program_printStream 146 - -146 zbc_program_read 268 - -268 ------------------------------------------------------------------------------ (add/remove: 2/2 grow/shrink: 1/1 up/down: 521/-550) Total: -29 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 25150a9eb..a7b8aa4bb 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -6695,9 +6695,18 @@ static BC_STATUS zbc_vm_process(const char *text) // "print 1" part. IF_BC(s = zbc_parse_stmt_or_funcdef(&G.prs)); } else { + // Most of dc parsing assumes all whitespace, + // including '\n', is eaten. + while (G.prs.l.t.t == BC_LEX_NLINE) { + s = zbc_lex_next(&G.prs.l); + if (s) goto err; + if (G.prs.l.t.t == BC_LEX_EOF) + goto done; + } IF_DC(s = zdc_parse_expr(&G.prs)); } if (s || G_interrupt) { + err: bc_parse_reset(&G.prs); // includes bc_program_reset() RETURN_STATUS(BC_STATUS_FAILURE); } @@ -6735,13 +6744,6 @@ static BC_STATUS zbc_vm_process(const char *text) IF_BC(bc_vec_pop_all(&f->strs);) IF_BC(bc_vec_pop_all(&f->consts);) } else { - // Most of dc parsing assumes all whitespace, - // including '\n', is eaten. - if (G.prs.l.t.t == BC_LEX_NLINE) { - s = zbc_lex_next(&G.prs.l); - if (s) RETURN_STATUS(s); - } - if (G.prog.results.len == 0 && G.prog.vars.len == 0 ) { @@ -6762,7 +6764,7 @@ static BC_STATUS zbc_vm_process(const char *text) bc_vec_pop_all(&f->code); ip->inst_idx = 0; } - + done: dbg_lex_done("%s:%d done", __func__, __LINE__); RETURN_STATUS(s); } -- cgit v1.2.3-55-g6feb From ad0bd381e97214c6c978f5214bcd328bfea4b3da Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 24 Dec 2018 00:50:32 +0100 Subject: bc: for "dc only" remove handling of LAST, move OBASE enums up to IBASE function old new delta dc_LEX_to_INST - 82 +82 bc_parse_pushNUM - 62 +62 zbc_program_num 981 978 -3 bc_result_free 46 43 -3 zbc_program_binOpPrep 305 300 -5 static.msg 24 12 -12 zbc_program_exec 4013 3994 -19 zdc_parse_expr 583 507 -76 dc_parse_insts 83 - -83 ------------------------------------------------------------------------------ (add/remove: 2/1 grow/shrink: 0/6 up/down: 144/-201) Total: -57 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 157 ++++++++++++++++++++++++++++++--------------------------- 1 file changed, 82 insertions(+), 75 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index a7b8aa4bb..85eeb6743 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -141,7 +141,7 @@ //usage:#define dc_full_usage "\n" //usage: "\nTiny RPN calculator. Operations:" //usage: "\n+, -, *, /, %, ~, ^," IF_NOT_FEATURE_DC_SMALL(" |,") -//usage: "\np - print top of the stack (without popping)" +//usage: "\np - print top of the stack without popping" //usage: "\nf - print entire stack" //usage: "\nk - pop the value and set the precision" //usage: "\ni - pop the value and set input radix" @@ -286,14 +286,14 @@ typedef enum BcInst { BC_INST_VAR, BC_INST_ARRAY_ELEM, BC_INST_ARRAY, - BC_INST_SCALE_FUNC, - BC_INST_IBASE, - BC_INST_SCALE, - BC_INST_LAST, + + BC_INST_IBASE, // order of these constans should match other enums + BC_INST_OBASE, // order of these constans should match other enums + BC_INST_SCALE, // order of these constans should match other enums + IF_BC(BC_INST_LAST,) // order of these constans should match other enums BC_INST_LENGTH, BC_INST_READ, - BC_INST_OBASE, BC_INST_SQRT, BC_INST_PRINT, @@ -365,12 +365,12 @@ typedef enum BcResultType { BC_RESULT_STR, //code uses "inst - BC_INST_IBASE + BC_RESULT_IBASE" construct, - BC_RESULT_IBASE, // relative order should match for: BC_INST_IBASE - BC_RESULT_SCALE, // relative order should match for: BC_INST_SCALE - BC_RESULT_LAST, // relative order should match for: BC_INST_LAST + BC_RESULT_IBASE, // relative order should match for: BC_INST_IBASE + BC_RESULT_OBASE, // relative order should match for: BC_INST_OBASE + BC_RESULT_SCALE, // relative order should match for: BC_INST_SCALE + IF_BC(BC_RESULT_LAST,) // relative order should match for: BC_INST_LAST BC_RESULT_CONSTANT, BC_RESULT_ONE, - BC_RESULT_OBASE, // relative order should match for: BC_INST_OBASE } BcResultType; typedef union BcResultData { @@ -453,12 +453,12 @@ typedef enum BcLexType { BC_LEX_KEY_FOR, BC_LEX_KEY_HALT, // code uses "type - BC_LEX_KEY_IBASE + BC_INST_IBASE" construct, - BC_LEX_KEY_IBASE, // relative order should match for: BC_INST_IBASE + BC_LEX_KEY_IBASE, // relative order should match for: BC_INST_IBASE + BC_LEX_KEY_OBASE, // relative order should match for: BC_INST_OBASE BC_LEX_KEY_IF, - BC_LEX_KEY_LAST, // relative order should match for: BC_INST_LAST + IF_BC(BC_LEX_KEY_LAST,) // relative order should match for: BC_INST_LAST BC_LEX_KEY_LENGTH, BC_LEX_KEY_LIMITS, - BC_LEX_KEY_OBASE, // relative order should match for: BC_INST_OBASE BC_LEX_KEY_PRINT, BC_LEX_KEY_QUIT, BC_LEX_KEY_READ, @@ -487,11 +487,11 @@ typedef enum BcLexType { // code uses "t - BC_LEX_STORE_IBASE + BC_INST_IBASE" construct, BC_LEX_STORE_IBASE, // relative order should match for: BC_INST_IBASE + BC_LEX_STORE_OBASE, // relative order should match for: BC_INST_OBASE BC_LEX_STORE_SCALE, // relative order should match for: BC_INST_SCALE BC_LEX_LOAD, BC_LEX_LOAD_POP, BC_LEX_STORE_PUSH, - BC_LEX_STORE_OBASE, // relative order should match for: BC_INST_OBASE BC_LEX_PRINT_POP, BC_LEX_NQUIT, BC_LEX_SCALE_FACTOR, @@ -513,11 +513,11 @@ static const struct BcLexKeyword bc_lex_kws[20] = { BC_LEX_KW_ENTRY("for" , 1), // 5 BC_LEX_KW_ENTRY("halt" , 0), // 6 BC_LEX_KW_ENTRY("ibase" , 1), // 7 - BC_LEX_KW_ENTRY("if" , 1), // 8 - BC_LEX_KW_ENTRY("last" , 0), // 9 - BC_LEX_KW_ENTRY("length" , 1), // 10 - BC_LEX_KW_ENTRY("limits" , 0), // 11 - BC_LEX_KW_ENTRY("obase" , 1), // 12 + BC_LEX_KW_ENTRY("obase" , 1), // 8 + BC_LEX_KW_ENTRY("if" , 1), // 9 + BC_LEX_KW_ENTRY("last" , 0), // 10 + BC_LEX_KW_ENTRY("length" , 1), // 11 + BC_LEX_KW_ENTRY("limits" , 0), // 12 BC_LEX_KW_ENTRY("print" , 0), // 13 BC_LEX_KW_ENTRY("quit" , 1), // 14 BC_LEX_KW_ENTRY("read" , 0), // 15 @@ -527,10 +527,10 @@ static const struct BcLexKeyword bc_lex_kws[20] = { BC_LEX_KW_ENTRY("while" , 1), // 19 }; #undef BC_LEX_KW_ENTRY -#define STRING_if (bc_lex_kws[8].name8) #define STRING_else (bc_lex_kws[4].name8) -#define STRING_while (bc_lex_kws[19].name8) #define STRING_for (bc_lex_kws[5].name8) +#define STRING_if (bc_lex_kws[9].name8) +#define STRING_while (bc_lex_kws[19].name8) enum { POSIX_KWORD_MASK = 0 | (1 << 0) // 0 @@ -542,10 +542,10 @@ enum { | (0 << 6) // 6 | (1 << 7) // 7 | (1 << 8) // 8 - | (0 << 9) // 9 - | (1 << 10) // 10 - | (0 << 11) // 11 - | (1 << 12) // 12 + | (1 << 9) // 9 + | (0 << 10) // 10 + | (1 << 11) // 11 + | (0 << 12) // 12 | (0 << 13) // 13 | (1 << 14) // 14 | (0 << 15) // 15 @@ -560,19 +560,19 @@ enum { // true if the token is valid in an expression, false otherwise. // Used to figure out when expr parsing should stop *without error message* // - 0 element indicates this condition. 1 means "this token is to be eaten -// as part of the expression", token can them still be determined to be invalid +// as part of the expression", it can then still be determined to be invalid // by later processing. enum { #define EXBITS(a,b,c,d,e,f,g,h) \ ((uint64_t)((a << 0)+(b << 1)+(c << 2)+(d << 3)+(e << 4)+(f << 5)+(g << 6)+(h << 7))) - BC_PARSE_EXPRS_BITS = 0 - + (EXBITS(0,0,1,1,1,1,1,1) << (0*8)) // 0: eof inval ++ -- - ^ * / - + (EXBITS(1,1,1,1,1,1,1,1) << (1*8)) // 8: % + - == <= >= != < - + (EXBITS(1,1,1,1,1,1,1,1) << (2*8)) // 16: > ! || && ^= *= /= %= - + (EXBITS(1,1,1,0,0,1,1,0) << (3*8)) // 24: += -= = NL WS ( ) [ - + (EXBITS(0,0,0,0,0,0,1,1) << (4*8)) // 32: , ] { ; } STR NAME NUM - + (EXBITS(0,0,0,0,0,0,0,1) << (5*8)) // 40: auto break cont define else for halt ibase - + (EXBITS(0,1,1,1,1,0,0,1) << (6*8)) // 48: if last len limits obase print quit read - bug, why "limits" is allowed? + BC_PARSE_EXPRS_BITS = 0 // corresponding BC_LEX_xyz: + + (EXBITS(0,0,1,1,1,1,1,1) << (0*8)) // 0: eof inval ++ -- - ^ * / + + (EXBITS(1,1,1,1,1,1,1,1) << (1*8)) // 8: % + - == <= >= != < + + (EXBITS(1,1,1,1,1,1,1,1) << (2*8)) // 16: > ! || && ^= *= /= %= + + (EXBITS(1,1,1,0,0,1,1,0) << (3*8)) // 24: += -= = NL WS ( ) [ + + (EXBITS(0,0,0,0,0,0,1,1) << (4*8)) // 32: , ] { ; } STR NAME NUM + + (EXBITS(0,0,0,0,0,0,0,1) << (5*8)) // 40: auto break cont define else for halt ibase + + (EXBITS(1,0,1,1,1,0,0,1) << (6*8)) // 48: obase if last len limits print quit read - bug, why "limits" is allowed? + (EXBITS(0,1,1,0,0,0,0,0) << (7*8)) // 56: return scale sqrt while #undef EXBITS }; @@ -615,30 +615,30 @@ static const uint8_t bc_parse_ops[] = { #if ENABLE_DC static const //BcInst - should be this type. Using signed narrow type since BC_INST_INVALID is -1 int8_t -dc_parse_insts[] = { - BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_REL_GE, - BC_INST_INVALID, BC_INST_POWER, BC_INST_MULTIPLY, BC_INST_DIVIDE, - BC_INST_MODULUS, BC_INST_PLUS, BC_INST_MINUS, - BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, - BC_INST_INVALID, BC_INST_INVALID, - BC_INST_BOOL_NOT, BC_INST_INVALID, BC_INST_INVALID, - BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, - BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, - BC_INST_INVALID, BC_INST_INVALID, BC_INST_REL_GT, BC_INST_INVALID, - BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_REL_GE, - BC_INST_INVALID, BC_INST_INVALID, - BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, - BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, - BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_IBASE, - BC_INST_INVALID, BC_INST_INVALID, BC_INST_LENGTH, BC_INST_INVALID, - BC_INST_OBASE, BC_INST_PRINT, BC_INST_QUIT, BC_INST_INVALID, - BC_INST_INVALID, BC_INST_SCALE, BC_INST_SQRT, BC_INST_INVALID, - BC_INST_REL_EQ, BC_INST_MODEXP, BC_INST_DIVMOD, BC_INST_INVALID, - BC_INST_INVALID, BC_INST_EXECUTE, BC_INST_PRINT_STACK, BC_INST_CLEAR_STACK, - BC_INST_STACK_LEN, BC_INST_DUPLICATE, BC_INST_SWAP, BC_INST_POP, - BC_INST_ASCIIFY, BC_INST_PRINT_STREAM, BC_INST_INVALID, BC_INST_INVALID, - BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, - BC_INST_PRINT, BC_INST_NQUIT, BC_INST_SCALE_FUNC, +dc_LEX_to_INST[] = { // (so many INVALIDs b/c dc parser does not generate these LEXs) // corresponding BC_LEX_xyz: + BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_REL_GE, // EOF INVALID OP_INC OP_DEC + BC_INST_INVALID, BC_INST_POWER, BC_INST_MULTIPLY, BC_INST_DIVIDE, // NEG OP_POWER OP_MULTIPLY OP_DIVIDE + BC_INST_MODULUS, BC_INST_PLUS, BC_INST_MINUS, // OP_MODULUS OP_PLUS OP_MINUS + BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, // OP_REL_EQ OP_REL_LE OP_REL_GE OP_REL_NE + BC_INST_INVALID, BC_INST_INVALID, // OP_REL_LT OP_REL_GT + BC_INST_BOOL_NOT, BC_INST_INVALID, BC_INST_INVALID, // OP_BOOL_NOT OP_BOOL_OR OP_BOOL_AND + BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, // OP_ASSIGN_POWER OP_ASSIGN_MULTIPLY OP_ASSIGN_DIVIDE OP_ASSIGN_MODULUS + BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, // OP_ASSIGN_PLUS OP_ASSIGN_MINUS OP_ASSIGN + BC_INST_INVALID, BC_INST_INVALID, BC_INST_REL_GT, BC_INST_INVALID, // NLINE WHITESPACE LPAREN RPAREN + BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_REL_GE, // LBRACKET COMMA RBRACKET LBRACE + BC_INST_INVALID, BC_INST_INVALID, // SCOLON RBRACE + BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, // STR NAME NUMBER + BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, // KEY_AUTO KEY_BREAK KEY_CONTINUE KEY_DEFINE + BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_IBASE, // KEY_ELSE KEY_FOR KEY_HALT KEY_IBASE + BC_INST_OBASE, BC_INST_INVALID, IF_BC(BC_INST_INVALID,) BC_INST_LENGTH,//KEY_OBASE KEY_IF KEY_LAST(bc) KEY_LENGTH + BC_INST_INVALID, BC_INST_PRINT, BC_INST_QUIT, BC_INST_INVALID, // KEY_LIMITS KEY_PRINT KEY_QUIT KEY_READ + BC_INST_INVALID, BC_INST_SCALE, BC_INST_SQRT, BC_INST_INVALID, // KEY_RETURN KEY_SCALE KEY_SQRT KEY_WHILE + BC_INST_REL_EQ, BC_INST_MODEXP, BC_INST_DIVMOD, BC_INST_INVALID, // EQ_NO_REG OP_MODEXP OP_DIVMOD COLON + BC_INST_INVALID, BC_INST_EXECUTE, BC_INST_PRINT_STACK, BC_INST_CLEAR_STACK, //ELSE EXECUTE PRINT_STACK CLEAR_STACK + BC_INST_STACK_LEN, BC_INST_DUPLICATE, BC_INST_SWAP, BC_INST_POP, // STACK_LEVEL DUPLICATE SWAP POP + BC_INST_ASCIIFY, BC_INST_PRINT_STREAM, BC_INST_INVALID, BC_INST_INVALID, //ASCIIFY PRINT_STREAM STORE_IBASE STORE_OBASE + BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, // STORE_SCALE LOAD LOAD_POP STORE_PUSH + BC_INST_PRINT, BC_INST_NQUIT, BC_INST_SCALE_FUNC, // PRINT_POP NQUIT SCALE_FACTOR }; #endif // ENABLE_DC @@ -2667,7 +2667,7 @@ static void dc_result_copy(BcResult *d, BcResult *src) d->d.id.name = xstrdup(src->d.id.name); break; case BC_RESULT_CONSTANT: - case BC_RESULT_LAST: + IF_BC(case BC_RESULT_LAST:) case BC_RESULT_ONE: case BC_RESULT_STR: memcpy(&d->d.n, &src->d.n, sizeof(BcNum)); @@ -4919,11 +4919,13 @@ static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t) case BC_LEX_OP_REL_NE: case BC_LEX_OP_REL_LT: case BC_LEX_OP_REL_GT: + dbg_lex("%s:%d LEX_OP_REL_xyz", __func__, __LINE__); s = zdc_parse_cond(p, t - BC_LEX_OP_REL_EQ + BC_INST_REL_EQ); get_token = false; break; case BC_LEX_SCOLON: case BC_LEX_COLON: + dbg_lex("%s:%d LEX_[S]COLON", __func__, __LINE__); s = zdc_parse_mem(p, BC_INST_ARRAY_ELEM, true, t == BC_LEX_COLON); break; case BC_LEX_STR: @@ -4931,34 +4933,39 @@ static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t) dc_parse_string(p); break; case BC_LEX_NEG: + dbg_lex("%s:%d LEX_NEG", __func__, __LINE__); + s = zbc_lex_next(&p->l); + if (s) RETURN_STATUS(s); + if (p->l.t.t != BC_LEX_NUMBER) + RETURN_STATUS(bc_error_bad_token()); + bc_parse_pushNUM(p); + bc_parse_push(p, BC_INST_NEG); + break; case BC_LEX_NUMBER: - dbg_lex("%s:%d LEX_NEG/NUMBER", __func__, __LINE__); - if (t == BC_LEX_NEG) { - s = zbc_lex_next(&p->l); - if (s) RETURN_STATUS(s); - if (p->l.t.t != BC_LEX_NUMBER) - RETURN_STATUS(bc_error_bad_token()); - } + dbg_lex("%s:%d LEX_NUMBER", __func__, __LINE__); bc_parse_pushNUM(p); - if (t == BC_LEX_NEG) bc_parse_push(p, BC_INST_NEG); break; case BC_LEX_KEY_READ: + dbg_lex("%s:%d LEX_KEY_READ", __func__, __LINE__); bc_parse_push(p, BC_INST_READ); break; case BC_LEX_OP_ASSIGN: case BC_LEX_STORE_PUSH: + dbg_lex("%s:%d LEX_OP_ASSIGN/STORE_PUSH", __func__, __LINE__); assign = t == BC_LEX_OP_ASSIGN; inst = assign ? BC_INST_VAR : BC_INST_PUSH_TO_VAR; s = zdc_parse_mem(p, inst, true, assign); break; case BC_LEX_LOAD: case BC_LEX_LOAD_POP: + dbg_lex("%s:%d LEX_OP_LOAD[_POP]", __func__, __LINE__); inst = t == BC_LEX_LOAD_POP ? BC_INST_PUSH_VAR : BC_INST_LOAD; s = zdc_parse_mem(p, inst, true, false); break; case BC_LEX_STORE_IBASE: case BC_LEX_STORE_SCALE: case BC_LEX_STORE_OBASE: + dbg_lex("%s:%d LEX_OP_STORE_I/OBASE/SCALE", __func__, __LINE__); inst = t - BC_LEX_STORE_IBASE + BC_INST_IBASE; s = zdc_parse_mem(p, inst, false, true); break; @@ -4979,7 +4986,7 @@ static BC_STATUS zdc_parse_expr(BcParse *p) BcInst inst; BcStatus s; - inst = dc_parse_insts[p->l.t.t]; + inst = dc_LEX_to_INST[p->l.t.t]; if (inst != BC_INST_INVALID) { bc_parse_push(p, inst); s = zbc_lex_next(&p->l); @@ -5086,9 +5093,11 @@ static BC_STATUS zbc_program_num(BcResult *r, BcNum **num, bool hex) *num = &G.prog.one; break; #endif +#if SANITY_CHECKS default: // Testing the theory that dc does not reach LAST/ONE bb_error_msg_and_die("BUG:%d", r->t); +#endif } RETURN_STATUS(BC_STATUS_SUCCESS); @@ -5750,11 +5759,8 @@ static BC_STATUS zbc_program_assign(char inst) if (ib || sc || left->t == BC_RESULT_OBASE) { static const char *const msg[] = { "bad ibase; must be [2,16]", //BC_RESULT_IBASE - "bad scale; must be [0,"BC_MAX_SCALE_STR"]", //BC_RESULT_SCALE - NULL, //can't happen //BC_RESULT_LAST - NULL, //can't happen //BC_RESULT_CONSTANT - NULL, //can't happen //BC_RESULT_ONE "bad obase; must be [2,"BC_MAX_OBASE_STR"]", //BC_RESULT_OBASE + "bad scale; must be [0,"BC_MAX_SCALE_STR"]", //BC_RESULT_SCALE }; size_t *ptr; size_t max; @@ -6474,16 +6480,17 @@ static BC_STATUS zbc_program_exec(void) dbg_exec("BC_INST_ARRAY[_ELEM]:"); s = zbc_program_pushArray(code, &ip->inst_idx, inst); break; +#if ENABLE_BC case BC_INST_LAST: -//TODO: this can't happen on dc, right? dbg_exec("BC_INST_LAST:"); r.t = BC_RESULT_LAST; bc_vec_push(&G.prog.results, &r); break; +#endif case BC_INST_IBASE: - case BC_INST_SCALE: case BC_INST_OBASE: - dbg_exec("BC_INST_internalvar:"); + case BC_INST_SCALE: + dbg_exec("BC_INST_internalvar(%d):", inst - BC_INST_IBASE); bc_program_pushGlobal(inst); break; case BC_INST_SCALE_FUNC: -- cgit v1.2.3-55-g6feb From 73b2c6082574aff51e5bb6560449c5fc746cf7bf Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 24 Dec 2018 01:02:59 +0100 Subject: bc: fix incorrect bit in BC_PARSE_EXPRS_BITS: 'limits' is not allowed Alsl, move and rename dc_lex_tokens[] to dc_char_to_LEX[] Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 90 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 85eeb6743..d2583313c 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -572,7 +572,7 @@ enum { + (EXBITS(1,1,1,0,0,1,1,0) << (3*8)) // 24: += -= = NL WS ( ) [ + (EXBITS(0,0,0,0,0,0,1,1) << (4*8)) // 32: , ] { ; } STR NAME NUM + (EXBITS(0,0,0,0,0,0,0,1) << (5*8)) // 40: auto break cont define else for halt ibase - + (EXBITS(1,0,1,1,1,0,0,1) << (6*8)) // 48: obase if last len limits print quit read - bug, why "limits" is allowed? + + (EXBITS(1,0,1,1,0,0,0,1) << (6*8)) // 48: obase if last length limits print quit read + (EXBITS(0,1,1,0,0,0,0,0) << (7*8)) // 56: return scale sqrt while #undef EXBITS }; @@ -613,6 +613,49 @@ static const uint8_t bc_parse_ops[] = { #endif // ENABLE_BC #if ENABLE_DC +static const //BcLexType - should be this type +uint8_t +dc_char_to_LEX[] = { + /* %&'( */ + BC_LEX_OP_MODULUS, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_LPAREN, + /* )*+, */ + BC_LEX_INVALID, BC_LEX_OP_MULTIPLY, BC_LEX_OP_PLUS, BC_LEX_INVALID, + /* -./ */ + BC_LEX_OP_MINUS, BC_LEX_INVALID, BC_LEX_OP_DIVIDE, + /* 0123456789 */ + BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, + BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, + BC_LEX_INVALID, BC_LEX_INVALID, + /* :;<=>?@ */ + BC_LEX_COLON, BC_LEX_SCOLON, BC_LEX_OP_REL_GT, BC_LEX_OP_REL_EQ, + BC_LEX_OP_REL_LT, BC_LEX_KEY_READ, BC_LEX_INVALID, + /* ABCDEFGH */ + BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, + BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_EQ_NO_REG, BC_LEX_INVALID, + /* IJKLMNOP */ + BC_LEX_KEY_IBASE, BC_LEX_INVALID, BC_LEX_KEY_SCALE, BC_LEX_LOAD_POP, + BC_LEX_INVALID, BC_LEX_OP_BOOL_NOT, BC_LEX_KEY_OBASE, BC_LEX_PRINT_STREAM, + /* QRSTUVWXY */ + BC_LEX_NQUIT, BC_LEX_POP, BC_LEX_STORE_PUSH, BC_LEX_INVALID, BC_LEX_INVALID, + BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_SCALE_FACTOR, BC_LEX_INVALID, + /* Z[\] */ + BC_LEX_KEY_LENGTH, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, + /* ^_` */ + BC_LEX_OP_POWER, BC_LEX_NEG, BC_LEX_INVALID, + /* abcdefgh */ + BC_LEX_ASCIIFY, BC_LEX_INVALID, BC_LEX_CLEAR_STACK, BC_LEX_DUPLICATE, + BC_LEX_ELSE, BC_LEX_PRINT_STACK, BC_LEX_INVALID, BC_LEX_INVALID, + /* ijklmnop */ + BC_LEX_STORE_IBASE, BC_LEX_INVALID, BC_LEX_STORE_SCALE, BC_LEX_LOAD, + BC_LEX_INVALID, BC_LEX_PRINT_POP, BC_LEX_STORE_OBASE, BC_LEX_KEY_PRINT, + /* qrstuvwx */ + BC_LEX_KEY_QUIT, BC_LEX_SWAP, BC_LEX_OP_ASSIGN, BC_LEX_INVALID, + BC_LEX_INVALID, BC_LEX_KEY_SQRT, BC_LEX_INVALID, BC_LEX_EXECUTE, + /* yz */ + BC_LEX_INVALID, BC_LEX_STACK_LEVEL, + /* {|}~ */ + BC_LEX_LBRACE, BC_LEX_OP_MODEXP, BC_LEX_INVALID, BC_LEX_OP_DIVMOD, +}; static const //BcInst - should be this type. Using signed narrow type since BC_INST_INVALID is -1 int8_t dc_LEX_to_INST[] = { // (so many INVALIDs b/c dc parser does not generate these LEXs) // corresponding BC_LEX_xyz: @@ -3381,49 +3424,6 @@ static BC_STATUS zdc_lex_token(BcLex *l) BC_LEX_ELSE, BC_LEX_LOAD, BC_LEX_LOAD_POP, BC_LEX_OP_ASSIGN, BC_LEX_STORE_PUSH, }; - static const //BcLexType - should be this type - uint8_t - dc_lex_tokens[] = { - /* %&'( */ - BC_LEX_OP_MODULUS, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_LPAREN, - /* )*+, */ - BC_LEX_INVALID, BC_LEX_OP_MULTIPLY, BC_LEX_OP_PLUS, BC_LEX_INVALID, - /* -./ */ - BC_LEX_OP_MINUS, BC_LEX_INVALID, BC_LEX_OP_DIVIDE, - /* 0123456789 */ - BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, - BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, - BC_LEX_INVALID, BC_LEX_INVALID, - /* :;<=>?@ */ - BC_LEX_COLON, BC_LEX_SCOLON, BC_LEX_OP_REL_GT, BC_LEX_OP_REL_EQ, - BC_LEX_OP_REL_LT, BC_LEX_KEY_READ, BC_LEX_INVALID, - /* ABCDEFGH */ - BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, - BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_EQ_NO_REG, BC_LEX_INVALID, - /* IJKLMNOP */ - BC_LEX_KEY_IBASE, BC_LEX_INVALID, BC_LEX_KEY_SCALE, BC_LEX_LOAD_POP, - BC_LEX_INVALID, BC_LEX_OP_BOOL_NOT, BC_LEX_KEY_OBASE, BC_LEX_PRINT_STREAM, - /* QRSTUVWXY */ - BC_LEX_NQUIT, BC_LEX_POP, BC_LEX_STORE_PUSH, BC_LEX_INVALID, BC_LEX_INVALID, - BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_SCALE_FACTOR, BC_LEX_INVALID, - /* Z[\] */ - BC_LEX_KEY_LENGTH, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, - /* ^_` */ - BC_LEX_OP_POWER, BC_LEX_NEG, BC_LEX_INVALID, - /* abcdefgh */ - BC_LEX_ASCIIFY, BC_LEX_INVALID, BC_LEX_CLEAR_STACK, BC_LEX_DUPLICATE, - BC_LEX_ELSE, BC_LEX_PRINT_STACK, BC_LEX_INVALID, BC_LEX_INVALID, - /* ijklmnop */ - BC_LEX_STORE_IBASE, BC_LEX_INVALID, BC_LEX_STORE_SCALE, BC_LEX_LOAD, - BC_LEX_INVALID, BC_LEX_PRINT_POP, BC_LEX_STORE_OBASE, BC_LEX_KEY_PRINT, - /* qrstuvwx */ - BC_LEX_KEY_QUIT, BC_LEX_SWAP, BC_LEX_OP_ASSIGN, BC_LEX_INVALID, - BC_LEX_INVALID, BC_LEX_KEY_SQRT, BC_LEX_INVALID, BC_LEX_EXECUTE, - /* yz */ - BC_LEX_INVALID, BC_LEX_STACK_LEVEL, - /* {|}~ */ - BC_LEX_LBRACE, BC_LEX_OP_MODEXP, BC_LEX_INVALID, BC_LEX_OP_DIVMOD, - }; BcStatus s = BC_STATUS_SUCCESS; char c = l->buf[l->i++], c2; @@ -3435,7 +3435,7 @@ static BC_STATUS zdc_lex_token(BcLex *l) } if (c >= '%' && c <= '~' - && (l->t.t = dc_lex_tokens[c - '%']) != BC_LEX_INVALID + && (l->t.t = dc_char_to_LEX[c - '%']) != BC_LEX_INVALID ) { RETURN_STATUS(s); } -- cgit v1.2.3-55-g6feb From 81293c8af04913a632c32a305e505dcbf059d9d5 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 24 Dec 2018 01:53:55 +0100 Subject: dc: without -x, do not parse extended regs: 's p' means: store to ' ' reg, print function old new delta zbc_lex_next 2240 2233 -7 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-7) Total: -7 bytes text data bss dec hex filename 981437 485 7296 989218 f1822 busybox_old 981412 485 7296 989193 f1809 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index d2583313c..ac3eaff96 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -3352,16 +3352,13 @@ static BC_STATUS zbc_lex_token(BcLex *l) #if ENABLE_DC static BC_STATUS zdc_lex_register(BcLex *l) { - if (isspace(l->buf[l->i - 1])) { - bc_lex_whitespace(l); - ++l->i; - if (!G_exreg) - RETURN_STATUS(bc_error("extended register")); + if (G_exreg && isspace(l->buf[l->i])) { + bc_lex_whitespace(l); // eats whitespace (but not newline) + l->i++; // bc_lex_name() expects this bc_lex_name(l); - } - else { + } else { bc_vec_pop_all(&l->t.v); - bc_vec_push(&l->t.v, &l->buf[l->i - 1]); + bc_vec_push(&l->t.v, &l->buf[l->i++]); bc_vec_pushZeroByte(&l->t.v); l->t.t = BC_LEX_NAME; } @@ -3425,8 +3422,8 @@ static BC_STATUS zdc_lex_token(BcLex *l) BC_LEX_STORE_PUSH, }; - BcStatus s = BC_STATUS_SUCCESS; - char c = l->buf[l->i++], c2; + BcStatus s; + char c, c2; size_t i; for (i = 0; i < ARRAY_SIZE(dc_lex_regs); ++i) { @@ -3434,6 +3431,8 @@ static BC_STATUS zdc_lex_token(BcLex *l) RETURN_STATUS(zdc_lex_register(l)); } + s = BC_STATUS_SUCCESS; + c = l->buf[l->i++]; if (c >= '%' && c <= '~' && (l->t.t = dc_char_to_LEX[c - '%']) != BC_LEX_INVALID ) { @@ -3462,7 +3461,7 @@ static BC_STATUS zdc_lex_token(BcLex *l) case '\f': case '\r': case ' ': - l->newline = (c == '\n'); + l->newline = 0; // was (c == '\n') bc_lex_whitespace(l); break; case '!': -- cgit v1.2.3-55-g6feb From a7732d11204d04f14ec69103128a3a6bec7d525d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 24 Dec 2018 04:26:07 +0100 Subject: bc: rename common INST constants to XC_, dc-specific ones to DC_ This will assist in disentangling dc and bc LEX constants Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 485 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 242 insertions(+), 243 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index ac3eaff96..7d3b6b7ed 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -251,26 +251,25 @@ typedef enum BcInst { BC_INST_INC_POST, BC_INST_DEC_POST, #endif - - BC_INST_NEG, - - BC_INST_POWER, - BC_INST_MULTIPLY, - BC_INST_DIVIDE, - BC_INST_MODULUS, - BC_INST_PLUS, - BC_INST_MINUS, - - BC_INST_REL_EQ, - BC_INST_REL_LE, - BC_INST_REL_GE, - BC_INST_REL_NE, - BC_INST_REL_LT, - BC_INST_REL_GT, - - BC_INST_BOOL_NOT, - BC_INST_BOOL_OR, - BC_INST_BOOL_AND, + XC_INST_NEG, + + XC_INST_POWER, + XC_INST_MULTIPLY, + XC_INST_DIVIDE, + XC_INST_MODULUS, + XC_INST_PLUS, + XC_INST_MINUS, + + XC_INST_REL_EQ, + XC_INST_REL_LE, + XC_INST_REL_GE, + XC_INST_REL_NE, + XC_INST_REL_LT, + XC_INST_REL_GT, + + XC_INST_BOOL_NOT, + XC_INST_BOOL_OR, + XC_INST_BOOL_AND, #if ENABLE_BC BC_INST_ASSIGN_POWER, @@ -280,26 +279,26 @@ typedef enum BcInst { BC_INST_ASSIGN_PLUS, BC_INST_ASSIGN_MINUS, #endif - BC_INST_ASSIGN, + XC_INST_ASSIGN, - BC_INST_NUM, - BC_INST_VAR, - BC_INST_ARRAY_ELEM, - BC_INST_ARRAY, - BC_INST_SCALE_FUNC, + XC_INST_NUM, + XC_INST_VAR, + XC_INST_ARRAY_ELEM, + XC_INST_ARRAY, + XC_INST_SCALE_FUNC, - BC_INST_IBASE, // order of these constans should match other enums - BC_INST_OBASE, // order of these constans should match other enums - BC_INST_SCALE, // order of these constans should match other enums + XC_INST_IBASE, // order of these constans should match other enums + XC_INST_OBASE, // order of these constans should match other enums + XC_INST_SCALE, // order of these constans should match other enums IF_BC(BC_INST_LAST,) // order of these constans should match other enums - BC_INST_LENGTH, - BC_INST_READ, - BC_INST_SQRT, + XC_INST_LENGTH, + XC_INST_READ, + XC_INST_SQRT, - BC_INST_PRINT, - BC_INST_PRINT_POP, - BC_INST_STR, - BC_INST_PRINT_STR, + XC_INST_PRINT, + XC_INST_PRINT_POP, + XC_INST_STR, + XC_INST_PRINT_STR, #if ENABLE_BC BC_INST_HALT, @@ -309,35 +308,35 @@ typedef enum BcInst { BC_INST_CALL, BC_INST_RET0, #endif - BC_INST_RET, + XC_INST_RET, - BC_INST_POP, + XC_INST_POP, #if ENABLE_DC - BC_INST_POP_EXEC, + DC_INST_POP_EXEC, - BC_INST_MODEXP, - BC_INST_DIVMOD, + DC_INST_MODEXP, + DC_INST_DIVMOD, - BC_INST_EXECUTE, - BC_INST_EXEC_COND, + DC_INST_EXECUTE, + DC_INST_EXEC_COND, - BC_INST_ASCIIFY, - BC_INST_PRINT_STREAM, + DC_INST_ASCIIFY, + DC_INST_PRINT_STREAM, - BC_INST_PRINT_STACK, - BC_INST_CLEAR_STACK, - BC_INST_STACK_LEN, - BC_INST_DUPLICATE, - BC_INST_SWAP, + DC_INST_PRINT_STACK, + DC_INST_CLEAR_STACK, + DC_INST_STACK_LEN, + DC_INST_DUPLICATE, + DC_INST_SWAP, - BC_INST_LOAD, - BC_INST_PUSH_VAR, - BC_INST_PUSH_TO_VAR, + DC_INST_LOAD, + DC_INST_PUSH_VAR, + DC_INST_PUSH_TO_VAR, - BC_INST_QUIT, - BC_INST_NQUIT, + DC_INST_QUIT, + DC_INST_NQUIT, - BC_INST_INVALID = -1, + DC_INST_INVALID = -1, #endif } BcInst; @@ -364,10 +363,10 @@ typedef enum BcResultType { BC_RESULT_STR, - //code uses "inst - BC_INST_IBASE + BC_RESULT_IBASE" construct, - BC_RESULT_IBASE, // relative order should match for: BC_INST_IBASE - BC_RESULT_OBASE, // relative order should match for: BC_INST_OBASE - BC_RESULT_SCALE, // relative order should match for: BC_INST_SCALE + //code uses "inst - XC_INST_IBASE + BC_RESULT_IBASE" construct, + BC_RESULT_IBASE, // relative order should match for: XC_INST_IBASE + BC_RESULT_OBASE, // relative order should match for: XC_INST_OBASE + BC_RESULT_SCALE, // relative order should match for: XC_INST_SCALE IF_BC(BC_RESULT_LAST,) // relative order should match for: BC_INST_LAST BC_RESULT_CONSTANT, BC_RESULT_ONE, @@ -452,9 +451,9 @@ typedef enum BcLexType { BC_LEX_KEY_ELSE, BC_LEX_KEY_FOR, BC_LEX_KEY_HALT, - // code uses "type - BC_LEX_KEY_IBASE + BC_INST_IBASE" construct, - BC_LEX_KEY_IBASE, // relative order should match for: BC_INST_IBASE - BC_LEX_KEY_OBASE, // relative order should match for: BC_INST_OBASE + // code uses "type - BC_LEX_KEY_IBASE + XC_INST_IBASE" construct, + BC_LEX_KEY_IBASE, // relative order should match for: XC_INST_IBASE + BC_LEX_KEY_OBASE, // relative order should match for: XC_INST_OBASE BC_LEX_KEY_IF, IF_BC(BC_LEX_KEY_LAST,) // relative order should match for: BC_INST_LAST BC_LEX_KEY_LENGTH, @@ -485,10 +484,10 @@ typedef enum BcLexType { BC_LEX_ASCIIFY, BC_LEX_PRINT_STREAM, - // code uses "t - BC_LEX_STORE_IBASE + BC_INST_IBASE" construct, - BC_LEX_STORE_IBASE, // relative order should match for: BC_INST_IBASE - BC_LEX_STORE_OBASE, // relative order should match for: BC_INST_OBASE - BC_LEX_STORE_SCALE, // relative order should match for: BC_INST_SCALE + // code uses "t - BC_LEX_STORE_IBASE + XC_INST_IBASE" construct, + BC_LEX_STORE_IBASE, // relative order should match for: XC_INST_IBASE + BC_LEX_STORE_OBASE, // relative order should match for: XC_INST_OBASE + BC_LEX_STORE_SCALE, // relative order should match for: XC_INST_SCALE BC_LEX_LOAD, BC_LEX_LOAD_POP, BC_LEX_STORE_PUSH, @@ -656,32 +655,32 @@ dc_char_to_LEX[] = { /* {|}~ */ BC_LEX_LBRACE, BC_LEX_OP_MODEXP, BC_LEX_INVALID, BC_LEX_OP_DIVMOD, }; -static const //BcInst - should be this type. Using signed narrow type since BC_INST_INVALID is -1 +static const //BcInst - should be this type. Using signed narrow type since DC_INST_INVALID is -1 int8_t dc_LEX_to_INST[] = { // (so many INVALIDs b/c dc parser does not generate these LEXs) // corresponding BC_LEX_xyz: - BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_REL_GE, // EOF INVALID OP_INC OP_DEC - BC_INST_INVALID, BC_INST_POWER, BC_INST_MULTIPLY, BC_INST_DIVIDE, // NEG OP_POWER OP_MULTIPLY OP_DIVIDE - BC_INST_MODULUS, BC_INST_PLUS, BC_INST_MINUS, // OP_MODULUS OP_PLUS OP_MINUS - BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, // OP_REL_EQ OP_REL_LE OP_REL_GE OP_REL_NE - BC_INST_INVALID, BC_INST_INVALID, // OP_REL_LT OP_REL_GT - BC_INST_BOOL_NOT, BC_INST_INVALID, BC_INST_INVALID, // OP_BOOL_NOT OP_BOOL_OR OP_BOOL_AND - BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, // OP_ASSIGN_POWER OP_ASSIGN_MULTIPLY OP_ASSIGN_DIVIDE OP_ASSIGN_MODULUS - BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, // OP_ASSIGN_PLUS OP_ASSIGN_MINUS OP_ASSIGN - BC_INST_INVALID, BC_INST_INVALID, BC_INST_REL_GT, BC_INST_INVALID, // NLINE WHITESPACE LPAREN RPAREN - BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_REL_GE, // LBRACKET COMMA RBRACKET LBRACE - BC_INST_INVALID, BC_INST_INVALID, // SCOLON RBRACE - BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, // STR NAME NUMBER - BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, // KEY_AUTO KEY_BREAK KEY_CONTINUE KEY_DEFINE - BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_IBASE, // KEY_ELSE KEY_FOR KEY_HALT KEY_IBASE - BC_INST_OBASE, BC_INST_INVALID, IF_BC(BC_INST_INVALID,) BC_INST_LENGTH,//KEY_OBASE KEY_IF KEY_LAST(bc) KEY_LENGTH - BC_INST_INVALID, BC_INST_PRINT, BC_INST_QUIT, BC_INST_INVALID, // KEY_LIMITS KEY_PRINT KEY_QUIT KEY_READ - BC_INST_INVALID, BC_INST_SCALE, BC_INST_SQRT, BC_INST_INVALID, // KEY_RETURN KEY_SCALE KEY_SQRT KEY_WHILE - BC_INST_REL_EQ, BC_INST_MODEXP, BC_INST_DIVMOD, BC_INST_INVALID, // EQ_NO_REG OP_MODEXP OP_DIVMOD COLON - BC_INST_INVALID, BC_INST_EXECUTE, BC_INST_PRINT_STACK, BC_INST_CLEAR_STACK, //ELSE EXECUTE PRINT_STACK CLEAR_STACK - BC_INST_STACK_LEN, BC_INST_DUPLICATE, BC_INST_SWAP, BC_INST_POP, // STACK_LEVEL DUPLICATE SWAP POP - BC_INST_ASCIIFY, BC_INST_PRINT_STREAM, BC_INST_INVALID, BC_INST_INVALID, //ASCIIFY PRINT_STREAM STORE_IBASE STORE_OBASE - BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, // STORE_SCALE LOAD LOAD_POP STORE_PUSH - BC_INST_PRINT, BC_INST_NQUIT, BC_INST_SCALE_FUNC, // PRINT_POP NQUIT SCALE_FACTOR + DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, XC_INST_REL_GE, // EOF INVALID OP_INC OP_DEC + DC_INST_INVALID, XC_INST_POWER, XC_INST_MULTIPLY, XC_INST_DIVIDE, // NEG OP_POWER OP_MULTIPLY OP_DIVIDE + XC_INST_MODULUS, XC_INST_PLUS, XC_INST_MINUS, // OP_MODULUS OP_PLUS OP_MINUS + DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, // OP_REL_EQ OP_REL_LE OP_REL_GE OP_REL_NE + DC_INST_INVALID, DC_INST_INVALID, // OP_REL_LT OP_REL_GT + XC_INST_BOOL_NOT, DC_INST_INVALID, DC_INST_INVALID, // OP_BOOL_NOT OP_BOOL_OR OP_BOOL_AND + DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, // OP_ASSIGN_POWER OP_ASSIGN_MULTIPLY OP_ASSIGN_DIVIDE OP_ASSIGN_MODULUS + DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, // OP_ASSIGN_PLUS OP_ASSIGN_MINUS OP_ASSIGN + DC_INST_INVALID, DC_INST_INVALID, XC_INST_REL_GT, DC_INST_INVALID, // NLINE WHITESPACE LPAREN RPAREN + DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, XC_INST_REL_GE, // LBRACKET COMMA RBRACKET LBRACE + DC_INST_INVALID, DC_INST_INVALID, // SCOLON RBRACE + DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, // STR NAME NUMBER + DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, // KEY_AUTO KEY_BREAK KEY_CONTINUE KEY_DEFINE + DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, XC_INST_IBASE, // KEY_ELSE KEY_FOR KEY_HALT KEY_IBASE + XC_INST_OBASE, DC_INST_INVALID, IF_BC(DC_INST_INVALID,) XC_INST_LENGTH,//KEY_OBASE KEY_IF KEY_LAST(bc) KEY_LENGTH + DC_INST_INVALID, XC_INST_PRINT, DC_INST_QUIT, DC_INST_INVALID, // KEY_LIMITS KEY_PRINT KEY_QUIT KEY_READ + DC_INST_INVALID, XC_INST_SCALE, XC_INST_SQRT, DC_INST_INVALID, // KEY_RETURN KEY_SCALE KEY_SQRT KEY_WHILE + XC_INST_REL_EQ, DC_INST_MODEXP, DC_INST_DIVMOD, DC_INST_INVALID, // EQ_NO_REG OP_MODEXP OP_DIVMOD COLON + DC_INST_INVALID, DC_INST_EXECUTE, DC_INST_PRINT_STACK, DC_INST_CLEAR_STACK, //ELSE EXECUTE PRINT_STACK CLEAR_STACK + DC_INST_STACK_LEN, DC_INST_DUPLICATE, DC_INST_SWAP, XC_INST_POP, // STACK_LEVEL DUPLICATE SWAP POP + DC_INST_ASCIIFY, DC_INST_PRINT_STREAM, DC_INST_INVALID, DC_INST_INVALID, //ASCIIFY PRINT_STREAM STORE_IBASE STORE_OBASE + DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, // STORE_SCALE LOAD LOAD_POP STORE_PUSH + XC_INST_PRINT, DC_INST_NQUIT, XC_INST_SCALE_FUNC, // PRINT_POP NQUIT SCALE_FACTOR }; #endif // ENABLE_DC @@ -3569,7 +3568,7 @@ static BC_STATUS zbc_parse_pushSTR(BcParse *p) { char *str = xstrdup(p->l.t.v.v); - bc_parse_push(p, BC_INST_STR); + bc_parse_push(p, XC_INST_STR); bc_parse_pushIndex(p, p->func->strs.len); bc_vec_push(&p->func->strs, &str); @@ -3588,7 +3587,7 @@ static void bc_parse_pushNUM(BcParse *p) #else // DC size_t idx = bc_vec_push(&G.prog.consts, &num); #endif - bc_parse_push(p, BC_INST_NUM); + bc_parse_push(p, XC_INST_NUM); bc_parse_pushIndex(p, idx); } @@ -3701,13 +3700,13 @@ static size_t bc_program_addFunc(char *name) #define BC_PARSE_TOP_OP(p) (*((BcLexType *) bc_vec_top(&(p)->ops))) #define BC_PARSE_LEAF(p, rparen) \ - (((p) >= BC_INST_NUM && (p) <= BC_INST_SQRT) || (rparen) || \ + (((p) >= XC_INST_NUM && (p) <= XC_INST_SQRT) || (rparen) || \ (p) == BC_INST_INC_POST || (p) == BC_INST_DEC_POST) // We can calculate the conversion between tokens and exprs by subtracting the // position of the first operator in the lex enum and adding the position of the // first in the expr enum. Note: This only works for binary operators. -#define BC_TOKEN_2_INST(t) ((char) ((t) - BC_LEX_NEG + BC_INST_NEG)) +#define BC_TOKEN_2_INST(t) ((char) ((t) - BC_LEX_NEG + XC_INST_NEG)) static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags); @@ -3878,9 +3877,9 @@ static BC_STATUS zbc_parse_name(BcParse *p, BcInst *type, uint8_t flags) s = bc_error_bad_expression(); goto err; } - *type = BC_INST_ARRAY; + *type = XC_INST_ARRAY; } else { - *type = BC_INST_ARRAY_ELEM; + *type = XC_INST_ARRAY_ELEM; flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL); s = zbc_parse_expr(p, flags); if (s) goto err; @@ -3898,8 +3897,8 @@ static BC_STATUS zbc_parse_name(BcParse *p, BcInst *type, uint8_t flags) *type = BC_INST_CALL; s = zbc_parse_call(p, name, flags); } else { - *type = BC_INST_VAR; - bc_parse_push(p, BC_INST_VAR); + *type = XC_INST_VAR; + bc_parse_push(p, XC_INST_VAR); bc_parse_pushName(p, name); free(name); } @@ -3923,7 +3922,7 @@ static BC_STATUS zbc_parse_read(BcParse *p) if (s) RETURN_STATUS(s); if (p->l.t.t != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); - bc_parse_push(p, BC_INST_READ); + bc_parse_push(p, XC_INST_READ); RETURN_STATUS(zbc_lex_next(&p->l)); } @@ -3948,7 +3947,7 @@ static BC_STATUS zbc_parse_builtin(BcParse *p, BcLexType type, uint8_t flags, if (p->l.t.t != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); - *prev = (type == BC_LEX_KEY_LENGTH) ? BC_INST_LENGTH : BC_INST_SQRT; + *prev = (type == BC_LEX_KEY_LENGTH) ? XC_INST_LENGTH : XC_INST_SQRT; bc_parse_push(p, *prev); RETURN_STATUS(zbc_lex_next(&p->l)); @@ -3963,12 +3962,12 @@ static BC_STATUS zbc_parse_scale(BcParse *p, BcInst *type, uint8_t flags) if (s) RETURN_STATUS(s); if (p->l.t.t != BC_LEX_LPAREN) { - *type = BC_INST_SCALE; - bc_parse_push(p, BC_INST_SCALE); + *type = XC_INST_SCALE; + bc_parse_push(p, XC_INST_SCALE); RETURN_STATUS(BC_STATUS_SUCCESS); } - *type = BC_INST_SCALE_FUNC; + *type = XC_INST_SCALE_FUNC; flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL); s = zbc_lex_next(&p->l); @@ -3978,7 +3977,7 @@ static BC_STATUS zbc_parse_scale(BcParse *p, BcInst *type, uint8_t flags) if (s) RETURN_STATUS(s); if (p->l.t.t != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); - bc_parse_push(p, BC_INST_SCALE_FUNC); + bc_parse_push(p, XC_INST_SCALE_FUNC); RETURN_STATUS(zbc_lex_next(&p->l)); } @@ -3992,9 +3991,9 @@ static BC_STATUS zbc_parse_incdec(BcParse *p, BcInst *prev, bool *paren_expr, char inst; BcInst etype = *prev; - if (etype == BC_INST_VAR || etype == BC_INST_ARRAY_ELEM - || etype == BC_INST_SCALE || etype == BC_INST_LAST - || etype == BC_INST_IBASE || etype == BC_INST_OBASE + if (etype == XC_INST_VAR || etype == XC_INST_ARRAY_ELEM + || etype == XC_INST_SCALE || etype == BC_INST_LAST + || etype == XC_INST_IBASE || etype == XC_INST_OBASE ) { *prev = inst = BC_INST_INC_POST + (p->l.t.t != BC_LEX_OP_INC); bc_parse_push(p, inst); @@ -4018,7 +4017,7 @@ static BC_STATUS zbc_parse_incdec(BcParse *p, BcInst *prev, bool *paren_expr, case BC_LEX_KEY_IBASE: case BC_LEX_KEY_LAST: case BC_LEX_KEY_OBASE: - bc_parse_push(p, type - BC_LEX_KEY_IBASE + BC_INST_IBASE); + bc_parse_push(p, type - BC_LEX_KEY_IBASE + XC_INST_IBASE); s = zbc_lex_next(&p->l); break; case BC_LEX_KEY_SCALE: @@ -4027,7 +4026,7 @@ static BC_STATUS zbc_parse_incdec(BcParse *p, BcInst *prev, bool *paren_expr, if (p->l.t.t == BC_LEX_LPAREN) s = bc_error_bad_token(); else - bc_parse_push(p, BC_INST_SCALE); + bc_parse_push(p, XC_INST_SCALE); break; default: s = bc_error_bad_token(); @@ -4052,7 +4051,7 @@ static BC_STATUS zbc_parse_minus(BcParse *p, BcInst *prev, size_t ops_bgn, if (s) RETURN_STATUS(s); type = rparen || etype == BC_INST_INC_POST || etype == BC_INST_DEC_POST || - (etype >= BC_INST_NUM && etype <= BC_INST_SQRT) ? + (etype >= XC_INST_NUM && etype <= XC_INST_SQRT) ? BC_LEX_OP_MINUS : BC_LEX_NEG; *prev = BC_TOKEN_2_INST(type); @@ -4083,7 +4082,7 @@ static BC_STATUS zbc_parse_print(BcParse *p) s = zbc_parse_expr(p, 0); } if (s) RETURN_STATUS(s); - bc_parse_push(p, BC_INST_PRINT_POP); + bc_parse_push(p, XC_INST_PRINT_POP); if (p->l.t.t != BC_LEX_COMMA) break; } @@ -4118,7 +4117,7 @@ static BC_STATUS zbc_parse_return(BcParse *p) IF_ERROR_RETURN_POSSIBLE(if (s) RETURN_STATUS(s)); } - bc_parse_push(p, BC_INST_RET); + bc_parse_push(p, XC_INST_RET); } dbg_lex_done("%s:%d done", __func__, __LINE__); @@ -4238,7 +4237,7 @@ static BC_STATUS zbc_parse_for(BcParse *p) if (p->l.t.t != BC_LEX_SCOLON) { s = zbc_parse_expr(p, 0); - bc_parse_push(p, BC_INST_POP); + bc_parse_push(p, XC_INST_POP); if (s) RETURN_STATUS(s); } else { s = bc_POSIX_does_not_allow_empty_X_expression_in_for("init"); @@ -4281,7 +4280,7 @@ static BC_STATUS zbc_parse_for(BcParse *p) s = zbc_parse_expr(p, 0); if (s) RETURN_STATUS(s); if (p->l.t.t != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); - bc_parse_push(p, BC_INST_POP); + bc_parse_push(p, XC_INST_POP); } else { s = bc_POSIX_does_not_allow_empty_X_expression_in_for("update"); IF_ERROR_RETURN_POSSIBLE(if (s) RETURN_STATUS(s);) @@ -4541,7 +4540,7 @@ static BC_STATUS zbc_parse_stmt_possibly_auto(BcParse *p, bool auto_allowed) break; case BC_LEX_STR: s = zbc_parse_pushSTR(p); - bc_parse_push(p, BC_INST_PRINT_STR); + bc_parse_push(p, XC_INST_PRINT_STR); break; case BC_LEX_KEY_BREAK: case BC_LEX_KEY_CONTINUE: @@ -4622,7 +4621,7 @@ static BC_STATUS zbc_parse_stmt_or_funcdef(BcParse *p) static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) { BcStatus s = BC_STATUS_SUCCESS; - BcInst prev = BC_INST_PRINT; + BcInst prev = XC_INST_PRINT; BcLexType top, t = p->l.t.t; size_t nexprs = 0, ops_bgn = p->ops.len; unsigned nparens, nrelops; @@ -4645,7 +4644,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) case BC_LEX_OP_MINUS: s = zbc_parse_minus(p, &prev, ops_bgn, rprn, &nexprs); rprn = get_token = false; - bin_last = prev == BC_INST_MINUS; + bin_last = prev == XC_INST_MINUS; break; case BC_LEX_OP_ASSIGN_POWER: case BC_LEX_OP_ASSIGN_MULTIPLY: @@ -4654,9 +4653,9 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) case BC_LEX_OP_ASSIGN_PLUS: case BC_LEX_OP_ASSIGN_MINUS: case BC_LEX_OP_ASSIGN: - if (prev != BC_INST_VAR && prev != BC_INST_ARRAY_ELEM - && prev != BC_INST_SCALE && prev != BC_INST_IBASE - && prev != BC_INST_OBASE && prev != BC_INST_LAST + if (prev != XC_INST_VAR && prev != XC_INST_ARRAY_ELEM + && prev != XC_INST_SCALE && prev != XC_INST_IBASE + && prev != XC_INST_OBASE && prev != BC_INST_LAST ) { s = bc_error("bad assignment:" " left side must be variable" @@ -4680,7 +4679,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) case BC_LEX_OP_BOOL_OR: case BC_LEX_OP_BOOL_AND: if (((t == BC_LEX_OP_BOOL_NOT) != bin_last) - || (t != BC_LEX_OP_BOOL_NOT && prev == BC_INST_BOOL_NOT) + || (t != BC_LEX_OP_BOOL_NOT && prev == XC_INST_BOOL_NOT) ) { return bc_error_bad_expression(); } @@ -4700,7 +4699,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) bc_vec_push(&p->ops, &t); break; case BC_LEX_RPAREN: - if (bin_last || prev == BC_INST_BOOL_NOT) + if (bin_last || prev == XC_INST_BOOL_NOT) return bc_error_bad_expression(); if (nparens == 0) { s = BC_STATUS_SUCCESS; @@ -4730,7 +4729,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) return bc_error_bad_expression(); bc_parse_pushNUM(p); nexprs++; - prev = BC_INST_NUM; + prev = XC_INST_NUM; paren_expr = get_token = true; rprn = bin_last = false; break; @@ -4739,7 +4738,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) case BC_LEX_KEY_OBASE: if (BC_PARSE_LEAF(prev, rprn)) return bc_error_bad_expression(); - prev = (char) (t - BC_LEX_KEY_IBASE + BC_INST_IBASE); + prev = (char) (t - BC_LEX_KEY_IBASE + XC_INST_IBASE); bc_parse_push(p, (char) prev); paren_expr = get_token = true; rprn = bin_last = false; @@ -4762,7 +4761,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) paren_expr = true; rprn = get_token = bin_last = false; ++nexprs; - prev = BC_INST_READ; + prev = XC_INST_READ; break; case BC_LEX_KEY_SCALE: if (BC_PARSE_LEAF(prev, rprn)) @@ -4771,7 +4770,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) paren_expr = true; rprn = get_token = bin_last = false; ++nexprs; - prev = BC_INST_SCALE; + prev = XC_INST_SCALE; break; default: s = bc_error_bad_token(); @@ -4797,7 +4796,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) bc_vec_pop(&p->ops); } - if (prev == BC_INST_BOOL_NOT || nexprs != 1) + if (prev == XC_INST_BOOL_NOT || nexprs != 1) return bc_error_bad_expression(); if (!(flags & BC_PARSE_REL) && nrelops) { @@ -4809,8 +4808,8 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) } if (flags & BC_PARSE_PRINT) { - if (paren_first || !assign) bc_parse_push(p, BC_INST_PRINT); - bc_parse_push(p, BC_INST_POP); + if (paren_first || !assign) bc_parse_push(p, XC_INST_PRINT); + bc_parse_push(p, XC_INST_POP); } dbg_lex_done("%s:%d done", __func__, __LINE__); @@ -4843,7 +4842,7 @@ static void dc_parse_string(BcParse *p) dbg_lex_enter("%s:%d entered", __func__, __LINE__); str = xstrdup(p->l.t.v.v); - bc_parse_push(p, BC_INST_STR); + bc_parse_push(p, XC_INST_STR); bc_parse_pushIndex(p, len); bc_vec_push(&G.prog.strs, &str); @@ -4865,9 +4864,9 @@ static BC_STATUS zdc_parse_mem(BcParse *p, uint8_t inst, bool name, bool store) } if (store) { - bc_parse_push(p, BC_INST_SWAP); - bc_parse_push(p, BC_INST_ASSIGN); - bc_parse_push(p, BC_INST_POP); + bc_parse_push(p, DC_INST_SWAP); + bc_parse_push(p, XC_INST_ASSIGN); + bc_parse_push(p, XC_INST_POP); } RETURN_STATUS(BC_STATUS_SUCCESS); @@ -4879,7 +4878,7 @@ static BC_STATUS zdc_parse_cond(BcParse *p, uint8_t inst) BcStatus s; bc_parse_push(p, inst); - bc_parse_push(p, BC_INST_EXEC_COND); + bc_parse_push(p, DC_INST_EXEC_COND); s = zdc_parse_register(p); if (s) RETURN_STATUS(s); @@ -4919,13 +4918,13 @@ static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t) case BC_LEX_OP_REL_LT: case BC_LEX_OP_REL_GT: dbg_lex("%s:%d LEX_OP_REL_xyz", __func__, __LINE__); - s = zdc_parse_cond(p, t - BC_LEX_OP_REL_EQ + BC_INST_REL_EQ); + s = zdc_parse_cond(p, t - BC_LEX_OP_REL_EQ + XC_INST_REL_EQ); get_token = false; break; case BC_LEX_SCOLON: case BC_LEX_COLON: dbg_lex("%s:%d LEX_[S]COLON", __func__, __LINE__); - s = zdc_parse_mem(p, BC_INST_ARRAY_ELEM, true, t == BC_LEX_COLON); + s = zdc_parse_mem(p, XC_INST_ARRAY_ELEM, true, t == BC_LEX_COLON); break; case BC_LEX_STR: dbg_lex("%s:%d LEX_STR", __func__, __LINE__); @@ -4938,7 +4937,7 @@ static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t) if (p->l.t.t != BC_LEX_NUMBER) RETURN_STATUS(bc_error_bad_token()); bc_parse_pushNUM(p); - bc_parse_push(p, BC_INST_NEG); + bc_parse_push(p, XC_INST_NEG); break; case BC_LEX_NUMBER: dbg_lex("%s:%d LEX_NUMBER", __func__, __LINE__); @@ -4946,26 +4945,26 @@ static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t) break; case BC_LEX_KEY_READ: dbg_lex("%s:%d LEX_KEY_READ", __func__, __LINE__); - bc_parse_push(p, BC_INST_READ); + bc_parse_push(p, XC_INST_READ); break; case BC_LEX_OP_ASSIGN: case BC_LEX_STORE_PUSH: dbg_lex("%s:%d LEX_OP_ASSIGN/STORE_PUSH", __func__, __LINE__); assign = t == BC_LEX_OP_ASSIGN; - inst = assign ? BC_INST_VAR : BC_INST_PUSH_TO_VAR; + inst = assign ? XC_INST_VAR : DC_INST_PUSH_TO_VAR; s = zdc_parse_mem(p, inst, true, assign); break; case BC_LEX_LOAD: case BC_LEX_LOAD_POP: dbg_lex("%s:%d LEX_OP_LOAD[_POP]", __func__, __LINE__); - inst = t == BC_LEX_LOAD_POP ? BC_INST_PUSH_VAR : BC_INST_LOAD; + inst = t == BC_LEX_LOAD_POP ? DC_INST_PUSH_VAR : DC_INST_LOAD; s = zdc_parse_mem(p, inst, true, false); break; case BC_LEX_STORE_IBASE: case BC_LEX_STORE_SCALE: case BC_LEX_STORE_OBASE: dbg_lex("%s:%d LEX_OP_STORE_I/OBASE/SCALE", __func__, __LINE__); - inst = t - BC_LEX_STORE_IBASE + BC_INST_IBASE; + inst = t - BC_LEX_STORE_IBASE + XC_INST_IBASE; s = zdc_parse_mem(p, inst, false, true); break; default: @@ -4986,7 +4985,7 @@ static BC_STATUS zdc_parse_expr(BcParse *p) BcStatus s; inst = dc_LEX_to_INST[p->l.t.t]; - if (inst != BC_INST_INVALID) { + if (inst != DC_INST_INVALID) { bc_parse_push(p, inst); s = zbc_lex_next(&p->l); } else { @@ -5183,7 +5182,7 @@ static BC_STATUS zbc_program_op(char inst) bc_num_init_DEF_SIZE(&res.d.n); s = BC_STATUS_SUCCESS; - IF_ERROR_RETURN_POSSIBLE(s =) zbc_program_ops[inst - BC_INST_POWER](n1, n2, &res.d.n, G.prog.scale); + IF_ERROR_RETURN_POSSIBLE(s =) zbc_program_ops[inst - XC_INST_POWER](n1, n2, &res.d.n, G.prog.scale); if (s) goto err; bc_program_binOpRetire(&res); @@ -5233,7 +5232,7 @@ static BC_STATUS zbc_program_read(void) ip.inst_idx = 0; IF_BC(ip.results_len_before_call = G.prog.results.len;) - bc_parse_push(&parse, BC_INST_RET); + bc_parse_push(&parse, XC_INST_RET); bc_vec_push(&G.prog.exestack, &ip); exec_err: bc_parse_free(&parse); @@ -5533,7 +5532,7 @@ static BC_STATUS zbc_program_print(char inst, size_t idx) BcStatus s; BcResult *r; BcNum *num; - bool pop = inst != BC_INST_PRINT; + bool pop = inst != XC_INST_PRINT; if (!STACK_HAS_MORE_THAN(&G.prog.results, idx)) RETURN_STATUS(bc_error_stack_has_too_few_elements()); @@ -5553,7 +5552,7 @@ static BC_STATUS zbc_program_print(char inst, size_t idx) idx = (r->t == BC_RESULT_STR) ? r->d.id.idx : num->rdx; str = *bc_program_str(idx); - if (inst == BC_INST_PRINT_STR) { + if (inst == XC_INST_PRINT_STR) { for (;;) { char c = *str++; if (c == '\0') break; @@ -5563,7 +5562,7 @@ static BC_STATUS zbc_program_print(char inst, size_t idx) } } else { bc_program_printString(str); - if (inst == BC_INST_PRINT) bb_putchar('\n'); + if (inst == XC_INST_PRINT) bb_putchar('\n'); } } @@ -5604,29 +5603,29 @@ static BC_STATUS zbc_program_logical(char inst) bc_num_init_DEF_SIZE(&res.d.n); - if (inst == BC_INST_BOOL_AND) + if (inst == XC_INST_BOOL_AND) cond = bc_num_cmp(n1, &G.prog.zero) && bc_num_cmp(n2, &G.prog.zero); - else if (inst == BC_INST_BOOL_OR) + else if (inst == XC_INST_BOOL_OR) cond = bc_num_cmp(n1, &G.prog.zero) || bc_num_cmp(n2, &G.prog.zero); else { cond = bc_num_cmp(n1, n2); switch (inst) { - case BC_INST_REL_EQ: + case XC_INST_REL_EQ: cond = (cond == 0); break; - case BC_INST_REL_LE: + case XC_INST_REL_LE: cond = (cond <= 0); break; - case BC_INST_REL_GE: + case XC_INST_REL_GE: cond = (cond >= 0); break; - case BC_INST_REL_LT: + case XC_INST_REL_LT: cond = (cond < 0); break; - case BC_INST_REL_GT: + case XC_INST_REL_GT: cond = (cond > 0); break; - default: // = case BC_INST_REL_NE: + default: // = case XC_INST_REL_NE: //cond = (cond != 0); - not needed break; } @@ -5714,7 +5713,7 @@ static BC_STATUS zbc_program_assign(char inst) BcStatus s; BcResult *left, *right, res; BcNum *l = NULL, *r = NULL; - bool assign = inst == BC_INST_ASSIGN, ib, sc; + bool assign = inst == XC_INST_ASSIGN, ib, sc; s = zbc_program_binOpPrep(&left, &l, &right, &r, assign); if (s) RETURN_STATUS(s); @@ -5844,7 +5843,7 @@ static BC_STATUS zbc_program_pushArray(char *code, size_t *bgn, char inst) r.d.id.name = bc_program_name(code, bgn); - if (inst == BC_INST_ARRAY) { + if (inst == XC_INST_ARRAY) { r.t = BC_RESULT_ARRAY; bc_vec_push(&G.prog.results, &r); } else { @@ -5968,13 +5967,13 @@ static BC_STATUS zbc_program_return(char inst) size_t i; BcInstPtr *ip = bc_vec_top(&G.prog.exestack); - if (!STACK_HAS_EQUAL_OR_MORE_THAN(&G.prog.results, ip->results_len_before_call + (inst == BC_INST_RET))) + if (!STACK_HAS_EQUAL_OR_MORE_THAN(&G.prog.results, ip->results_len_before_call + (inst == XC_INST_RET))) RETURN_STATUS(bc_error_stack_has_too_few_elements()); f = bc_program_func(ip->func); res.t = BC_RESULT_TEMP; - if (inst == BC_INST_RET) { + if (inst == XC_INST_RET) { BcStatus s; BcNum *num; BcResult *operand = bc_vec_top(&G.prog.results); @@ -6029,7 +6028,7 @@ static BC_STATUS zbc_program_builtin(char inst) BcResult *opnd; BcNum *num = NULL; BcResult res; - bool len = inst == BC_INST_LENGTH; + bool len = inst == XC_INST_LENGTH; if (!STACK_HAS_MORE_THAN(&G.prog.results, 0)) RETURN_STATUS(bc_error_stack_has_too_few_elements()); @@ -6045,7 +6044,7 @@ static BC_STATUS zbc_program_builtin(char inst) bc_num_init_DEF_SIZE(&res.d.n); - if (inst == BC_INST_SQRT) + if (inst == XC_INST_SQRT) s = zbc_num_sqrt(num, &res.d.n, G.prog.scale); #if ENABLE_BC else if (len != 0 && opnd->t == BC_RESULT_ARRAY) { @@ -6361,7 +6360,7 @@ static BC_STATUS zdc_program_execStr(char *code, size_t *bgn, bool cond) bc_vec_pop_all(&f->code); goto exit; } - bc_parse_push(&prs, BC_INST_POP_EXEC); + bc_parse_push(&prs, DC_INST_POP_EXEC); bc_parse_free(&prs); } @@ -6384,10 +6383,10 @@ static void bc_program_pushGlobal(char inst) BcResult res; unsigned long val; - res.t = inst - BC_INST_IBASE + BC_RESULT_IBASE; - if (inst == BC_INST_IBASE) + res.t = inst - XC_INST_IBASE + BC_RESULT_IBASE; + if (inst == XC_INST_IBASE) val = (unsigned long) G.prog.ib_t; - else if (inst == BC_INST_SCALE) + else if (inst == XC_INST_SCALE) val = (unsigned long) G.prog.scale; else val = (unsigned long) G.prog.ob_t; @@ -6449,34 +6448,34 @@ static BC_STATUS zbc_program_exec(void) dbg_exec("BC_INST_HALT:"); QUIT_OR_RETURN_TO_MAIN; break; - case BC_INST_RET: + case XC_INST_RET: case BC_INST_RET0: dbg_exec("BC_INST_RET[0]:"); s = zbc_program_return(inst); goto read_updated_ip; - case BC_INST_BOOL_OR: - case BC_INST_BOOL_AND: + case XC_INST_BOOL_OR: + case XC_INST_BOOL_AND: #endif // ENABLE_BC - case BC_INST_REL_EQ: - case BC_INST_REL_LE: - case BC_INST_REL_GE: - case BC_INST_REL_NE: - case BC_INST_REL_LT: - case BC_INST_REL_GT: + case XC_INST_REL_EQ: + case XC_INST_REL_LE: + case XC_INST_REL_GE: + case XC_INST_REL_NE: + case XC_INST_REL_LT: + case XC_INST_REL_GT: dbg_exec("BC_INST_BOOL:"); s = zbc_program_logical(inst); break; - case BC_INST_READ: - dbg_exec("BC_INST_READ:"); + case XC_INST_READ: + dbg_exec("XC_INST_READ:"); s = zbc_program_read(); goto read_updated_ip; - case BC_INST_VAR: - dbg_exec("BC_INST_VAR:"); + case XC_INST_VAR: + dbg_exec("XC_INST_VAR:"); s = zbc_program_pushVar(code, &ip->inst_idx, false, false); break; - case BC_INST_ARRAY_ELEM: - case BC_INST_ARRAY: - dbg_exec("BC_INST_ARRAY[_ELEM]:"); + case XC_INST_ARRAY_ELEM: + case XC_INST_ARRAY: + dbg_exec("XC_INST_ARRAY[_ELEM]:"); s = zbc_program_pushArray(code, &ip->inst_idx, inst); break; #if ENABLE_BC @@ -6486,54 +6485,54 @@ static BC_STATUS zbc_program_exec(void) bc_vec_push(&G.prog.results, &r); break; #endif - case BC_INST_IBASE: - case BC_INST_OBASE: - case BC_INST_SCALE: - dbg_exec("BC_INST_internalvar(%d):", inst - BC_INST_IBASE); + case XC_INST_IBASE: + case XC_INST_OBASE: + case XC_INST_SCALE: + dbg_exec("XC_INST_internalvar(%d):", inst - XC_INST_IBASE); bc_program_pushGlobal(inst); break; - case BC_INST_SCALE_FUNC: - case BC_INST_LENGTH: - case BC_INST_SQRT: + case XC_INST_SCALE_FUNC: + case XC_INST_LENGTH: + case XC_INST_SQRT: dbg_exec("BC_INST_builtin:"); s = zbc_program_builtin(inst); break; - case BC_INST_NUM: - dbg_exec("BC_INST_NUM:"); + case XC_INST_NUM: + dbg_exec("XC_INST_NUM:"); r.t = BC_RESULT_CONSTANT; r.d.id.idx = bc_program_index(code, &ip->inst_idx); bc_vec_push(&G.prog.results, &r); break; - case BC_INST_POP: - dbg_exec("BC_INST_POP:"); + case XC_INST_POP: + dbg_exec("XC_INST_POP:"); if (!STACK_HAS_MORE_THAN(&G.prog.results, 0)) s = bc_error_stack_has_too_few_elements(); else bc_vec_pop(&G.prog.results); break; - case BC_INST_PRINT: - case BC_INST_PRINT_POP: - case BC_INST_PRINT_STR: - dbg_exec("BC_INST_PRINTxyz:"); + case XC_INST_PRINT: + case XC_INST_PRINT_POP: + case XC_INST_PRINT_STR: + dbg_exec("XC_INST_PRINTxyz:"); s = zbc_program_print(inst, 0); break; - case BC_INST_STR: - dbg_exec("BC_INST_STR:"); + case XC_INST_STR: + dbg_exec("XC_INST_STR:"); r.t = BC_RESULT_STR; r.d.id.idx = bc_program_index(code, &ip->inst_idx); bc_vec_push(&G.prog.results, &r); break; - case BC_INST_POWER: - case BC_INST_MULTIPLY: - case BC_INST_DIVIDE: - case BC_INST_MODULUS: - case BC_INST_PLUS: - case BC_INST_MINUS: + case XC_INST_POWER: + case XC_INST_MULTIPLY: + case XC_INST_DIVIDE: + case XC_INST_MODULUS: + case XC_INST_PLUS: + case XC_INST_MINUS: dbg_exec("BC_INST_binaryop:"); s = zbc_program_op(inst); break; - case BC_INST_BOOL_NOT: - dbg_exec("BC_INST_BOOL_NOT:"); + case XC_INST_BOOL_NOT: + dbg_exec("XC_INST_BOOL_NOT:"); s = zbc_program_prep(&ptr, &num); if (s) RETURN_STATUS(s); bc_num_init_DEF_SIZE(&r.d.n); @@ -6542,8 +6541,8 @@ static BC_STATUS zbc_program_exec(void) //else bc_num_zero(&r.d.n); - already is bc_program_retire(&r, BC_RESULT_TEMP); break; - case BC_INST_NEG: - dbg_exec("BC_INST_NEG:"); + case XC_INST_NEG: + dbg_exec("XC_INST_NEG:"); s = zbc_program_negate(); break; #if ENABLE_BC @@ -6554,56 +6553,56 @@ static BC_STATUS zbc_program_exec(void) case BC_INST_ASSIGN_PLUS: case BC_INST_ASSIGN_MINUS: #endif - case BC_INST_ASSIGN: + case XC_INST_ASSIGN: dbg_exec("BC_INST_ASSIGNxyz:"); s = zbc_program_assign(inst); break; #if ENABLE_DC - case BC_INST_POP_EXEC: - dbg_exec("BC_INST_POP_EXEC:"); + case DC_INST_POP_EXEC: + dbg_exec("DC_INST_POP_EXEC:"); bc_vec_pop(&G.prog.exestack); goto read_updated_ip; - case BC_INST_MODEXP: - dbg_exec("BC_INST_MODEXP:"); + case DC_INST_MODEXP: + dbg_exec("DC_INST_MODEXP:"); s = zdc_program_modexp(); break; - case BC_INST_DIVMOD: - dbg_exec("BC_INST_DIVMOD:"); + case DC_INST_DIVMOD: + dbg_exec("DC_INST_DIVMOD:"); s = zdc_program_divmod(); break; - case BC_INST_EXECUTE: - case BC_INST_EXEC_COND: - dbg_exec("BC_INST_EXEC[_COND]:"); - s = zdc_program_execStr(code, &ip->inst_idx, inst == BC_INST_EXEC_COND); + case DC_INST_EXECUTE: + case DC_INST_EXEC_COND: + dbg_exec("DC_INST_EXEC[_COND]:"); + s = zdc_program_execStr(code, &ip->inst_idx, inst == DC_INST_EXEC_COND); goto read_updated_ip; - case BC_INST_PRINT_STACK: { + case DC_INST_PRINT_STACK: { size_t idx; - dbg_exec("BC_INST_PRINT_STACK:"); + dbg_exec("DC_INST_PRINT_STACK:"); for (idx = 0; idx < G.prog.results.len; ++idx) { - s = zbc_program_print(BC_INST_PRINT, idx); + s = zbc_program_print(XC_INST_PRINT, idx); if (s) break; } break; } - case BC_INST_CLEAR_STACK: - dbg_exec("BC_INST_CLEAR_STACK:"); + case DC_INST_CLEAR_STACK: + dbg_exec("DC_INST_CLEAR_STACK:"); bc_vec_pop_all(&G.prog.results); break; - case BC_INST_STACK_LEN: - dbg_exec("BC_INST_STACK_LEN:"); + case DC_INST_STACK_LEN: + dbg_exec("DC_INST_STACK_LEN:"); dc_program_stackLen(); break; - case BC_INST_DUPLICATE: - dbg_exec("BC_INST_DUPLICATE:"); + case DC_INST_DUPLICATE: + dbg_exec("DC_INST_DUPLICATE:"); if (!STACK_HAS_MORE_THAN(&G.prog.results, 0)) RETURN_STATUS(bc_error_stack_has_too_few_elements()); ptr = bc_vec_top(&G.prog.results); dc_result_copy(&r, ptr); bc_vec_push(&G.prog.results, &r); break; - case BC_INST_SWAP: { + case DC_INST_SWAP: { BcResult *ptr2; - dbg_exec("BC_INST_SWAP:"); + dbg_exec("DC_INST_SWAP:"); if (!STACK_HAS_MORE_THAN(&G.prog.results, 1)) RETURN_STATUS(bc_error_stack_has_too_few_elements()); ptr = bc_vec_item_rev(&G.prog.results, 0); @@ -6613,34 +6612,34 @@ static BC_STATUS zbc_program_exec(void) memcpy(ptr2, &r, sizeof(BcResult)); break; } - case BC_INST_ASCIIFY: - dbg_exec("BC_INST_ASCIIFY:"); + case DC_INST_ASCIIFY: + dbg_exec("DC_INST_ASCIIFY:"); s = zdc_program_asciify(); break; - case BC_INST_PRINT_STREAM: - dbg_exec("BC_INST_STREAM:"); + case DC_INST_PRINT_STREAM: + dbg_exec("DC_INST_PRINT_STREAM:"); s = zdc_program_printStream(); break; - case BC_INST_LOAD: - case BC_INST_PUSH_VAR: { - bool copy = inst == BC_INST_LOAD; + case DC_INST_LOAD: + case DC_INST_PUSH_VAR: { + bool copy = inst == DC_INST_LOAD; s = zbc_program_pushVar(code, &ip->inst_idx, true, copy); break; } - case BC_INST_PUSH_TO_VAR: { + case DC_INST_PUSH_TO_VAR: { char *name = bc_program_name(code, &ip->inst_idx); s = zbc_program_copyToVar(name, true); free(name); break; } - case BC_INST_QUIT: - dbg_exec("BC_INST_QUIT:"); + case DC_INST_QUIT: + dbg_exec("DC_INST_QUIT:"); if (G.prog.exestack.len <= 2) QUIT_OR_RETURN_TO_MAIN; bc_vec_npop(&G.prog.exestack, 2); goto read_updated_ip; - case BC_INST_NQUIT: - dbg_exec("BC_INST_NQUIT:"); + case DC_INST_NQUIT: + dbg_exec("DC_INST_NQUIT:"); s = zdc_program_nquit(); //goto read_updated_ip; - just fall through to it #endif // ENABLE_DC -- cgit v1.2.3-55-g6feb From 2097ac8d9e07320ff0f087bd6b3f6987aa02eb69 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 24 Dec 2018 05:00:36 +0100 Subject: bc: move functions/macros around, no code changes Order now is: enums/structures/defines, utility/common functions, parsing, execution, main loop, main() Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 1210 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 609 insertions(+), 601 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 7d3b6b7ed..7a69a0816 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -877,82 +877,9 @@ struct globals { # define COMMA_SUCCESS ,BC_STATUS_SUCCESS #endif -#define STACK_HAS_MORE_THAN(s, n) ((s)->len > ((size_t)(n))) -#define STACK_HAS_EQUAL_OR_MORE_THAN(s, n) ((s)->len >= ((size_t)(n))) - -#define BC_NUM_NEG(n, neg) ((((ssize_t)(n)) ^ -((ssize_t)(neg))) + (neg)) -#define BC_NUM_ONE(n) ((n)->len == 1 && (n)->rdx == 0 && (n)->num[0] == 1) -#define BC_NUM_INT(n) ((n)->len - (n)->rdx) -//#define BC_NUM_AREQ(a, b) (BC_MAX((a)->rdx, (b)->rdx) + BC_MAX(BC_NUM_INT(a), BC_NUM_INT(b)) + 1) -static /*ALWAYS_INLINE*/ size_t BC_NUM_AREQ(BcNum *a, BcNum *b) -{ - return BC_MAX(a->rdx, b->rdx) + BC_MAX(BC_NUM_INT(a), BC_NUM_INT(b)) + 1; -} -//#define BC_NUM_MREQ(a, b, scale) (BC_NUM_INT(a) + BC_NUM_INT(b) + BC_MAX((scale), (a)->rdx + (b)->rdx) + 1) -static /*ALWAYS_INLINE*/ size_t BC_NUM_MREQ(BcNum *a, BcNum *b, size_t scale) -{ - return BC_NUM_INT(a) + BC_NUM_INT(b) + BC_MAX(scale, a->rdx + b->rdx) + 1; -} - -typedef void (*BcNumDigitOp)(size_t, size_t, bool) FAST_FUNC; - -typedef BC_STATUS (*BcNumBinaryOp)(BcNum *, BcNum *, BcNum *, size_t) FAST_FUNC; - -static BC_STATUS zbc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale, - BcNumBinaryOp op, size_t req); -static FAST_FUNC BC_STATUS zbc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale); -static FAST_FUNC BC_STATUS zbc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale); -static FAST_FUNC BC_STATUS zbc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale); -static FAST_FUNC BC_STATUS zbc_num_m(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale); -static FAST_FUNC BC_STATUS zbc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale); -static FAST_FUNC BC_STATUS zbc_num_rem(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale); - -static FAST_FUNC BC_STATUS zbc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale) -{ - BcNumBinaryOp op = (!a->neg == !b->neg) ? zbc_num_a : zbc_num_s; - (void) scale; - RETURN_STATUS(zbc_num_binary(a, b, c, false, op, BC_NUM_AREQ(a, b))); -} - -static FAST_FUNC BC_STATUS zbc_num_sub(BcNum *a, BcNum *b, BcNum *c, size_t scale) -{ - BcNumBinaryOp op = (!a->neg == !b->neg) ? zbc_num_s : zbc_num_a; - (void) scale; - RETURN_STATUS(zbc_num_binary(a, b, c, true, op, BC_NUM_AREQ(a, b))); -} - -static FAST_FUNC BC_STATUS zbc_num_mul(BcNum *a, BcNum *b, BcNum *c, size_t scale) -{ - size_t req = BC_NUM_MREQ(a, b, scale); - RETURN_STATUS(zbc_num_binary(a, b, c, scale, zbc_num_m, req)); -} - -static FAST_FUNC BC_STATUS zbc_num_div(BcNum *a, BcNum *b, BcNum *c, size_t scale) -{ - size_t req = BC_NUM_MREQ(a, b, scale); - RETURN_STATUS(zbc_num_binary(a, b, c, scale, zbc_num_d, req)); -} - -static FAST_FUNC BC_STATUS zbc_num_mod(BcNum *a, BcNum *b, BcNum *c, size_t scale) -{ - size_t req = BC_NUM_MREQ(a, b, scale); - RETURN_STATUS(zbc_num_binary(a, b, c, scale, zbc_num_rem, req)); -} - -static FAST_FUNC BC_STATUS zbc_num_pow(BcNum *a, BcNum *b, BcNum *c, size_t scale) -{ - RETURN_STATUS(zbc_num_binary(a, b, c, scale, zbc_num_p, a->len * b->len + 1)); -} - -static const BcNumBinaryOp zbc_program_ops[] = { - zbc_num_pow, zbc_num_mul, zbc_num_div, zbc_num_mod, zbc_num_add, zbc_num_sub, -}; -#define zbc_num_add(...) (zbc_num_add(__VA_ARGS__) COMMA_SUCCESS) -#define zbc_num_sub(...) (zbc_num_sub(__VA_ARGS__) COMMA_SUCCESS) -#define zbc_num_mul(...) (zbc_num_mul(__VA_ARGS__) COMMA_SUCCESS) -#define zbc_num_div(...) (zbc_num_div(__VA_ARGS__) COMMA_SUCCESS) -#define zbc_num_mod(...) (zbc_num_mod(__VA_ARGS__) COMMA_SUCCESS) -#define zbc_num_pow(...) (zbc_num_pow(__VA_ARGS__) COMMA_SUCCESS) +// +// Utility routines +// static void fflush_and_check(void) { @@ -1324,102 +1251,6 @@ static size_t bc_map_find_exact(const BcVec *v, const void *ptr) } #endif -static int bad_input_byte(char c) -{ - if ((c < ' ' && c != '\t' && c != '\r' && c != '\n') // also allow '\v' '\f'? - || c > 0x7e - ) { - bc_error_fmt("illegal character 0x%02x", c); - return 1; - } - return 0; -} - -// Note: it _appends_ data from fp to vec. -static void bc_read_line(BcVec *vec, FILE *fp) -{ - again: - fflush_and_check(); - -#if ENABLE_FEATURE_BC_SIGNALS - if (G_interrupt) { // ^C was pressed - intr: - if (fp != stdin) { - // ^C while running a script (bc SCRIPT): die. - // We do not return to interactive prompt: - // user might be running us from a shell, - // and SCRIPT might be intended to terminate - // (e.g. contain a "halt" stmt). - // ^C dropping user into a bc prompt instead of - // the shell would be unexpected. - xfunc_die(); - } - // ^C while interactive input - G_interrupt = 0; - // GNU bc says "interrupted execution." - // GNU dc says "Interrupt!" - fputs("\ninterrupted execution\n", stderr); - } - -# if ENABLE_FEATURE_EDITING - if (G_ttyin && fp == stdin) { - int n, i; -# define line_buf bb_common_bufsiz1 - n = read_line_input(G.line_input_state, "", line_buf, COMMON_BUFSIZE); - if (n <= 0) { // read errors or EOF, or ^D, or ^C - if (n == 0) // ^C - goto intr; - bc_vec_pushZeroByte(vec); // ^D or EOF (or error) - return; - } - i = 0; - for (;;) { - char c = line_buf[i++]; - if (!c) break; - if (bad_input_byte(c)) goto again; - } - bc_vec_concat(vec, line_buf); -# undef line_buf - } else -# endif -#endif - { - int c; - bool bad_chars = 0; - size_t len = vec->len; - - do { -#if ENABLE_FEATURE_BC_SIGNALS - if (G_interrupt) { - // ^C was pressed: ignore entire line, get another one - vec->len = len; - goto intr; - } -#endif - do c = fgetc(fp); while (c == '\0'); - if (c == EOF) { - if (ferror(fp)) - bb_perror_msg_and_die("input error"); - // Note: EOF does not append '\n' - break; - } - bad_chars |= bad_input_byte(c); - bc_vec_pushByte(vec, (char)c); - } while (c != '\n'); - - if (bad_chars) { - // Bad chars on this line - if (!G.prog.file) { // stdin - // ignore entire line, get another one - vec->len = len; - goto again; - } - bb_perror_msg_and_die("file '%s' is not text", G.prog.file); - } - bc_vec_pushZeroByte(vec); - } -} - static void bc_num_setToZero(BcNum *n, size_t scale) { n->len = 0; @@ -1569,6 +1400,20 @@ static ssize_t bc_num_compare(BcDig *restrict a, BcDig *restrict b, size_t len) } } +#define BC_NUM_NEG(n, neg) ((((ssize_t)(n)) ^ -((ssize_t)(neg))) + (neg)) +#define BC_NUM_ONE(n) ((n)->len == 1 && (n)->rdx == 0 && (n)->num[0] == 1) +#define BC_NUM_INT(n) ((n)->len - (n)->rdx) +//#define BC_NUM_AREQ(a, b) (BC_MAX((a)->rdx, (b)->rdx) + BC_MAX(BC_NUM_INT(a), BC_NUM_INT(b)) + 1) +static /*ALWAYS_INLINE*/ size_t BC_NUM_AREQ(BcNum *a, BcNum *b) +{ + return BC_MAX(a->rdx, b->rdx) + BC_MAX(BC_NUM_INT(a), BC_NUM_INT(b)) + 1; +} +//#define BC_NUM_MREQ(a, b, scale) (BC_NUM_INT(a) + BC_NUM_INT(b) + BC_MAX((scale), (a)->rdx + (b)->rdx) + 1) +static /*ALWAYS_INLINE*/ size_t BC_NUM_MREQ(BcNum *a, BcNum *b, size_t scale) +{ + return BC_NUM_INT(a) + BC_NUM_INT(b) + BC_MAX(scale, a->rdx + b->rdx) + 1; +} + static ssize_t bc_num_cmp(BcNum *a, BcNum *b) { size_t i, min, a_int, b_int, diff; @@ -1705,52 +1550,145 @@ static BC_STATUS zbc_num_shift(BcNum *n, size_t places) } #define zbc_num_shift(...) (zbc_num_shift(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zbc_num_inv(BcNum *a, BcNum *b, size_t scale) +typedef BC_STATUS (*BcNumBinaryOp)(BcNum *, BcNum *, BcNum *, size_t) FAST_FUNC; + +static BC_STATUS zbc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale, + BcNumBinaryOp op, size_t req) { - BcNum one; - BcDig num[2]; + BcStatus s; + BcNum num2, *ptr_a, *ptr_b; + bool init = false; - one.cap = 2; - one.num = num; - bc_num_one(&one); + if (c == a) { + ptr_a = &num2; + memcpy(ptr_a, c, sizeof(BcNum)); + init = true; + } else + ptr_a = a; - RETURN_STATUS(zbc_num_div(&one, a, b, scale)); -} -#define zbc_num_inv(...) (zbc_num_inv(__VA_ARGS__) COMMA_SUCCESS) + if (c == b) { + ptr_b = &num2; + if (c != a) { + memcpy(ptr_b, c, sizeof(BcNum)); + init = true; + } + } else + ptr_b = b; -static FAST_FUNC BC_STATUS zbc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) -{ - BcDig *ptr, *ptr_a, *ptr_b, *ptr_c; - size_t i, max, min_rdx, min_int, diff, a_int, b_int; - unsigned carry; + if (init) + bc_num_init(c, req); + else + bc_num_expand(c, req); - // Because this function doesn't need to use scale (per the bc spec), - // I am hijacking it to say whether it's doing an add or a subtract. + s = BC_STATUS_SUCCESS; + IF_ERROR_RETURN_POSSIBLE(s =) op(ptr_a, ptr_b, c, scale); - if (a->len == 0) { - bc_num_copy(c, b); - if (sub && c->len) c->neg = !c->neg; - RETURN_STATUS(BC_STATUS_SUCCESS); - } - if (b->len == 0) { - bc_num_copy(c, a); - RETURN_STATUS(BC_STATUS_SUCCESS); - } + if (init) bc_num_free(&num2); - c->neg = a->neg; - c->rdx = BC_MAX(a->rdx, b->rdx); - min_rdx = BC_MIN(a->rdx, b->rdx); - c->len = 0; + RETURN_STATUS(s); +} +#define zbc_num_binary(...) (zbc_num_binary(__VA_ARGS__) COMMA_SUCCESS) - if (a->rdx > b->rdx) { - diff = a->rdx - b->rdx; - ptr = a->num; - ptr_a = a->num + diff; - ptr_b = b->num; - } else { - diff = b->rdx - a->rdx; - ptr = b->num; - ptr_a = a->num; +static FAST_FUNC BC_STATUS zbc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale); +static FAST_FUNC BC_STATUS zbc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale); +static FAST_FUNC BC_STATUS zbc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale); +static FAST_FUNC BC_STATUS zbc_num_m(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale); +static FAST_FUNC BC_STATUS zbc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale); +static FAST_FUNC BC_STATUS zbc_num_rem(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale); + +static FAST_FUNC BC_STATUS zbc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale) +{ + BcNumBinaryOp op = (!a->neg == !b->neg) ? zbc_num_a : zbc_num_s; + (void) scale; + RETURN_STATUS(zbc_num_binary(a, b, c, false, op, BC_NUM_AREQ(a, b))); +} + +static FAST_FUNC BC_STATUS zbc_num_sub(BcNum *a, BcNum *b, BcNum *c, size_t scale) +{ + BcNumBinaryOp op = (!a->neg == !b->neg) ? zbc_num_s : zbc_num_a; + (void) scale; + RETURN_STATUS(zbc_num_binary(a, b, c, true, op, BC_NUM_AREQ(a, b))); +} + +static FAST_FUNC BC_STATUS zbc_num_mul(BcNum *a, BcNum *b, BcNum *c, size_t scale) +{ + size_t req = BC_NUM_MREQ(a, b, scale); + RETURN_STATUS(zbc_num_binary(a, b, c, scale, zbc_num_m, req)); +} + +static FAST_FUNC BC_STATUS zbc_num_div(BcNum *a, BcNum *b, BcNum *c, size_t scale) +{ + size_t req = BC_NUM_MREQ(a, b, scale); + RETURN_STATUS(zbc_num_binary(a, b, c, scale, zbc_num_d, req)); +} + +static FAST_FUNC BC_STATUS zbc_num_mod(BcNum *a, BcNum *b, BcNum *c, size_t scale) +{ + size_t req = BC_NUM_MREQ(a, b, scale); + RETURN_STATUS(zbc_num_binary(a, b, c, scale, zbc_num_rem, req)); +} + +static FAST_FUNC BC_STATUS zbc_num_pow(BcNum *a, BcNum *b, BcNum *c, size_t scale) +{ + RETURN_STATUS(zbc_num_binary(a, b, c, scale, zbc_num_p, a->len * b->len + 1)); +} + +static const BcNumBinaryOp zbc_program_ops[] = { + zbc_num_pow, zbc_num_mul, zbc_num_div, zbc_num_mod, zbc_num_add, zbc_num_sub, +}; +#define zbc_num_add(...) (zbc_num_add(__VA_ARGS__) COMMA_SUCCESS) +#define zbc_num_sub(...) (zbc_num_sub(__VA_ARGS__) COMMA_SUCCESS) +#define zbc_num_mul(...) (zbc_num_mul(__VA_ARGS__) COMMA_SUCCESS) +#define zbc_num_div(...) (zbc_num_div(__VA_ARGS__) COMMA_SUCCESS) +#define zbc_num_mod(...) (zbc_num_mod(__VA_ARGS__) COMMA_SUCCESS) +#define zbc_num_pow(...) (zbc_num_pow(__VA_ARGS__) COMMA_SUCCESS) + +static BC_STATUS zbc_num_inv(BcNum *a, BcNum *b, size_t scale) +{ + BcNum one; + BcDig num[2]; + + one.cap = 2; + one.num = num; + bc_num_one(&one); + + RETURN_STATUS(zbc_num_div(&one, a, b, scale)); +} +#define zbc_num_inv(...) (zbc_num_inv(__VA_ARGS__) COMMA_SUCCESS) + +static FAST_FUNC BC_STATUS zbc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) +{ + BcDig *ptr, *ptr_a, *ptr_b, *ptr_c; + size_t i, max, min_rdx, min_int, diff, a_int, b_int; + unsigned carry; + + // Because this function doesn't need to use scale (per the bc spec), + // I am hijacking it to say whether it's doing an add or a subtract. + + if (a->len == 0) { + bc_num_copy(c, b); + if (sub && c->len) c->neg = !c->neg; + RETURN_STATUS(BC_STATUS_SUCCESS); + } + if (b->len == 0) { + bc_num_copy(c, a); + RETURN_STATUS(BC_STATUS_SUCCESS); + } + + c->neg = a->neg; + c->rdx = BC_MAX(a->rdx, b->rdx); + min_rdx = BC_MIN(a->rdx, b->rdx); + c->len = 0; + + if (a->rdx > b->rdx) { + diff = a->rdx - b->rdx; + ptr = a->num; + ptr_a = a->num + diff; + ptr_b = b->num; + } else { + diff = b->rdx - a->rdx; + ptr = b->num; + ptr_a = a->num; ptr_b = b->num + diff; } @@ -2224,295 +2162,106 @@ static FAST_FUNC BC_STATUS zbc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size } #define zbc_num_p(...) (zbc_num_p(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zbc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale, - BcNumBinaryOp op, size_t req) +static BC_STATUS zbc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale) { BcStatus s; - BcNum num2, *ptr_a, *ptr_b; - bool init = false; + BcNum num1, num2, half, f, fprime, *x0, *x1, *temp; + size_t pow, len, digs, digs1, resrdx, req, times = 0; + ssize_t cmp = 1, cmp1 = SSIZE_MAX, cmp2 = SSIZE_MAX; - if (c == a) { - ptr_a = &num2; - memcpy(ptr_a, c, sizeof(BcNum)); - init = true; - } else - ptr_a = a; + req = BC_MAX(scale, a->rdx) + ((BC_NUM_INT(a) + 1) >> 1) + 1; + bc_num_expand(b, req); - if (c == b) { - ptr_b = &num2; - if (c != a) { - memcpy(ptr_b, c, sizeof(BcNum)); - init = true; - } - } else - ptr_b = b; + if (a->len == 0) { + bc_num_setToZero(b, scale); + RETURN_STATUS(BC_STATUS_SUCCESS); + } + if (a->neg) { + RETURN_STATUS(bc_error("negative number")); + } + if (BC_NUM_ONE(a)) { + bc_num_one(b); + bc_num_extend(b, scale); + RETURN_STATUS(BC_STATUS_SUCCESS); + } - if (init) - bc_num_init(c, req); - else - bc_num_expand(c, req); + scale = BC_MAX(scale, a->rdx) + 1; + len = a->len + scale; - s = BC_STATUS_SUCCESS; - IF_ERROR_RETURN_POSSIBLE(s =) op(ptr_a, ptr_b, c, scale); + bc_num_init(&num1, len); + bc_num_init(&num2, len); + bc_num_init_DEF_SIZE(&half); - if (init) bc_num_free(&num2); + bc_num_one(&half); + half.num[0] = 5; + half.rdx = 1; - RETURN_STATUS(s); -} -#define zbc_num_binary(...) (zbc_num_binary(__VA_ARGS__) COMMA_SUCCESS) + bc_num_init(&f, len); + bc_num_init(&fprime, len); -static bool bc_num_strValid(const char *val, size_t base) -{ - BcDig b; - bool radix; + x0 = &num1; + x1 = &num2; - b = (BcDig)(base <= 10 ? base + '0' : base - 10 + 'A'); - radix = false; - for (;;) { - BcDig c = *val++; - if (c == '\0') - break; - if (c == '.') { - if (radix) return false; - radix = true; - continue; - } - if (c < '0' || c >= b || (c > '9' && c < 'A')) - return false; + bc_num_one(x0); + pow = BC_NUM_INT(a); + + if (pow) { + if (pow & 1) + x0->num[0] = 2; + else + x0->num[0] = 6; + + pow -= 2 - (pow & 1); + + bc_num_extend(x0, pow); + + // Make sure to move the radix back. + x0->rdx -= pow; } - return true; -} -// Note: n is already "bc_num_zero()"ed, -// leading zeroes in "val" are removed -static void bc_num_parseDecimal(BcNum *n, const char *val) -{ - size_t len, i; - const char *ptr; + x0->rdx = digs = digs1 = 0; + resrdx = scale + 2; + len = BC_NUM_INT(x0) + resrdx - 1; - len = strlen(val); - if (len == 0) - return; + while (cmp != 0 || digs < len) { + s = zbc_num_div(a, x0, &f, resrdx); + if (s) goto err; + s = zbc_num_add(x0, &f, &fprime, resrdx); + if (s) goto err; + s = zbc_num_mul(&fprime, &half, x1, resrdx); + if (s) goto err; - bc_num_expand(n, len); + cmp = bc_num_cmp(x1, x0); + digs = x1->len - (unsigned long long) llabs(cmp); - ptr = strchr(val, '.'); + if (cmp == cmp2 && digs == digs1) + times += 1; + else + times = 0; - n->rdx = 0; - if (ptr != NULL) - n->rdx = (size_t)((val + len) - (ptr + 1)); + resrdx += times > 4; - for (i = 0; val[i]; ++i) { - if (val[i] != '0' && val[i] != '.') { - // Not entirely zero value - convert it, and exit - i = len - 1; - for (;;) { - n->num[n->len] = val[i] - '0'; - ++n->len; - skip_dot: - if (i == 0) break; - if (val[--i] == '.') goto skip_dot; - } - break; - } + cmp2 = cmp1; + cmp1 = cmp; + digs1 = digs; + + temp = x0; + x0 = x1; + x1 = temp; } - // if for() exits without hitting if(), the value is entirely zero + + bc_num_copy(b, x0); + scale -= 1; + if (b->rdx > scale) bc_num_truncate(b, b->rdx - scale); + err: + bc_num_free(&fprime); + bc_num_free(&f); + bc_num_free(&half); + bc_num_free(&num2); + bc_num_free(&num1); + RETURN_STATUS(s); } - -// Note: n is already "bc_num_zero()"ed, -// leading zeroes in "val" are removed -static void bc_num_parseBase(BcNum *n, const char *val, unsigned base_t) -{ - BcStatus s; - BcNum temp, mult, result; - BcNum base; - BcDig base_digs[ULONG_NUM_BUFSIZE]; - BcDig c = '\0'; - unsigned long v; - size_t i, digits; - - for (i = 0; ; ++i) { - if (val[i] == '\0') - return; - if (val[i] != '.' && val[i] != '0') - break; - } - - bc_num_init_DEF_SIZE(&temp); - bc_num_init_DEF_SIZE(&mult); - base.cap = ARRAY_SIZE(base_digs); - base.num = base_digs; - bc_num_ulong2num(&base, base_t); - - for (;;) { - c = *val++; - if (c == '\0') goto int_err; - if (c == '.') break; - - v = (unsigned long) (c <= '9' ? c - '0' : c - 'A' + 10); - - s = zbc_num_mul(n, &base, &mult, 0); - if (s) goto int_err; - bc_num_ulong2num(&temp, v); - s = zbc_num_add(&mult, &temp, n, 0); - if (s) goto int_err; - } - - bc_num_init(&result, base.len); - //bc_num_zero(&result); - already is - bc_num_one(&mult); - - digits = 0; - for (;;) { - c = *val++; - if (c == '\0') break; - digits++; - - v = (unsigned long) (c <= '9' ? c - '0' : c - 'A' + 10); - - s = zbc_num_mul(&result, &base, &result, 0); - if (s) goto err; - bc_num_ulong2num(&temp, v); - s = zbc_num_add(&result, &temp, &result, 0); - if (s) goto err; - s = zbc_num_mul(&mult, &base, &mult, 0); - if (s) goto err; - } - - s = zbc_num_div(&result, &mult, &result, digits); - if (s) goto err; - s = zbc_num_add(n, &result, n, digits); - if (s) goto err; - - if (n->len != 0) { - if (n->rdx < digits) - bc_num_extend(n, digits - n->rdx); - } else - bc_num_zero(n); - err: - bc_num_free(&result); - int_err: - bc_num_free(&mult); - bc_num_free(&temp); -} - -static BC_STATUS zbc_num_parse(BcNum *n, const char *val, unsigned base_t) -{ - if (!bc_num_strValid(val, base_t)) - RETURN_STATUS(bc_error("bad number string")); - - bc_num_zero(n); - while (*val == '0') val++; - - if (base_t == 10) - bc_num_parseDecimal(n, val); - else - bc_num_parseBase(n, val, base_t); - - RETURN_STATUS(BC_STATUS_SUCCESS); -} -#define zbc_num_parse(...) (zbc_num_parse(__VA_ARGS__) COMMA_SUCCESS) - -static BC_STATUS zbc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale) -{ - BcStatus s; - BcNum num1, num2, half, f, fprime, *x0, *x1, *temp; - size_t pow, len, digs, digs1, resrdx, req, times = 0; - ssize_t cmp = 1, cmp1 = SSIZE_MAX, cmp2 = SSIZE_MAX; - - req = BC_MAX(scale, a->rdx) + ((BC_NUM_INT(a) + 1) >> 1) + 1; - bc_num_expand(b, req); - - if (a->len == 0) { - bc_num_setToZero(b, scale); - RETURN_STATUS(BC_STATUS_SUCCESS); - } - if (a->neg) { - RETURN_STATUS(bc_error("negative number")); - } - if (BC_NUM_ONE(a)) { - bc_num_one(b); - bc_num_extend(b, scale); - RETURN_STATUS(BC_STATUS_SUCCESS); - } - - scale = BC_MAX(scale, a->rdx) + 1; - len = a->len + scale; - - bc_num_init(&num1, len); - bc_num_init(&num2, len); - bc_num_init_DEF_SIZE(&half); - - bc_num_one(&half); - half.num[0] = 5; - half.rdx = 1; - - bc_num_init(&f, len); - bc_num_init(&fprime, len); - - x0 = &num1; - x1 = &num2; - - bc_num_one(x0); - pow = BC_NUM_INT(a); - - if (pow) { - if (pow & 1) - x0->num[0] = 2; - else - x0->num[0] = 6; - - pow -= 2 - (pow & 1); - - bc_num_extend(x0, pow); - - // Make sure to move the radix back. - x0->rdx -= pow; - } - - x0->rdx = digs = digs1 = 0; - resrdx = scale + 2; - len = BC_NUM_INT(x0) + resrdx - 1; - - while (cmp != 0 || digs < len) { - s = zbc_num_div(a, x0, &f, resrdx); - if (s) goto err; - s = zbc_num_add(x0, &f, &fprime, resrdx); - if (s) goto err; - s = zbc_num_mul(&fprime, &half, x1, resrdx); - if (s) goto err; - - cmp = bc_num_cmp(x1, x0); - digs = x1->len - (unsigned long long) llabs(cmp); - - if (cmp == cmp2 && digs == digs1) - times += 1; - else - times = 0; - - resrdx += times > 4; - - cmp2 = cmp1; - cmp1 = cmp; - digs1 = digs; - - temp = x0; - x0 = x1; - x1 = temp; - } - - bc_num_copy(b, x0); - scale -= 1; - if (b->rdx > scale) bc_num_truncate(b, b->rdx - scale); - err: - bc_num_free(&fprime); - bc_num_free(&f); - bc_num_free(&half); - bc_num_free(&num2); - bc_num_free(&num1); - RETURN_STATUS(s); -} -#define zbc_num_sqrt(...) (zbc_num_sqrt(__VA_ARGS__) COMMA_SUCCESS) +#define zbc_num_sqrt(...) (zbc_num_sqrt(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d, size_t scale) @@ -2592,153 +2341,382 @@ static BC_STATUS zdc_num_modexp(BcNum *a, BcNum *b, BcNum *c, BcNum *restrict d) bc_num_free(&base); RETURN_STATUS(s); } -#define zdc_num_modexp(...) (zdc_num_modexp(__VA_ARGS__) COMMA_SUCCESS) -#endif // ENABLE_DC +#define zdc_num_modexp(...) (zdc_num_modexp(__VA_ARGS__) COMMA_SUCCESS) +#endif // ENABLE_DC + +static FAST_FUNC void bc_string_free(void *string) +{ + free(*(char**)string); +} + +static void bc_func_init(BcFunc *f) +{ + bc_char_vec_init(&f->code); + IF_BC(bc_vec_init(&f->labels, sizeof(size_t), NULL);) + IF_BC(bc_vec_init(&f->autos, sizeof(BcId), bc_id_free);) + IF_BC(bc_vec_init(&f->strs, sizeof(char *), bc_string_free);) + IF_BC(bc_vec_init(&f->consts, sizeof(char *), bc_string_free);) + IF_BC(f->nparams = 0;) +} + +static FAST_FUNC void bc_func_free(void *func) +{ + BcFunc *f = (BcFunc *) func; + bc_vec_free(&f->code); + IF_BC(bc_vec_free(&f->labels);) + IF_BC(bc_vec_free(&f->autos);) + IF_BC(bc_vec_free(&f->strs);) + IF_BC(bc_vec_free(&f->consts);) +} + +static void bc_array_expand(BcVec *a, size_t len); + +static void bc_array_init(BcVec *a, bool nums) +{ + if (nums) + bc_vec_init(a, sizeof(BcNum), bc_num_free); + else + bc_vec_init(a, sizeof(BcVec), bc_vec_free); + bc_array_expand(a, 1); +} + +static void bc_array_expand(BcVec *a, size_t len) +{ + if (a->dtor == bc_num_free + // && a->size == sizeof(BcNum) - always true + ) { + BcNum n; + while (len > a->len) { + bc_num_init_DEF_SIZE(&n); + bc_vec_push(a, &n); + } + } else { + BcVec v; + while (len > a->len) { + bc_array_init(&v, true); + bc_vec_push(a, &v); + } + } +} + +static void bc_array_copy(BcVec *d, const BcVec *s) +{ + BcNum *dnum, *snum; + size_t i; + + bc_vec_pop_all(d); + bc_vec_expand(d, s->cap); + d->len = s->len; + + dnum = (void*)d->v; + snum = (void*)s->v; + for (i = 0; i < s->len; i++, dnum++, snum++) { + bc_num_init(dnum, snum->len); + bc_num_copy(dnum, snum); + } +} + +#if ENABLE_DC +static void dc_result_copy(BcResult *d, BcResult *src) +{ + d->t = src->t; + + switch (d->t) { + case BC_RESULT_TEMP: + case BC_RESULT_IBASE: + case BC_RESULT_SCALE: + case BC_RESULT_OBASE: + bc_num_init(&d->d.n, src->d.n.len); + bc_num_copy(&d->d.n, &src->d.n); + break; + case BC_RESULT_VAR: + case BC_RESULT_ARRAY: + case BC_RESULT_ARRAY_ELEM: + d->d.id.name = xstrdup(src->d.id.name); + break; + case BC_RESULT_CONSTANT: + IF_BC(case BC_RESULT_LAST:) + case BC_RESULT_ONE: + case BC_RESULT_STR: + memcpy(&d->d.n, &src->d.n, sizeof(BcNum)); + break; + } +} +#endif // ENABLE_DC + +static FAST_FUNC void bc_result_free(void *result) +{ + BcResult *r = (BcResult *) result; + + switch (r->t) { + case BC_RESULT_TEMP: + case BC_RESULT_IBASE: + case BC_RESULT_SCALE: + case BC_RESULT_OBASE: + bc_num_free(&r->d.n); + break; + case BC_RESULT_VAR: + case BC_RESULT_ARRAY: + case BC_RESULT_ARRAY_ELEM: + free(r->d.id.name); + break; + default: + // Do nothing. + break; + } +} + +static int bad_input_byte(char c) +{ + if ((c < ' ' && c != '\t' && c != '\r' && c != '\n') // also allow '\v' '\f'? + || c > 0x7e + ) { + bc_error_fmt("illegal character 0x%02x", c); + return 1; + } + return 0; +} + +// Note: it _appends_ data from fp to vec. +static void bc_read_line(BcVec *vec, FILE *fp) +{ + again: + fflush_and_check(); + +#if ENABLE_FEATURE_BC_SIGNALS + if (G_interrupt) { // ^C was pressed + intr: + if (fp != stdin) { + // ^C while running a script (bc SCRIPT): die. + // We do not return to interactive prompt: + // user might be running us from a shell, + // and SCRIPT might be intended to terminate + // (e.g. contain a "halt" stmt). + // ^C dropping user into a bc prompt instead of + // the shell would be unexpected. + xfunc_die(); + } + // ^C while interactive input + G_interrupt = 0; + // GNU bc says "interrupted execution." + // GNU dc says "Interrupt!" + fputs("\ninterrupted execution\n", stderr); + } + +# if ENABLE_FEATURE_EDITING + if (G_ttyin && fp == stdin) { + int n, i; +# define line_buf bb_common_bufsiz1 + n = read_line_input(G.line_input_state, "", line_buf, COMMON_BUFSIZE); + if (n <= 0) { // read errors or EOF, or ^D, or ^C + if (n == 0) // ^C + goto intr; + bc_vec_pushZeroByte(vec); // ^D or EOF (or error) + return; + } + i = 0; + for (;;) { + char c = line_buf[i++]; + if (!c) break; + if (bad_input_byte(c)) goto again; + } + bc_vec_concat(vec, line_buf); +# undef line_buf + } else +# endif +#endif + { + int c; + bool bad_chars = 0; + size_t len = vec->len; + + do { +#if ENABLE_FEATURE_BC_SIGNALS + if (G_interrupt) { + // ^C was pressed: ignore entire line, get another one + vec->len = len; + goto intr; + } +#endif + do c = fgetc(fp); while (c == '\0'); + if (c == EOF) { + if (ferror(fp)) + bb_perror_msg_and_die("input error"); + // Note: EOF does not append '\n' + break; + } + bad_chars |= bad_input_byte(c); + bc_vec_pushByte(vec, (char)c); + } while (c != '\n'); + + if (bad_chars) { + // Bad chars on this line + if (!G.prog.file) { // stdin + // ignore entire line, get another one + vec->len = len; + goto again; + } + bb_perror_msg_and_die("file '%s' is not text", G.prog.file); + } + bc_vec_pushZeroByte(vec); + } +} + +// +// Parsing routines +// + +static bool bc_num_strValid(const char *val, size_t base) +{ + BcDig b; + bool radix; + + b = (BcDig)(base <= 10 ? base + '0' : base - 10 + 'A'); + radix = false; + for (;;) { + BcDig c = *val++; + if (c == '\0') + break; + if (c == '.') { + if (radix) return false; + radix = true; + continue; + } + if (c < '0' || c >= b || (c > '9' && c < 'A')) + return false; + } + return true; +} -#if ENABLE_BC -static BC_STATUS zbc_func_insert(BcFunc *f, char *name, bool var) +// Note: n is already "bc_num_zero()"ed, +// leading zeroes in "val" are removed +static void bc_num_parseDecimal(BcNum *n, const char *val) { - BcId *autoid; - BcId a; - size_t i; + size_t len, i; + const char *ptr; - autoid = (void*)f->autos.v; - for (i = 0; i < f->autos.len; i++, autoid++) { - if (strcmp(name, autoid->name) == 0) - RETURN_STATUS(bc_error("function parameter or auto var has the same name as another")); - } + len = strlen(val); + if (len == 0) + return; - a.idx = var; - a.name = name; + bc_num_expand(n, len); - bc_vec_push(&f->autos, &a); + ptr = strchr(val, '.'); - RETURN_STATUS(BC_STATUS_SUCCESS); -} -#define zbc_func_insert(...) (zbc_func_insert(__VA_ARGS__) COMMA_SUCCESS) -#endif + n->rdx = 0; + if (ptr != NULL) + n->rdx = (size_t)((val + len) - (ptr + 1)); -static FAST_FUNC void bc_string_free(void *string) -{ - free(*(char**)string); + for (i = 0; val[i]; ++i) { + if (val[i] != '0' && val[i] != '.') { + // Not entirely zero value - convert it, and exit + i = len - 1; + for (;;) { + n->num[n->len] = val[i] - '0'; + ++n->len; + skip_dot: + if (i == 0) break; + if (val[--i] == '.') goto skip_dot; + } + break; + } + } + // if for() exits without hitting if(), the value is entirely zero } -static void bc_func_init(BcFunc *f) +// Note: n is already "bc_num_zero()"ed, +// leading zeroes in "val" are removed +static void bc_num_parseBase(BcNum *n, const char *val, unsigned base_t) { - bc_char_vec_init(&f->code); - IF_BC(bc_vec_init(&f->labels, sizeof(size_t), NULL);) - IF_BC(bc_vec_init(&f->autos, sizeof(BcId), bc_id_free);) - IF_BC(bc_vec_init(&f->strs, sizeof(char *), bc_string_free);) - IF_BC(bc_vec_init(&f->consts, sizeof(char *), bc_string_free);) - IF_BC(f->nparams = 0;) -} + BcStatus s; + BcNum temp, mult, result; + BcNum base; + BcDig base_digs[ULONG_NUM_BUFSIZE]; + BcDig c = '\0'; + unsigned long v; + size_t i, digits; -static FAST_FUNC void bc_func_free(void *func) -{ - BcFunc *f = (BcFunc *) func; - bc_vec_free(&f->code); - IF_BC(bc_vec_free(&f->labels);) - IF_BC(bc_vec_free(&f->autos);) - IF_BC(bc_vec_free(&f->strs);) - IF_BC(bc_vec_free(&f->consts);) -} + for (i = 0; ; ++i) { + if (val[i] == '\0') + return; + if (val[i] != '.' && val[i] != '0') + break; + } -static void bc_array_expand(BcVec *a, size_t len); + bc_num_init_DEF_SIZE(&temp); + bc_num_init_DEF_SIZE(&mult); + base.cap = ARRAY_SIZE(base_digs); + base.num = base_digs; + bc_num_ulong2num(&base, base_t); -static void bc_array_init(BcVec *a, bool nums) -{ - if (nums) - bc_vec_init(a, sizeof(BcNum), bc_num_free); - else - bc_vec_init(a, sizeof(BcVec), bc_vec_free); - bc_array_expand(a, 1); -} + for (;;) { + c = *val++; + if (c == '\0') goto int_err; + if (c == '.') break; -static void bc_array_expand(BcVec *a, size_t len) -{ - if (a->dtor == bc_num_free - // && a->size == sizeof(BcNum) - always true - ) { - BcNum n; - while (len > a->len) { - bc_num_init_DEF_SIZE(&n); - bc_vec_push(a, &n); - } - } else { - BcVec v; - while (len > a->len) { - bc_array_init(&v, true); - bc_vec_push(a, &v); - } + v = (unsigned long) (c <= '9' ? c - '0' : c - 'A' + 10); + + s = zbc_num_mul(n, &base, &mult, 0); + if (s) goto int_err; + bc_num_ulong2num(&temp, v); + s = zbc_num_add(&mult, &temp, n, 0); + if (s) goto int_err; } -} -static void bc_array_copy(BcVec *d, const BcVec *s) -{ - BcNum *dnum, *snum; - size_t i; + bc_num_init(&result, base.len); + //bc_num_zero(&result); - already is + bc_num_one(&mult); - bc_vec_pop_all(d); - bc_vec_expand(d, s->cap); - d->len = s->len; + digits = 0; + for (;;) { + c = *val++; + if (c == '\0') break; + digits++; - dnum = (void*)d->v; - snum = (void*)s->v; - for (i = 0; i < s->len; i++, dnum++, snum++) { - bc_num_init(dnum, snum->len); - bc_num_copy(dnum, snum); + v = (unsigned long) (c <= '9' ? c - '0' : c - 'A' + 10); + + s = zbc_num_mul(&result, &base, &result, 0); + if (s) goto err; + bc_num_ulong2num(&temp, v); + s = zbc_num_add(&result, &temp, &result, 0); + if (s) goto err; + s = zbc_num_mul(&mult, &base, &mult, 0); + if (s) goto err; } -} -#if ENABLE_DC -static void dc_result_copy(BcResult *d, BcResult *src) -{ - d->t = src->t; + s = zbc_num_div(&result, &mult, &result, digits); + if (s) goto err; + s = zbc_num_add(n, &result, n, digits); + if (s) goto err; - switch (d->t) { - case BC_RESULT_TEMP: - case BC_RESULT_IBASE: - case BC_RESULT_SCALE: - case BC_RESULT_OBASE: - bc_num_init(&d->d.n, src->d.n.len); - bc_num_copy(&d->d.n, &src->d.n); - break; - case BC_RESULT_VAR: - case BC_RESULT_ARRAY: - case BC_RESULT_ARRAY_ELEM: - d->d.id.name = xstrdup(src->d.id.name); - break; - case BC_RESULT_CONSTANT: - IF_BC(case BC_RESULT_LAST:) - case BC_RESULT_ONE: - case BC_RESULT_STR: - memcpy(&d->d.n, &src->d.n, sizeof(BcNum)); - break; - } + if (n->len != 0) { + if (n->rdx < digits) + bc_num_extend(n, digits - n->rdx); + } else + bc_num_zero(n); + err: + bc_num_free(&result); + int_err: + bc_num_free(&mult); + bc_num_free(&temp); } -#endif // ENABLE_DC -static FAST_FUNC void bc_result_free(void *result) +static BC_STATUS zbc_num_parse(BcNum *n, const char *val, unsigned base_t) { - BcResult *r = (BcResult *) result; + if (!bc_num_strValid(val, base_t)) + RETURN_STATUS(bc_error("bad number string")); - switch (r->t) { - case BC_RESULT_TEMP: - case BC_RESULT_IBASE: - case BC_RESULT_SCALE: - case BC_RESULT_OBASE: - bc_num_free(&r->d.n); - break; - case BC_RESULT_VAR: - case BC_RESULT_ARRAY: - case BC_RESULT_ARRAY_ELEM: - free(r->d.id.name); - break; - default: - // Do nothing. - break; - } + bc_num_zero(n); + while (*val == '0') val++; + + if (base_t == 10) + bc_num_parseDecimal(n, val); + else + bc_num_parseBase(n, val, base_t); + + RETURN_STATUS(BC_STATUS_SUCCESS); } +#define zbc_num_parse(...) (zbc_num_parse(__VA_ARGS__) COMMA_SUCCESS) static void bc_lex_lineComment(BcLex *l) { @@ -4333,6 +4311,27 @@ static BC_STATUS zbc_parse_break_or_continue(BcParse *p, BcLexType type) } #define zbc_parse_break_or_continue(...) (zbc_parse_break_or_continue(__VA_ARGS__) COMMA_SUCCESS) +static BC_STATUS zbc_func_insert(BcFunc *f, char *name, bool var) +{ + BcId *autoid; + BcId a; + size_t i; + + autoid = (void*)f->autos.v; + for (i = 0; i < f->autos.len; i++, autoid++) { + if (strcmp(name, autoid->name) == 0) + RETURN_STATUS(bc_error("function parameter or auto var has the same name as another")); + } + + a.idx = var; + a.name = name; + + bc_vec_push(&f->autos, &a); + + RETURN_STATUS(BC_STATUS_SUCCESS); +} +#define zbc_func_insert(...) (zbc_func_insert(__VA_ARGS__) COMMA_SUCCESS) + static BC_STATUS zbc_parse_funcdef(BcParse *p) { BcStatus s; @@ -5010,6 +5009,13 @@ static BC_STATUS zdc_parse_exprs_until_eof(BcParse *p) #endif // ENABLE_DC +// +// Execution engine +// + +#define STACK_HAS_MORE_THAN(s, n) ((s)->len > ((size_t)(n))) +#define STACK_HAS_EQUAL_OR_MORE_THAN(s, n) ((s)->len >= ((size_t)(n))) + static BcVec* bc_program_search(char *id, bool var) { BcId e, *ptr; @@ -5400,6 +5406,8 @@ static void bc_num_printDecimal(BcNum *n) bc_num_printHex((size_t) n->num[i], 1, i == rdx); } +typedef void (*BcNumDigitOp)(size_t, size_t, bool) FAST_FUNC; + static BC_STATUS zbc_num_printNum(BcNum *n, unsigned base_t, size_t width, BcNumDigitOp print) { BcStatus s; -- cgit v1.2.3-55-g6feb From 7d9be0bc6dc3efdbaf39810240e47553f9c8b90d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 24 Dec 2018 12:25:20 +0100 Subject: bc: rename BC_LEXs to XC_LEXs for common constants, and to DC_LEXs for dc-specific Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 168 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 84 insertions(+), 84 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 7a69a0816..b4e9e6cb1 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -391,8 +391,8 @@ typedef struct BcInstPtr { // BC_LEX_NEG is not used in lexing; it is only for parsing. typedef enum BcLexType { - BC_LEX_EOF, - BC_LEX_INVALID, + XC_LEX_EOF, + XC_LEX_INVALID, BC_LEX_OP_INC, BC_LEX_OP_DEC, @@ -467,33 +467,33 @@ typedef enum BcLexType { BC_LEX_KEY_WHILE, #if ENABLE_DC - BC_LEX_EQ_NO_REG, - BC_LEX_OP_MODEXP, - BC_LEX_OP_DIVMOD, - - BC_LEX_COLON, - BC_LEX_ELSE, - BC_LEX_EXECUTE, - BC_LEX_PRINT_STACK, - BC_LEX_CLEAR_STACK, - BC_LEX_STACK_LEVEL, - BC_LEX_DUPLICATE, - BC_LEX_SWAP, - BC_LEX_POP, - - BC_LEX_ASCIIFY, - BC_LEX_PRINT_STREAM, - - // code uses "t - BC_LEX_STORE_IBASE + XC_INST_IBASE" construct, - BC_LEX_STORE_IBASE, // relative order should match for: XC_INST_IBASE - BC_LEX_STORE_OBASE, // relative order should match for: XC_INST_OBASE - BC_LEX_STORE_SCALE, // relative order should match for: XC_INST_SCALE - BC_LEX_LOAD, - BC_LEX_LOAD_POP, - BC_LEX_STORE_PUSH, - BC_LEX_PRINT_POP, - BC_LEX_NQUIT, - BC_LEX_SCALE_FACTOR, + DC_LEX_EQ_NO_REG, + DC_LEX_OP_MODEXP, + DC_LEX_OP_DIVMOD, + + DC_LEX_COLON, + DC_LEX_ELSE, + DC_LEX_EXECUTE, + DC_LEX_PRINT_STACK, + DC_LEX_CLEAR_STACK, + DC_LEX_STACK_LEVEL, + DC_LEX_DUPLICATE, + DC_LEX_SWAP, + DC_LEX_POP, + + DC_LEX_ASCIIFY, + DC_LEX_PRINT_STREAM, + + // code uses "t - DC_LEX_STORE_IBASE + XC_INST_IBASE" construct, + DC_LEX_STORE_IBASE, // relative order should match for: XC_INST_IBASE + DC_LEX_STORE_OBASE, // relative order should match for: XC_INST_OBASE + DC_LEX_STORE_SCALE, // relative order should match for: XC_INST_SCALE + DC_LEX_LOAD, + DC_LEX_LOAD_POP, + DC_LEX_STORE_PUSH, + DC_LEX_PRINT_POP, + DC_LEX_NQUIT, + DC_LEX_SCALE_FACTOR, #endif } BcLexType; // must match order of BC_LEX_KEY_foo etc above @@ -616,44 +616,44 @@ static const //BcLexType - should be this type uint8_t dc_char_to_LEX[] = { /* %&'( */ - BC_LEX_OP_MODULUS, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_LPAREN, + BC_LEX_OP_MODULUS, XC_LEX_INVALID, XC_LEX_INVALID, BC_LEX_LPAREN, /* )*+, */ - BC_LEX_INVALID, BC_LEX_OP_MULTIPLY, BC_LEX_OP_PLUS, BC_LEX_INVALID, + XC_LEX_INVALID, BC_LEX_OP_MULTIPLY, BC_LEX_OP_PLUS, XC_LEX_INVALID, /* -./ */ - BC_LEX_OP_MINUS, BC_LEX_INVALID, BC_LEX_OP_DIVIDE, + BC_LEX_OP_MINUS, XC_LEX_INVALID, BC_LEX_OP_DIVIDE, /* 0123456789 */ - BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, - BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, - BC_LEX_INVALID, BC_LEX_INVALID, + XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, + XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, + XC_LEX_INVALID, XC_LEX_INVALID, /* :;<=>?@ */ - BC_LEX_COLON, BC_LEX_SCOLON, BC_LEX_OP_REL_GT, BC_LEX_OP_REL_EQ, - BC_LEX_OP_REL_LT, BC_LEX_KEY_READ, BC_LEX_INVALID, + DC_LEX_COLON, BC_LEX_SCOLON, BC_LEX_OP_REL_GT, BC_LEX_OP_REL_EQ, + BC_LEX_OP_REL_LT, BC_LEX_KEY_READ, XC_LEX_INVALID, /* ABCDEFGH */ - BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, - BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_EQ_NO_REG, BC_LEX_INVALID, + XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, + XC_LEX_INVALID, XC_LEX_INVALID, DC_LEX_EQ_NO_REG, XC_LEX_INVALID, /* IJKLMNOP */ - BC_LEX_KEY_IBASE, BC_LEX_INVALID, BC_LEX_KEY_SCALE, BC_LEX_LOAD_POP, - BC_LEX_INVALID, BC_LEX_OP_BOOL_NOT, BC_LEX_KEY_OBASE, BC_LEX_PRINT_STREAM, + BC_LEX_KEY_IBASE, XC_LEX_INVALID, BC_LEX_KEY_SCALE, DC_LEX_LOAD_POP, + XC_LEX_INVALID, BC_LEX_OP_BOOL_NOT, BC_LEX_KEY_OBASE, DC_LEX_PRINT_STREAM, /* QRSTUVWXY */ - BC_LEX_NQUIT, BC_LEX_POP, BC_LEX_STORE_PUSH, BC_LEX_INVALID, BC_LEX_INVALID, - BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_SCALE_FACTOR, BC_LEX_INVALID, + DC_LEX_NQUIT, DC_LEX_POP, DC_LEX_STORE_PUSH, XC_LEX_INVALID, XC_LEX_INVALID, + XC_LEX_INVALID, XC_LEX_INVALID, DC_LEX_SCALE_FACTOR, XC_LEX_INVALID, /* Z[\] */ - BC_LEX_KEY_LENGTH, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, + BC_LEX_KEY_LENGTH, XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, /* ^_` */ - BC_LEX_OP_POWER, BC_LEX_NEG, BC_LEX_INVALID, + BC_LEX_OP_POWER, BC_LEX_NEG, XC_LEX_INVALID, /* abcdefgh */ - BC_LEX_ASCIIFY, BC_LEX_INVALID, BC_LEX_CLEAR_STACK, BC_LEX_DUPLICATE, - BC_LEX_ELSE, BC_LEX_PRINT_STACK, BC_LEX_INVALID, BC_LEX_INVALID, + DC_LEX_ASCIIFY, XC_LEX_INVALID, DC_LEX_CLEAR_STACK, DC_LEX_DUPLICATE, + DC_LEX_ELSE, DC_LEX_PRINT_STACK, XC_LEX_INVALID, XC_LEX_INVALID, /* ijklmnop */ - BC_LEX_STORE_IBASE, BC_LEX_INVALID, BC_LEX_STORE_SCALE, BC_LEX_LOAD, - BC_LEX_INVALID, BC_LEX_PRINT_POP, BC_LEX_STORE_OBASE, BC_LEX_KEY_PRINT, + DC_LEX_STORE_IBASE, XC_LEX_INVALID, DC_LEX_STORE_SCALE, DC_LEX_LOAD, + XC_LEX_INVALID, DC_LEX_PRINT_POP, DC_LEX_STORE_OBASE, BC_LEX_KEY_PRINT, /* qrstuvwx */ - BC_LEX_KEY_QUIT, BC_LEX_SWAP, BC_LEX_OP_ASSIGN, BC_LEX_INVALID, - BC_LEX_INVALID, BC_LEX_KEY_SQRT, BC_LEX_INVALID, BC_LEX_EXECUTE, + BC_LEX_KEY_QUIT, DC_LEX_SWAP, BC_LEX_OP_ASSIGN, XC_LEX_INVALID, + XC_LEX_INVALID, BC_LEX_KEY_SQRT, XC_LEX_INVALID, DC_LEX_EXECUTE, /* yz */ - BC_LEX_INVALID, BC_LEX_STACK_LEVEL, + XC_LEX_INVALID, DC_LEX_STACK_LEVEL, /* {|}~ */ - BC_LEX_LBRACE, BC_LEX_OP_MODEXP, BC_LEX_INVALID, BC_LEX_OP_DIVMOD, + BC_LEX_LBRACE, DC_LEX_OP_MODEXP, XC_LEX_INVALID, DC_LEX_OP_DIVMOD, }; static const //BcInst - should be this type. Using signed narrow type since DC_INST_INVALID is -1 int8_t @@ -2940,7 +2940,7 @@ static BC_STATUS zbc_lex_next(BcLex *l) BcStatus s; l->t.last = l->t.t; - if (l->t.last == BC_LEX_EOF) RETURN_STATUS(bc_error("end of file")); + if (l->t.last == XC_LEX_EOF) RETURN_STATUS(bc_error("end of file")); l->line += l->newline; G.err_line = l->line; @@ -2952,7 +2952,7 @@ static BC_STATUS zbc_lex_next(BcLex *l) s = BC_STATUS_SUCCESS; do { if (l->i == l->len) { - l->t.t = BC_LEX_EOF; + l->t.t = XC_LEX_EOF; if (!G.input_fp) RETURN_STATUS(BC_STATUS_SUCCESS); if (!bc_lex_more_input(l)) { @@ -3002,7 +3002,7 @@ static BC_STATUS zbc_lex_text_init(BcLex *l, const char *text) l->buf = text; l->i = 0; l->len = strlen(text); - l->t.t = l->t.last = BC_LEX_INVALID; + l->t.t = l->t.last = XC_LEX_INVALID; RETURN_STATUS(zbc_lex_next(l)); } #define zbc_lex_text_init(...) (zbc_lex_text_init(__VA_ARGS__) COMMA_SUCCESS) @@ -3142,7 +3142,7 @@ static BC_STATUS zbc_lex_token(BcLex *l) switch (c) { // case '\0': // probably never reached // l->i--; -// l->t.t = BC_LEX_EOF; +// l->t.t = XC_LEX_EOF; // l->newline = true; // break; case '\n': @@ -3182,7 +3182,7 @@ static BC_STATUS zbc_lex_token(BcLex *l) ++l->i; l->t.t = BC_LEX_OP_BOOL_AND; } else { - l->t.t = BC_LEX_INVALID; + l->t.t = XC_LEX_INVALID; s = bc_error_bad_character('&'); } break; @@ -3311,12 +3311,12 @@ static BC_STATUS zbc_lex_token(BcLex *l) ++l->i; l->t.t = BC_LEX_OP_BOOL_OR; } else { - l->t.t = BC_LEX_INVALID; + l->t.t = XC_LEX_INVALID; s = bc_error_bad_character(c); } break; default: - l->t.t = BC_LEX_INVALID; + l->t.t = XC_LEX_INVALID; s = bc_error_bad_character(c); break; } @@ -3394,9 +3394,9 @@ static BC_STATUS zdc_lex_token(BcLex *l) uint8_t dc_lex_regs[] = { BC_LEX_OP_REL_EQ, BC_LEX_OP_REL_LE, BC_LEX_OP_REL_GE, BC_LEX_OP_REL_NE, - BC_LEX_OP_REL_LT, BC_LEX_OP_REL_GT, BC_LEX_SCOLON, BC_LEX_COLON, - BC_LEX_ELSE, BC_LEX_LOAD, BC_LEX_LOAD_POP, BC_LEX_OP_ASSIGN, - BC_LEX_STORE_PUSH, + BC_LEX_OP_REL_LT, BC_LEX_OP_REL_GT, BC_LEX_SCOLON, DC_LEX_COLON, + DC_LEX_ELSE, DC_LEX_LOAD, DC_LEX_LOAD_POP, BC_LEX_OP_ASSIGN, + DC_LEX_STORE_PUSH, }; BcStatus s; @@ -3411,7 +3411,7 @@ static BC_STATUS zdc_lex_token(BcLex *l) s = BC_STATUS_SUCCESS; c = l->buf[l->i++]; if (c >= '%' && c <= '~' - && (l->t.t = dc_char_to_LEX[c - '%']) != BC_LEX_INVALID + && (l->t.t = dc_char_to_LEX[c - '%']) != XC_LEX_INVALID ) { RETURN_STATUS(s); } @@ -3419,7 +3419,7 @@ static BC_STATUS zdc_lex_token(BcLex *l) // This is the workhorse of the lexer. switch (c) { // case '\0': // probably never reached -// l->t.t = BC_LEX_EOF; +// l->t.t = XC_LEX_EOF; // break; case '\n': // '\n' is BC_LEX_NLINE, not BC_LEX_WHITESPACE @@ -3484,7 +3484,7 @@ static BC_STATUS zdc_lex_token(BcLex *l) s = zdc_lex_string(l); break; default: - l->t.t = BC_LEX_INVALID; + l->t.t = XC_LEX_INVALID; s = bc_error_bad_character(c); break; } @@ -3605,7 +3605,7 @@ static void bc_parse_reset(BcParse *p) } p->l.i = p->l.len; - p->l.t.t = BC_LEX_EOF; + p->l.t.t = XC_LEX_EOF; IF_BC(bc_vec_pop_all(&p->exits);) IF_BC(bc_vec_pop_all(&p->conds);) @@ -4601,7 +4601,7 @@ static BC_STATUS zbc_parse_stmt_or_funcdef(BcParse *p) BcStatus s; dbg_lex_enter("%s:%d entered", __func__, __LINE__); - if (p->l.t.t == BC_LEX_EOF) + if (p->l.t.t == XC_LEX_EOF) s = bc_error("end of file"); else if (p->l.t.t == BC_LEX_KEY_DEFINE) { dbg_lex("%s:%d p->l.t.t:BC_LEX_KEY_DEFINE", __func__, __LINE__); @@ -4888,7 +4888,7 @@ static BC_STATUS zdc_parse_cond(BcParse *p, uint8_t inst) // Note that 'else' part can not be on the next line: // echo -e '[1p]sa [2p]sb 2 1>a eb' | dc - OK, prints "2" // echo -e '[1p]sa [2p]sb 2 1>a\neb' | dc - parse error - if (p->l.t.t == BC_LEX_ELSE) { + if (p->l.t.t == DC_LEX_ELSE) { s = zdc_parse_register(p); if (s) RETURN_STATUS(s); s = zbc_lex_next(&p->l); @@ -4921,9 +4921,9 @@ static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t) get_token = false; break; case BC_LEX_SCOLON: - case BC_LEX_COLON: + case DC_LEX_COLON: dbg_lex("%s:%d LEX_[S]COLON", __func__, __LINE__); - s = zdc_parse_mem(p, XC_INST_ARRAY_ELEM, true, t == BC_LEX_COLON); + s = zdc_parse_mem(p, XC_INST_ARRAY_ELEM, true, t == DC_LEX_COLON); break; case BC_LEX_STR: dbg_lex("%s:%d LEX_STR", __func__, __LINE__); @@ -4947,23 +4947,23 @@ static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t) bc_parse_push(p, XC_INST_READ); break; case BC_LEX_OP_ASSIGN: - case BC_LEX_STORE_PUSH: + case DC_LEX_STORE_PUSH: dbg_lex("%s:%d LEX_OP_ASSIGN/STORE_PUSH", __func__, __LINE__); assign = t == BC_LEX_OP_ASSIGN; inst = assign ? XC_INST_VAR : DC_INST_PUSH_TO_VAR; s = zdc_parse_mem(p, inst, true, assign); break; - case BC_LEX_LOAD: - case BC_LEX_LOAD_POP: + case DC_LEX_LOAD: + case DC_LEX_LOAD_POP: dbg_lex("%s:%d LEX_OP_LOAD[_POP]", __func__, __LINE__); - inst = t == BC_LEX_LOAD_POP ? DC_INST_PUSH_VAR : DC_INST_LOAD; + inst = t == DC_LEX_LOAD_POP ? DC_INST_PUSH_VAR : DC_INST_LOAD; s = zdc_parse_mem(p, inst, true, false); break; - case BC_LEX_STORE_IBASE: - case BC_LEX_STORE_SCALE: - case BC_LEX_STORE_OBASE: + case DC_LEX_STORE_IBASE: + case DC_LEX_STORE_SCALE: + case DC_LEX_STORE_OBASE: dbg_lex("%s:%d LEX_OP_STORE_I/OBASE/SCALE", __func__, __LINE__); - inst = t - BC_LEX_STORE_IBASE + XC_INST_IBASE; + inst = t - DC_LEX_STORE_IBASE + XC_INST_IBASE; s = zdc_parse_mem(p, inst, false, true); break; default: @@ -4997,7 +4997,7 @@ static BC_STATUS zdc_parse_expr(BcParse *p) static BC_STATUS zdc_parse_exprs_until_eof(BcParse *p) { dbg_lex_enter("%s:%d entered, p->l.t.t:%d", __func__, __LINE__, p->l.t.t); - while (p->l.t.t != BC_LEX_EOF) { + while (p->l.t.t != XC_LEX_EOF) { BcStatus s = zdc_parse_expr(p); if (s) RETURN_STATUS(s); } @@ -5229,7 +5229,7 @@ static BC_STATUS zbc_program_read(void) } if (s) goto exec_err; - if (parse.l.t.t != BC_LEX_NLINE && parse.l.t.t != BC_LEX_EOF) { + if (parse.l.t.t != BC_LEX_NLINE && parse.l.t.t != XC_LEX_EOF) { s = bc_error("bad read() expression"); goto exec_err; } @@ -6361,7 +6361,7 @@ static BC_STATUS zdc_program_execStr(char *code, size_t *bgn, bool cond) G.input_fp = sv_input_fp; if (s) goto err; - if (prs.l.t.t != BC_LEX_EOF) { + if (prs.l.t.t != XC_LEX_EOF) { s = bc_error_bad_expression(); err: bc_parse_free(&prs); @@ -6695,7 +6695,7 @@ static BC_STATUS zbc_vm_process(const char *text) s = zbc_parse_text_init(&G.prs, text); // does the first zbc_lex_next() if (s) RETURN_STATUS(s); - while (G.prs.l.t.t != BC_LEX_EOF) { + while (G.prs.l.t.t != XC_LEX_EOF) { BcInstPtr *ip; BcFunc *f; @@ -6713,7 +6713,7 @@ static BC_STATUS zbc_vm_process(const char *text) while (G.prs.l.t.t == BC_LEX_NLINE) { s = zbc_lex_next(&G.prs.l); if (s) goto err; - if (G.prs.l.t.t == BC_LEX_EOF) + if (G.prs.l.t.t == XC_LEX_EOF) goto done; } IF_DC(s = zdc_parse_expr(&G.prs)); -- cgit v1.2.3-55-g6feb From abf6cf67654425a7ede2f9c18e83f35c48cd67f8 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 24 Dec 2018 13:20:57 +0100 Subject: bc: move BC_LEX_OP_INC/DEC to the end of operation LEX constants Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 188 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 95 insertions(+), 93 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index b4e9e6cb1..3ae88f1a5 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -251,35 +251,34 @@ typedef enum BcInst { BC_INST_INC_POST, BC_INST_DEC_POST, #endif - XC_INST_NEG, - - XC_INST_POWER, - XC_INST_MULTIPLY, - XC_INST_DIVIDE, - XC_INST_MODULUS, - XC_INST_PLUS, - XC_INST_MINUS, - - XC_INST_REL_EQ, - XC_INST_REL_LE, - XC_INST_REL_GE, - XC_INST_REL_NE, - XC_INST_REL_LT, - XC_INST_REL_GT, - - XC_INST_BOOL_NOT, - XC_INST_BOOL_OR, - XC_INST_BOOL_AND, - + XC_INST_NEG, // order + + XC_INST_POWER, // should + XC_INST_MULTIPLY, // match + XC_INST_DIVIDE, // LEX + XC_INST_MODULUS, // constants + XC_INST_PLUS, // for + XC_INST_MINUS, // these + + XC_INST_REL_EQ, // opeartions + XC_INST_REL_LE, // | + XC_INST_REL_GE, // | + XC_INST_REL_NE, // | + XC_INST_REL_LT, // | + XC_INST_REL_GT, // | + + XC_INST_BOOL_NOT, // | + XC_INST_BOOL_OR, // | + XC_INST_BOOL_AND, // | #if ENABLE_BC - BC_INST_ASSIGN_POWER, - BC_INST_ASSIGN_MULTIPLY, - BC_INST_ASSIGN_DIVIDE, - BC_INST_ASSIGN_MODULUS, - BC_INST_ASSIGN_PLUS, - BC_INST_ASSIGN_MINUS, + BC_INST_ASSIGN_POWER, // | + BC_INST_ASSIGN_MULTIPLY,// | + BC_INST_ASSIGN_DIVIDE, // | + BC_INST_ASSIGN_MODULUS, // | + BC_INST_ASSIGN_PLUS, // | + BC_INST_ASSIGN_MINUS, // | #endif - XC_INST_ASSIGN, + XC_INST_ASSIGN, // V XC_INST_NUM, XC_INST_VAR, @@ -394,37 +393,39 @@ typedef enum BcLexType { XC_LEX_EOF, XC_LEX_INVALID, + BC_LEX_1st_op, + BC_LEX_NEG = BC_LEX_1st_op, // order + + BC_LEX_OP_POWER, // should + BC_LEX_OP_MULTIPLY, // match + BC_LEX_OP_DIVIDE, // INST + BC_LEX_OP_MODULUS, // constants + BC_LEX_OP_PLUS, // for + BC_LEX_OP_MINUS, // these + + BC_LEX_OP_REL_EQ, // opeartions + BC_LEX_OP_REL_LE, // | + BC_LEX_OP_REL_GE, // | + BC_LEX_OP_REL_NE, // | + BC_LEX_OP_REL_LT, // | + BC_LEX_OP_REL_GT, // | + + BC_LEX_OP_BOOL_NOT, // | + BC_LEX_OP_BOOL_OR, // | + BC_LEX_OP_BOOL_AND, // | + + BC_LEX_OP_ASSIGN_POWER, // | + BC_LEX_OP_ASSIGN_MULTIPLY, // | + BC_LEX_OP_ASSIGN_DIVIDE, // | + BC_LEX_OP_ASSIGN_MODULUS, // | + BC_LEX_OP_ASSIGN_PLUS, // | + BC_LEX_OP_ASSIGN_MINUS, // | + + BC_LEX_OP_ASSIGN, // V + BC_LEX_OP_INC, BC_LEX_OP_DEC, - BC_LEX_NEG, - - BC_LEX_OP_POWER, - BC_LEX_OP_MULTIPLY, - BC_LEX_OP_DIVIDE, - BC_LEX_OP_MODULUS, - BC_LEX_OP_PLUS, - BC_LEX_OP_MINUS, - - BC_LEX_OP_REL_EQ, - BC_LEX_OP_REL_LE, - BC_LEX_OP_REL_GE, - BC_LEX_OP_REL_NE, - BC_LEX_OP_REL_LT, - BC_LEX_OP_REL_GT, - - BC_LEX_OP_BOOL_NOT, - BC_LEX_OP_BOOL_OR, - BC_LEX_OP_BOOL_AND, - - BC_LEX_OP_ASSIGN_POWER, - BC_LEX_OP_ASSIGN_MULTIPLY, - BC_LEX_OP_ASSIGN_DIVIDE, - BC_LEX_OP_ASSIGN_MODULUS, - BC_LEX_OP_ASSIGN_PLUS, - BC_LEX_OP_ASSIGN_MINUS, - BC_LEX_OP_ASSIGN, - BC_LEX_NLINE, BC_LEX_WHITESPACE, @@ -565,14 +566,14 @@ enum { #define EXBITS(a,b,c,d,e,f,g,h) \ ((uint64_t)((a << 0)+(b << 1)+(c << 2)+(d << 3)+(e << 4)+(f << 5)+(g << 6)+(h << 7))) BC_PARSE_EXPRS_BITS = 0 // corresponding BC_LEX_xyz: - + (EXBITS(0,0,1,1,1,1,1,1) << (0*8)) // 0: eof inval ++ -- - ^ * / - + (EXBITS(1,1,1,1,1,1,1,1) << (1*8)) // 8: % + - == <= >= != < - + (EXBITS(1,1,1,1,1,1,1,1) << (2*8)) // 16: > ! || && ^= *= /= %= - + (EXBITS(1,1,1,0,0,1,1,0) << (3*8)) // 24: += -= = NL WS ( ) [ - + (EXBITS(0,0,0,0,0,0,1,1) << (4*8)) // 32: , ] { ; } STR NAME NUM - + (EXBITS(0,0,0,0,0,0,0,1) << (5*8)) // 40: auto break cont define else for halt ibase - + (EXBITS(1,0,1,1,0,0,0,1) << (6*8)) // 48: obase if last length limits print quit read - + (EXBITS(0,1,1,0,0,0,0,0) << (7*8)) // 56: return scale sqrt while + + (EXBITS(0,0,1,1,1,1,1,1) << (0*8)) // 0: eof inval - ^ * / % + + + (EXBITS(1,1,1,1,1,1,1,1) << (1*8)) // 8: - == <= >= != < > ! + + (EXBITS(1,1,1,1,1,1,1,1) << (2*8)) // 16: || && ^= *= /= %= += -= + + (EXBITS(1,1,1,0,0,1,1,0) << (3*8)) // 24: = ++ -- NL WS ( ) [ + + (EXBITS(0,0,0,0,0,0,1,1) << (4*8)) // 32: , ] { ; } STR NAME NUM + + (EXBITS(0,0,0,0,0,0,0,1) << (5*8)) // 40: auto break cont define else for halt ibase + + (EXBITS(1,0,1,1,0,0,0,1) << (6*8)) // 48: obase if last length limits print quit read + + (EXBITS(0,1,1,0,0,0,0,0) << (7*8)) // 56: return scale sqrt while #undef EXBITS }; static ALWAYS_INLINE long bc_parse_exprs(unsigned i) @@ -592,10 +593,9 @@ static ALWAYS_INLINE long bc_parse_exprs(unsigned i) } // This is an array of data for operators that correspond to -// [BC_LEX_OP_INC...BC_LEX_OP_ASSIGN] token types. +// [BC_LEX_1st_op...BC_LEX_last_op] token types. static const uint8_t bc_parse_ops[] = { #define OP(p,l) ((int)(l) * 0x10 + (p)) - OP(0, false), OP( 0, false ), // inc dec OP(1, false), // neg OP(2, false), // pow OP(3, true ), OP( 3, true ), OP( 3, true ), // mul div mod @@ -605,6 +605,7 @@ static const uint8_t bc_parse_ops[] = { OP(7, true ), OP( 7, true ), // or and OP(5, false), OP( 5, false ), OP( 5, false ), OP( 5, false ), OP( 5, false ), // ^= *= /= %= += OP(5, false), OP( 5, false ), // -= = + OP(0, false), OP( 0, false ), // inc dec #undef OP }; #define bc_parse_op_PREC(i) (bc_parse_ops[i] & 0x0f) @@ -658,29 +659,30 @@ dc_char_to_LEX[] = { static const //BcInst - should be this type. Using signed narrow type since DC_INST_INVALID is -1 int8_t dc_LEX_to_INST[] = { // (so many INVALIDs b/c dc parser does not generate these LEXs) // corresponding BC_LEX_xyz: - DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, XC_INST_REL_GE, // EOF INVALID OP_INC OP_DEC - DC_INST_INVALID, XC_INST_POWER, XC_INST_MULTIPLY, XC_INST_DIVIDE, // NEG OP_POWER OP_MULTIPLY OP_DIVIDE - XC_INST_MODULUS, XC_INST_PLUS, XC_INST_MINUS, // OP_MODULUS OP_PLUS OP_MINUS - DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, // OP_REL_EQ OP_REL_LE OP_REL_GE OP_REL_NE - DC_INST_INVALID, DC_INST_INVALID, // OP_REL_LT OP_REL_GT - XC_INST_BOOL_NOT, DC_INST_INVALID, DC_INST_INVALID, // OP_BOOL_NOT OP_BOOL_OR OP_BOOL_AND + DC_INST_INVALID, DC_INST_INVALID, // EOF INVALID + DC_INST_INVALID, XC_INST_POWER, XC_INST_MULTIPLY, XC_INST_DIVIDE, // NEG OP_POWER OP_MULTIPLY OP_DIVIDE + XC_INST_MODULUS, XC_INST_PLUS, XC_INST_MINUS, // OP_MODULUS OP_PLUS OP_MINUS + DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, // OP_REL_EQ OP_REL_LE OP_REL_GE OP_REL_NE + DC_INST_INVALID, DC_INST_INVALID, // OP_REL_LT OP_REL_GT + XC_INST_BOOL_NOT, DC_INST_INVALID, DC_INST_INVALID, // OP_BOOL_NOT OP_BOOL_OR OP_BOOL_AND DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, // OP_ASSIGN_POWER OP_ASSIGN_MULTIPLY OP_ASSIGN_DIVIDE OP_ASSIGN_MODULUS - DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, // OP_ASSIGN_PLUS OP_ASSIGN_MINUS OP_ASSIGN - DC_INST_INVALID, DC_INST_INVALID, XC_INST_REL_GT, DC_INST_INVALID, // NLINE WHITESPACE LPAREN RPAREN - DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, XC_INST_REL_GE, // LBRACKET COMMA RBRACKET LBRACE - DC_INST_INVALID, DC_INST_INVALID, // SCOLON RBRACE - DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, // STR NAME NUMBER - DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, // KEY_AUTO KEY_BREAK KEY_CONTINUE KEY_DEFINE - DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, XC_INST_IBASE, // KEY_ELSE KEY_FOR KEY_HALT KEY_IBASE - XC_INST_OBASE, DC_INST_INVALID, IF_BC(DC_INST_INVALID,) XC_INST_LENGTH,//KEY_OBASE KEY_IF KEY_LAST(bc) KEY_LENGTH - DC_INST_INVALID, XC_INST_PRINT, DC_INST_QUIT, DC_INST_INVALID, // KEY_LIMITS KEY_PRINT KEY_QUIT KEY_READ - DC_INST_INVALID, XC_INST_SCALE, XC_INST_SQRT, DC_INST_INVALID, // KEY_RETURN KEY_SCALE KEY_SQRT KEY_WHILE - XC_INST_REL_EQ, DC_INST_MODEXP, DC_INST_DIVMOD, DC_INST_INVALID, // EQ_NO_REG OP_MODEXP OP_DIVMOD COLON - DC_INST_INVALID, DC_INST_EXECUTE, DC_INST_PRINT_STACK, DC_INST_CLEAR_STACK, //ELSE EXECUTE PRINT_STACK CLEAR_STACK - DC_INST_STACK_LEN, DC_INST_DUPLICATE, DC_INST_SWAP, XC_INST_POP, // STACK_LEVEL DUPLICATE SWAP POP - DC_INST_ASCIIFY, DC_INST_PRINT_STREAM, DC_INST_INVALID, DC_INST_INVALID, //ASCIIFY PRINT_STREAM STORE_IBASE STORE_OBASE - DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, // STORE_SCALE LOAD LOAD_POP STORE_PUSH - XC_INST_PRINT, DC_INST_NQUIT, XC_INST_SCALE_FUNC, // PRINT_POP NQUIT SCALE_FACTOR + DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, // OP_ASSIGN_PLUS OP_ASSIGN_MINUS OP_ASSIGN + DC_INST_INVALID, XC_INST_REL_GE, // OP_INC OP_DEC + DC_INST_INVALID, DC_INST_INVALID, XC_INST_REL_GT, DC_INST_INVALID, // NLINE WHITESPACE LPAREN RPAREN + DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, XC_INST_REL_GE, // LBRACKET COMMA RBRACKET LBRACE + DC_INST_INVALID, DC_INST_INVALID, // SCOLON RBRACE + DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, // STR NAME NUMBER + DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, // KEY_AUTO KEY_BREAK KEY_CONTINUE KEY_DEFINE + DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, XC_INST_IBASE, // KEY_ELSE KEY_FOR KEY_HALT KEY_IBASE + XC_INST_OBASE, DC_INST_INVALID, IF_BC(DC_INST_INVALID,) XC_INST_LENGTH,//KEY_OBASE KEY_IF KEY_LAST(bc) KEY_LENGTH + DC_INST_INVALID, XC_INST_PRINT, DC_INST_QUIT, DC_INST_INVALID, // KEY_LIMITS KEY_PRINT KEY_QUIT KEY_READ + DC_INST_INVALID, XC_INST_SCALE, XC_INST_SQRT, DC_INST_INVALID, // KEY_RETURN KEY_SCALE KEY_SQRT KEY_WHILE + XC_INST_REL_EQ, DC_INST_MODEXP, DC_INST_DIVMOD, DC_INST_INVALID, // EQ_NO_REG OP_MODEXP OP_DIVMOD COLON + DC_INST_INVALID, DC_INST_EXECUTE, DC_INST_PRINT_STACK, DC_INST_CLEAR_STACK, //ELSE EXECUTE PRINT_STACK CLEAR_STACK + DC_INST_STACK_LEN, DC_INST_DUPLICATE, DC_INST_SWAP, XC_INST_POP, // STACK_LEVEL DUPLICATE SWAP POP + DC_INST_ASCIIFY, DC_INST_PRINT_STREAM, DC_INST_INVALID, DC_INST_INVALID, //ASCIIFY PRINT_STREAM STORE_IBASE STORE_OBASE + DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, // STORE_SCALE LOAD LOAD_POP STORE_PUSH + XC_INST_PRINT, DC_INST_NQUIT, XC_INST_SCALE_FUNC, // PRINT_POP NQUIT SCALE_FACTOR }; #endif // ENABLE_DC @@ -3684,7 +3686,7 @@ static size_t bc_program_addFunc(char *name) // We can calculate the conversion between tokens and exprs by subtracting the // position of the first operator in the lex enum and adding the position of the // first in the expr enum. Note: This only works for binary operators. -#define BC_TOKEN_2_INST(t) ((char) ((t) - BC_LEX_NEG + XC_INST_NEG)) +#define BC_TOKEN_2_INST(t) ((char) ((t) - BC_LEX_OP_POWER + XC_INST_POWER)) static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags); @@ -3724,14 +3726,14 @@ static BC_STATUS zbc_parse_stmt_allow_NLINE_before(BcParse *p, const char *after static void bc_parse_operator(BcParse *p, BcLexType type, size_t start, size_t *nexprs) { - char l, r = bc_parse_op_PREC(type - BC_LEX_OP_INC); - bool left = bc_parse_op_LEFT(type - BC_LEX_OP_INC); + char l, r = bc_parse_op_PREC(type - BC_LEX_1st_op); + bool left = bc_parse_op_LEFT(type - BC_LEX_1st_op); while (p->ops.len > start) { BcLexType t = BC_PARSE_TOP_OP(p); if (t == BC_LEX_LPAREN) break; - l = bc_parse_op_PREC(t - BC_LEX_OP_INC); + l = bc_parse_op_PREC(t - BC_LEX_1st_op); if (l >= r && (l != r || !left)) break; bc_parse_push(p, BC_TOKEN_2_INST(t)); @@ -3754,7 +3756,7 @@ static BC_STATUS zbc_parse_rightParen(BcParse *p, size_t ops_bgn, size_t *nexs) bc_parse_push(p, BC_TOKEN_2_INST(top)); bc_vec_pop(&p->ops); - *nexs -= top != BC_LEX_OP_BOOL_NOT && top != BC_LEX_NEG; + *nexs -= (top != BC_LEX_OP_BOOL_NOT && top != BC_LEX_NEG); if (p->ops.len <= ops_bgn) RETURN_STATUS(bc_error_bad_expression()); @@ -4791,7 +4793,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) bc_parse_push(p, BC_TOKEN_2_INST(top)); - nexprs -= top != BC_LEX_OP_BOOL_NOT && top != BC_LEX_NEG; + nexprs -= (top != BC_LEX_OP_BOOL_NOT && top != BC_LEX_NEG); bc_vec_pop(&p->ops); } -- cgit v1.2.3-55-g6feb From 69560f42da3deb5c87a9ccdbcaae26a5ff0cabaf Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 24 Dec 2018 14:14:23 +0100 Subject: bc: rename several BC_LEX_OPs to XC_LEX_OPs. Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 143 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 72 insertions(+), 71 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 3ae88f1a5..f9d654afb 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -388,27 +388,27 @@ typedef struct BcInstPtr { IF_BC(size_t results_len_before_call;) } BcInstPtr; -// BC_LEX_NEG is not used in lexing; it is only for parsing. +// XC_LEX_NEG is not used in lexing; it is only for parsing. typedef enum BcLexType { XC_LEX_EOF, XC_LEX_INVALID, - BC_LEX_1st_op, - BC_LEX_NEG = BC_LEX_1st_op, // order + XC_LEX_1st_op, + XC_LEX_NEG = XC_LEX_1st_op, // order - BC_LEX_OP_POWER, // should - BC_LEX_OP_MULTIPLY, // match - BC_LEX_OP_DIVIDE, // INST - BC_LEX_OP_MODULUS, // constants - BC_LEX_OP_PLUS, // for - BC_LEX_OP_MINUS, // these + XC_LEX_OP_POWER, // should + XC_LEX_OP_MULTIPLY, // match + XC_LEX_OP_DIVIDE, // INST + XC_LEX_OP_MODULUS, // constants + XC_LEX_OP_PLUS, // for + XC_LEX_OP_MINUS, // these - BC_LEX_OP_REL_EQ, // opeartions - BC_LEX_OP_REL_LE, // | - BC_LEX_OP_REL_GE, // | - BC_LEX_OP_REL_NE, // | - BC_LEX_OP_REL_LT, // | - BC_LEX_OP_REL_GT, // | + XC_LEX_OP_REL_EQ, // opeartions + XC_LEX_OP_REL_LE, // | + XC_LEX_OP_REL_GE, // | + XC_LEX_OP_REL_NE, // | + XC_LEX_OP_REL_LT, // | + XC_LEX_OP_REL_GT, // | BC_LEX_OP_BOOL_NOT, // | BC_LEX_OP_BOOL_OR, // | @@ -593,7 +593,7 @@ static ALWAYS_INLINE long bc_parse_exprs(unsigned i) } // This is an array of data for operators that correspond to -// [BC_LEX_1st_op...BC_LEX_last_op] token types. +// [XC_LEX_1st_op...] token types. static const uint8_t bc_parse_ops[] = { #define OP(p,l) ((int)(l) * 0x10 + (p)) OP(1, false), // neg @@ -617,18 +617,18 @@ static const //BcLexType - should be this type uint8_t dc_char_to_LEX[] = { /* %&'( */ - BC_LEX_OP_MODULUS, XC_LEX_INVALID, XC_LEX_INVALID, BC_LEX_LPAREN, + XC_LEX_OP_MODULUS, XC_LEX_INVALID, XC_LEX_INVALID, BC_LEX_LPAREN, /* )*+, */ - XC_LEX_INVALID, BC_LEX_OP_MULTIPLY, BC_LEX_OP_PLUS, XC_LEX_INVALID, + XC_LEX_INVALID, XC_LEX_OP_MULTIPLY, XC_LEX_OP_PLUS, XC_LEX_INVALID, /* -./ */ - BC_LEX_OP_MINUS, XC_LEX_INVALID, BC_LEX_OP_DIVIDE, + XC_LEX_OP_MINUS, XC_LEX_INVALID, XC_LEX_OP_DIVIDE, /* 0123456789 */ XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, /* :;<=>?@ */ - DC_LEX_COLON, BC_LEX_SCOLON, BC_LEX_OP_REL_GT, BC_LEX_OP_REL_EQ, - BC_LEX_OP_REL_LT, BC_LEX_KEY_READ, XC_LEX_INVALID, + DC_LEX_COLON, BC_LEX_SCOLON, XC_LEX_OP_REL_GT, XC_LEX_OP_REL_EQ, + XC_LEX_OP_REL_LT, BC_LEX_KEY_READ, XC_LEX_INVALID, /* ABCDEFGH */ XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, DC_LEX_EQ_NO_REG, XC_LEX_INVALID, @@ -641,7 +641,7 @@ dc_char_to_LEX[] = { /* Z[\] */ BC_LEX_KEY_LENGTH, XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, /* ^_` */ - BC_LEX_OP_POWER, BC_LEX_NEG, XC_LEX_INVALID, + XC_LEX_OP_POWER, XC_LEX_NEG, XC_LEX_INVALID, /* abcdefgh */ DC_LEX_ASCIIFY, XC_LEX_INVALID, DC_LEX_CLEAR_STACK, DC_LEX_DUPLICATE, DC_LEX_ELSE, DC_LEX_PRINT_STACK, XC_LEX_INVALID, XC_LEX_INVALID, @@ -660,7 +660,8 @@ static const //BcInst - should be this type. Using signed narrow type since DC_I int8_t dc_LEX_to_INST[] = { // (so many INVALIDs b/c dc parser does not generate these LEXs) // corresponding BC_LEX_xyz: DC_INST_INVALID, DC_INST_INVALID, // EOF INVALID - DC_INST_INVALID, XC_INST_POWER, XC_INST_MULTIPLY, XC_INST_DIVIDE, // NEG OP_POWER OP_MULTIPLY OP_DIVIDE + DC_INST_INVALID, // NEG + XC_INST_POWER, XC_INST_MULTIPLY, XC_INST_DIVIDE, // OP_POWER OP_MULTIPLY OP_DIVIDE XC_INST_MODULUS, XC_INST_PLUS, XC_INST_MINUS, // OP_MODULUS OP_PLUS OP_MINUS DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, // OP_REL_EQ OP_REL_LE OP_REL_GE OP_REL_NE DC_INST_INVALID, DC_INST_INVALID, // OP_REL_LT OP_REL_GT @@ -3159,7 +3160,7 @@ static BC_STATUS zbc_lex_token(BcLex *l) bc_lex_whitespace(l); break; case '!': - bc_lex_assign(l, BC_LEX_OP_REL_NE, BC_LEX_OP_BOOL_NOT); + bc_lex_assign(l, XC_LEX_OP_REL_NE, BC_LEX_OP_BOOL_NOT); if (l->t.t == BC_LEX_OP_BOOL_NOT) { s = bc_POSIX_does_not_allow_bool_ops_this_is_bad("!"); IF_ERROR_RETURN_POSSIBLE(if (s) RETURN_STATUS(s)); @@ -3174,7 +3175,7 @@ static BC_STATUS zbc_lex_token(BcLex *l) bc_lex_lineComment(l); break; case '%': - bc_lex_assign(l, BC_LEX_OP_ASSIGN_MODULUS, BC_LEX_OP_MODULUS); + bc_lex_assign(l, BC_LEX_OP_ASSIGN_MODULUS, XC_LEX_OP_MODULUS); break; case '&': c2 = l->buf[l->i]; @@ -3193,7 +3194,7 @@ static BC_STATUS zbc_lex_token(BcLex *l) l->t.t = (BcLexType)(c - '(' + BC_LEX_LPAREN); break; case '*': - bc_lex_assign(l, BC_LEX_OP_ASSIGN_MULTIPLY, BC_LEX_OP_MULTIPLY); + bc_lex_assign(l, BC_LEX_OP_ASSIGN_MULTIPLY, XC_LEX_OP_MULTIPLY); break; case '+': c2 = l->buf[l->i]; @@ -3201,7 +3202,7 @@ static BC_STATUS zbc_lex_token(BcLex *l) ++l->i; l->t.t = BC_LEX_OP_INC; } else - bc_lex_assign(l, BC_LEX_OP_ASSIGN_PLUS, BC_LEX_OP_PLUS); + bc_lex_assign(l, BC_LEX_OP_ASSIGN_PLUS, XC_LEX_OP_PLUS); break; case ',': l->t.t = BC_LEX_COMMA; @@ -3212,7 +3213,7 @@ static BC_STATUS zbc_lex_token(BcLex *l) ++l->i; l->t.t = BC_LEX_OP_DEC; } else - bc_lex_assign(l, BC_LEX_OP_ASSIGN_MINUS, BC_LEX_OP_MINUS); + bc_lex_assign(l, BC_LEX_OP_ASSIGN_MINUS, XC_LEX_OP_MINUS); break; case '.': if (isdigit(l->buf[l->i])) @@ -3227,7 +3228,7 @@ static BC_STATUS zbc_lex_token(BcLex *l) if (c2 == '*') s = zbc_lex_comment(l); else - bc_lex_assign(l, BC_LEX_OP_ASSIGN_DIVIDE, BC_LEX_OP_DIVIDE); + bc_lex_assign(l, BC_LEX_OP_ASSIGN_DIVIDE, XC_LEX_OP_DIVIDE); break; case '0': case '1': @@ -3251,13 +3252,13 @@ static BC_STATUS zbc_lex_token(BcLex *l) l->t.t = BC_LEX_SCOLON; break; case '<': - bc_lex_assign(l, BC_LEX_OP_REL_LE, BC_LEX_OP_REL_LT); + bc_lex_assign(l, XC_LEX_OP_REL_LE, XC_LEX_OP_REL_LT); break; case '=': - bc_lex_assign(l, BC_LEX_OP_REL_EQ, BC_LEX_OP_ASSIGN); + bc_lex_assign(l, XC_LEX_OP_REL_EQ, BC_LEX_OP_ASSIGN); break; case '>': - bc_lex_assign(l, BC_LEX_OP_REL_GE, BC_LEX_OP_REL_GT); + bc_lex_assign(l, XC_LEX_OP_REL_GE, XC_LEX_OP_REL_GT); break; case '[': case ']': @@ -3271,7 +3272,7 @@ static BC_STATUS zbc_lex_token(BcLex *l) s = bc_error_bad_character(c); break; case '^': - bc_lex_assign(l, BC_LEX_OP_ASSIGN_POWER, BC_LEX_OP_POWER); + bc_lex_assign(l, BC_LEX_OP_ASSIGN_POWER, XC_LEX_OP_POWER); break; case 'a': case 'b': @@ -3395,8 +3396,8 @@ static BC_STATUS zdc_lex_token(BcLex *l) static const //BcLexType - should be this type, but narrower type saves size: uint8_t dc_lex_regs[] = { - BC_LEX_OP_REL_EQ, BC_LEX_OP_REL_LE, BC_LEX_OP_REL_GE, BC_LEX_OP_REL_NE, - BC_LEX_OP_REL_LT, BC_LEX_OP_REL_GT, BC_LEX_SCOLON, DC_LEX_COLON, + XC_LEX_OP_REL_EQ, XC_LEX_OP_REL_LE, XC_LEX_OP_REL_GE, XC_LEX_OP_REL_NE, + XC_LEX_OP_REL_LT, XC_LEX_OP_REL_GT, BC_LEX_SCOLON, DC_LEX_COLON, DC_LEX_ELSE, DC_LEX_LOAD, DC_LEX_LOAD_POP, BC_LEX_OP_ASSIGN, DC_LEX_STORE_PUSH, }; @@ -3446,11 +3447,11 @@ static BC_STATUS zdc_lex_token(BcLex *l) case '!': c2 = l->buf[l->i]; if (c2 == '=') - l->t.t = BC_LEX_OP_REL_NE; + l->t.t = XC_LEX_OP_REL_NE; else if (c2 == '<') - l->t.t = BC_LEX_OP_REL_LE; + l->t.t = XC_LEX_OP_REL_LE; else if (c2 == '>') - l->t.t = BC_LEX_OP_REL_GE; + l->t.t = XC_LEX_OP_REL_GE; else RETURN_STATUS(bc_error_bad_character(c)); ++l->i; @@ -3686,7 +3687,7 @@ static size_t bc_program_addFunc(char *name) // We can calculate the conversion between tokens and exprs by subtracting the // position of the first operator in the lex enum and adding the position of the // first in the expr enum. Note: This only works for binary operators. -#define BC_TOKEN_2_INST(t) ((char) ((t) - BC_LEX_OP_POWER + XC_INST_POWER)) +#define BC_TOKEN_2_INST(t) ((char) ((t) - XC_LEX_OP_POWER + XC_INST_POWER)) static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags); @@ -3726,19 +3727,19 @@ static BC_STATUS zbc_parse_stmt_allow_NLINE_before(BcParse *p, const char *after static void bc_parse_operator(BcParse *p, BcLexType type, size_t start, size_t *nexprs) { - char l, r = bc_parse_op_PREC(type - BC_LEX_1st_op); - bool left = bc_parse_op_LEFT(type - BC_LEX_1st_op); + char l, r = bc_parse_op_PREC(type - XC_LEX_1st_op); + bool left = bc_parse_op_LEFT(type - XC_LEX_1st_op); while (p->ops.len > start) { BcLexType t = BC_PARSE_TOP_OP(p); if (t == BC_LEX_LPAREN) break; - l = bc_parse_op_PREC(t - BC_LEX_1st_op); + l = bc_parse_op_PREC(t - XC_LEX_1st_op); if (l >= r && (l != r || !left)) break; bc_parse_push(p, BC_TOKEN_2_INST(t)); bc_vec_pop(&p->ops); - *nexprs -= (t != BC_LEX_OP_BOOL_NOT && t != BC_LEX_NEG); + *nexprs -= (t != BC_LEX_OP_BOOL_NOT && t != XC_LEX_NEG); } bc_vec_push(&p->ops, &type); @@ -3756,7 +3757,7 @@ static BC_STATUS zbc_parse_rightParen(BcParse *p, size_t ops_bgn, size_t *nexs) bc_parse_push(p, BC_TOKEN_2_INST(top)); bc_vec_pop(&p->ops); - *nexs -= (top != BC_LEX_OP_BOOL_NOT && top != BC_LEX_NEG); + *nexs -= (top != BC_LEX_OP_BOOL_NOT && top != XC_LEX_NEG); if (p->ops.len <= ops_bgn) RETURN_STATUS(bc_error_bad_expression()); @@ -4032,13 +4033,13 @@ static BC_STATUS zbc_parse_minus(BcParse *p, BcInst *prev, size_t ops_bgn, type = rparen || etype == BC_INST_INC_POST || etype == BC_INST_DEC_POST || (etype >= XC_INST_NUM && etype <= XC_INST_SQRT) ? - BC_LEX_OP_MINUS : - BC_LEX_NEG; + XC_LEX_OP_MINUS : + XC_LEX_NEG; *prev = BC_TOKEN_2_INST(type); // We can just push onto the op stack because this is the largest // precedence operator that gets pushed. Inc/dec does not. - if (type != BC_LEX_OP_MINUS) + if (type != XC_LEX_OP_MINUS) bc_vec_push(&p->ops, &type); else bc_parse_operator(p, type, ops_bgn, nexprs); @@ -4523,9 +4524,9 @@ static BC_STATUS zbc_parse_stmt_possibly_auto(BcParse *p, bool auto_allowed) dbg_lex("%s:%d p->l.t.t:%d", __func__, __LINE__, p->l.t.t); switch (p->l.t.t) { + case XC_LEX_OP_MINUS: case BC_LEX_OP_INC: case BC_LEX_OP_DEC: - case BC_LEX_OP_MINUS: case BC_LEX_OP_BOOL_NOT: case BC_LEX_LPAREN: case BC_LEX_NAME: @@ -4642,7 +4643,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) s = zbc_parse_incdec(p, &prev, &paren_expr, &nexprs, flags); rprn = get_token = bin_last = false; break; - case BC_LEX_OP_MINUS: + case XC_LEX_OP_MINUS: s = zbc_parse_minus(p, &prev, ops_bgn, rprn, &nexprs); rprn = get_token = false; bin_last = prev == XC_INST_MINUS; @@ -4665,17 +4666,17 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) break; } // Fallthrough. - case BC_LEX_OP_POWER: - case BC_LEX_OP_MULTIPLY: - case BC_LEX_OP_DIVIDE: - case BC_LEX_OP_MODULUS: - case BC_LEX_OP_PLUS: - case BC_LEX_OP_REL_EQ: - case BC_LEX_OP_REL_LE: - case BC_LEX_OP_REL_GE: - case BC_LEX_OP_REL_NE: - case BC_LEX_OP_REL_LT: - case BC_LEX_OP_REL_GT: + case XC_LEX_OP_POWER: + case XC_LEX_OP_MULTIPLY: + case XC_LEX_OP_DIVIDE: + case XC_LEX_OP_MODULUS: + case XC_LEX_OP_PLUS: + case XC_LEX_OP_REL_EQ: + case XC_LEX_OP_REL_LE: + case XC_LEX_OP_REL_GE: + case XC_LEX_OP_REL_NE: + case XC_LEX_OP_REL_LT: + case XC_LEX_OP_REL_GT: case BC_LEX_OP_BOOL_NOT: case BC_LEX_OP_BOOL_OR: case BC_LEX_OP_BOOL_AND: @@ -4684,12 +4685,12 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) ) { return bc_error_bad_expression(); } - nrelops += t >= BC_LEX_OP_REL_EQ && t <= BC_LEX_OP_REL_GT; + nrelops += (t >= XC_LEX_OP_REL_EQ && t <= XC_LEX_OP_REL_GT); prev = BC_TOKEN_2_INST(t); bc_parse_operator(p, t, ops_bgn, &nexprs); s = zbc_lex_next(&p->l); rprn = get_token = false; - bin_last = t != BC_LEX_OP_BOOL_NOT; + bin_last = (t != BC_LEX_OP_BOOL_NOT); break; case BC_LEX_LPAREN: if (BC_PARSE_LEAF(prev, rprn)) @@ -4793,7 +4794,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) bc_parse_push(p, BC_TOKEN_2_INST(top)); - nexprs -= (top != BC_LEX_OP_BOOL_NOT && top != BC_LEX_NEG); + nexprs -= (top != BC_LEX_OP_BOOL_NOT && top != XC_LEX_NEG); bc_vec_pop(&p->ops); } @@ -4912,14 +4913,14 @@ static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t) s = BC_STATUS_SUCCESS; get_token = true; switch (t) { - case BC_LEX_OP_REL_EQ: - case BC_LEX_OP_REL_LE: - case BC_LEX_OP_REL_GE: - case BC_LEX_OP_REL_NE: - case BC_LEX_OP_REL_LT: - case BC_LEX_OP_REL_GT: + case XC_LEX_OP_REL_EQ: + case XC_LEX_OP_REL_LE: + case XC_LEX_OP_REL_GE: + case XC_LEX_OP_REL_NE: + case XC_LEX_OP_REL_LT: + case XC_LEX_OP_REL_GT: dbg_lex("%s:%d LEX_OP_REL_xyz", __func__, __LINE__); - s = zdc_parse_cond(p, t - BC_LEX_OP_REL_EQ + XC_INST_REL_EQ); + s = zdc_parse_cond(p, t - XC_LEX_OP_REL_EQ + XC_INST_REL_EQ); get_token = false; break; case BC_LEX_SCOLON: @@ -4931,7 +4932,7 @@ static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t) dbg_lex("%s:%d LEX_STR", __func__, __LINE__); dc_parse_string(p); break; - case BC_LEX_NEG: + case XC_LEX_NEG: dbg_lex("%s:%d LEX_NEG", __func__, __LINE__); s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); -- cgit v1.2.3-55-g6feb From 9d9c97efbdc0f30851a5e56398c371d4171df34e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 24 Dec 2018 15:00:56 +0100 Subject: bc: separate many bc and dc LEX constants function old new delta zdc_parse_expr 510 516 +6 bc_parse_expr_empty_ok 1963 1966 +3 dc_LEX_to_INST 83 56 -27 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/1 up/down: 9/-27) Total: -18 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 118 +++++++++++++++++++++++++++++++++------------------------ 1 file changed, 69 insertions(+), 49 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index f9d654afb..a67cfbfcd 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -260,7 +260,7 @@ typedef enum BcInst { XC_INST_PLUS, // for XC_INST_MINUS, // these - XC_INST_REL_EQ, // opeartions + XC_INST_REL_EQ, // operations XC_INST_REL_LE, // | XC_INST_REL_GE, // | XC_INST_REL_NE, // | @@ -388,11 +388,16 @@ typedef struct BcInstPtr { IF_BC(size_t results_len_before_call;) } BcInstPtr; -// XC_LEX_NEG is not used in lexing; it is only for parsing. typedef enum BcLexType { XC_LEX_EOF, XC_LEX_INVALID, + BC_LEX_NLINE, + BC_LEX_WHITESPACE, + BC_LEX_STR, + BC_LEX_NAME, + BC_LEX_NUMBER, + XC_LEX_1st_op, XC_LEX_NEG = XC_LEX_1st_op, // order @@ -403,13 +408,14 @@ typedef enum BcLexType { XC_LEX_OP_PLUS, // for XC_LEX_OP_MINUS, // these - XC_LEX_OP_REL_EQ, // opeartions + XC_LEX_OP_REL_EQ, // operations XC_LEX_OP_REL_LE, // | XC_LEX_OP_REL_GE, // | XC_LEX_OP_REL_NE, // | XC_LEX_OP_REL_LT, // | XC_LEX_OP_REL_GT, // | - + XC_LEX_OP_last = XC_LEX_OP_REL_GT, +#if ENABLE_BC BC_LEX_OP_BOOL_NOT, // | BC_LEX_OP_BOOL_OR, // | BC_LEX_OP_BOOL_AND, // | @@ -426,9 +432,6 @@ typedef enum BcLexType { BC_LEX_OP_INC, BC_LEX_OP_DEC, - BC_LEX_NLINE, - BC_LEX_WHITESPACE, - BC_LEX_LPAREN, BC_LEX_RPAREN, @@ -440,10 +443,6 @@ typedef enum BcLexType { BC_LEX_SCOLON, BC_LEX_RBRACE, // should be LBRACE+2: code uses (c - '{' + BC_LEX_LBRACE) - BC_LEX_STR, - BC_LEX_NAME, - BC_LEX_NUMBER, - BC_LEX_KEY_1st_keyword, BC_LEX_KEY_AUTO = BC_LEX_KEY_1st_keyword, BC_LEX_KEY_BREAK, @@ -466,8 +465,24 @@ typedef enum BcLexType { BC_LEX_KEY_SCALE, BC_LEX_KEY_SQRT, BC_LEX_KEY_WHILE, +#endif // ENABLE_BC #if ENABLE_DC + DC_LEX_OP_BOOL_NOT = XC_LEX_OP_last + 1, + DC_LEX_OP_ASSIGN, + + DC_LEX_LPAREN, + DC_LEX_SCOLON, + DC_LEX_READ, + DC_LEX_IBASE, + DC_LEX_SCALE, + DC_LEX_OBASE, + DC_LEX_LENGTH, + DC_LEX_PRINT, + DC_LEX_QUIT, + DC_LEX_SQRT, + DC_LEX_LBRACE, + DC_LEX_EQ_NO_REG, DC_LEX_OP_MODEXP, DC_LEX_OP_DIVMOD, @@ -566,11 +581,11 @@ enum { #define EXBITS(a,b,c,d,e,f,g,h) \ ((uint64_t)((a << 0)+(b << 1)+(c << 2)+(d << 3)+(e << 4)+(f << 5)+(g << 6)+(h << 7))) BC_PARSE_EXPRS_BITS = 0 // corresponding BC_LEX_xyz: - + (EXBITS(0,0,1,1,1,1,1,1) << (0*8)) // 0: eof inval - ^ * / % + - + (EXBITS(1,1,1,1,1,1,1,1) << (1*8)) // 8: - == <= >= != < > ! - + (EXBITS(1,1,1,1,1,1,1,1) << (2*8)) // 16: || && ^= *= /= %= += -= - + (EXBITS(1,1,1,0,0,1,1,0) << (3*8)) // 24: = ++ -- NL WS ( ) [ - + (EXBITS(0,0,0,0,0,0,1,1) << (4*8)) // 32: , ] { ; } STR NAME NUM + + (EXBITS(0,0,0,0,0,1,1,1) << (0*8)) // 0: EOF INVAL NL WS STR NAME NUM - + + (EXBITS(1,1,1,1,1,1,1,1) << (1*8)) // 8: ^ * / % + - == <= + + (EXBITS(1,1,1,1,1,1,1,1) << (2*8)) // 16: >= != < > ! || && ^= + + (EXBITS(1,1,1,1,1,1,1,1) << (3*8)) // 24: *= /= %= += -= = ++ -- + + (EXBITS(1,1,0,0,0,0,0,0) << (4*8)) // 32: ( ) [ , ] { ; } + (EXBITS(0,0,0,0,0,0,0,1) << (5*8)) // 40: auto break cont define else for halt ibase + (EXBITS(1,0,1,1,0,0,0,1) << (6*8)) // 48: obase if last length limits print quit read + (EXBITS(0,1,1,0,0,0,0,0) << (7*8)) // 56: return scale sqrt while @@ -617,7 +632,7 @@ static const //BcLexType - should be this type uint8_t dc_char_to_LEX[] = { /* %&'( */ - XC_LEX_OP_MODULUS, XC_LEX_INVALID, XC_LEX_INVALID, BC_LEX_LPAREN, + XC_LEX_OP_MODULUS, XC_LEX_INVALID, XC_LEX_INVALID, DC_LEX_LPAREN, /* )*+, */ XC_LEX_INVALID, XC_LEX_OP_MULTIPLY, XC_LEX_OP_PLUS, XC_LEX_INVALID, /* -./ */ @@ -627,19 +642,19 @@ dc_char_to_LEX[] = { XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, /* :;<=>?@ */ - DC_LEX_COLON, BC_LEX_SCOLON, XC_LEX_OP_REL_GT, XC_LEX_OP_REL_EQ, - XC_LEX_OP_REL_LT, BC_LEX_KEY_READ, XC_LEX_INVALID, + DC_LEX_COLON, DC_LEX_SCOLON, XC_LEX_OP_REL_GT, XC_LEX_OP_REL_EQ, + XC_LEX_OP_REL_LT, DC_LEX_READ, XC_LEX_INVALID, /* ABCDEFGH */ XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, DC_LEX_EQ_NO_REG, XC_LEX_INVALID, /* IJKLMNOP */ - BC_LEX_KEY_IBASE, XC_LEX_INVALID, BC_LEX_KEY_SCALE, DC_LEX_LOAD_POP, - XC_LEX_INVALID, BC_LEX_OP_BOOL_NOT, BC_LEX_KEY_OBASE, DC_LEX_PRINT_STREAM, + DC_LEX_IBASE, XC_LEX_INVALID, DC_LEX_SCALE, DC_LEX_LOAD_POP, + XC_LEX_INVALID, DC_LEX_OP_BOOL_NOT, DC_LEX_OBASE, DC_LEX_PRINT_STREAM, /* QRSTUVWXY */ DC_LEX_NQUIT, DC_LEX_POP, DC_LEX_STORE_PUSH, XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, DC_LEX_SCALE_FACTOR, XC_LEX_INVALID, /* Z[\] */ - BC_LEX_KEY_LENGTH, XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, + DC_LEX_LENGTH, XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, /* ^_` */ XC_LEX_OP_POWER, XC_LEX_NEG, XC_LEX_INVALID, /* abcdefgh */ @@ -647,43 +662,48 @@ dc_char_to_LEX[] = { DC_LEX_ELSE, DC_LEX_PRINT_STACK, XC_LEX_INVALID, XC_LEX_INVALID, /* ijklmnop */ DC_LEX_STORE_IBASE, XC_LEX_INVALID, DC_LEX_STORE_SCALE, DC_LEX_LOAD, - XC_LEX_INVALID, DC_LEX_PRINT_POP, DC_LEX_STORE_OBASE, BC_LEX_KEY_PRINT, + XC_LEX_INVALID, DC_LEX_PRINT_POP, DC_LEX_STORE_OBASE, DC_LEX_PRINT, /* qrstuvwx */ - BC_LEX_KEY_QUIT, DC_LEX_SWAP, BC_LEX_OP_ASSIGN, XC_LEX_INVALID, - XC_LEX_INVALID, BC_LEX_KEY_SQRT, XC_LEX_INVALID, DC_LEX_EXECUTE, + DC_LEX_QUIT, DC_LEX_SWAP, DC_LEX_OP_ASSIGN, XC_LEX_INVALID, + XC_LEX_INVALID, DC_LEX_SQRT, XC_LEX_INVALID, DC_LEX_EXECUTE, /* yz */ XC_LEX_INVALID, DC_LEX_STACK_LEVEL, /* {|}~ */ - BC_LEX_LBRACE, DC_LEX_OP_MODEXP, XC_LEX_INVALID, DC_LEX_OP_DIVMOD, + DC_LEX_LBRACE, DC_LEX_OP_MODEXP, XC_LEX_INVALID, DC_LEX_OP_DIVMOD, }; static const //BcInst - should be this type. Using signed narrow type since DC_INST_INVALID is -1 int8_t -dc_LEX_to_INST[] = { // (so many INVALIDs b/c dc parser does not generate these LEXs) // corresponding BC_LEX_xyz: +dc_LEX_to_INST[] = { // (so many INVALIDs b/c dc parser does not generate these LEXs) // corresponding XC/DC_LEX_xyz: DC_INST_INVALID, DC_INST_INVALID, // EOF INVALID + DC_INST_INVALID, DC_INST_INVALID, // NLINE WHITESPACE + DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, // STR NAME NUMBER DC_INST_INVALID, // NEG - XC_INST_POWER, XC_INST_MULTIPLY, XC_INST_DIVIDE, // OP_POWER OP_MULTIPLY OP_DIVIDE - XC_INST_MODULUS, XC_INST_PLUS, XC_INST_MINUS, // OP_MODULUS OP_PLUS OP_MINUS - DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, // OP_REL_EQ OP_REL_LE OP_REL_GE OP_REL_NE + XC_INST_POWER, XC_INST_MULTIPLY, XC_INST_DIVIDE, // OP_POWER OP_MULTIPLY OP_DIVIDE + XC_INST_MODULUS, XC_INST_PLUS, XC_INST_MINUS, // OP_MODULUS OP_PLUS OP_MINUS + DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, // OP_REL_EQ OP_REL_LE OP_REL_GE OP_REL_NE DC_INST_INVALID, DC_INST_INVALID, // OP_REL_LT OP_REL_GT - XC_INST_BOOL_NOT, DC_INST_INVALID, DC_INST_INVALID, // OP_BOOL_NOT OP_BOOL_OR OP_BOOL_AND - DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, // OP_ASSIGN_POWER OP_ASSIGN_MULTIPLY OP_ASSIGN_DIVIDE OP_ASSIGN_MODULUS - DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, // OP_ASSIGN_PLUS OP_ASSIGN_MINUS OP_ASSIGN - DC_INST_INVALID, XC_INST_REL_GE, // OP_INC OP_DEC - DC_INST_INVALID, DC_INST_INVALID, XC_INST_REL_GT, DC_INST_INVALID, // NLINE WHITESPACE LPAREN RPAREN - DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, XC_INST_REL_GE, // LBRACKET COMMA RBRACKET LBRACE - DC_INST_INVALID, DC_INST_INVALID, // SCOLON RBRACE - DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, // STR NAME NUMBER - DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, // KEY_AUTO KEY_BREAK KEY_CONTINUE KEY_DEFINE - DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, XC_INST_IBASE, // KEY_ELSE KEY_FOR KEY_HALT KEY_IBASE - XC_INST_OBASE, DC_INST_INVALID, IF_BC(DC_INST_INVALID,) XC_INST_LENGTH,//KEY_OBASE KEY_IF KEY_LAST(bc) KEY_LENGTH - DC_INST_INVALID, XC_INST_PRINT, DC_INST_QUIT, DC_INST_INVALID, // KEY_LIMITS KEY_PRINT KEY_QUIT KEY_READ - DC_INST_INVALID, XC_INST_SCALE, XC_INST_SQRT, DC_INST_INVALID, // KEY_RETURN KEY_SCALE KEY_SQRT KEY_WHILE + XC_INST_BOOL_NOT, // DC_LEX_OP_BOOL_NOT + DC_INST_INVALID, // DC_LEX_OP_ASSIGN + XC_INST_REL_GT, // DC_LEX_LPAREN + DC_INST_INVALID, // DC_LEX_SCOLON + DC_INST_INVALID, // DC_LEX_READ + XC_INST_IBASE, // DC_LEX_IBASE + XC_INST_SCALE, // DC_LEX_SCALE + XC_INST_OBASE, // DC_LEX_OBASE + XC_INST_LENGTH, // DC_LEX_LENGTH + XC_INST_PRINT, // DC_LEX_PRINT + DC_INST_QUIT, // DC_LEX_QUIT + XC_INST_SQRT, // DC_LEX_SQRT + XC_INST_REL_GE, // DC_LEX_LBRACE XC_INST_REL_EQ, DC_INST_MODEXP, DC_INST_DIVMOD, DC_INST_INVALID, // EQ_NO_REG OP_MODEXP OP_DIVMOD COLON DC_INST_INVALID, DC_INST_EXECUTE, DC_INST_PRINT_STACK, DC_INST_CLEAR_STACK, //ELSE EXECUTE PRINT_STACK CLEAR_STACK DC_INST_STACK_LEN, DC_INST_DUPLICATE, DC_INST_SWAP, XC_INST_POP, // STACK_LEVEL DUPLICATE SWAP POP DC_INST_ASCIIFY, DC_INST_PRINT_STREAM, DC_INST_INVALID, DC_INST_INVALID, //ASCIIFY PRINT_STREAM STORE_IBASE STORE_OBASE DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, // STORE_SCALE LOAD LOAD_POP STORE_PUSH XC_INST_PRINT, DC_INST_NQUIT, XC_INST_SCALE_FUNC, // PRINT_POP NQUIT SCALE_FACTOR + // DC_INST_INVALID in this table either means that corresponding LEX + // is not possible for dc, or that it does not compile one-to-one + // to a single INST. }; #endif // ENABLE_DC @@ -3397,8 +3417,8 @@ static BC_STATUS zdc_lex_token(BcLex *l) uint8_t dc_lex_regs[] = { XC_LEX_OP_REL_EQ, XC_LEX_OP_REL_LE, XC_LEX_OP_REL_GE, XC_LEX_OP_REL_NE, - XC_LEX_OP_REL_LT, XC_LEX_OP_REL_GT, BC_LEX_SCOLON, DC_LEX_COLON, - DC_LEX_ELSE, DC_LEX_LOAD, DC_LEX_LOAD_POP, BC_LEX_OP_ASSIGN, + XC_LEX_OP_REL_LT, XC_LEX_OP_REL_GT, DC_LEX_SCOLON, DC_LEX_COLON, + DC_LEX_ELSE, DC_LEX_LOAD, DC_LEX_LOAD_POP, DC_LEX_OP_ASSIGN, DC_LEX_STORE_PUSH, }; @@ -4923,7 +4943,7 @@ static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t) s = zdc_parse_cond(p, t - XC_LEX_OP_REL_EQ + XC_INST_REL_EQ); get_token = false; break; - case BC_LEX_SCOLON: + case DC_LEX_SCOLON: case DC_LEX_COLON: dbg_lex("%s:%d LEX_[S]COLON", __func__, __LINE__); s = zdc_parse_mem(p, XC_INST_ARRAY_ELEM, true, t == DC_LEX_COLON); @@ -4945,14 +4965,14 @@ static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t) dbg_lex("%s:%d LEX_NUMBER", __func__, __LINE__); bc_parse_pushNUM(p); break; - case BC_LEX_KEY_READ: + case DC_LEX_READ: dbg_lex("%s:%d LEX_KEY_READ", __func__, __LINE__); bc_parse_push(p, XC_INST_READ); break; - case BC_LEX_OP_ASSIGN: + case DC_LEX_OP_ASSIGN: case DC_LEX_STORE_PUSH: dbg_lex("%s:%d LEX_OP_ASSIGN/STORE_PUSH", __func__, __LINE__); - assign = t == BC_LEX_OP_ASSIGN; + assign = (t == DC_LEX_OP_ASSIGN); inst = assign ? XC_INST_VAR : DC_INST_PUSH_TO_VAR; s = zdc_parse_mem(p, inst, true, assign); break; -- cgit v1.2.3-55-g6feb From 23ea0734e1622eac33ec1437854afe8adad1a52f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 24 Dec 2018 15:05:49 +0100 Subject: bc: rename BC_LEX_NLINE/WHITESPACE/STR/NAME/NUMBER to XC_LEX_ Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 90 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index a67cfbfcd..d2b74ea90 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -392,11 +392,11 @@ typedef enum BcLexType { XC_LEX_EOF, XC_LEX_INVALID, - BC_LEX_NLINE, - BC_LEX_WHITESPACE, - BC_LEX_STR, - BC_LEX_NAME, - BC_LEX_NUMBER, + XC_LEX_NLINE, + XC_LEX_WHITESPACE, + XC_LEX_STR, + XC_LEX_NAME, + XC_LEX_NUMBER, XC_LEX_1st_op, XC_LEX_NEG = XC_LEX_1st_op, // order @@ -2745,7 +2745,7 @@ static void bc_lex_lineComment(BcLex *l) { // Try: echo -n '#foo' | bc size_t i; - l->t.t = BC_LEX_WHITESPACE; + l->t.t = XC_LEX_WHITESPACE; i = l->i; while (i < l->len && l->buf[i] != '\n') i++; @@ -2754,10 +2754,10 @@ static void bc_lex_lineComment(BcLex *l) static void bc_lex_whitespace(BcLex *l) { - l->t.t = BC_LEX_WHITESPACE; + l->t.t = XC_LEX_WHITESPACE; for (;;) { char c = l->buf[l->i]; - if (c == '\n') // this is BC_LEX_NLINE, not BC_LEX_WHITESPACE + if (c == '\n') // this is XC_LEX_NLINE, not XC_LEX_WHITESPACE break; if (!isspace(c)) break; @@ -2772,7 +2772,7 @@ static BC_STATUS zbc_lex_number(BcLex *l, char start) bool pt; pt = (start == '.'); - l->t.t = BC_LEX_NUMBER; + l->t.t = XC_LEX_NUMBER; ccnt = i = 0; for (;;) { char c = buf[i]; @@ -2840,7 +2840,7 @@ static void bc_lex_name(BcLex *l) size_t i; const char *buf; - l->t.t = BC_LEX_NAME; + l->t.t = XC_LEX_NAME; i = 0; buf = l->buf + l->i - 1; @@ -2971,7 +2971,7 @@ static BC_STATUS zbc_lex_next(BcLex *l) // Loop until failure or we don't have whitespace. This // is so the parser doesn't get inundated with whitespace. - // Comments are also BC_LEX_WHITESPACE tokens and eaten here. + // Comments are also XC_LEX_WHITESPACE tokens and eaten here. s = BC_STATUS_SUCCESS; do { if (l->i == l->len) { @@ -2992,7 +2992,7 @@ static BC_STATUS zbc_lex_next(BcLex *l) } else { IF_DC(s = zdc_lex_token(l)); } - } while (!s && l->t.t == BC_LEX_WHITESPACE); + } while (!s && l->t.t == XC_LEX_WHITESPACE); dbg_lex("l->t.t from string:%d", l->t.t); RETURN_STATUS(s); @@ -3002,7 +3002,7 @@ static BC_STATUS zbc_lex_next(BcLex *l) #if ENABLE_BC static BC_STATUS zbc_lex_skip_if_at_NLINE(BcLex *l) { - if (l->t.t == BC_LEX_NLINE) + if (l->t.t == XC_LEX_NLINE) RETURN_STATUS(zbc_lex_next(l)); RETURN_STATUS(BC_STATUS_SUCCESS); } @@ -3081,7 +3081,7 @@ static BC_STATUS zbc_lex_string(BcLex *l) { size_t len, nls, i; - l->t.t = BC_LEX_STR; + l->t.t = XC_LEX_STR; nls = 0; i = l->i; @@ -3129,7 +3129,7 @@ static BC_STATUS zbc_lex_comment(BcLex *l) size_t i, nls = 0; const char *buf = l->buf; - l->t.t = BC_LEX_WHITESPACE; + l->t.t = XC_LEX_WHITESPACE; i = l->i; /* here buf[l->i] is the '*' of opening comment delimiter */ for (;;) { char c = buf[++i]; @@ -3169,7 +3169,7 @@ static BC_STATUS zbc_lex_token(BcLex *l) // l->newline = true; // break; case '\n': - l->t.t = BC_LEX_NLINE; + l->t.t = XC_LEX_NLINE; l->newline = true; break; case '\t': @@ -3286,7 +3286,7 @@ static BC_STATUS zbc_lex_token(BcLex *l) break; case '\\': if (l->buf[l->i] == '\n') { - l->t.t = BC_LEX_WHITESPACE; + l->t.t = XC_LEX_WHITESPACE; ++l->i; } else s = bc_error_bad_character(c); @@ -3360,7 +3360,7 @@ static BC_STATUS zdc_lex_register(BcLex *l) bc_vec_pop_all(&l->t.v); bc_vec_push(&l->t.v, &l->buf[l->i++]); bc_vec_pushZeroByte(&l->t.v); - l->t.t = BC_LEX_NAME; + l->t.t = XC_LEX_NAME; } RETURN_STATUS(BC_STATUS_SUCCESS); @@ -3371,7 +3371,7 @@ static BC_STATUS zdc_lex_string(BcLex *l) { size_t depth, nls, i; - l->t.t = BC_LEX_STR; + l->t.t = XC_LEX_STR; bc_vec_pop_all(&l->t.v); nls = 0; @@ -3445,7 +3445,7 @@ static BC_STATUS zdc_lex_token(BcLex *l) // l->t.t = XC_LEX_EOF; // break; case '\n': - // '\n' is BC_LEX_NLINE, not BC_LEX_WHITESPACE + // '\n' is XC_LEX_NLINE, not XC_LEX_WHITESPACE // (and "case '\n':" is not just empty here) // only to allow interactive dc have a way to exit // "parse" stage of "parse,execute" loop @@ -3453,7 +3453,7 @@ static BC_STATUS zdc_lex_token(BcLex *l) // commands are not executed on pressing ). // IOW: typing "1p" should print "1" _at once_, // not after some more input. - l->t.t = BC_LEX_NLINE; + l->t.t = XC_LEX_NLINE; l->newline = true; break; case '\t': @@ -3737,7 +3737,7 @@ static BC_STATUS zbc_parse_stmt_allow_NLINE_before(BcParse *p, const char *after // Same for "else", "while()", "for()". BcStatus s = zbc_lex_next_and_skip_NLINE(&p->l); if (s) RETURN_STATUS(s); - if (p->l.t.t == BC_LEX_NLINE) + if (p->l.t.t == XC_LEX_NLINE) RETURN_STATUS(bc_error_fmt("no statement after '%s'", after_X)); RETURN_STATUS(zbc_parse_stmt(p)); @@ -4012,7 +4012,7 @@ static BC_STATUS zbc_parse_incdec(BcParse *p, BcInst *prev, bool *paren_expr, *nexprs = *nexprs + 1; switch (type) { - case BC_LEX_NAME: + case XC_LEX_NAME: s = zbc_parse_name(p, prev, flags | BC_PARSE_NOCALL); break; case BC_LEX_KEY_IBASE: @@ -4077,7 +4077,7 @@ static BC_STATUS zbc_parse_print(BcParse *p) s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); type = p->l.t.t; - if (type == BC_LEX_STR) { + if (type == XC_LEX_STR) { s = zbc_parse_pushSTR(p); } else { s = zbc_parse_expr(p, 0); @@ -4102,7 +4102,7 @@ static BC_STATUS zbc_parse_return(BcParse *p) if (s) RETURN_STATUS(s); t = p->l.t.t; - if (t == BC_LEX_NLINE || t == BC_LEX_SCOLON) + if (t == XC_LEX_NLINE || t == BC_LEX_SCOLON) bc_parse_push(p, BC_INST_RET0); else { bool paren = (t == BC_LEX_LPAREN); @@ -4327,7 +4327,7 @@ static BC_STATUS zbc_parse_break_or_continue(BcParse *p, BcLexType type) s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); - if (p->l.t.t != BC_LEX_SCOLON && p->l.t.t != BC_LEX_NLINE) + if (p->l.t.t != BC_LEX_SCOLON && p->l.t.t != XC_LEX_NLINE) RETURN_STATUS(bc_error_bad_token()); RETURN_STATUS(zbc_lex_next(&p->l)); @@ -4364,7 +4364,7 @@ static BC_STATUS zbc_parse_funcdef(BcParse *p) dbg_lex_enter("%s:%d entered", __func__, __LINE__); s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); - if (p->l.t.t != BC_LEX_NAME) + if (p->l.t.t != XC_LEX_NAME) RETURN_STATUS(bc_error("bad function definition")); name = xstrdup(p->l.t.v.v); @@ -4379,7 +4379,7 @@ static BC_STATUS zbc_parse_funcdef(BcParse *p) if (s) RETURN_STATUS(s); while (p->l.t.t != BC_LEX_RPAREN) { - if (p->l.t.t != BC_LEX_NAME) + if (p->l.t.t != XC_LEX_NAME) RETURN_STATUS(bc_error("bad function definition")); ++p->func->nparams; @@ -4459,9 +4459,9 @@ static BC_STATUS zbc_parse_auto(BcParse *p) if (s) RETURN_STATUS(s); comma = false; - one = p->l.t.t == BC_LEX_NAME; + one = p->l.t.t == XC_LEX_NAME; - while (p->l.t.t == BC_LEX_NAME) { + while (p->l.t.t == XC_LEX_NAME) { name = xstrdup(p->l.t.v.v); s = zbc_lex_next(&p->l); if (s) goto err; @@ -4493,7 +4493,7 @@ static BC_STATUS zbc_parse_auto(BcParse *p) if (comma) RETURN_STATUS(bc_error("bad function definition")); if (!one) RETURN_STATUS(bc_error("no auto variable found")); - if (p->l.t.t != BC_LEX_NLINE && p->l.t.t != BC_LEX_SCOLON) + if (p->l.t.t != XC_LEX_NLINE && p->l.t.t != BC_LEX_SCOLON) RETURN_STATUS(bc_error_bad_token()); dbg_lex_done("%s:%d done", __func__, __LINE__); @@ -4512,8 +4512,8 @@ static BC_STATUS zbc_parse_stmt_possibly_auto(BcParse *p, bool auto_allowed) dbg_lex_enter("%s:%d entered, p->l.t.t:%d", __func__, __LINE__, p->l.t.t); - if (p->l.t.t == BC_LEX_NLINE) { - dbg_lex_done("%s:%d done (seen BC_LEX_NLINE)", __func__, __LINE__); + if (p->l.t.t == XC_LEX_NLINE) { + dbg_lex_done("%s:%d done (seen XC_LEX_NLINE)", __func__, __LINE__); RETURN_STATUS(zbc_lex_next(&p->l)); } if (p->l.t.t == BC_LEX_SCOLON) { @@ -4526,7 +4526,7 @@ static BC_STATUS zbc_parse_stmt_possibly_auto(BcParse *p, bool auto_allowed) do { s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); - } while (p->l.t.t == BC_LEX_NLINE); + } while (p->l.t.t == XC_LEX_NLINE); if (auto_allowed && p->l.t.t == BC_LEX_KEY_AUTO) { dbg_lex("%s:%d calling zbc_parse_auto()", __func__, __LINE__); s = zbc_parse_auto(p); @@ -4549,8 +4549,8 @@ static BC_STATUS zbc_parse_stmt_possibly_auto(BcParse *p, bool auto_allowed) case BC_LEX_OP_DEC: case BC_LEX_OP_BOOL_NOT: case BC_LEX_LPAREN: - case BC_LEX_NAME: - case BC_LEX_NUMBER: + case XC_LEX_NAME: + case XC_LEX_NUMBER: case BC_LEX_KEY_IBASE: case BC_LEX_KEY_LAST: case BC_LEX_KEY_LENGTH: @@ -4560,7 +4560,7 @@ static BC_STATUS zbc_parse_stmt_possibly_auto(BcParse *p, bool auto_allowed) case BC_LEX_KEY_SQRT: s = zbc_parse_expr(p, BC_PARSE_PRINT); break; - case BC_LEX_STR: + case XC_LEX_STR: s = zbc_parse_pushSTR(p); bc_parse_push(p, XC_INST_PRINT_STR); break; @@ -4738,7 +4738,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) get_token = bin_last = false; s = zbc_parse_rightParen(p, ops_bgn, &nexprs); break; - case BC_LEX_NAME: + case XC_LEX_NAME: if (BC_PARSE_LEAF(prev, rprn)) return bc_error_bad_expression(); paren_expr = true; @@ -4746,7 +4746,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) s = zbc_parse_name(p, &prev, flags & ~BC_PARSE_NOCALL); ++nexprs; break; - case BC_LEX_NUMBER: + case XC_LEX_NUMBER: if (BC_PARSE_LEAF(prev, rprn)) return bc_error_bad_expression(); bc_parse_pushNUM(p); @@ -4848,7 +4848,7 @@ static BC_STATUS zdc_parse_register(BcParse *p) s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); - if (p->l.t.t != BC_LEX_NAME) RETURN_STATUS(bc_error_bad_token()); + if (p->l.t.t != XC_LEX_NAME) RETURN_STATUS(bc_error_bad_token()); bc_parse_pushName(p, p->l.t.v.v); @@ -4948,7 +4948,7 @@ static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t) dbg_lex("%s:%d LEX_[S]COLON", __func__, __LINE__); s = zdc_parse_mem(p, XC_INST_ARRAY_ELEM, true, t == DC_LEX_COLON); break; - case BC_LEX_STR: + case XC_LEX_STR: dbg_lex("%s:%d LEX_STR", __func__, __LINE__); dc_parse_string(p); break; @@ -4956,12 +4956,12 @@ static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t) dbg_lex("%s:%d LEX_NEG", __func__, __LINE__); s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); - if (p->l.t.t != BC_LEX_NUMBER) + if (p->l.t.t != XC_LEX_NUMBER) RETURN_STATUS(bc_error_bad_token()); bc_parse_pushNUM(p); bc_parse_push(p, XC_INST_NEG); break; - case BC_LEX_NUMBER: + case XC_LEX_NUMBER: dbg_lex("%s:%d LEX_NUMBER", __func__, __LINE__); bc_parse_pushNUM(p); break; @@ -5252,7 +5252,7 @@ static BC_STATUS zbc_program_read(void) } if (s) goto exec_err; - if (parse.l.t.t != BC_LEX_NLINE && parse.l.t.t != XC_LEX_EOF) { + if (parse.l.t.t != XC_LEX_NLINE && parse.l.t.t != XC_LEX_EOF) { s = bc_error("bad read() expression"); goto exec_err; } @@ -6733,7 +6733,7 @@ static BC_STATUS zbc_vm_process(const char *text) } else { // Most of dc parsing assumes all whitespace, // including '\n', is eaten. - while (G.prs.l.t.t == BC_LEX_NLINE) { + while (G.prs.l.t.t == XC_LEX_NLINE) { s = zbc_lex_next(&G.prs.l); if (s) goto err; if (G.prs.l.t.t == XC_LEX_EOF) -- cgit v1.2.3-55-g6feb From 4accb6bba8ac89a35f20147196441c1f829be360 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 24 Dec 2018 15:29:08 +0100 Subject: bc: offset dc_LEX_to_INST[] start function old new delta zdc_parse_expr 516 523 +7 dc_LEX_to_INST 56 48 -8 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/1 up/down: 7/-8) Total: -1 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 79 +++++++++++++++++++++++++++++++--------------------------- 1 file changed, 42 insertions(+), 37 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index d2b74ea90..8556a0e73 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -673,34 +673,39 @@ dc_char_to_LEX[] = { }; static const //BcInst - should be this type. Using signed narrow type since DC_INST_INVALID is -1 int8_t -dc_LEX_to_INST[] = { // (so many INVALIDs b/c dc parser does not generate these LEXs) // corresponding XC/DC_LEX_xyz: - DC_INST_INVALID, DC_INST_INVALID, // EOF INVALID - DC_INST_INVALID, DC_INST_INVALID, // NLINE WHITESPACE - DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, // STR NAME NUMBER - DC_INST_INVALID, // NEG - XC_INST_POWER, XC_INST_MULTIPLY, XC_INST_DIVIDE, // OP_POWER OP_MULTIPLY OP_DIVIDE - XC_INST_MODULUS, XC_INST_PLUS, XC_INST_MINUS, // OP_MODULUS OP_PLUS OP_MINUS - DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, // OP_REL_EQ OP_REL_LE OP_REL_GE OP_REL_NE - DC_INST_INVALID, DC_INST_INVALID, // OP_REL_LT OP_REL_GT - XC_INST_BOOL_NOT, // DC_LEX_OP_BOOL_NOT - DC_INST_INVALID, // DC_LEX_OP_ASSIGN - XC_INST_REL_GT, // DC_LEX_LPAREN - DC_INST_INVALID, // DC_LEX_SCOLON - DC_INST_INVALID, // DC_LEX_READ - XC_INST_IBASE, // DC_LEX_IBASE - XC_INST_SCALE, // DC_LEX_SCALE - XC_INST_OBASE, // DC_LEX_OBASE - XC_INST_LENGTH, // DC_LEX_LENGTH - XC_INST_PRINT, // DC_LEX_PRINT - DC_INST_QUIT, // DC_LEX_QUIT - XC_INST_SQRT, // DC_LEX_SQRT - XC_INST_REL_GE, // DC_LEX_LBRACE - XC_INST_REL_EQ, DC_INST_MODEXP, DC_INST_DIVMOD, DC_INST_INVALID, // EQ_NO_REG OP_MODEXP OP_DIVMOD COLON - DC_INST_INVALID, DC_INST_EXECUTE, DC_INST_PRINT_STACK, DC_INST_CLEAR_STACK, //ELSE EXECUTE PRINT_STACK CLEAR_STACK - DC_INST_STACK_LEN, DC_INST_DUPLICATE, DC_INST_SWAP, XC_INST_POP, // STACK_LEVEL DUPLICATE SWAP POP - DC_INST_ASCIIFY, DC_INST_PRINT_STREAM, DC_INST_INVALID, DC_INST_INVALID, //ASCIIFY PRINT_STREAM STORE_IBASE STORE_OBASE - DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, DC_INST_INVALID, // STORE_SCALE LOAD LOAD_POP STORE_PUSH - XC_INST_PRINT, DC_INST_NQUIT, XC_INST_SCALE_FUNC, // PRINT_POP NQUIT SCALE_FACTOR +dc_LEX_to_INST[] = { // starts at XC_LEX_OP_POWER // corresponding XC/DC_LEX_xyz: + XC_INST_POWER, XC_INST_MULTIPLY, // OP_POWER OP_MULTIPLY + XC_INST_DIVIDE, XC_INST_MODULUS, // OP_DIVIDE OP_MODULUS + XC_INST_PLUS, XC_INST_MINUS, // OP_PLUS OP_MINUS + DC_INST_INVALID, DC_INST_INVALID, // OP_REL_EQ OP_REL_LE + DC_INST_INVALID, DC_INST_INVALID, // OP_REL_GE OP_REL_NE + DC_INST_INVALID, DC_INST_INVALID, // OP_REL_LT OP_REL_GT + XC_INST_BOOL_NOT, // DC_LEX_OP_BOOL_NOT + DC_INST_INVALID, // DC_LEX_OP_ASSIGN + XC_INST_REL_GT, // DC_LEX_LPAREN + DC_INST_INVALID, // DC_LEX_SCOLON + DC_INST_INVALID, // DC_LEX_READ + XC_INST_IBASE, // DC_LEX_IBASE + XC_INST_SCALE, // DC_LEX_SCALE + XC_INST_OBASE, // DC_LEX_OBASE + XC_INST_LENGTH, // DC_LEX_LENGTH + XC_INST_PRINT, // DC_LEX_PRINT + DC_INST_QUIT, // DC_LEX_QUIT + XC_INST_SQRT, // DC_LEX_SQRT + XC_INST_REL_GE, // DC_LEX_LBRACE + XC_INST_REL_EQ, // DC_LEX_EQ_NO_REG + DC_INST_MODEXP, DC_INST_DIVMOD, // OP_MODEXP OP_DIVMOD + DC_INST_INVALID, DC_INST_INVALID, // COLON ELSE + DC_INST_EXECUTE, // EXECUTE + DC_INST_PRINT_STACK, DC_INST_CLEAR_STACK, // PRINT_STACK CLEAR_STACK + DC_INST_STACK_LEN, DC_INST_DUPLICATE, // STACK_LEVEL DUPLICATE + DC_INST_SWAP, XC_INST_POP, // SWAP POP + DC_INST_ASCIIFY, DC_INST_PRINT_STREAM, // ASCIIFY PRINT_STREAM + DC_INST_INVALID, DC_INST_INVALID, // STORE_IBASE STORE_OBASE + DC_INST_INVALID, DC_INST_INVALID, // STORE_SCALE LOAD + DC_INST_INVALID, DC_INST_INVALID, // LOAD_POP STORE_PUSH + XC_INST_PRINT, DC_INST_NQUIT, // PRINT_POP NQUIT + XC_INST_SCALE_FUNC, // SCALE_FACTOR // DC_INST_INVALID in this table either means that corresponding LEX // is not possible for dc, or that it does not compile one-to-one // to a single INST. @@ -5003,17 +5008,17 @@ static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t) static BC_STATUS zdc_parse_expr(BcParse *p) { - BcInst inst; - BcStatus s; + int i; - inst = dc_LEX_to_INST[p->l.t.t]; - if (inst != DC_INST_INVALID) { - bc_parse_push(p, inst); - s = zbc_lex_next(&p->l); - } else { - s = zdc_parse_token(p, p->l.t.t); + i = (int)p->l.t.t - (int)XC_LEX_OP_POWER; + if (i >= 0) { + BcInst inst = dc_LEX_to_INST[i]; + if (inst != DC_INST_INVALID) { + bc_parse_push(p, inst); + RETURN_STATUS(zbc_lex_next(&p->l)); + } } - RETURN_STATUS(s); + RETURN_STATUS(zdc_parse_token(p, p->l.t.t)); } #define zdc_parse_expr(...) (zdc_parse_expr(__VA_ARGS__) COMMA_SUCCESS) -- cgit v1.2.3-55-g6feb From a5bf53e4bb7a45236c44e5f564cb044fbf654ea5 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 24 Dec 2018 17:06:37 +0100 Subject: bc: move relational LEXs before math LEXs - shorten dc_LEX_to_INST[] function old new delta dc_LEX_to_INST 48 42 -6 zdc_parse_expr 523 514 -9 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-15) Total: -15 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 81 ++++++++++++++++++++++++++++------------------------------ 1 file changed, 39 insertions(+), 42 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 8556a0e73..68e3668c4 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -253,19 +253,19 @@ typedef enum BcInst { #endif XC_INST_NEG, // order - XC_INST_POWER, // should - XC_INST_MULTIPLY, // match - XC_INST_DIVIDE, // LEX - XC_INST_MODULUS, // constants - XC_INST_PLUS, // for - XC_INST_MINUS, // these - - XC_INST_REL_EQ, // operations - XC_INST_REL_LE, // | - XC_INST_REL_GE, // | - XC_INST_REL_NE, // | - XC_INST_REL_LT, // | - XC_INST_REL_GT, // | + XC_INST_REL_EQ, // should + XC_INST_REL_LE, // match + XC_INST_REL_GE, // LEX + XC_INST_REL_NE, // constants + XC_INST_REL_LT, // for + XC_INST_REL_GT, // these + + XC_INST_POWER, // operations + XC_INST_MULTIPLY, // | + XC_INST_DIVIDE, // | + XC_INST_MODULUS, // | + XC_INST_PLUS, // | + XC_INST_MINUS, // | XC_INST_BOOL_NOT, // | XC_INST_BOOL_OR, // | @@ -401,20 +401,20 @@ typedef enum BcLexType { XC_LEX_1st_op, XC_LEX_NEG = XC_LEX_1st_op, // order - XC_LEX_OP_POWER, // should - XC_LEX_OP_MULTIPLY, // match - XC_LEX_OP_DIVIDE, // INST - XC_LEX_OP_MODULUS, // constants - XC_LEX_OP_PLUS, // for - XC_LEX_OP_MINUS, // these - - XC_LEX_OP_REL_EQ, // operations - XC_LEX_OP_REL_LE, // | - XC_LEX_OP_REL_GE, // | - XC_LEX_OP_REL_NE, // | - XC_LEX_OP_REL_LT, // | - XC_LEX_OP_REL_GT, // | - XC_LEX_OP_last = XC_LEX_OP_REL_GT, + XC_LEX_OP_REL_EQ, // should + XC_LEX_OP_REL_LE, // match + XC_LEX_OP_REL_GE, // INST + XC_LEX_OP_REL_NE, // constants + XC_LEX_OP_REL_LT, // for + XC_LEX_OP_REL_GT, // these + + XC_LEX_OP_POWER, // operations + XC_LEX_OP_MULTIPLY, // | + XC_LEX_OP_DIVIDE, // | + XC_LEX_OP_MODULUS, // | + XC_LEX_OP_PLUS, // | + XC_LEX_OP_MINUS, // | + XC_LEX_OP_last = XC_LEX_OP_MINUS, #if ENABLE_BC BC_LEX_OP_BOOL_NOT, // | BC_LEX_OP_BOOL_OR, // | @@ -432,16 +432,16 @@ typedef enum BcLexType { BC_LEX_OP_INC, BC_LEX_OP_DEC, - BC_LEX_LPAREN, - BC_LEX_RPAREN, + BC_LEX_LPAREN, // () are 0x28 and 0x29 + BC_LEX_RPAREN, // must be LPAREN+1: code uses (c - '(' + BC_LEX_LPAREN) - BC_LEX_LBRACKET, + BC_LEX_LBRACKET, // [] are 0x5B and 5D BC_LEX_COMMA, - BC_LEX_RBRACKET, + BC_LEX_RBRACKET, // must be LBRACKET+2: code uses (c - '[' + BC_LEX_LBRACKET) - BC_LEX_LBRACE, // '{' is 0x7B, '}' is 0x7D, + BC_LEX_LBRACE, // {} are 0x7B and 0x7D BC_LEX_SCOLON, - BC_LEX_RBRACE, // should be LBRACE+2: code uses (c - '{' + BC_LEX_LBRACE) + BC_LEX_RBRACE, // must be LBRACE+2: code uses (c - '{' + BC_LEX_LBRACE) BC_LEX_KEY_1st_keyword, BC_LEX_KEY_AUTO = BC_LEX_KEY_1st_keyword, @@ -582,8 +582,8 @@ enum { ((uint64_t)((a << 0)+(b << 1)+(c << 2)+(d << 3)+(e << 4)+(f << 5)+(g << 6)+(h << 7))) BC_PARSE_EXPRS_BITS = 0 // corresponding BC_LEX_xyz: + (EXBITS(0,0,0,0,0,1,1,1) << (0*8)) // 0: EOF INVAL NL WS STR NAME NUM - - + (EXBITS(1,1,1,1,1,1,1,1) << (1*8)) // 8: ^ * / % + - == <= - + (EXBITS(1,1,1,1,1,1,1,1) << (2*8)) // 16: >= != < > ! || && ^= + + (EXBITS(1,1,1,1,1,1,1,1) << (1*8)) // 8: == <= >= != < > ^ * + + (EXBITS(1,1,1,1,1,1,1,1) << (2*8)) // 16: / % + - ! || && ^= + (EXBITS(1,1,1,1,1,1,1,1) << (3*8)) // 24: *= /= %= += -= = ++ -- + (EXBITS(1,1,0,0,0,0,0,0) << (4*8)) // 32: ( ) [ , ] { ; } + (EXBITS(0,0,0,0,0,0,0,1) << (5*8)) // 40: auto break cont define else for halt ibase @@ -612,10 +612,10 @@ static ALWAYS_INLINE long bc_parse_exprs(unsigned i) static const uint8_t bc_parse_ops[] = { #define OP(p,l) ((int)(l) * 0x10 + (p)) OP(1, false), // neg + OP(6, true ), OP( 6, true ), OP( 6, true ), OP( 6, true ), OP( 6, true ), OP( 6, true ), // == <= >= != < > OP(2, false), // pow OP(3, true ), OP( 3, true ), OP( 3, true ), // mul div mod OP(4, true ), OP( 4, true ), // + - - OP(6, true ), OP( 6, true ), OP( 6, true ), OP( 6, true ), OP( 6, true ), OP( 6, true ), // == <= >= != < > OP(1, false), // not OP(7, true ), OP( 7, true ), // or and OP(5, false), OP( 5, false ), OP( 5, false ), OP( 5, false ), OP( 5, false ), // ^= *= /= %= += @@ -677,9 +677,6 @@ dc_LEX_to_INST[] = { // starts at XC_LEX_OP_POWER // corresponding XC/DC_L XC_INST_POWER, XC_INST_MULTIPLY, // OP_POWER OP_MULTIPLY XC_INST_DIVIDE, XC_INST_MODULUS, // OP_DIVIDE OP_MODULUS XC_INST_PLUS, XC_INST_MINUS, // OP_PLUS OP_MINUS - DC_INST_INVALID, DC_INST_INVALID, // OP_REL_EQ OP_REL_LE - DC_INST_INVALID, DC_INST_INVALID, // OP_REL_GE OP_REL_NE - DC_INST_INVALID, DC_INST_INVALID, // OP_REL_LT OP_REL_GT XC_INST_BOOL_NOT, // DC_LEX_OP_BOOL_NOT DC_INST_INVALID, // DC_LEX_OP_ASSIGN XC_INST_REL_GT, // DC_LEX_LPAREN @@ -4655,7 +4652,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) bool paren_first, paren_expr, rprn, done, get_token, assign, bin_last; dbg_lex_enter("%s:%d entered", __func__, __LINE__); - paren_first = p->l.t.t == BC_LEX_LPAREN; + paren_first = (p->l.t.t == BC_LEX_LPAREN); nparens = nrelops = 0; paren_expr = rprn = done = get_token = assign = false; bin_last = true; @@ -4671,7 +4668,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) case XC_LEX_OP_MINUS: s = zbc_parse_minus(p, &prev, ops_bgn, rprn, &nexprs); rprn = get_token = false; - bin_last = prev == XC_INST_MINUS; + bin_last = (prev == XC_INST_MINUS); break; case BC_LEX_OP_ASSIGN_POWER: case BC_LEX_OP_ASSIGN_MULTIPLY: @@ -4812,7 +4809,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) while (p->ops.len > ops_bgn) { top = BC_PARSE_TOP_OP(p); - assign = top >= BC_LEX_OP_ASSIGN_POWER && top <= BC_LEX_OP_ASSIGN; + assign = (top >= BC_LEX_OP_ASSIGN_POWER && top <= BC_LEX_OP_ASSIGN); if (top == BC_LEX_LPAREN || top == BC_LEX_RPAREN) return bc_error_bad_expression(); -- cgit v1.2.3-55-g6feb From 65b6fe09c4c6a25090b86ec4a6abcc6ab92f767e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 24 Dec 2018 17:15:34 +0100 Subject: bc: remove unnecessary NULL initializers function old new delta zbc_program_assign 442 426 -16 zbc_program_exec 4043 3977 -66 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-82) Total: -82 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 68e3668c4..4fac2c99a 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -5178,6 +5178,7 @@ static void bc_program_binOpRetire(BcResult *r) bc_result_pop_and_push(r); } +// Note: *r and *n need not be initialized by caller static BC_STATUS zbc_program_prep(BcResult **r, BcNum **n) { BcStatus s; @@ -5206,7 +5207,7 @@ static BC_STATUS zbc_program_op(char inst) { BcStatus s; BcResult *opd1, *opd2, res; - BcNum *n1, *n2 = NULL; + BcNum *n1, *n2; s = zbc_program_binOpPrep(&opd1, &n1, &opd2, &n2, false); if (s) RETURN_STATUS(s); @@ -5565,7 +5566,7 @@ static BC_STATUS zbc_program_print(char inst, size_t idx) BcStatus s; BcResult *r; BcNum *num; - bool pop = inst != XC_INST_PRINT; + bool pop = (inst != XC_INST_PRINT); if (!STACK_HAS_MORE_THAN(&G.prog.results, idx)) RETURN_STATUS(bc_error_stack_has_too_few_elements()); @@ -5609,7 +5610,7 @@ static BC_STATUS zbc_program_negate(void) { BcStatus s; BcResult res, *ptr; - BcNum *num = NULL; + BcNum *num; s = zbc_program_prep(&ptr, &num); if (s) RETURN_STATUS(s); @@ -5745,8 +5746,9 @@ static BC_STATUS zbc_program_assign(char inst) { BcStatus s; BcResult *left, *right, res; - BcNum *l = NULL, *r = NULL; - bool assign = inst == XC_INST_ASSIGN, ib, sc; + BcNum *l, *r; + bool assign = (inst == XC_INST_ASSIGN); + bool ib, sc; s = zbc_program_binOpPrep(&left, &l, &right, &r, assign); if (s) RETURN_STATUS(s); @@ -5907,7 +5909,7 @@ static BC_STATUS zbc_program_incdec(char inst) { BcStatus s; BcResult *ptr, res, copy; - BcNum *num = NULL; + BcNum *num; char inst2 = inst; s = zbc_program_prep(&ptr, &num); @@ -5920,9 +5922,9 @@ static BC_STATUS zbc_program_incdec(char inst) } res.t = BC_RESULT_ONE; - inst = inst == BC_INST_INC_PRE || inst == BC_INST_INC_POST ? - BC_INST_ASSIGN_PLUS : - BC_INST_ASSIGN_MINUS; + inst = (inst == BC_INST_INC_PRE || inst == BC_INST_INC_POST) + ? BC_INST_ASSIGN_PLUS + : BC_INST_ASSIGN_MINUS; bc_vec_push(&G.prog.results, &res); s = zbc_program_assign(inst); @@ -6059,9 +6061,9 @@ static BC_STATUS zbc_program_builtin(char inst) { BcStatus s; BcResult *opnd; - BcNum *num = NULL; + BcNum *num; BcResult res; - bool len = inst == XC_INST_LENGTH; + bool len = (inst == XC_INST_LENGTH); if (!STACK_HAS_MORE_THAN(&G.prog.results, 0)) RETURN_STATUS(bc_error_stack_has_too_few_elements()); @@ -6108,7 +6110,7 @@ static BC_STATUS zdc_program_divmod(void) { BcStatus s; BcResult *opd1, *opd2, res, res2; - BcNum *n1, *n2 = NULL; + BcNum *n1, *n2; s = zbc_program_binOpPrep(&opd1, &n1, &opd2, &n2, false); if (s) RETURN_STATUS(s); @@ -6284,7 +6286,7 @@ static BC_STATUS zdc_program_nquit(void) { BcStatus s; BcResult *opnd; - BcNum *num = NULL; + BcNum *num; unsigned long val; s = zbc_program_prep(&opnd, &num); @@ -6432,7 +6434,6 @@ static void bc_program_pushGlobal(char inst) static BC_STATUS zbc_program_exec(void) { BcResult r, *ptr; - BcNum *num; BcInstPtr *ip = bc_vec_top(&G.prog.exestack); BcFunc *func = bc_program_func(ip->func); char *code = func->code.v; @@ -6447,6 +6448,7 @@ static BC_STATUS zbc_program_exec(void) switch (inst) { #if ENABLE_BC case BC_INST_JUMP_ZERO: { + BcNum *num; bool zero; dbg_exec("BC_INST_JUMP_ZERO:"); s = zbc_program_prep(&ptr, &num); @@ -6564,16 +6566,18 @@ static BC_STATUS zbc_program_exec(void) dbg_exec("BC_INST_binaryop:"); s = zbc_program_op(inst); break; - case XC_INST_BOOL_NOT: + case XC_INST_BOOL_NOT: { + BcNum *num; dbg_exec("XC_INST_BOOL_NOT:"); s = zbc_program_prep(&ptr, &num); if (s) RETURN_STATUS(s); bc_num_init_DEF_SIZE(&r.d.n); - if (!bc_num_cmp(num, &G.prog.zero)) + if (bc_num_cmp(num, &G.prog.zero) == 0) bc_num_one(&r.d.n); //else bc_num_zero(&r.d.n); - already is bc_program_retire(&r, BC_RESULT_TEMP); break; + } case XC_INST_NEG: dbg_exec("XC_INST_NEG:"); s = zbc_program_negate(); -- cgit v1.2.3-55-g6feb From 79587cb442d022bf8d9e388398834270785d2049 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 24 Dec 2018 18:11:41 +0100 Subject: bc: POSIX error/warn functions can be 'z' functions too In non-interactive config, they either return 'success', or do not return. function old new delta zbc_posix_error_fmt 41 39 -2 bc_parse_expr_empty_ok 1751 1744 -7 zbc_parse_stmt_possibly_auto 1322 1314 -8 ------------------------------------------------------------------------------ (add/remove: 5/5 grow/shrink: 0/2 up/down: 118/-135) Total: -17 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 78 +++++++++++++++++++++++++++++++--------------------------- 1 file changed, 42 insertions(+), 36 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 4fac2c99a..12bc80b3e 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -962,13 +962,13 @@ static NOINLINE ERRORFUNC int bc_error_fmt(const char *fmt, ...) } #if ENABLE_BC -static NOINLINE int bc_posix_error_fmt(const char *fmt, ...) +static NOINLINE BC_STATUS zbc_posix_error_fmt(const char *fmt, ...) { va_list p; // Are non-POSIX constructs totally ok? if (!(option_mask32 & (BC_FLAG_S|BC_FLAG_W))) - return BC_STATUS_SUCCESS; // yes + RETURN_STATUS(BC_STATUS_SUCCESS); // yes va_start(p, fmt); bc_verror_msg(fmt, p); @@ -976,11 +976,13 @@ static NOINLINE int bc_posix_error_fmt(const char *fmt, ...) // Do we treat non-POSIX constructs as errors? if (!(option_mask32 & BC_FLAG_S)) - return BC_STATUS_SUCCESS; // no, it's a warning + RETURN_STATUS(BC_STATUS_SUCCESS); // no, it's a warning + if (ENABLE_FEATURE_CLEAN_UP || G_ttyin) - return BC_STATUS_FAILURE; + RETURN_STATUS(BC_STATUS_FAILURE); exit(1); } +#define zbc_posix_error_fmt(...) (zbc_posix_error_fmt(__VA_ARGS__) COMMA_SUCCESS) #endif // We use error functions with "return bc_error(FMT[, PARAMS])" idiom. @@ -1015,22 +1017,26 @@ static ERRORFUNC int bc_error_variable_is_wrong_type(void) IF_ERROR_RETURN_POSSIBLE(return) bc_error("variable is wrong type"); } #if ENABLE_BC -static int bc_POSIX_requires(const char *msg) +static BC_STATUS zbc_POSIX_requires(const char *msg) { - return bc_posix_error_fmt("POSIX requires %s", msg); + RETURN_STATUS(zbc_posix_error_fmt("POSIX requires %s", msg)); } -static int bc_POSIX_does_not_allow(const char *msg) +#define zbc_POSIX_requires(...) (zbc_POSIX_requires(__VA_ARGS__) COMMA_SUCCESS) +static BC_STATUS zbc_POSIX_does_not_allow(const char *msg) { - return bc_posix_error_fmt("%s%s", "POSIX does not allow ", msg); + RETURN_STATUS(zbc_posix_error_fmt("%s%s", "POSIX does not allow ", msg)); } -static int bc_POSIX_does_not_allow_bool_ops_this_is_bad(const char *msg) +#define zbc_POSIX_does_not_allow(...) (zbc_POSIX_does_not_allow(__VA_ARGS__) COMMA_SUCCESS) +static BC_STATUS zbc_POSIX_does_not_allow_bool_ops_this_is_bad(const char *msg) { - return bc_posix_error_fmt("%s%s %s", "POSIX does not allow ", "boolean operators; the following is bad:", msg); + RETURN_STATUS(zbc_posix_error_fmt("%s%s %s", "POSIX does not allow ", "boolean operators; the following is bad:", msg)); } -static int bc_POSIX_does_not_allow_empty_X_expression_in_for(const char *msg) +#define zbc_POSIX_does_not_allow_bool_ops_this_is_bad(...) (zbc_POSIX_does_not_allow_bool_ops_this_is_bad(__VA_ARGS__) COMMA_SUCCESS) +static BC_STATUS zbc_POSIX_does_not_allow_empty_X_expression_in_for(const char *msg) { - return bc_posix_error_fmt("%san empty %s expression in a for loop", "POSIX does not allow ", msg); + RETURN_STATUS(zbc_posix_error_fmt("%san empty %s expression in a for loop", "POSIX does not allow ", msg)); } +#define zbc_POSIX_does_not_allow_empty_X_expression_in_for(...) (zbc_POSIX_does_not_allow_empty_X_expression_in_for(__VA_ARGS__) COMMA_SUCCESS) #endif static void bc_vec_grow(BcVec *v, size_t n) @@ -3054,8 +3060,8 @@ static BC_STATUS zbc_lex_identifier(BcLex *l) continue; // "ifz" does not match "if" keyword, "if." does l->t.t = BC_LEX_KEY_1st_keyword + i; if (!bc_lex_kws_POSIX(i)) { - s = bc_posix_error_fmt("%sthe '%.8s' keyword", "POSIX does not allow ", bc_lex_kws[i].name8); - IF_ERROR_RETURN_POSSIBLE(if (s) RETURN_STATUS(s)); + s = zbc_posix_error_fmt("%sthe '%.8s' keyword", "POSIX does not allow ", bc_lex_kws[i].name8); + if (s) RETURN_STATUS(s); } // We minus 1 because the index has already been incremented. @@ -3072,7 +3078,7 @@ static BC_STATUS zbc_lex_identifier(BcLex *l) // bc: POSIX only allows one character names; the following is bad: 'qwe=1 // ' unsigned len = strchrnul(buf, '\n') - buf; - s = bc_posix_error_fmt("POSIX only allows one character names; the following is bad: '%.*s'", len, buf); + s = zbc_posix_error_fmt("POSIX only allows one character names; the following is bad: '%.*s'", len, buf); } RETURN_STATUS(s); @@ -3184,16 +3190,16 @@ static BC_STATUS zbc_lex_token(BcLex *l) case '!': bc_lex_assign(l, XC_LEX_OP_REL_NE, BC_LEX_OP_BOOL_NOT); if (l->t.t == BC_LEX_OP_BOOL_NOT) { - s = bc_POSIX_does_not_allow_bool_ops_this_is_bad("!"); - IF_ERROR_RETURN_POSSIBLE(if (s) RETURN_STATUS(s)); + s = zbc_POSIX_does_not_allow_bool_ops_this_is_bad("!"); + if (s) RETURN_STATUS(s); } break; case '"': s = zbc_lex_string(l); break; case '#': - s = bc_POSIX_does_not_allow("'#' script comments"); - IF_ERROR_RETURN_POSSIBLE(if (s) RETURN_STATUS(s)); + s = zbc_POSIX_does_not_allow("'#' script comments"); + if (s) RETURN_STATUS(s); bc_lex_lineComment(l); break; case '%': @@ -3202,8 +3208,8 @@ static BC_STATUS zbc_lex_token(BcLex *l) case '&': c2 = l->buf[l->i]; if (c2 == '&') { - s = bc_POSIX_does_not_allow_bool_ops_this_is_bad("&&"); - IF_ERROR_RETURN_POSSIBLE(if (s) RETURN_STATUS(s)); + s = zbc_POSIX_does_not_allow_bool_ops_this_is_bad("&&"); + if (s) RETURN_STATUS(s); ++l->i; l->t.t = BC_LEX_OP_BOOL_AND; } else { @@ -3242,7 +3248,7 @@ static BC_STATUS zbc_lex_token(BcLex *l) s = zbc_lex_number(l, c); else { l->t.t = BC_LEX_KEY_LAST; - s = bc_POSIX_does_not_allow("a period ('.') as a shortcut for the last result"); + s = zbc_POSIX_does_not_allow("a period ('.') as a shortcut for the last result"); } break; case '/': @@ -3331,8 +3337,8 @@ static BC_STATUS zbc_lex_token(BcLex *l) case '|': c2 = l->buf[l->i]; if (c2 == '|') { - s = bc_POSIX_does_not_allow_bool_ops_this_is_bad("||"); - IF_ERROR_RETURN_POSSIBLE(if (s) RETURN_STATUS(s)); + s = zbc_POSIX_does_not_allow_bool_ops_this_is_bad("||"); + if (s) RETURN_STATUS(s); ++l->i; l->t.t = BC_LEX_OP_BOOL_OR; } else { @@ -4116,8 +4122,8 @@ static BC_STATUS zbc_parse_return(BcParse *p) if (s) RETURN_STATUS(s); if (!paren || p->l.t.last != BC_LEX_RPAREN) { - s = bc_POSIX_requires("parentheses around return expressions"); - IF_ERROR_RETURN_POSSIBLE(if (s) RETURN_STATUS(s)); + s = zbc_POSIX_requires("parentheses around return expressions"); + if (s) RETURN_STATUS(s); } bc_parse_push(p, XC_INST_RET); @@ -4243,8 +4249,8 @@ static BC_STATUS zbc_parse_for(BcParse *p) bc_parse_push(p, XC_INST_POP); if (s) RETURN_STATUS(s); } else { - s = bc_POSIX_does_not_allow_empty_X_expression_in_for("init"); - IF_ERROR_RETURN_POSSIBLE(if (s) RETURN_STATUS(s);) + s = zbc_POSIX_does_not_allow_empty_X_expression_in_for("init"); + if (s) RETURN_STATUS(s); } if (p->l.t.t != BC_LEX_SCOLON) RETURN_STATUS(bc_error_bad_token()); @@ -4264,7 +4270,7 @@ static BC_STATUS zbc_parse_for(BcParse *p) // which has no string requirement. bc_vec_string(&p->l.t.v, 1, "1"); bc_parse_pushNUM(p); - s = bc_POSIX_does_not_allow_empty_X_expression_in_for("condition"); + s = zbc_POSIX_does_not_allow_empty_X_expression_in_for("condition"); } if (s) RETURN_STATUS(s); @@ -4285,8 +4291,8 @@ static BC_STATUS zbc_parse_for(BcParse *p) if (p->l.t.t != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); bc_parse_push(p, XC_INST_POP); } else { - s = bc_POSIX_does_not_allow_empty_X_expression_in_for("update"); - IF_ERROR_RETURN_POSSIBLE(if (s) RETURN_STATUS(s);) + s = zbc_POSIX_does_not_allow_empty_X_expression_in_for("update"); + if (s) RETURN_STATUS(s); } bc_parse_pushJUMP(p, cond_idx); @@ -4421,7 +4427,7 @@ static BC_STATUS zbc_parse_funcdef(BcParse *p) if (s) RETURN_STATUS(s); if (p->l.t.t != BC_LEX_LBRACE) - s = bc_POSIX_requires("the left brace be on the same line as the function header"); + s = zbc_POSIX_requires("the left brace be on the same line as the function header"); // Prevent "define z()" from being interpreted as function with empty stmt as body s = zbc_lex_skip_if_at_NLINE(&p->l); @@ -4824,11 +4830,11 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) return bc_error_bad_expression(); if (!(flags & BC_PARSE_REL) && nrelops) { - s = bc_POSIX_does_not_allow("comparison operators outside if or loops"); - IF_ERROR_RETURN_POSSIBLE(if (s) return s); + s = zbc_POSIX_does_not_allow("comparison operators outside if or loops"); + if (s) return s; } else if ((flags & BC_PARSE_REL) && nrelops > 1) { - s = bc_POSIX_requires("exactly one comparison operator per condition"); - IF_ERROR_RETURN_POSSIBLE(if (s) return s); + s = zbc_POSIX_requires("exactly one comparison operator per condition"); + if (s) return s; } if (flags & BC_PARSE_PRINT) { -- cgit v1.2.3-55-g6feb From d279d809ac0f1c41c358e9ad72ea5d0b606ae47c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 24 Dec 2018 18:28:56 +0100 Subject: bc: fix "bc -s" only warning on "define f()", not exiting Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 12bc80b3e..35778ff1c 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -4426,8 +4426,10 @@ static BC_STATUS zbc_parse_funcdef(BcParse *p) s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); - if (p->l.t.t != BC_LEX_LBRACE) + if (p->l.t.t != BC_LEX_LBRACE) { s = zbc_POSIX_requires("the left brace be on the same line as the function header"); + if (s) RETURN_STATUS(s); + } // Prevent "define z()" from being interpreted as function with empty stmt as body s = zbc_lex_skip_if_at_NLINE(&p->l); -- cgit v1.2.3-55-g6feb From a17d95d0d098db4bfd91a7bac71351c6100510da Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 24 Dec 2018 22:55:54 +0100 Subject: bc: rename lexer variables, use smallints where appropriate function old new delta bc_parse_expr_empty_ok 1966 1972 +6 zdc_parse_expr 514 518 +4 zbc_lex_number 177 174 -3 dc_num_printChar 24 21 -3 bc_lex_whitespace 41 38 -3 bc_lex_name 69 66 -3 bc_lex_lineComment 36 33 -3 bc_lex_assign 31 28 -3 zbc_parse_name 472 468 -4 zbc_vm_process 836 831 -5 zdc_program_execStr 512 506 -6 zbc_parse_text_init 59 53 -6 bc_num_printNewline 51 45 -6 bc_num_printHex 67 61 -6 bc_num_printDigits 137 131 -6 zbc_program_assign 426 419 -7 zbc_parse_stmt_possibly_auto 1682 1675 -7 zbc_program_exec 3977 3964 -13 zbc_program_print 683 656 -27 zbc_lex_next 2233 2161 -72 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/18 up/down: 10/-183) Total: -173 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 312 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 155 insertions(+), 157 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 35778ff1c..5cd80c1e5 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -714,12 +714,10 @@ typedef struct BcLex { size_t i; size_t line; size_t len; - bool newline; - struct { - BcLexType t; - BcLexType last; - BcVec v; - } t; + bool newline; + smallint lex; // was BcLexType + smallint lex_last; // was BcLexType + BcVec lex_buf; } BcLex; #define BC_PARSE_STREND (0xff) @@ -2753,7 +2751,7 @@ static void bc_lex_lineComment(BcLex *l) { // Try: echo -n '#foo' | bc size_t i; - l->t.t = XC_LEX_WHITESPACE; + l->lex = XC_LEX_WHITESPACE; i = l->i; while (i < l->len && l->buf[i] != '\n') i++; @@ -2762,7 +2760,7 @@ static void bc_lex_lineComment(BcLex *l) static void bc_lex_whitespace(BcLex *l) { - l->t.t = XC_LEX_WHITESPACE; + l->lex = XC_LEX_WHITESPACE; for (;;) { char c = l->buf[l->i]; if (c == '\n') // this is XC_LEX_NLINE, not XC_LEX_WHITESPACE @@ -2780,7 +2778,7 @@ static BC_STATUS zbc_lex_number(BcLex *l, char start) bool pt; pt = (start == '.'); - l->t.t = XC_LEX_NUMBER; + l->lex = XC_LEX_NUMBER; ccnt = i = 0; for (;;) { char c = buf[i]; @@ -2820,9 +2818,9 @@ static BC_STATUS zbc_lex_number(BcLex *l, char start) RETURN_STATUS(bc_error("number too long: must be [1,"BC_MAX_NUM_STR"]")); } - bc_vec_pop_all(&l->t.v); - bc_vec_expand(&l->t.v, 1 + len); - bc_vec_push(&l->t.v, &start); + bc_vec_pop_all(&l->lex_buf); + bc_vec_expand(&l->lex_buf, 1 + len); + bc_vec_push(&l->lex_buf, &start); while (ccnt != 0) { // If we have hit a backslash, skip it. We don't have @@ -2832,12 +2830,12 @@ static BC_STATUS zbc_lex_number(BcLex *l, char start) ccnt -= 2; continue; } - bc_vec_push(&l->t.v, buf); + bc_vec_push(&l->lex_buf, buf); buf++; ccnt--; } - bc_vec_pushZeroByte(&l->t.v); + bc_vec_pushZeroByte(&l->lex_buf); RETURN_STATUS(BC_STATUS_SUCCESS); } @@ -2848,7 +2846,7 @@ static void bc_lex_name(BcLex *l) size_t i; const char *buf; - l->t.t = XC_LEX_NAME; + l->lex = XC_LEX_NAME; i = 0; buf = l->buf + l->i - 1; @@ -2865,7 +2863,7 @@ static void bc_lex_name(BcLex *l) return bc_error("name too long: must be [1,"BC_MAX_STRING_STR"]"); } #endif - bc_vec_string(&l->t.v, i, buf); + bc_vec_string(&l->lex_buf, i, buf); // Increment the index. We minus 1 because it has already been incremented. l->i += i - 1; @@ -2875,12 +2873,12 @@ static void bc_lex_name(BcLex *l) static void bc_lex_init(BcLex *l) { - bc_char_vec_init(&l->t.v); + bc_char_vec_init(&l->lex_buf); } static void bc_lex_free(BcLex *l) { - bc_vec_free(&l->t.v); + bc_vec_free(&l->lex_buf); } static void bc_lex_file(BcLex *l) @@ -2970,8 +2968,8 @@ static BC_STATUS zbc_lex_next(BcLex *l) { BcStatus s; - l->t.last = l->t.t; - if (l->t.last == XC_LEX_EOF) RETURN_STATUS(bc_error("end of file")); + l->lex_last = l->lex; + if (l->lex_last == XC_LEX_EOF) RETURN_STATUS(bc_error("end of file")); l->line += l->newline; G.err_line = l->line; @@ -2983,7 +2981,7 @@ static BC_STATUS zbc_lex_next(BcLex *l) s = BC_STATUS_SUCCESS; do { if (l->i == l->len) { - l->t.t = XC_LEX_EOF; + l->lex = XC_LEX_EOF; if (!G.input_fp) RETURN_STATUS(BC_STATUS_SUCCESS); if (!bc_lex_more_input(l)) { @@ -3000,8 +2998,8 @@ static BC_STATUS zbc_lex_next(BcLex *l) } else { IF_DC(s = zdc_lex_token(l)); } - } while (!s && l->t.t == XC_LEX_WHITESPACE); - dbg_lex("l->t.t from string:%d", l->t.t); + } while (!s && l->lex == XC_LEX_WHITESPACE); + dbg_lex("l->lex from string:%d", l->lex); RETURN_STATUS(s); } @@ -3010,7 +3008,7 @@ static BC_STATUS zbc_lex_next(BcLex *l) #if ENABLE_BC static BC_STATUS zbc_lex_skip_if_at_NLINE(BcLex *l) { - if (l->t.t == XC_LEX_NLINE) + if (l->lex == XC_LEX_NLINE) RETURN_STATUS(zbc_lex_next(l)); RETURN_STATUS(BC_STATUS_SUCCESS); } @@ -3033,7 +3031,7 @@ static BC_STATUS zbc_lex_text_init(BcLex *l, const char *text) l->buf = text; l->i = 0; l->len = strlen(text); - l->t.t = l->t.last = XC_LEX_INVALID; + l->lex = l->lex_last = XC_LEX_INVALID; RETURN_STATUS(zbc_lex_next(l)); } #define zbc_lex_text_init(...) (zbc_lex_text_init(__VA_ARGS__) COMMA_SUCCESS) @@ -3058,7 +3056,7 @@ static BC_STATUS zbc_lex_identifier(BcLex *l) // buf starts with keyword bc_lex_kws[i] if (isalnum(buf[j]) || buf[j]=='_') continue; // "ifz" does not match "if" keyword, "if." does - l->t.t = BC_LEX_KEY_1st_keyword + i; + l->lex = BC_LEX_KEY_1st_keyword + i; if (!bc_lex_kws_POSIX(i)) { s = zbc_posix_error_fmt("%sthe '%.8s' keyword", "POSIX does not allow ", bc_lex_kws[i].name8); if (s) RETURN_STATUS(s); @@ -3072,7 +3070,7 @@ static BC_STATUS zbc_lex_identifier(BcLex *l) bc_lex_name(l); s = BC_STATUS_SUCCESS; - if (l->t.v.len > 2) { + if (l->lex_buf.len > 2) { // Prevent this: // >>> qwe=1 // bc: POSIX only allows one character names; the following is bad: 'qwe=1 @@ -3089,7 +3087,7 @@ static BC_STATUS zbc_lex_string(BcLex *l) { size_t len, nls, i; - l->t.t = XC_LEX_STR; + l->lex = XC_LEX_STR; nls = 0; i = l->i; @@ -3111,7 +3109,7 @@ static BC_STATUS zbc_lex_string(BcLex *l) if (len > BC_MAX_STRING) RETURN_STATUS(bc_error("string too long: must be [1,"BC_MAX_STRING_STR"]")); } - bc_vec_string(&l->t.v, len, l->buf + l->i); + bc_vec_string(&l->lex_buf, len, l->buf + l->i); l->i = i + 1; l->line += nls; @@ -3127,7 +3125,7 @@ static void bc_lex_assign(BcLex *l, unsigned with_and_without) ++l->i; with_and_without >>= 8; // store "with" value } // else store "without" value - l->t.t = (with_and_without & 0xff); + l->lex = (with_and_without & 0xff); } #define bc_lex_assign(l, with, without) \ bc_lex_assign(l, ((with)<<8)|(without)) @@ -3137,7 +3135,7 @@ static BC_STATUS zbc_lex_comment(BcLex *l) size_t i, nls = 0; const char *buf = l->buf; - l->t.t = XC_LEX_WHITESPACE; + l->lex = XC_LEX_WHITESPACE; i = l->i; /* here buf[l->i] is the '*' of opening comment delimiter */ for (;;) { char c = buf[++i]; @@ -3173,11 +3171,11 @@ static BC_STATUS zbc_lex_token(BcLex *l) switch (c) { // case '\0': // probably never reached // l->i--; -// l->t.t = XC_LEX_EOF; +// l->lex = XC_LEX_EOF; // l->newline = true; // break; case '\n': - l->t.t = XC_LEX_NLINE; + l->lex = XC_LEX_NLINE; l->newline = true; break; case '\t': @@ -3189,7 +3187,7 @@ static BC_STATUS zbc_lex_token(BcLex *l) break; case '!': bc_lex_assign(l, XC_LEX_OP_REL_NE, BC_LEX_OP_BOOL_NOT); - if (l->t.t == BC_LEX_OP_BOOL_NOT) { + if (l->lex == BC_LEX_OP_BOOL_NOT) { s = zbc_POSIX_does_not_allow_bool_ops_this_is_bad("!"); if (s) RETURN_STATUS(s); } @@ -3211,15 +3209,15 @@ static BC_STATUS zbc_lex_token(BcLex *l) s = zbc_POSIX_does_not_allow_bool_ops_this_is_bad("&&"); if (s) RETURN_STATUS(s); ++l->i; - l->t.t = BC_LEX_OP_BOOL_AND; + l->lex = BC_LEX_OP_BOOL_AND; } else { - l->t.t = XC_LEX_INVALID; + l->lex = XC_LEX_INVALID; s = bc_error_bad_character('&'); } break; case '(': case ')': - l->t.t = (BcLexType)(c - '(' + BC_LEX_LPAREN); + l->lex = (BcLexType)(c - '(' + BC_LEX_LPAREN); break; case '*': bc_lex_assign(l, BC_LEX_OP_ASSIGN_MULTIPLY, XC_LEX_OP_MULTIPLY); @@ -3228,18 +3226,18 @@ static BC_STATUS zbc_lex_token(BcLex *l) c2 = l->buf[l->i]; if (c2 == '+') { ++l->i; - l->t.t = BC_LEX_OP_INC; + l->lex = BC_LEX_OP_INC; } else bc_lex_assign(l, BC_LEX_OP_ASSIGN_PLUS, XC_LEX_OP_PLUS); break; case ',': - l->t.t = BC_LEX_COMMA; + l->lex = BC_LEX_COMMA; break; case '-': c2 = l->buf[l->i]; if (c2 == '-') { ++l->i; - l->t.t = BC_LEX_OP_DEC; + l->lex = BC_LEX_OP_DEC; } else bc_lex_assign(l, BC_LEX_OP_ASSIGN_MINUS, XC_LEX_OP_MINUS); break; @@ -3247,7 +3245,7 @@ static BC_STATUS zbc_lex_token(BcLex *l) if (isdigit(l->buf[l->i])) s = zbc_lex_number(l, c); else { - l->t.t = BC_LEX_KEY_LAST; + l->lex = BC_LEX_KEY_LAST; s = zbc_POSIX_does_not_allow("a period ('.') as a shortcut for the last result"); } break; @@ -3277,7 +3275,7 @@ static BC_STATUS zbc_lex_token(BcLex *l) s = zbc_lex_number(l, c); break; case ';': - l->t.t = BC_LEX_SCOLON; + l->lex = BC_LEX_SCOLON; break; case '<': bc_lex_assign(l, XC_LEX_OP_REL_LE, XC_LEX_OP_REL_LT); @@ -3290,11 +3288,11 @@ static BC_STATUS zbc_lex_token(BcLex *l) break; case '[': case ']': - l->t.t = (BcLexType)(c - '[' + BC_LEX_LBRACKET); + l->lex = (BcLexType)(c - '[' + BC_LEX_LBRACKET); break; case '\\': if (l->buf[l->i] == '\n') { - l->t.t = XC_LEX_WHITESPACE; + l->lex = XC_LEX_WHITESPACE; ++l->i; } else s = bc_error_bad_character(c); @@ -3332,7 +3330,7 @@ static BC_STATUS zbc_lex_token(BcLex *l) break; case '{': case '}': - l->t.t = (BcLexType)(c - '{' + BC_LEX_LBRACE); + l->lex = (BcLexType)(c - '{' + BC_LEX_LBRACE); break; case '|': c2 = l->buf[l->i]; @@ -3340,14 +3338,14 @@ static BC_STATUS zbc_lex_token(BcLex *l) s = zbc_POSIX_does_not_allow_bool_ops_this_is_bad("||"); if (s) RETURN_STATUS(s); ++l->i; - l->t.t = BC_LEX_OP_BOOL_OR; + l->lex = BC_LEX_OP_BOOL_OR; } else { - l->t.t = XC_LEX_INVALID; + l->lex = XC_LEX_INVALID; s = bc_error_bad_character(c); } break; default: - l->t.t = XC_LEX_INVALID; + l->lex = XC_LEX_INVALID; s = bc_error_bad_character(c); break; } @@ -3365,10 +3363,10 @@ static BC_STATUS zdc_lex_register(BcLex *l) l->i++; // bc_lex_name() expects this bc_lex_name(l); } else { - bc_vec_pop_all(&l->t.v); - bc_vec_push(&l->t.v, &l->buf[l->i++]); - bc_vec_pushZeroByte(&l->t.v); - l->t.t = XC_LEX_NAME; + bc_vec_pop_all(&l->lex_buf); + bc_vec_push(&l->lex_buf, &l->buf[l->i++]); + bc_vec_pushZeroByte(&l->lex_buf); + l->lex = XC_LEX_NAME; } RETURN_STATUS(BC_STATUS_SUCCESS); @@ -3379,8 +3377,8 @@ static BC_STATUS zdc_lex_string(BcLex *l) { size_t depth, nls, i; - l->t.t = XC_LEX_STR; - bc_vec_pop_all(&l->t.v); + l->lex = XC_LEX_STR; + bc_vec_pop_all(&l->lex_buf); nls = 0; depth = 1; @@ -3398,12 +3396,12 @@ static BC_STATUS zdc_lex_string(BcLex *l) if (--depth == 0) break; } - bc_vec_push(&l->t.v, &l->buf[i]); + bc_vec_push(&l->lex_buf, &l->buf[i]); i++; } i++; - bc_vec_pushZeroByte(&l->t.v); + bc_vec_pushZeroByte(&l->lex_buf); // This check makes sense only if size_t is (much) larger than BC_MAX_STRING. if (SIZE_MAX > (BC_MAX_STRING | 0xff)) { if (i - l->i > BC_MAX_STRING) @@ -3435,14 +3433,14 @@ static BC_STATUS zdc_lex_token(BcLex *l) size_t i; for (i = 0; i < ARRAY_SIZE(dc_lex_regs); ++i) { - if (l->t.last == dc_lex_regs[i]) + if (l->lex_last == dc_lex_regs[i]) RETURN_STATUS(zdc_lex_register(l)); } s = BC_STATUS_SUCCESS; c = l->buf[l->i++]; if (c >= '%' && c <= '~' - && (l->t.t = dc_char_to_LEX[c - '%']) != XC_LEX_INVALID + && (l->lex = dc_char_to_LEX[c - '%']) != XC_LEX_INVALID ) { RETURN_STATUS(s); } @@ -3450,7 +3448,7 @@ static BC_STATUS zdc_lex_token(BcLex *l) // This is the workhorse of the lexer. switch (c) { // case '\0': // probably never reached -// l->t.t = XC_LEX_EOF; +// l->lex = XC_LEX_EOF; // break; case '\n': // '\n' is XC_LEX_NLINE, not XC_LEX_WHITESPACE @@ -3461,7 +3459,7 @@ static BC_STATUS zdc_lex_token(BcLex *l) // commands are not executed on pressing ). // IOW: typing "1p" should print "1" _at once_, // not after some more input. - l->t.t = XC_LEX_NLINE; + l->lex = XC_LEX_NLINE; l->newline = true; break; case '\t': @@ -3475,11 +3473,11 @@ static BC_STATUS zdc_lex_token(BcLex *l) case '!': c2 = l->buf[l->i]; if (c2 == '=') - l->t.t = XC_LEX_OP_REL_NE; + l->lex = XC_LEX_OP_REL_NE; else if (c2 == '<') - l->t.t = XC_LEX_OP_REL_LE; + l->lex = XC_LEX_OP_REL_LE; else if (c2 == '>') - l->t.t = XC_LEX_OP_REL_GE; + l->lex = XC_LEX_OP_REL_GE; else RETURN_STATUS(bc_error_bad_character(c)); ++l->i; @@ -3515,7 +3513,7 @@ static BC_STATUS zdc_lex_token(BcLex *l) s = zdc_lex_string(l); break; default: - l->t.t = XC_LEX_INVALID; + l->lex = XC_LEX_INVALID; s = bc_error_bad_character(c); break; } @@ -3575,7 +3573,7 @@ static void bc_parse_pushJUMP_ZERO(BcParse *p, size_t idx) static BC_STATUS zbc_parse_pushSTR(BcParse *p) { - char *str = xstrdup(p->l.t.v.v); + char *str = xstrdup(p->l.lex_buf.v); bc_parse_push(p, XC_INST_STR); bc_parse_pushIndex(p, p->func->strs.len); @@ -3588,7 +3586,7 @@ static BC_STATUS zbc_parse_pushSTR(BcParse *p) static void bc_parse_pushNUM(BcParse *p) { - char *num = xstrdup(p->l.t.v.v); + char *num = xstrdup(p->l.lex_buf.v); #if ENABLE_BC && ENABLE_DC size_t idx = bc_vec_push(IS_BC ? &p->func->consts : &G.prog.consts, &num); #elif ENABLE_BC @@ -3636,7 +3634,7 @@ static void bc_parse_reset(BcParse *p) } p->l.i = p->l.len; - p->l.t.t = XC_LEX_EOF; + p->l.lex = XC_LEX_EOF; IF_BC(bc_vec_pop_all(&p->exits);) IF_BC(bc_vec_pop_all(&p->conds);) @@ -3745,7 +3743,7 @@ static BC_STATUS zbc_parse_stmt_allow_NLINE_before(BcParse *p, const char *after // Same for "else", "while()", "for()". BcStatus s = zbc_lex_next_and_skip_NLINE(&p->l); if (s) RETURN_STATUS(s); - if (p->l.t.t == XC_LEX_NLINE) + if (p->l.lex == XC_LEX_NLINE) RETURN_STATUS(bc_error_fmt("no statement after '%s'", after_X)); RETURN_STATUS(zbc_parse_stmt(p)); @@ -3803,20 +3801,20 @@ static BC_STATUS zbc_parse_params(BcParse *p, uint8_t flags) BcStatus s; size_t nparams; - dbg_lex("%s:%d p->l.t.t:%d", __func__, __LINE__, p->l.t.t); + dbg_lex("%s:%d p->l.lex:%d", __func__, __LINE__, p->l.lex); flags = (flags & ~(BC_PARSE_PRINT | BC_PARSE_REL)) | BC_PARSE_ARRAY; s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); nparams = 0; - if (p->l.t.t != BC_LEX_RPAREN) { + if (p->l.lex != BC_LEX_RPAREN) { for (;;) { s = zbc_parse_expr(p, flags); if (s) RETURN_STATUS(s); nparams++; - if (p->l.t.t != BC_LEX_COMMA) { - if (p->l.t.t == BC_LEX_RPAREN) + if (p->l.lex != BC_LEX_COMMA) { + if (p->l.lex == BC_LEX_RPAREN) break; RETURN_STATUS(bc_error_bad_token()); } @@ -3844,7 +3842,7 @@ static BC_STATUS zbc_parse_call(BcParse *p, char *name, uint8_t flags) s = zbc_parse_params(p, flags); if (s) goto err; - if (p->l.t.t != BC_LEX_RPAREN) { + if (p->l.lex != BC_LEX_RPAREN) { s = bc_error_bad_token(); goto err; } @@ -3873,15 +3871,15 @@ static BC_STATUS zbc_parse_name(BcParse *p, BcInst *type, uint8_t flags) BcStatus s; char *name; - name = xstrdup(p->l.t.v.v); + name = xstrdup(p->l.lex_buf.v); s = zbc_lex_next(&p->l); if (s) goto err; - if (p->l.t.t == BC_LEX_LBRACKET) { + if (p->l.lex == BC_LEX_LBRACKET) { s = zbc_lex_next(&p->l); if (s) goto err; - if (p->l.t.t == BC_LEX_RBRACKET) { + if (p->l.lex == BC_LEX_RBRACKET) { if (!(flags & BC_PARSE_ARRAY)) { s = bc_error_bad_expression(); goto err; @@ -3898,7 +3896,7 @@ static BC_STATUS zbc_parse_name(BcParse *p, BcInst *type, uint8_t flags) bc_parse_push(p, *type); bc_parse_pushName(p, name); free(name); - } else if (p->l.t.t == BC_LEX_LPAREN) { + } else if (p->l.lex == BC_LEX_LPAREN) { if (flags & BC_PARSE_NOCALL) { s = bc_error_bad_token(); goto err; @@ -3925,11 +3923,11 @@ static BC_STATUS zbc_parse_read(BcParse *p) s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); - if (p->l.t.t != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); + if (p->l.lex != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); - if (p->l.t.t != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); + if (p->l.lex != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); bc_parse_push(p, XC_INST_READ); @@ -3944,7 +3942,7 @@ static BC_STATUS zbc_parse_builtin(BcParse *p, BcLexType type, uint8_t flags, s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); - if (p->l.t.t != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); + if (p->l.lex != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); flags = (flags & ~(BC_PARSE_PRINT | BC_PARSE_REL)) | BC_PARSE_ARRAY; @@ -3954,7 +3952,7 @@ static BC_STATUS zbc_parse_builtin(BcParse *p, BcLexType type, uint8_t flags, s = zbc_parse_expr(p, flags); if (s) RETURN_STATUS(s); - if (p->l.t.t != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); + if (p->l.lex != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); *prev = (type == BC_LEX_KEY_LENGTH) ? XC_INST_LENGTH : XC_INST_SQRT; bc_parse_push(p, *prev); @@ -3970,7 +3968,7 @@ static BC_STATUS zbc_parse_scale(BcParse *p, BcInst *type, uint8_t flags) s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); - if (p->l.t.t != BC_LEX_LPAREN) { + if (p->l.lex != BC_LEX_LPAREN) { *type = XC_INST_SCALE; bc_parse_push(p, XC_INST_SCALE); RETURN_STATUS(BC_STATUS_SUCCESS); @@ -3984,7 +3982,7 @@ static BC_STATUS zbc_parse_scale(BcParse *p, BcInst *type, uint8_t flags) s = zbc_parse_expr(p, flags); if (s) RETURN_STATUS(s); - if (p->l.t.t != BC_LEX_RPAREN) + if (p->l.lex != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); bc_parse_push(p, XC_INST_SCALE_FUNC); @@ -4004,16 +4002,16 @@ static BC_STATUS zbc_parse_incdec(BcParse *p, BcInst *prev, bool *paren_expr, || etype == XC_INST_SCALE || etype == BC_INST_LAST || etype == XC_INST_IBASE || etype == XC_INST_OBASE ) { - *prev = inst = BC_INST_INC_POST + (p->l.t.t != BC_LEX_OP_INC); + *prev = inst = BC_INST_INC_POST + (p->l.lex != BC_LEX_OP_INC); bc_parse_push(p, inst); s = zbc_lex_next(&p->l); } else { - *prev = inst = BC_INST_INC_PRE + (p->l.t.t != BC_LEX_OP_INC); + *prev = inst = BC_INST_INC_PRE + (p->l.lex != BC_LEX_OP_INC); *paren_expr = true; s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); - type = p->l.t.t; + type = p->l.lex; // Because we parse the next part of the expression // right here, we need to increment this. @@ -4032,7 +4030,7 @@ static BC_STATUS zbc_parse_incdec(BcParse *p, BcInst *prev, bool *paren_expr, case BC_LEX_KEY_SCALE: s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); - if (p->l.t.t == BC_LEX_LPAREN) + if (p->l.lex == BC_LEX_LPAREN) s = bc_error_bad_token(); else bc_parse_push(p, XC_INST_SCALE); @@ -4084,7 +4082,7 @@ static BC_STATUS zbc_parse_print(BcParse *p) for (;;) { s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); - type = p->l.t.t; + type = p->l.lex; if (type == XC_LEX_STR) { s = zbc_parse_pushSTR(p); } else { @@ -4092,7 +4090,7 @@ static BC_STATUS zbc_parse_print(BcParse *p) } if (s) RETURN_STATUS(s); bc_parse_push(p, XC_INST_PRINT_POP); - if (p->l.t.t != BC_LEX_COMMA) + if (p->l.lex != BC_LEX_COMMA) break; } @@ -4109,7 +4107,7 @@ static BC_STATUS zbc_parse_return(BcParse *p) s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); - t = p->l.t.t; + t = p->l.lex; if (t == XC_LEX_NLINE || t == BC_LEX_SCOLON) bc_parse_push(p, BC_INST_RET0); else { @@ -4121,7 +4119,7 @@ static BC_STATUS zbc_parse_return(BcParse *p) } if (s) RETURN_STATUS(s); - if (!paren || p->l.t.last != BC_LEX_RPAREN) { + if (!paren || p->l.lex_last != BC_LEX_RPAREN) { s = zbc_POSIX_requires("parentheses around return expressions"); if (s) RETURN_STATUS(s); } @@ -4148,13 +4146,13 @@ static BC_STATUS zbc_parse_if(BcParse *p) dbg_lex_enter("%s:%d entered", __func__, __LINE__); s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); - if (p->l.t.t != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); + if (p->l.lex != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); s = zbc_parse_expr(p, BC_PARSE_REL); if (s) RETURN_STATUS(s); - if (p->l.t.t != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); + if (p->l.lex != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); // Encode "if zero, jump to ..." // Pushed value (destination of the jump) is uninitialized, @@ -4165,8 +4163,8 @@ static BC_STATUS zbc_parse_if(BcParse *p) s = zbc_parse_stmt_allow_NLINE_before(p, STRING_if); if (s) RETURN_STATUS(s); - dbg_lex("%s:%d in if after stmt: p->l.t.t:%d", __func__, __LINE__, p->l.t.t); - if (p->l.t.t == BC_LEX_KEY_ELSE) { + dbg_lex("%s:%d in if after stmt: p->l.lex:%d", __func__, __LINE__, p->l.lex); + if (p->l.lex == BC_LEX_KEY_ELSE) { size_t ip2_idx; // Encode "after then_stmt, jump to end of if()" @@ -4199,7 +4197,7 @@ static BC_STATUS zbc_parse_while(BcParse *p) s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); - if (p->l.t.t != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); + if (p->l.lex != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); @@ -4212,7 +4210,7 @@ static BC_STATUS zbc_parse_while(BcParse *p) s = zbc_parse_expr(p, BC_PARSE_REL); if (s) RETURN_STATUS(s); - if (p->l.t.t != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); + if (p->l.lex != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); bc_parse_pushJUMP_ZERO(p, ip_idx); @@ -4237,14 +4235,14 @@ static BC_STATUS zbc_parse_for(BcParse *p) BcStatus s; size_t cond_idx, exit_idx, body_idx, update_idx; - dbg_lex("%s:%d p->l.t.t:%d", __func__, __LINE__, p->l.t.t); + dbg_lex("%s:%d p->l.lex:%d", __func__, __LINE__, p->l.lex); s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); - if (p->l.t.t != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); + if (p->l.lex != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); - if (p->l.t.t != BC_LEX_SCOLON) { + if (p->l.lex != BC_LEX_SCOLON) { s = zbc_parse_expr(p, 0); bc_parse_push(p, XC_INST_POP); if (s) RETURN_STATUS(s); @@ -4253,7 +4251,7 @@ static BC_STATUS zbc_parse_for(BcParse *p) if (s) RETURN_STATUS(s); } - if (p->l.t.t != BC_LEX_SCOLON) RETURN_STATUS(bc_error_bad_token()); + if (p->l.lex != BC_LEX_SCOLON) RETURN_STATUS(bc_error_bad_token()); s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); @@ -4262,19 +4260,19 @@ static BC_STATUS zbc_parse_for(BcParse *p) body_idx = update_idx + 1; exit_idx = body_idx + 1; - if (p->l.t.t != BC_LEX_SCOLON) + if (p->l.lex != BC_LEX_SCOLON) s = zbc_parse_expr(p, BC_PARSE_REL); else { // Set this for the next call to bc_parse_pushNUM(). // This is safe to set because the current token is a semicolon, // which has no string requirement. - bc_vec_string(&p->l.t.v, 1, "1"); + bc_vec_string(&p->l.lex_buf, 1, "1"); bc_parse_pushNUM(p); s = zbc_POSIX_does_not_allow_empty_X_expression_in_for("condition"); } if (s) RETURN_STATUS(s); - if (p->l.t.t != BC_LEX_SCOLON) RETURN_STATUS(bc_error_bad_token()); + if (p->l.lex != BC_LEX_SCOLON) RETURN_STATUS(bc_error_bad_token()); s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); @@ -4285,10 +4283,10 @@ static BC_STATUS zbc_parse_for(BcParse *p) bc_vec_push(&p->conds, &update_idx); bc_vec_push(&p->func->labels, &p->func->code.len); - if (p->l.t.t != BC_LEX_RPAREN) { + if (p->l.lex != BC_LEX_RPAREN) { s = zbc_parse_expr(p, 0); if (s) RETURN_STATUS(s); - if (p->l.t.t != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); + if (p->l.lex != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); bc_parse_push(p, XC_INST_POP); } else { s = zbc_POSIX_does_not_allow_empty_X_expression_in_for("update"); @@ -4335,7 +4333,7 @@ static BC_STATUS zbc_parse_break_or_continue(BcParse *p, BcLexType type) s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); - if (p->l.t.t != BC_LEX_SCOLON && p->l.t.t != XC_LEX_NLINE) + if (p->l.lex != BC_LEX_SCOLON && p->l.lex != XC_LEX_NLINE) RETURN_STATUS(bc_error_bad_token()); RETURN_STATUS(zbc_lex_next(&p->l)); @@ -4372,37 +4370,37 @@ static BC_STATUS zbc_parse_funcdef(BcParse *p) dbg_lex_enter("%s:%d entered", __func__, __LINE__); s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); - if (p->l.t.t != XC_LEX_NAME) + if (p->l.lex != XC_LEX_NAME) RETURN_STATUS(bc_error("bad function definition")); - name = xstrdup(p->l.t.v.v); + name = xstrdup(p->l.lex_buf.v); p->fidx = bc_program_addFunc(name); p->func = bc_program_func(p->fidx); s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); - if (p->l.t.t != BC_LEX_LPAREN) + if (p->l.lex != BC_LEX_LPAREN) RETURN_STATUS(bc_error("bad function definition")); s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); - while (p->l.t.t != BC_LEX_RPAREN) { - if (p->l.t.t != XC_LEX_NAME) + while (p->l.lex != BC_LEX_RPAREN) { + if (p->l.lex != XC_LEX_NAME) RETURN_STATUS(bc_error("bad function definition")); ++p->func->nparams; - name = xstrdup(p->l.t.v.v); + name = xstrdup(p->l.lex_buf.v); s = zbc_lex_next(&p->l); if (s) goto err; - var = p->l.t.t != BC_LEX_LBRACKET; + var = p->l.lex != BC_LEX_LBRACKET; if (!var) { s = zbc_lex_next(&p->l); if (s) goto err; - if (p->l.t.t != BC_LEX_RBRACKET) { + if (p->l.lex != BC_LEX_RBRACKET) { s = bc_error("bad function definition"); goto err; } @@ -4411,7 +4409,7 @@ static BC_STATUS zbc_parse_funcdef(BcParse *p) if (s) goto err; } - comma = p->l.t.t == BC_LEX_COMMA; + comma = p->l.lex == BC_LEX_COMMA; if (comma) { s = zbc_lex_next(&p->l); if (s) goto err; @@ -4426,7 +4424,7 @@ static BC_STATUS zbc_parse_funcdef(BcParse *p) s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); - if (p->l.t.t != BC_LEX_LBRACE) { + if (p->l.lex != BC_LEX_LBRACE) { s = zbc_POSIX_requires("the left brace be on the same line as the function header"); if (s) RETURN_STATUS(s); } @@ -4435,7 +4433,7 @@ static BC_STATUS zbc_parse_funcdef(BcParse *p) s = zbc_lex_skip_if_at_NLINE(&p->l); if (s) RETURN_STATUS(s); //GNU bc requires a {} block even if function body has single stmt, enforce this? - if (p->l.t.t != BC_LEX_LBRACE) + if (p->l.lex != BC_LEX_LBRACE) RETURN_STATUS(bc_error("function { body } expected")); p->in_funcdef++; // to determine whether "return" stmt is allowed, and such @@ -4469,19 +4467,19 @@ static BC_STATUS zbc_parse_auto(BcParse *p) if (s) RETURN_STATUS(s); comma = false; - one = p->l.t.t == XC_LEX_NAME; + one = p->l.lex == XC_LEX_NAME; - while (p->l.t.t == XC_LEX_NAME) { - name = xstrdup(p->l.t.v.v); + while (p->l.lex == XC_LEX_NAME) { + name = xstrdup(p->l.lex_buf.v); s = zbc_lex_next(&p->l); if (s) goto err; - var = p->l.t.t != BC_LEX_LBRACKET; + var = p->l.lex != BC_LEX_LBRACKET; if (!var) { s = zbc_lex_next(&p->l); if (s) goto err; - if (p->l.t.t != BC_LEX_RBRACKET) { + if (p->l.lex != BC_LEX_RBRACKET) { s = bc_error("bad function definition"); goto err; } @@ -4490,7 +4488,7 @@ static BC_STATUS zbc_parse_auto(BcParse *p) if (s) goto err; } - comma = p->l.t.t == BC_LEX_COMMA; + comma = p->l.lex == BC_LEX_COMMA; if (comma) { s = zbc_lex_next(&p->l); if (s) goto err; @@ -4503,7 +4501,7 @@ static BC_STATUS zbc_parse_auto(BcParse *p) if (comma) RETURN_STATUS(bc_error("bad function definition")); if (!one) RETURN_STATUS(bc_error("no auto variable found")); - if (p->l.t.t != XC_LEX_NLINE && p->l.t.t != BC_LEX_SCOLON) + if (p->l.lex != XC_LEX_NLINE && p->l.lex != BC_LEX_SCOLON) RETURN_STATUS(bc_error_bad_token()); dbg_lex_done("%s:%d done", __func__, __LINE__); @@ -4520,29 +4518,29 @@ static BC_STATUS zbc_parse_stmt_possibly_auto(BcParse *p, bool auto_allowed) { BcStatus s = BC_STATUS_SUCCESS; - dbg_lex_enter("%s:%d entered, p->l.t.t:%d", __func__, __LINE__, p->l.t.t); + dbg_lex_enter("%s:%d entered, p->l.lex:%d", __func__, __LINE__, p->l.lex); - if (p->l.t.t == XC_LEX_NLINE) { + if (p->l.lex == XC_LEX_NLINE) { dbg_lex_done("%s:%d done (seen XC_LEX_NLINE)", __func__, __LINE__); RETURN_STATUS(zbc_lex_next(&p->l)); } - if (p->l.t.t == BC_LEX_SCOLON) { + if (p->l.lex == BC_LEX_SCOLON) { dbg_lex_done("%s:%d done (seen BC_LEX_SCOLON)", __func__, __LINE__); RETURN_STATUS(zbc_lex_next(&p->l)); } - if (p->l.t.t == BC_LEX_LBRACE) { + if (p->l.lex == BC_LEX_LBRACE) { dbg_lex("%s:%d BC_LEX_LBRACE: (auto_allowed:%d)", __func__, __LINE__, auto_allowed); do { s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); - } while (p->l.t.t == XC_LEX_NLINE); - if (auto_allowed && p->l.t.t == BC_LEX_KEY_AUTO) { + } while (p->l.lex == XC_LEX_NLINE); + if (auto_allowed && p->l.lex == BC_LEX_KEY_AUTO) { dbg_lex("%s:%d calling zbc_parse_auto()", __func__, __LINE__); s = zbc_parse_auto(p); if (s) RETURN_STATUS(s); } - while (p->l.t.t != BC_LEX_RBRACE) { + while (p->l.lex != BC_LEX_RBRACE) { dbg_lex("%s:%d block parsing loop", __func__, __LINE__); s = zbc_parse_stmt(p); if (s) RETURN_STATUS(s); @@ -4552,8 +4550,8 @@ static BC_STATUS zbc_parse_stmt_possibly_auto(BcParse *p, bool auto_allowed) RETURN_STATUS(s); } - dbg_lex("%s:%d p->l.t.t:%d", __func__, __LINE__, p->l.t.t); - switch (p->l.t.t) { + dbg_lex("%s:%d p->l.lex:%d", __func__, __LINE__, p->l.lex); + switch (p->l.lex) { case XC_LEX_OP_MINUS: case BC_LEX_OP_INC: case BC_LEX_OP_DEC: @@ -4576,7 +4574,7 @@ static BC_STATUS zbc_parse_stmt_possibly_auto(BcParse *p, bool auto_allowed) break; case BC_LEX_KEY_BREAK: case BC_LEX_KEY_CONTINUE: - s = zbc_parse_break_or_continue(p, p->l.t.t); + s = zbc_parse_break_or_continue(p, p->l.lex); break; case BC_LEX_KEY_FOR: s = zbc_parse_for(p); @@ -4634,13 +4632,13 @@ static BC_STATUS zbc_parse_stmt_or_funcdef(BcParse *p) BcStatus s; dbg_lex_enter("%s:%d entered", __func__, __LINE__); - if (p->l.t.t == XC_LEX_EOF) + if (p->l.lex == XC_LEX_EOF) s = bc_error("end of file"); - else if (p->l.t.t == BC_LEX_KEY_DEFINE) { - dbg_lex("%s:%d p->l.t.t:BC_LEX_KEY_DEFINE", __func__, __LINE__); + else if (p->l.lex == BC_LEX_KEY_DEFINE) { + dbg_lex("%s:%d p->l.lex:BC_LEX_KEY_DEFINE", __func__, __LINE__); s = zbc_parse_funcdef(p); } else { - dbg_lex("%s:%d p->l.t.t:%d (not BC_LEX_KEY_DEFINE)", __func__, __LINE__, p->l.t.t); + dbg_lex("%s:%d p->l.lex:%d (not BC_LEX_KEY_DEFINE)", __func__, __LINE__, p->l.lex); s = zbc_parse_stmt(p); } @@ -4654,18 +4652,18 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) { BcStatus s = BC_STATUS_SUCCESS; BcInst prev = XC_INST_PRINT; - BcLexType top, t = p->l.t.t; + BcLexType top, t = p->l.lex; size_t nexprs = 0, ops_bgn = p->ops.len; unsigned nparens, nrelops; bool paren_first, paren_expr, rprn, done, get_token, assign, bin_last; dbg_lex_enter("%s:%d entered", __func__, __LINE__); - paren_first = (p->l.t.t == BC_LEX_LPAREN); + paren_first = (p->l.lex == BC_LEX_LPAREN); nparens = nrelops = 0; paren_expr = rprn = done = get_token = assign = false; bin_last = true; - for (; !G_interrupt && !s && !done && bc_parse_exprs(t); t = p->l.t.t) { + for (; !G_interrupt && !s && !done && bc_parse_exprs(t); t = p->l.lex) { dbg_lex("%s:%d t:%d", __func__, __LINE__, t); switch (t) { case BC_LEX_OP_INC: @@ -4858,9 +4856,9 @@ static BC_STATUS zdc_parse_register(BcParse *p) s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); - if (p->l.t.t != XC_LEX_NAME) RETURN_STATUS(bc_error_bad_token()); + if (p->l.lex != XC_LEX_NAME) RETURN_STATUS(bc_error_bad_token()); - bc_parse_pushName(p, p->l.t.v.v); + bc_parse_pushName(p, p->l.lex_buf.v); RETURN_STATUS(s); } @@ -4873,7 +4871,7 @@ static void dc_parse_string(BcParse *p) dbg_lex_enter("%s:%d entered", __func__, __LINE__); - str = xstrdup(p->l.t.v.v); + str = xstrdup(p->l.lex_buf.v); bc_parse_push(p, XC_INST_STR); bc_parse_pushIndex(p, len); bc_vec_push(&G.prog.strs, &str); @@ -4921,7 +4919,7 @@ static BC_STATUS zdc_parse_cond(BcParse *p, uint8_t inst) // Note that 'else' part can not be on the next line: // echo -e '[1p]sa [2p]sb 2 1>a eb' | dc - OK, prints "2" // echo -e '[1p]sa [2p]sb 2 1>a\neb' | dc - parse error - if (p->l.t.t == DC_LEX_ELSE) { + if (p->l.lex == DC_LEX_ELSE) { s = zdc_parse_register(p); if (s) RETURN_STATUS(s); s = zbc_lex_next(&p->l); @@ -4966,7 +4964,7 @@ static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t) dbg_lex("%s:%d LEX_NEG", __func__, __LINE__); s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); - if (p->l.t.t != XC_LEX_NUMBER) + if (p->l.lex != XC_LEX_NUMBER) RETURN_STATUS(bc_error_bad_token()); bc_parse_pushNUM(p); bc_parse_push(p, XC_INST_NEG); @@ -5015,7 +5013,7 @@ static BC_STATUS zdc_parse_expr(BcParse *p) { int i; - i = (int)p->l.t.t - (int)XC_LEX_OP_POWER; + i = (int)p->l.lex - (int)XC_LEX_OP_POWER; if (i >= 0) { BcInst inst = dc_LEX_to_INST[i]; if (inst != DC_INST_INVALID) { @@ -5023,14 +5021,14 @@ static BC_STATUS zdc_parse_expr(BcParse *p) RETURN_STATUS(zbc_lex_next(&p->l)); } } - RETURN_STATUS(zdc_parse_token(p, p->l.t.t)); + RETURN_STATUS(zdc_parse_token(p, p->l.lex)); } #define zdc_parse_expr(...) (zdc_parse_expr(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zdc_parse_exprs_until_eof(BcParse *p) { - dbg_lex_enter("%s:%d entered, p->l.t.t:%d", __func__, __LINE__, p->l.t.t); - while (p->l.t.t != XC_LEX_EOF) { + dbg_lex_enter("%s:%d entered, p->l.lex:%d", __func__, __LINE__, p->l.lex); + while (p->l.lex != XC_LEX_EOF) { BcStatus s = zdc_parse_expr(p); if (s) RETURN_STATUS(s); } @@ -5263,7 +5261,7 @@ static BC_STATUS zbc_program_read(void) } if (s) goto exec_err; - if (parse.l.t.t != XC_LEX_NLINE && parse.l.t.t != XC_LEX_EOF) { + if (parse.l.lex != XC_LEX_NLINE && parse.l.lex != XC_LEX_EOF) { s = bc_error("bad read() expression"); goto exec_err; } @@ -6396,7 +6394,7 @@ static BC_STATUS zdc_program_execStr(char *code, size_t *bgn, bool cond) G.input_fp = sv_input_fp; if (s) goto err; - if (prs.l.t.t != XC_LEX_EOF) { + if (prs.l.lex != XC_LEX_EOF) { s = bc_error_bad_expression(); err: bc_parse_free(&prs); @@ -6732,11 +6730,11 @@ static BC_STATUS zbc_vm_process(const char *text) s = zbc_parse_text_init(&G.prs, text); // does the first zbc_lex_next() if (s) RETURN_STATUS(s); - while (G.prs.l.t.t != XC_LEX_EOF) { + while (G.prs.l.lex != XC_LEX_EOF) { BcInstPtr *ip; BcFunc *f; - dbg_lex("%s:%d G.prs.l.t.t:%d, parsing...", __func__, __LINE__, G.prs.l.t.t); + dbg_lex("%s:%d G.prs.l.lex:%d, parsing...", __func__, __LINE__, G.prs.l.lex); if (IS_BC) { // FIXME: "eating" of stmt delimiters is coded inconsistently // (sometimes zbc_parse_stmt() eats the delimiter, sometimes don't), @@ -6747,10 +6745,10 @@ static BC_STATUS zbc_vm_process(const char *text) } else { // Most of dc parsing assumes all whitespace, // including '\n', is eaten. - while (G.prs.l.t.t == XC_LEX_NLINE) { + while (G.prs.l.lex == XC_LEX_NLINE) { s = zbc_lex_next(&G.prs.l); if (s) goto err; - if (G.prs.l.t.t == XC_LEX_EOF) + if (G.prs.l.lex == XC_LEX_EOF) goto done; } IF_DC(s = zdc_parse_expr(&G.prs)); -- cgit v1.2.3-55-g6feb From 0c45bb22a092387a1d899965c69c15bfd78b0ee9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 24 Dec 2018 23:22:40 +0100 Subject: bc: partially deinline BC_PARSE_LEAF() macro function old new delta ok_in_expr - 30 +30 bc_parse_expr_empty_ok 1972 1846 -126 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 0/1 up/down: 30/-126) Total: -96 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 44 +++++++++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 5cd80c1e5..ee3061621 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -3705,11 +3705,7 @@ static size_t bc_program_addFunc(char *name) return idx; } -#define BC_PARSE_TOP_OP(p) (*((BcLexType *) bc_vec_top(&(p)->ops))) -#define BC_PARSE_LEAF(p, rparen) \ - (((p) >= XC_INST_NUM && (p) <= XC_INST_SQRT) || (rparen) || \ - (p) == BC_INST_INC_POST || (p) == BC_INST_DEC_POST) - +#define BC_PARSE_TOP_OP(p) (*(BcLexType*)bc_vec_top(&(p)->ops)) // We can calculate the conversion between tokens and exprs by subtracting the // position of the first operator in the lex enum and adding the position of the // first in the expr enum. Note: This only works for binary operators. @@ -4047,6 +4043,24 @@ static BC_STATUS zbc_parse_incdec(BcParse *p, BcInst *prev, bool *paren_expr, } #define zbc_parse_incdec(...) (zbc_parse_incdec(__VA_ARGS__) COMMA_SUCCESS) +#if 0 +#define BC_PARSE_LEAF(p, rparen) \ + ((rparen) \ + || ((p) >= XC_INST_NUM && (p) <= XC_INST_SQRT) \ + || (p) == BC_INST_INC_POST \ + || (p) == BC_INST_DEC_POST \ + ) +#else +static int ok_in_expr(BcInst p) +{ + return (p >= XC_INST_NUM && p <= XC_INST_SQRT) + || p == BC_INST_INC_POST + || p == BC_INST_DEC_POST + ; +} +#define BC_PARSE_LEAF(p, rparen) ((rparen) || ok_in_expr(p)) +#endif + static BC_STATUS zbc_parse_minus(BcParse *p, BcInst *prev, size_t ops_bgn, bool rparen, size_t *nexprs) { @@ -4057,10 +4071,7 @@ static BC_STATUS zbc_parse_minus(BcParse *p, BcInst *prev, size_t ops_bgn, s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); - type = rparen || etype == BC_INST_INC_POST || etype == BC_INST_DEC_POST || - (etype >= XC_INST_NUM && etype <= XC_INST_SQRT) ? - XC_LEX_OP_MINUS : - XC_LEX_NEG; + type = BC_PARSE_LEAF(etype, rparen) ? XC_LEX_OP_MINUS : XC_LEX_NEG; *prev = BC_TOKEN_2_INST(type); // We can just push onto the op stack because this is the largest @@ -4723,7 +4734,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) case BC_LEX_LPAREN: if (BC_PARSE_LEAF(prev, rprn)) return bc_error_bad_expression(); - ++nparens; + nparens++; paren_expr = rprn = bin_last = false; get_token = true; bc_vec_push(&p->ops, &t); @@ -4741,7 +4752,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) dbg_lex_done("%s:%d done (returning EMPTY_EXP)", __func__, __LINE__); return BC_STATUS_PARSE_EMPTY_EXP; } - --nparens; + nparens--; paren_expr = rprn = true; get_token = bin_last = false; s = zbc_parse_rightParen(p, ops_bgn, &nexprs); @@ -4772,7 +4783,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) bc_parse_push(p, (char) prev); paren_expr = get_token = true; rprn = bin_last = false; - ++nexprs; + nexprs++; break; case BC_LEX_KEY_LENGTH: case BC_LEX_KEY_SQRT: @@ -4781,16 +4792,15 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) s = zbc_parse_builtin(p, t, flags, &prev); paren_expr = true; rprn = get_token = bin_last = false; - ++nexprs; + nexprs++; break; case BC_LEX_KEY_READ: if (BC_PARSE_LEAF(prev, rprn)) return bc_error_bad_expression(); - else - s = zbc_parse_read(p); + s = zbc_parse_read(p); paren_expr = true; rprn = get_token = bin_last = false; - ++nexprs; + nexprs++; prev = XC_INST_READ; break; case BC_LEX_KEY_SCALE: @@ -4799,7 +4809,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) s = zbc_parse_scale(p, &prev, flags); paren_expr = true; rprn = get_token = bin_last = false; - ++nexprs; + nexprs++; prev = XC_INST_SCALE; break; default: -- cgit v1.2.3-55-g6feb From d897c9aca6424b9a143746f73df1c132292bb091 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 24 Dec 2018 23:41:31 +0100 Subject: bc: BC_RESULT_ONE is bc-specific Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 168 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 84 insertions(+), 84 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index ee3061621..62bdd9a44 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -354,21 +354,21 @@ typedef struct BcFunc { } BcFunc; typedef enum BcResultType { - BC_RESULT_TEMP, + XC_RESULT_TEMP, - BC_RESULT_VAR, - BC_RESULT_ARRAY_ELEM, - BC_RESULT_ARRAY, + XC_RESULT_VAR, + XC_RESULT_ARRAY_ELEM, + XC_RESULT_ARRAY, - BC_RESULT_STR, + XC_RESULT_STR, - //code uses "inst - XC_INST_IBASE + BC_RESULT_IBASE" construct, - BC_RESULT_IBASE, // relative order should match for: XC_INST_IBASE - BC_RESULT_OBASE, // relative order should match for: XC_INST_OBASE - BC_RESULT_SCALE, // relative order should match for: XC_INST_SCALE + //code uses "inst - XC_INST_IBASE + XC_RESULT_IBASE" construct, + XC_RESULT_IBASE, // relative order should match for: XC_INST_IBASE + XC_RESULT_OBASE, // relative order should match for: XC_INST_OBASE + XC_RESULT_SCALE, // relative order should match for: XC_INST_SCALE IF_BC(BC_RESULT_LAST,) // relative order should match for: BC_INST_LAST - BC_RESULT_CONSTANT, - BC_RESULT_ONE, + XC_RESULT_CONSTANT, + IF_BC(BC_RESULT_ONE,) } BcResultType; typedef union BcResultData { @@ -780,7 +780,7 @@ typedef struct BcProgram { #define BC_PROG_STR(n) (!(n)->num && !(n)->cap) #define BC_PROG_NUM(r, n) \ - ((r)->t != BC_RESULT_ARRAY && (r)->t != BC_RESULT_STR && !BC_PROG_STR(n)) + ((r)->t != XC_RESULT_ARRAY && (r)->t != XC_RESULT_STR && !BC_PROG_STR(n)) #define BC_FLAG_W (1 << 0) #define BC_FLAG_V (1 << 1) @@ -2451,22 +2451,22 @@ static void dc_result_copy(BcResult *d, BcResult *src) d->t = src->t; switch (d->t) { - case BC_RESULT_TEMP: - case BC_RESULT_IBASE: - case BC_RESULT_SCALE: - case BC_RESULT_OBASE: + case XC_RESULT_TEMP: + case XC_RESULT_IBASE: + case XC_RESULT_SCALE: + case XC_RESULT_OBASE: bc_num_init(&d->d.n, src->d.n.len); bc_num_copy(&d->d.n, &src->d.n); break; - case BC_RESULT_VAR: - case BC_RESULT_ARRAY: - case BC_RESULT_ARRAY_ELEM: + case XC_RESULT_VAR: + case XC_RESULT_ARRAY: + case XC_RESULT_ARRAY_ELEM: d->d.id.name = xstrdup(src->d.id.name); break; - case BC_RESULT_CONSTANT: + case XC_RESULT_CONSTANT: IF_BC(case BC_RESULT_LAST:) - case BC_RESULT_ONE: - case BC_RESULT_STR: + IF_BC(case BC_RESULT_ONE:) + case XC_RESULT_STR: memcpy(&d->d.n, &src->d.n, sizeof(BcNum)); break; } @@ -2478,15 +2478,15 @@ static FAST_FUNC void bc_result_free(void *result) BcResult *r = (BcResult *) result; switch (r->t) { - case BC_RESULT_TEMP: - case BC_RESULT_IBASE: - case BC_RESULT_SCALE: - case BC_RESULT_OBASE: + case XC_RESULT_TEMP: + case XC_RESULT_IBASE: + case XC_RESULT_SCALE: + case XC_RESULT_OBASE: bc_num_free(&r->d.n); break; - case BC_RESULT_VAR: - case BC_RESULT_ARRAY: - case BC_RESULT_ARRAY_ELEM: + case XC_RESULT_VAR: + case XC_RESULT_ARRAY: + case XC_RESULT_ARRAY_ELEM: free(r->d.id.name); break; default: @@ -5086,14 +5086,14 @@ static BcVec* bc_program_search(char *id, bool var) static BC_STATUS zbc_program_num(BcResult *r, BcNum **num, bool hex) { switch (r->t) { - case BC_RESULT_STR: - case BC_RESULT_TEMP: - case BC_RESULT_IBASE: - case BC_RESULT_SCALE: - case BC_RESULT_OBASE: + case XC_RESULT_STR: + case XC_RESULT_TEMP: + case XC_RESULT_IBASE: + case XC_RESULT_SCALE: + case XC_RESULT_OBASE: *num = &r->d.n; break; - case BC_RESULT_CONSTANT: { + case XC_RESULT_CONSTANT: { BcStatus s; char *str; unsigned base_t; @@ -5112,17 +5112,17 @@ static BC_STATUS zbc_program_num(BcResult *r, BcNum **num, bool hex) RETURN_STATUS(s); } *num = &r->d.n; - r->t = BC_RESULT_TEMP; + r->t = XC_RESULT_TEMP; break; } - case BC_RESULT_VAR: - case BC_RESULT_ARRAY: - case BC_RESULT_ARRAY_ELEM: { + case XC_RESULT_VAR: + case XC_RESULT_ARRAY: + case XC_RESULT_ARRAY_ELEM: { BcVec *v; - v = bc_program_search(r->d.id.name, r->t == BC_RESULT_VAR); + v = bc_program_search(r->d.id.name, r->t == XC_RESULT_VAR); - if (r->t == BC_RESULT_ARRAY_ELEM) { + if (r->t == XC_RESULT_ARRAY_ELEM) { v = bc_vec_top(v); if (v->len <= r->d.id.idx) bc_array_expand(v, r->d.id.idx + 1); *num = bc_vec_item(v, r->d.id.idx); @@ -5164,7 +5164,7 @@ static BC_STATUS zbc_program_binOpPrep(BcResult **l, BcNum **ln, lt = (*l)->t; rt = (*r)->t; - hex = assign && (lt == BC_RESULT_IBASE || lt == BC_RESULT_OBASE); + hex = assign && (lt == XC_RESULT_IBASE || lt == XC_RESULT_OBASE); s = zbc_program_num(*l, ln, false); if (s) RETURN_STATUS(s); @@ -5173,12 +5173,12 @@ static BC_STATUS zbc_program_binOpPrep(BcResult **l, BcNum **ln, // We run this again under these conditions in case any vector has been // reallocated out from under the BcNums or arrays we had. - if (lt == rt && (lt == BC_RESULT_VAR || lt == BC_RESULT_ARRAY_ELEM)) { + if (lt == rt && (lt == XC_RESULT_VAR || lt == XC_RESULT_ARRAY_ELEM)) { s = zbc_program_num(*l, ln, false); if (s) RETURN_STATUS(s); } - if (!BC_PROG_NUM((*l), (*ln)) && (!assign || (*l)->t != BC_RESULT_VAR)) + if (!BC_PROG_NUM((*l), (*ln)) && (!assign || (*l)->t != XC_RESULT_VAR)) RETURN_STATUS(bc_error_variable_is_wrong_type()); if (!assign && !BC_PROG_NUM((*r), (*ln))) RETURN_STATUS(bc_error_variable_is_wrong_type()); @@ -5189,7 +5189,7 @@ static BC_STATUS zbc_program_binOpPrep(BcResult **l, BcNum **ln, static void bc_program_binOpRetire(BcResult *r) { - r->t = BC_RESULT_TEMP; + r->t = XC_RESULT_TEMP; bc_vec_pop(&G.prog.results); bc_result_pop_and_push(r); } @@ -5599,7 +5599,7 @@ static BC_STATUS zbc_program_print(char inst, size_t idx) } else { char *str; - idx = (r->t == BC_RESULT_STR) ? r->d.id.idx : num->rdx; + idx = (r->t == XC_RESULT_STR) ? r->d.id.idx : num->rdx; str = *bc_program_str(idx); if (inst == XC_INST_PRINT_STR) { @@ -5635,7 +5635,7 @@ static BC_STATUS zbc_program_negate(void) bc_num_copy(&res.d.n, num); if (res.d.n.len) res.d.n.neg = !res.d.n.neg; - bc_program_retire(&res, BC_RESULT_TEMP); + bc_program_retire(&res, XC_RESULT_TEMP); RETURN_STATUS(s); } @@ -5698,7 +5698,7 @@ static BC_STATUS zdc_program_assignStr(BcResult *r, BcVec *v, bool push) memset(&n2, 0, sizeof(BcNum)); n2.rdx = res.d.id.idx = r->d.id.idx; - res.t = BC_RESULT_STR; + res.t = XC_RESULT_STR; if (!push) { if (!STACK_HAS_MORE_THAN(&G.prog.results, 1)) @@ -5726,14 +5726,14 @@ static BC_STATUS zbc_program_copyToVar(char *name, bool var) RETURN_STATUS(bc_error_stack_has_too_few_elements()); ptr = bc_vec_top(&G.prog.results); - if ((ptr->t == BC_RESULT_ARRAY) != !var) + if ((ptr->t == XC_RESULT_ARRAY) != !var) RETURN_STATUS(bc_error_variable_is_wrong_type()); v = bc_program_search(name, var); #if ENABLE_DC - if (ptr->t == BC_RESULT_STR && !var) + if (ptr->t == XC_RESULT_STR && !var) RETURN_STATUS(bc_error_variable_is_wrong_type()); - if (ptr->t == BC_RESULT_STR) + if (ptr->t == XC_RESULT_STR) RETURN_STATUS(zdc_program_assignStr(ptr, v, true)); #endif @@ -5769,14 +5769,14 @@ static BC_STATUS zbc_program_assign(char inst) s = zbc_program_binOpPrep(&left, &l, &right, &r, assign); if (s) RETURN_STATUS(s); - ib = left->t == BC_RESULT_IBASE; - sc = left->t == BC_RESULT_SCALE; + ib = left->t == XC_RESULT_IBASE; + sc = left->t == XC_RESULT_SCALE; #if ENABLE_DC - if (right->t == BC_RESULT_STR) { + if (right->t == XC_RESULT_STR) { BcVec *v; - if (left->t != BC_RESULT_VAR) + if (left->t != XC_RESULT_VAR) RETURN_STATUS(bc_error_variable_is_wrong_type()); v = bc_program_search(left->d.id.name, true); @@ -5784,7 +5784,7 @@ static BC_STATUS zbc_program_assign(char inst) } #endif - if (left->t == BC_RESULT_CONSTANT || left->t == BC_RESULT_TEMP) + if (left->t == XC_RESULT_CONSTANT || left->t == XC_RESULT_TEMP) RETURN_STATUS(bc_error("bad assignment:" " left side must be variable" " or array element" @@ -5805,11 +5805,11 @@ static BC_STATUS zbc_program_assign(char inst) bc_num_copy(l, r); #endif - if (ib || sc || left->t == BC_RESULT_OBASE) { + if (ib || sc || left->t == XC_RESULT_OBASE) { static const char *const msg[] = { - "bad ibase; must be [2,16]", //BC_RESULT_IBASE - "bad obase; must be [2,"BC_MAX_OBASE_STR"]", //BC_RESULT_OBASE - "bad scale; must be [0,"BC_MAX_SCALE_STR"]", //BC_RESULT_SCALE + "bad ibase; must be [2,16]", //XC_RESULT_IBASE + "bad obase; must be [2,"BC_MAX_OBASE_STR"]", //XC_RESULT_OBASE + "bad scale; must be [0,"BC_MAX_SCALE_STR"]", //XC_RESULT_SCALE }; size_t *ptr; size_t max; @@ -5817,7 +5817,7 @@ static BC_STATUS zbc_program_assign(char inst) s = zbc_num_ulong(l, &val); if (s) RETURN_STATUS(s); - s = left->t - BC_RESULT_IBASE; + s = left->t - XC_RESULT_IBASE; if (sc) { max = BC_MAX_SCALE; ptr = &G.prog.scale; @@ -5854,7 +5854,7 @@ static BC_STATUS bc_program_pushVar(char *code, size_t *bgn, BcResult r; char *name = bc_program_name(code, bgn); - r.t = BC_RESULT_VAR; + r.t = XC_RESULT_VAR; r.d.id.name = name; #if ENABLE_DC @@ -5868,11 +5868,11 @@ static BC_STATUS bc_program_pushVar(char *code, size_t *bgn, } if (!BC_PROG_STR(num)) { - r.t = BC_RESULT_TEMP; + r.t = XC_RESULT_TEMP; bc_num_init_DEF_SIZE(&r.d.n); bc_num_copy(&r.d.n, num); } else { - r.t = BC_RESULT_STR; + r.t = XC_RESULT_STR; r.d.id.idx = num->rdx; } @@ -5895,7 +5895,7 @@ static BC_STATUS zbc_program_pushArray(char *code, size_t *bgn, char inst) r.d.id.name = bc_program_name(code, bgn); if (inst == XC_INST_ARRAY) { - r.t = BC_RESULT_ARRAY; + r.t = XC_RESULT_ARRAY; bc_vec_push(&G.prog.results, &r); } else { BcResult *operand; @@ -5912,7 +5912,7 @@ static BC_STATUS zbc_program_pushArray(char *code, size_t *bgn, char inst) } r.d.id.idx = (size_t) temp; - bc_program_retire(&r, BC_RESULT_ARRAY_ELEM); + bc_program_retire(&r, XC_RESULT_ARRAY_ELEM); } err: if (s) free(r.d.id.name); @@ -5932,7 +5932,7 @@ static BC_STATUS zbc_program_incdec(char inst) if (s) RETURN_STATUS(s); if (inst == BC_INST_INC_POST || inst == BC_INST_DEC_POST) { - copy.t = BC_RESULT_TEMP; + copy.t = XC_RESULT_TEMP; bc_num_init(©.d.n, num->len); bc_num_copy(©.d.n, num); } @@ -5981,7 +5981,7 @@ static BC_STATUS zbc_program_call(char *code, size_t *idx) a = bc_vec_item(&func->autos, nparams - 1 - i); arg = bc_vec_top(&G.prog.results); - if ((!a->idx) != (arg->t == BC_RESULT_ARRAY) || arg->t == BC_RESULT_STR) + if ((!a->idx) != (arg->t == XC_RESULT_ARRAY) || arg->t == XC_RESULT_STR) RETURN_STATUS(bc_error_variable_is_wrong_type()); s = zbc_program_copyToVar(a->name, a->idx); @@ -6022,7 +6022,7 @@ static BC_STATUS zbc_program_return(char inst) RETURN_STATUS(bc_error_stack_has_too_few_elements()); f = bc_program_func(ip->func); - res.t = BC_RESULT_TEMP; + res.t = XC_RESULT_TEMP; if (inst == XC_INST_RET) { BcStatus s; @@ -6098,14 +6098,14 @@ static BC_STATUS zbc_program_builtin(char inst) if (inst == XC_INST_SQRT) s = zbc_num_sqrt(num, &res.d.n, G.prog.scale); #if ENABLE_BC - else if (len != 0 && opnd->t == BC_RESULT_ARRAY) { + else if (len != 0 && opnd->t == XC_RESULT_ARRAY) { bc_num_ulong2num(&res.d.n, (unsigned long) ((BcVec *) num)->len); } #endif #if ENABLE_DC else if (len != 0 && !BC_PROG_NUM(opnd, num)) { char **str; - size_t idx = opnd->t == BC_RESULT_STR ? opnd->d.id.idx : num->rdx; + size_t idx = opnd->t == XC_RESULT_STR ? opnd->d.id.idx : num->rdx; str = bc_program_str(idx); bc_num_ulong2num(&res.d.n, strlen(*str)); @@ -6115,7 +6115,7 @@ static BC_STATUS zbc_program_builtin(char inst) bc_num_ulong2num(&res.d.n, len ? bc_program_len(num) : bc_program_scale(num)); } - bc_program_retire(&res, BC_RESULT_TEMP); + bc_program_retire(&res, XC_RESULT_TEMP); RETURN_STATUS(s); } @@ -6138,7 +6138,7 @@ static BC_STATUS zdc_program_divmod(void) if (s) goto err; bc_program_binOpRetire(&res2); - res.t = BC_RESULT_TEMP; + res.t = XC_RESULT_TEMP; bc_vec_push(&G.prog.results, &res); RETURN_STATUS(s); @@ -6167,7 +6167,7 @@ static BC_STATUS zdc_program_modexp(void) RETURN_STATUS(bc_error_variable_is_wrong_type()); // Make sure that the values have their pointers updated, if necessary. - if (r1->t == BC_RESULT_VAR || r1->t == BC_RESULT_ARRAY_ELEM) { + if (r1->t == XC_RESULT_VAR || r1->t == XC_RESULT_ARRAY_ELEM) { if (r1->t == r2->t) { s = zbc_program_num(r2, &n2, false); if (s) RETURN_STATUS(s); @@ -6197,7 +6197,7 @@ static void dc_program_stackLen(void) BcResult res; size_t len = G.prog.results.len; - res.t = BC_RESULT_TEMP; + res.t = XC_RESULT_TEMP; bc_num_init_DEF_SIZE(&res.d.n); bc_num_ulong2num(&res.d.n, len); @@ -6244,7 +6244,7 @@ static BC_STATUS zdc_program_asciify(void) bc_num_free(&n); } else { char *sp; - idx = (r->t == BC_RESULT_STR) ? r->d.id.idx : num->rdx; + idx = (r->t == XC_RESULT_STR) ? r->d.id.idx : num->rdx; sp = *bc_program_str(idx); c = sp[0]; } @@ -6260,7 +6260,7 @@ static BC_STATUS zdc_program_asciify(void) //str[1] = '\0'; - already is bc_vec_push(&G.prog.strs, &str); dup: - res.t = BC_RESULT_STR; + res.t = XC_RESULT_STR; res.d.id.idx = idx; bc_result_pop_and_push(&res); @@ -6289,7 +6289,7 @@ static BC_STATUS zdc_program_printStream(void) s = zbc_num_printNum(n, 0x100, 1, dc_num_printChar); } else { char *str; - idx = (r->t == BC_RESULT_STR) ? r->d.id.idx : n->rdx; + idx = (r->t == XC_RESULT_STR) ? r->d.id.idx : n->rdx; str = *bc_program_str(idx); fputs(str, stdout); } @@ -6373,9 +6373,9 @@ static BC_STATUS zdc_program_execStr(char *code, size_t *bgn, bool cond) sidx = n->rdx; } else { - if (r->t == BC_RESULT_STR) { + if (r->t == XC_RESULT_STR) { sidx = r->d.id.idx; - } else if (r->t == BC_RESULT_VAR) { + } else if (r->t == XC_RESULT_VAR) { BcNum *n; s = zbc_program_num(r, &n, false); if (s || !BC_PROG_STR(n)) goto exit; @@ -6434,7 +6434,7 @@ static void bc_program_pushGlobal(char inst) BcResult res; unsigned long val; - res.t = inst - XC_INST_IBASE + BC_RESULT_IBASE; + res.t = inst - XC_INST_IBASE + XC_RESULT_IBASE; if (inst == XC_INST_IBASE) val = (unsigned long) G.prog.ib_t; else if (inst == XC_INST_SCALE) @@ -6550,7 +6550,7 @@ static BC_STATUS zbc_program_exec(void) break; case XC_INST_NUM: dbg_exec("XC_INST_NUM:"); - r.t = BC_RESULT_CONSTANT; + r.t = XC_RESULT_CONSTANT; r.d.id.idx = bc_program_index(code, &ip->inst_idx); bc_vec_push(&G.prog.results, &r); break; @@ -6569,7 +6569,7 @@ static BC_STATUS zbc_program_exec(void) break; case XC_INST_STR: dbg_exec("XC_INST_STR:"); - r.t = BC_RESULT_STR; + r.t = XC_RESULT_STR; r.d.id.idx = bc_program_index(code, &ip->inst_idx); bc_vec_push(&G.prog.results, &r); break; @@ -6591,7 +6591,7 @@ static BC_STATUS zbc_program_exec(void) if (bc_num_cmp(num, &G.prog.zero) == 0) bc_num_one(&r.d.n); //else bc_num_zero(&r.d.n); - already is - bc_program_retire(&r, BC_RESULT_TEMP); + bc_program_retire(&r, XC_RESULT_TEMP); break; } case XC_INST_NEG: -- cgit v1.2.3-55-g6feb From bb116031a038237ecc82896fb6b12b89b72f8d91 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 25 Dec 2018 01:16:37 +0100 Subject: bc: simplify bc_parse_expr_empty_ok() function old new delta bc_parse_expr_empty_ok 1846 1819 -27 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 62bdd9a44..5d9bae47e 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -4661,20 +4661,21 @@ static BC_STATUS zbc_parse_stmt_or_funcdef(BcParse *p) // This is not a "z" function: can also return BC_STATUS_PARSE_EMPTY_EXP static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) { - BcStatus s = BC_STATUS_SUCCESS; BcInst prev = XC_INST_PRINT; BcLexType top, t = p->l.lex; size_t nexprs = 0, ops_bgn = p->ops.len; unsigned nparens, nrelops; - bool paren_first, paren_expr, rprn, done, get_token, assign, bin_last; + bool paren_first, paren_expr, rprn, get_token, assign, bin_last; dbg_lex_enter("%s:%d entered", __func__, __LINE__); paren_first = (p->l.lex == BC_LEX_LPAREN); nparens = nrelops = 0; - paren_expr = rprn = done = get_token = assign = false; + paren_expr = rprn = get_token = assign = false; bin_last = true; - for (; !G_interrupt && !s && !done && bc_parse_exprs(t); t = p->l.lex) { + for (; bc_parse_exprs(t); t = p->l.lex) { + BcStatus s = BC_STATUS_SUCCESS; + dbg_lex("%s:%d t:%d", __func__, __LINE__, t); switch (t) { case BC_LEX_OP_INC: @@ -4743,10 +4744,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) if (bin_last || prev == XC_INST_BOOL_NOT) return bc_error_bad_expression(); if (nparens == 0) { - s = BC_STATUS_SUCCESS; - done = true; - get_token = false; - break; + goto exit_loop; } if (!paren_expr) { dbg_lex_done("%s:%d done (returning EMPTY_EXP)", __func__, __LINE__); @@ -4763,7 +4761,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) paren_expr = true; rprn = get_token = bin_last = false; s = zbc_parse_name(p, &prev, flags & ~BC_PARSE_NOCALL); - ++nexprs; + nexprs++; break; case XC_LEX_NUMBER: if (BC_PARSE_LEAF(prev, rprn)) @@ -4807,21 +4805,24 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) if (BC_PARSE_LEAF(prev, rprn)) return bc_error_bad_expression(); s = zbc_parse_scale(p, &prev, flags); + prev = XC_INST_SCALE; paren_expr = true; rprn = get_token = bin_last = false; nexprs++; - prev = XC_INST_SCALE; break; default: s = bc_error_bad_token(); break; } - if (!s && get_token) s = zbc_lex_next(&p->l); + if (s || G_interrupt) // error, or ^C: stop parsing + return BC_STATUS_FAILURE; + if (get_token) { + s = zbc_lex_next(&p->l); + if (s) return s; + } } - - if (s) return s; - if (G_interrupt) return BC_STATUS_FAILURE; // ^C: stop parsing + exit_loop: while (p->ops.len > ops_bgn) { top = BC_PARSE_TOP_OP(p); @@ -4840,20 +4841,23 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) return bc_error_bad_expression(); if (!(flags & BC_PARSE_REL) && nrelops) { + BcStatus s; s = zbc_POSIX_does_not_allow("comparison operators outside if or loops"); if (s) return s; } else if ((flags & BC_PARSE_REL) && nrelops > 1) { + BcStatus s; s = zbc_POSIX_requires("exactly one comparison operator per condition"); if (s) return s; } if (flags & BC_PARSE_PRINT) { - if (paren_first || !assign) bc_parse_push(p, XC_INST_PRINT); + if (paren_first || !assign) + bc_parse_push(p, XC_INST_PRINT); bc_parse_push(p, XC_INST_POP); } dbg_lex_done("%s:%d done", __func__, __LINE__); - return s; + return BC_STATUS_SUCCESS; } #endif // ENABLE_BC -- cgit v1.2.3-55-g6feb From d0238d83f0311cfab52897acc739148879598621 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 25 Dec 2018 01:21:16 +0100 Subject: bc: simplify bc_parse_expr_empty_ok() function old new delta bc_parse_expr_empty_ok 1819 1810 -9 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 5d9bae47e..a57de97a5 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -591,7 +591,7 @@ enum { + (EXBITS(0,1,1,0,0,0,0,0) << (7*8)) // 56: return scale sqrt while #undef EXBITS }; -static ALWAYS_INLINE long bc_parse_exprs(unsigned i) +static ALWAYS_INLINE long lex_allowed_in_bc_expr(unsigned i) { #if ULONG_MAX > 0xffffffff // 64-bit version (will not work correctly for 32-bit longs!) @@ -4662,7 +4662,6 @@ static BC_STATUS zbc_parse_stmt_or_funcdef(BcParse *p) static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) { BcInst prev = XC_INST_PRINT; - BcLexType top, t = p->l.lex; size_t nexprs = 0, ops_bgn = p->ops.len; unsigned nparens, nrelops; bool paren_first, paren_expr, rprn, get_token, assign, bin_last; @@ -4673,10 +4672,15 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) paren_expr = rprn = get_token = assign = false; bin_last = true; - for (; bc_parse_exprs(t); t = p->l.lex) { - BcStatus s = BC_STATUS_SUCCESS; + for (;;) { + BcStatus s; + BcLexType t = p->l.lex; + + if (!lex_allowed_in_bc_expr(t)) + break; dbg_lex("%s:%d t:%d", __func__, __LINE__, t); + s = BC_STATUS_SUCCESS; switch (t) { case BC_LEX_OP_INC: case BC_LEX_OP_DEC: @@ -4825,7 +4829,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) exit_loop: while (p->ops.len > ops_bgn) { - top = BC_PARSE_TOP_OP(p); + BcLexType top = BC_PARSE_TOP_OP(p); assign = (top >= BC_LEX_OP_ASSIGN_POWER && top <= BC_LEX_OP_ASSIGN); if (top == BC_LEX_LPAREN || top == BC_LEX_RPAREN) -- cgit v1.2.3-55-g6feb From 73b3ebc0e18f95d9eda7e33dfc878f9792d1b1e1 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 25 Dec 2018 01:43:52 +0100 Subject: bc: simplify bc_parse_expr_empty_ok() function old new delta bc_parse_expr_empty_ok 1810 1791 -19 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 52 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index a57de97a5..2b370888c 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -4664,15 +4664,16 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) BcInst prev = XC_INST_PRINT; size_t nexprs = 0, ops_bgn = p->ops.len; unsigned nparens, nrelops; - bool paren_first, paren_expr, rprn, get_token, assign, bin_last; + bool paren_first, paren_expr, rprn, assign, bin_last; dbg_lex_enter("%s:%d entered", __func__, __LINE__); paren_first = (p->l.lex == BC_LEX_LPAREN); nparens = nrelops = 0; - paren_expr = rprn = get_token = assign = false; + paren_expr = rprn = assign = false; bin_last = true; for (;;) { + bool get_token; BcStatus s; BcLexType t = p->l.lex; @@ -4680,16 +4681,19 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) break; dbg_lex("%s:%d t:%d", __func__, __LINE__, t); + get_token = false; s = BC_STATUS_SUCCESS; switch (t) { case BC_LEX_OP_INC: case BC_LEX_OP_DEC: s = zbc_parse_incdec(p, &prev, &paren_expr, &nexprs, flags); - rprn = get_token = bin_last = false; + rprn = bin_last = false; + //get_token = false; - already is break; case XC_LEX_OP_MINUS: s = zbc_parse_minus(p, &prev, ops_bgn, rprn, &nexprs); - rprn = get_token = false; + rprn = false; + //get_token = false; - already is bin_last = (prev == XC_INST_MINUS); break; case BC_LEX_OP_ASSIGN_POWER: @@ -4733,16 +4737,18 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) prev = BC_TOKEN_2_INST(t); bc_parse_operator(p, t, ops_bgn, &nexprs); s = zbc_lex_next(&p->l); - rprn = get_token = false; + rprn = false; + //get_token = false; - already is bin_last = (t != BC_LEX_OP_BOOL_NOT); break; case BC_LEX_LPAREN: if (BC_PARSE_LEAF(prev, rprn)) return bc_error_bad_expression(); + bc_vec_push(&p->ops, &t); nparens++; - paren_expr = rprn = bin_last = false; get_token = true; - bc_vec_push(&p->ops, &t); + paren_expr = false; + rprn = bin_last = false; break; case BC_LEX_RPAREN: if (bin_last || prev == XC_INST_BOOL_NOT) @@ -4754,27 +4760,30 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) dbg_lex_done("%s:%d done (returning EMPTY_EXP)", __func__, __LINE__); return BC_STATUS_PARSE_EMPTY_EXP; } + s = zbc_parse_rightParen(p, ops_bgn, &nexprs); nparens--; paren_expr = rprn = true; - get_token = bin_last = false; - s = zbc_parse_rightParen(p, ops_bgn, &nexprs); + bin_last = false; + //get_token = false; - already is break; case XC_LEX_NAME: if (BC_PARSE_LEAF(prev, rprn)) return bc_error_bad_expression(); - paren_expr = true; - rprn = get_token = bin_last = false; s = zbc_parse_name(p, &prev, flags & ~BC_PARSE_NOCALL); + paren_expr = true; + rprn = bin_last = false; + //get_token = false; - already is nexprs++; break; case XC_LEX_NUMBER: if (BC_PARSE_LEAF(prev, rprn)) return bc_error_bad_expression(); bc_parse_pushNUM(p); - nexprs++; prev = XC_INST_NUM; - paren_expr = get_token = true; + get_token = true; + paren_expr = true; rprn = bin_last = false; + nexprs++; break; case BC_LEX_KEY_IBASE: case BC_LEX_KEY_LAST: @@ -4783,7 +4792,8 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) return bc_error_bad_expression(); prev = (char) (t - BC_LEX_KEY_IBASE + XC_INST_IBASE); bc_parse_push(p, (char) prev); - paren_expr = get_token = true; + get_token = true; + paren_expr = true; rprn = bin_last = false; nexprs++; break; @@ -4793,17 +4803,19 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) return bc_error_bad_expression(); s = zbc_parse_builtin(p, t, flags, &prev); paren_expr = true; - rprn = get_token = bin_last = false; + rprn = bin_last = false; + //get_token = false; - already is nexprs++; break; case BC_LEX_KEY_READ: if (BC_PARSE_LEAF(prev, rprn)) return bc_error_bad_expression(); s = zbc_parse_read(p); + prev = XC_INST_READ; paren_expr = true; - rprn = get_token = bin_last = false; + rprn = bin_last = false; + //get_token = false; - already is nexprs++; - prev = XC_INST_READ; break; case BC_LEX_KEY_SCALE: if (BC_PARSE_LEAF(prev, rprn)) @@ -4811,12 +4823,12 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) s = zbc_parse_scale(p, &prev, flags); prev = XC_INST_SCALE; paren_expr = true; - rprn = get_token = bin_last = false; + rprn = bin_last = false; + //get_token = false; - already is nexprs++; break; default: - s = bc_error_bad_token(); - break; + return bc_error_bad_token(); } if (s || G_interrupt) // error, or ^C: stop parsing -- cgit v1.2.3-55-g6feb From d4b721cc8b708a2fa4ddd821179c00865c11619e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 25 Dec 2018 16:39:01 +0100 Subject: bc: shrink parsing code a bit more, disallow "auto a b c" (without commas) function old new delta bc_parse_expr_empty_ok 1791 1785 -6 zbc_parse_stmt_possibly_auto 1675 1599 -76 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-82) Total: -82 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 46 ++++++++++++++++++++++------------------------ 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 2b370888c..ec2f86133 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -3788,7 +3788,7 @@ static BC_STATUS zbc_parse_rightParen(BcParse *p, size_t ops_bgn, size_t *nexs) bc_vec_pop(&p->ops); - RETURN_STATUS(zbc_lex_next(&p->l)); + RETURN_STATUS(BC_STATUS_SUCCESS); } #define zbc_parse_rightParen(...) (zbc_parse_rightParen(__VA_ARGS__) COMMA_SUCCESS) @@ -4470,53 +4470,52 @@ static BC_STATUS zbc_parse_funcdef(BcParse *p) static BC_STATUS zbc_parse_auto(BcParse *p) { BcStatus s; - bool comma, var, one; char *name; dbg_lex_enter("%s:%d entered", __func__, __LINE__); s = zbc_lex_next(&p->l); if (s) RETURN_STATUS(s); - comma = false; - one = p->l.lex == XC_LEX_NAME; + for (;;) { + bool var; + + if (p->l.lex != XC_LEX_NAME) + RETURN_STATUS(bc_error("bad 'auto' syntax")); - while (p->l.lex == XC_LEX_NAME) { name = xstrdup(p->l.lex_buf.v); s = zbc_lex_next(&p->l); if (s) goto err; - var = p->l.lex != BC_LEX_LBRACKET; + var = (p->l.lex != BC_LEX_LBRACKET); if (!var) { s = zbc_lex_next(&p->l); if (s) goto err; if (p->l.lex != BC_LEX_RBRACKET) { - s = bc_error("bad function definition"); + s = bc_error("bad 'auto' syntax"); goto err; } - - s = zbc_lex_next(&p->l); - if (s) goto err; - } - - comma = p->l.lex == BC_LEX_COMMA; - if (comma) { s = zbc_lex_next(&p->l); if (s) goto err; } s = zbc_func_insert(p->func, name, var); if (s) goto err; - } - - if (comma) RETURN_STATUS(bc_error("bad function definition")); - if (!one) RETURN_STATUS(bc_error("no auto variable found")); - if (p->l.lex != XC_LEX_NLINE && p->l.lex != BC_LEX_SCOLON) - RETURN_STATUS(bc_error_bad_token()); + if (p->l.lex == XC_LEX_NLINE + || p->l.lex == BC_LEX_SCOLON + //|| p->l.lex == BC_LEX_RBRACE // allow "define f() {auto a}" + ) { + break; + } + if (p->l.lex != BC_LEX_COMMA) + RETURN_STATUS(bc_error("bad 'auto' syntax")); + s = zbc_lex_next(&p->l); // skip comma + if (s) RETURN_STATUS(s); + } dbg_lex_done("%s:%d done", __func__, __LINE__); - RETURN_STATUS(zbc_lex_next(&p->l)); + RETURN_STATUS(BC_STATUS_SUCCESS); err: free(name); dbg_lex_done("%s:%d done (ERROR)", __func__, __LINE__); @@ -4707,11 +4706,10 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) && prev != XC_INST_SCALE && prev != XC_INST_IBASE && prev != XC_INST_OBASE && prev != BC_INST_LAST ) { - s = bc_error("bad assignment:" + return bc_error("bad assignment:" " left side must be variable" " or array element" ); // note: shared string - break; } // Fallthrough. case XC_LEX_OP_POWER: @@ -4762,9 +4760,9 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) } s = zbc_parse_rightParen(p, ops_bgn, &nexprs); nparens--; + get_token = true; paren_expr = rprn = true; bin_last = false; - //get_token = false; - already is break; case XC_LEX_NAME: if (BC_PARSE_LEAF(prev, rprn)) -- cgit v1.2.3-55-g6feb From 5fa74b9efc538b55ec164ce3886eeea782016487 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 25 Dec 2018 17:07:51 +0100 Subject: bc: allow {break} and {continue} (allow RBRACE to terminate them) function old new delta zbc_parse_stmt_possibly_auto 1599 1560 -39 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 18 +++++------------- testsuite/bc.tests | 7 ++++++- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index ec2f86133..7c8edcf33 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -3927,7 +3927,7 @@ static BC_STATUS zbc_parse_read(BcParse *p) bc_parse_push(p, XC_INST_READ); - RETURN_STATUS(zbc_lex_next(&p->l)); + RETURN_STATUS(s); } #define zbc_parse_read(...) (zbc_parse_read(__VA_ARGS__) COMMA_SUCCESS) @@ -3953,7 +3953,7 @@ static BC_STATUS zbc_parse_builtin(BcParse *p, BcLexType type, uint8_t flags, *prev = (type == BC_LEX_KEY_LENGTH) ? XC_INST_LENGTH : XC_INST_SQRT; bc_parse_push(p, *prev); - RETURN_STATUS(zbc_lex_next(&p->l)); + RETURN_STATUS(s); } #define zbc_parse_builtin(...) (zbc_parse_builtin(__VA_ARGS__) COMMA_SUCCESS) @@ -4328,7 +4328,6 @@ static BC_STATUS zbc_parse_for(BcParse *p) static BC_STATUS zbc_parse_break_or_continue(BcParse *p, BcLexType type) { - BcStatus s; size_t i; if (type == BC_LEX_KEY_BREAK) { @@ -4338,15 +4337,8 @@ static BC_STATUS zbc_parse_break_or_continue(BcParse *p, BcLexType type) } else { i = *(size_t*)bc_vec_top(&p->conds); } - bc_parse_pushJUMP(p, i); - s = zbc_lex_next(&p->l); - if (s) RETURN_STATUS(s); - - if (p->l.lex != BC_LEX_SCOLON && p->l.lex != XC_LEX_NLINE) - RETURN_STATUS(bc_error_bad_token()); - RETURN_STATUS(zbc_lex_next(&p->l)); } #define zbc_parse_break_or_continue(...) (zbc_parse_break_or_continue(__VA_ARGS__) COMMA_SUCCESS) @@ -4800,9 +4792,9 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) if (BC_PARSE_LEAF(prev, rprn)) return bc_error_bad_expression(); s = zbc_parse_builtin(p, t, flags, &prev); + get_token = true; paren_expr = true; rprn = bin_last = false; - //get_token = false; - already is nexprs++; break; case BC_LEX_KEY_READ: @@ -4810,9 +4802,9 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) return bc_error_bad_expression(); s = zbc_parse_read(p); prev = XC_INST_READ; + get_token = true; paren_expr = true; rprn = bin_last = false; - //get_token = false; - already is nexprs++; break; case BC_LEX_KEY_SCALE: @@ -4820,9 +4812,9 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) return bc_error_bad_expression(); s = zbc_parse_scale(p, &prev, flags); prev = XC_INST_SCALE; + //get_token = false; - already is paren_expr = true; rprn = bin_last = false; - //get_token = false; - already is nexprs++; break; default: diff --git a/testsuite/bc.tests b/testsuite/bc.tests index c84a2987c..42fe83013 100755 --- a/testsuite/bc.tests +++ b/testsuite/bc.tests @@ -66,7 +66,7 @@ testing "bc if 0 else if 1" \ "2\n9\n" \ "" "if (0) 1 else if (1) 2; 9" -testing "bc for(;;)" \ +testing "bc for (;;)" \ "bc" \ "2\n3\n2\n9\n" \ "" "i=2; for (;;) { 2; if(--i==0) break; 3; }; 9" @@ -86,6 +86,11 @@ testing "bc for (init;cond;upd)" \ "1\n2\n3\n9\n" \ "" "for(i=1;i<4;i++)i; 9" +testing "bc for (;;) {break}" \ + "bc" \ + "2\n9\n" \ + "" "for (;;) {2;break}; 9" + testing "bc define auto" \ "bc" \ "8\n9\n" \ -- cgit v1.2.3-55-g6feb From 2638454464b944f9c407326257851bab13c045ec Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 25 Dec 2018 18:37:52 +0100 Subject: bc: add code to detect errors like "print 1 print 2" function old new delta zbc_vm_process 831 925 +94 zbc_program_exec 3964 3976 +12 zdc_program_execStr 506 512 +6 zbc_lex_next 2161 2167 +6 zbc_program_assign 419 424 +5 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 5/0 up/down: 123/0) Total: 123 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 49 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 7c8edcf33..8b44d4425 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -711,6 +711,7 @@ dc_LEX_to_INST[] = { // starts at XC_LEX_OP_POWER // corresponding XC/DC_L typedef struct BcLex { const char *buf; + const char *lex_next_at; // last lex_next() was called at this string size_t i; size_t line; size_t len; @@ -2990,9 +2991,11 @@ static BC_STATUS zbc_lex_next(BcLex *l) } // here it's guaranteed that l->i is below l->len } + l->lex_next_at = l->buf + l->i; dbg_lex("next string to parse:'%.*s'", - (int)(strchrnul(l->buf + l->i, '\n') - (l->buf + l->i)), - l->buf + l->i); + (int)(strchrnul(l->lex_next_at, '\n') - l->lex_next_at), + l->lex_next_at + ); if (IS_BC) { IF_BC(s = zbc_lex_token(l)); } else { @@ -6756,13 +6759,38 @@ static BC_STATUS zbc_vm_process(const char *text) dbg_lex("%s:%d G.prs.l.lex:%d, parsing...", __func__, __LINE__, G.prs.l.lex); if (IS_BC) { -// FIXME: "eating" of stmt delimiters is coded inconsistently -// (sometimes zbc_parse_stmt() eats the delimiter, sometimes don't), -// which causes bugs such as "print 1 print 2" erroneously accepted, -// or "print 1 else 2" detecting parse error only after executing -// "print 1" part. - IF_BC(s = zbc_parse_stmt_or_funcdef(&G.prs)); +#if ENABLE_BC + s = zbc_parse_stmt_or_funcdef(&G.prs); + if (s) goto err; + + // Check that next token is not bogus, and skip over + // stmt delimiter(s) - newlines and semicolons + s = 1; // s == 1 on first iteration only + for (;;) { + if (G.prs.l.lex == XC_LEX_EOF) + goto execute; // this goto avoids resetting 's' to zero + if (G.prs.l.lex != BC_LEX_SCOLON + && G.prs.l.lex != XC_LEX_NLINE + ) { + const char *err_at; + // Not newline and not semicolon + if (s == 0) // saw at least one NL/semicolon before it? + break; // yes, good +//TODO: commolalize for other parse errors: + err_at = G.prs.l.lex_next_at ? G.prs.l.lex_next_at : "UNKNOWN"; + bc_error_fmt("bad statement terminator at '%.*s'", + (int)(strchrnul(err_at, '\n') - err_at), + err_at + ); + goto err; + } + // NL or semicolon: skip it, set s = 0, repeat + s = zbc_lex_next(&G.prs.l); + if (s) goto err; + } +#endif } else { +#if ENABLE_DC // Most of dc parsing assumes all whitespace, // including '\n', is eaten. while (G.prs.l.lex == XC_LEX_NLINE) { @@ -6771,14 +6799,15 @@ static BC_STATUS zbc_vm_process(const char *text) if (G.prs.l.lex == XC_LEX_EOF) goto done; } - IF_DC(s = zdc_parse_expr(&G.prs)); + s = zdc_parse_expr(&G.prs); +#endif } if (s || G_interrupt) { err: bc_parse_reset(&G.prs); // includes bc_program_reset() RETURN_STATUS(BC_STATUS_FAILURE); } - + IF_BC(execute:) dbg_lex("%s:%d executing...", __func__, __LINE__); s = zbc_program_exec(); if (s) { -- cgit v1.2.3-55-g6feb From 53e569c06b12ef2cb9ef2ceeff92f04cfbf113e3 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 25 Dec 2018 19:37:23 +0100 Subject: bc: fix interactive read() Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 51 ++++++++++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 8b44d4425..79f981eaf 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -6753,6 +6753,7 @@ static BC_STATUS zbc_vm_process(const char *text) s = zbc_parse_text_init(&G.prs, text); // does the first zbc_lex_next() if (s) RETURN_STATUS(s); + IF_BC(check_eof:) while (G.prs.l.lex != XC_LEX_EOF) { BcInstPtr *ip; BcFunc *f; @@ -6760,34 +6761,34 @@ static BC_STATUS zbc_vm_process(const char *text) dbg_lex("%s:%d G.prs.l.lex:%d, parsing...", __func__, __LINE__, G.prs.l.lex); if (IS_BC) { #if ENABLE_BC + if (G.prs.l.lex == BC_LEX_SCOLON + || G.prs.l.lex == XC_LEX_NLINE + ) { + s = zbc_lex_next(&G.prs.l); + if (s) goto err; + goto check_eof; + } + s = zbc_parse_stmt_or_funcdef(&G.prs); if (s) goto err; - // Check that next token is not bogus, and skip over - // stmt delimiter(s) - newlines and semicolons - s = 1; // s == 1 on first iteration only - for (;;) { - if (G.prs.l.lex == XC_LEX_EOF) - goto execute; // this goto avoids resetting 's' to zero - if (G.prs.l.lex != BC_LEX_SCOLON - && G.prs.l.lex != XC_LEX_NLINE - ) { - const char *err_at; - // Not newline and not semicolon - if (s == 0) // saw at least one NL/semicolon before it? - break; // yes, good -//TODO: commolalize for other parse errors: - err_at = G.prs.l.lex_next_at ? G.prs.l.lex_next_at : "UNKNOWN"; - bc_error_fmt("bad statement terminator at '%.*s'", - (int)(strchrnul(err_at, '\n') - err_at), - err_at - ); - goto err; - } - // NL or semicolon: skip it, set s = 0, repeat - s = zbc_lex_next(&G.prs.l); - if (s) goto err; + // Check that next token is a correct stmt delimiter - + // disallows "print 1 print 2" and such. + if (G.prs.l.lex != BC_LEX_SCOLON + && G.prs.l.lex != XC_LEX_NLINE + && G.prs.l.lex != XC_LEX_EOF + ) { + const char *err_at; +//TODO: commonalize for other parse errors: + err_at = G.prs.l.lex_next_at ? G.prs.l.lex_next_at : "UNKNOWN"; + bc_error_fmt("bad statement terminator at '%.*s'", + (int)(strchrnul(err_at, '\n') - err_at), + err_at + ); + goto err; } + // The above logic is fragile. Check these examples: + // - interative read() still works #endif } else { #if ENABLE_DC @@ -6807,7 +6808,7 @@ static BC_STATUS zbc_vm_process(const char *text) bc_parse_reset(&G.prs); // includes bc_program_reset() RETURN_STATUS(BC_STATUS_FAILURE); } - IF_BC(execute:) + dbg_lex("%s:%d executing...", __func__, __LINE__); s = zbc_program_exec(); if (s) { -- cgit v1.2.3-55-g6feb From 1fbe35a7d8579d53df0f4f70b31ba8b272099b7c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 25 Dec 2018 19:38:13 +0100 Subject: bc: make zbc_program_read() and zdc_program_execStr() use G.prs function old new delta zbc_program_print 656 683 +27 zbc_program_exec 3976 4003 +27 zdc_program_execStr 512 524 +12 bc_num_printNewline 45 54 +9 bc_num_printHex 61 67 +6 bc_num_printDigits 131 137 +6 dc_num_printChar 21 24 +3 bc_vm_init 675 678 +3 zbc_program_assign 424 426 +2 bc_read_line 410 407 -3 bc_verror_msg 99 93 -6 zbc_lex_next 2167 2158 -9 zbc_vm_execute_FILE 67 55 -12 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 9/4 up/down: 95/-30) Total: 65 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 87 +++++++++++++++++++++++++++------------------------------- 1 file changed, 41 insertions(+), 46 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 79f981eaf..0fdb2963c 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -737,6 +737,9 @@ typedef struct BcParse { IF_BC(BcVec conds;) IF_BC(BcVec ops;) + const char *filename; + FILE *input_fp; + BcFunc *func; size_t fidx; @@ -766,8 +769,6 @@ typedef struct BcProgram { IF_DC(BcVec strs;) IF_DC(BcVec consts;) - const char *file; - BcNum zero; IF_BC(BcNum one;) IF_BC(BcNum last;) @@ -841,7 +842,6 @@ struct globals { BcVec files; BcVec input_buffer; - FILE *input_fp; char *env_args; @@ -936,12 +936,12 @@ static void quit(void) static void bc_verror_msg(const char *fmt, va_list p) { const char *sv = sv; // for compiler - if (G.prog.file) { + if (G.prs.filename) { sv = applet_name; - applet_name = xasprintf("%s: %s:%u", applet_name, G.prog.file, G.err_line); + applet_name = xasprintf("%s: %s:%u", applet_name, G.prs.filename, G.err_line); } bb_verror_msg(fmt, p, NULL); - if (G.prog.file) { + if (G.prs.filename) { free((char*)applet_name); applet_name = sv; } @@ -2581,12 +2581,12 @@ static void bc_read_line(BcVec *vec, FILE *fp) if (bad_chars) { // Bad chars on this line - if (!G.prog.file) { // stdin + if (!G.prs.filename) { // stdin // ignore entire line, get another one vec->len = len; goto again; } - bb_perror_msg_and_die("file '%s' is not text", G.prog.file); + bb_perror_msg_and_die("file '%s' is not text", G.prs.filename); } bc_vec_pushZeroByte(vec); } @@ -2905,7 +2905,7 @@ static bool bc_lex_more_input(BcLex *l) size_t prevlen = G.input_buffer.len; char *string; - bc_read_line(&G.input_buffer, G.input_fp); + bc_read_line(&G.input_buffer, G.prs.input_fp); // No more input means EOF if (G.input_buffer.len <= prevlen + 1) // (we expect +1 for NUL byte) break; @@ -2983,10 +2983,10 @@ static BC_STATUS zbc_lex_next(BcLex *l) do { if (l->i == l->len) { l->lex = XC_LEX_EOF; - if (!G.input_fp) + if (!G.prs.input_fp) RETURN_STATUS(BC_STATUS_SUCCESS); if (!bc_lex_more_input(l)) { - G.input_fp = NULL; + G.prs.input_fp = NULL; RETURN_STATUS(BC_STATUS_SUCCESS); } // here it's guaranteed that l->i is below l->len @@ -5256,35 +5256,32 @@ static BC_STATUS zbc_program_op(char inst) static BC_STATUS zbc_program_read(void) { - const char *sv_file; BcStatus s; - BcParse parse; + BcParse sv_parse; BcVec buf; BcInstPtr ip; BcFunc *f; - f = bc_program_func(BC_PROG_READ); - bc_vec_pop_all(&f->code); - - sv_file = G.prog.file; - G.prog.file = NULL; - bc_char_vec_init(&buf); bc_read_line(&buf, stdin); - bc_parse_create(&parse, BC_PROG_READ); - bc_lex_file(&parse.l); + f = bc_program_func(BC_PROG_READ); + bc_vec_pop_all(&f->code); - s = zbc_parse_text_init(&parse, buf.v); + sv_parse = G.prs; // struct copy + bc_parse_create(&G.prs, BC_PROG_READ); + //bc_lex_file(&G.prs.l); - not needed, error line info is not printed for read() + + s = zbc_parse_text_init(&G.prs, buf.v); if (s) goto exec_err; if (IS_BC) { - IF_BC(s = zbc_parse_expr(&parse, 0)); + IF_BC(s = zbc_parse_expr(&G.prs, 0)); } else { - IF_DC(s = zdc_parse_exprs_until_eof(&parse)); + IF_DC(s = zdc_parse_exprs_until_eof(&G.prs)); } if (s) goto exec_err; - if (parse.l.lex != XC_LEX_NLINE && parse.l.lex != XC_LEX_EOF) { + if (G.prs.l.lex != XC_LEX_NLINE && G.prs.l.lex != XC_LEX_EOF) { s = bc_error("bad read() expression"); goto exec_err; } @@ -5293,11 +5290,12 @@ static BC_STATUS zbc_program_read(void) ip.inst_idx = 0; IF_BC(ip.results_len_before_call = G.prog.results.len;) - bc_parse_push(&parse, XC_INST_RET); + bc_parse_push(&G.prs, XC_INST_RET); bc_vec_push(&G.prog.exestack, &ip); + exec_err: - bc_parse_free(&parse); - G.prog.file = sv_file; + bc_parse_free(&G.prs); + G.prs = sv_parse; // struct copy bc_vec_free(&buf); RETURN_STATUS(s); } @@ -6402,30 +6400,27 @@ static BC_STATUS zdc_program_execStr(char *code, size_t *bgn, bool cond) f = bc_program_func(fidx); if (f->code.len == 0) { - FILE *sv_input_fp; - BcParse prs; + BcParse sv_parse; char *str; - bc_parse_create(&prs, fidx); + sv_parse = G.prs; // struct copy + bc_parse_create(&G.prs, fidx); str = *bc_program_str(sidx); - s = zbc_parse_text_init(&prs, str); + s = zbc_parse_text_init(&G.prs, str); if (s) goto err; - sv_input_fp = G.input_fp; - G.input_fp = NULL; // "do not read from input file when reached" - s = zdc_parse_exprs_until_eof(&prs); - G.input_fp = sv_input_fp; - + s = zdc_parse_exprs_until_eof(&G.prs); if (s) goto err; - if (prs.l.lex != XC_LEX_EOF) { + bc_parse_push(&G.prs, DC_INST_POP_EXEC); + if (G.prs.l.lex != XC_LEX_EOF) s = bc_error_bad_expression(); + bc_parse_free(&G.prs); + G.prs = sv_parse; // struct copy + if (s) { err: - bc_parse_free(&prs); bc_vec_pop_all(&f->code); goto exit; } - bc_parse_push(&prs, DC_INST_POP_EXEC); - bc_parse_free(&prs); } ip.inst_idx = 0; @@ -6871,12 +6866,12 @@ static BC_STATUS zbc_vm_process(const char *text) static BC_STATUS zbc_vm_execute_FILE(FILE *fp, const char *filename) { // So far bc/dc have no way to include a file from another file, - // therefore we know G.prog.file == NULL on entry + // therefore we know G.prs.filename == NULL on entry //const char *sv_file; BcStatus s; - G.prog.file = filename; - G.input_fp = fp; + G.prs.filename = filename; + G.prs.input_fp = fp; bc_lex_file(&G.prs.l); do { @@ -6885,8 +6880,8 @@ static BC_STATUS zbc_vm_execute_FILE(FILE *fp, const char *filename) // Example: start interactive bc and enter "return". // It should say "'return' not in a function" // but should not exit. - } while (G.input_fp == stdin); - G.prog.file = NULL; + } while (G.prs.input_fp == stdin); + G.prs.filename = NULL; RETURN_STATUS(s); } #define zbc_vm_execute_FILE(...) (zbc_vm_execute_FILE(__VA_ARGS__) COMMA_SUCCESS) -- cgit v1.2.3-55-g6feb From a2e62e3e505aad4af81018f385d86d35e6485641 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 25 Dec 2018 20:40:55 +0100 Subject: bc: stop passing a pointer to G.prs down the call chain function old new delta rewrite_label_to_current 19 26 +7 bc_lex_assign 28 35 +7 zbc_lex_skip_if_at_NLINE 14 19 +5 bc_parse_push 11 16 +5 bc_parse_operator 147 152 +5 bc_parse_create 92 97 +5 bc_lex_whitespace 38 43 +5 bc_lex_name 66 71 +5 bc_lex_lineComment 33 38 +5 zbc_lex_number 174 178 +4 zbc_parse_text_init 53 56 +3 zdc_parse_register 43 45 +2 zdc_parse_exprs_until_eof 26 28 +2 bc_parse_free 38 40 +2 bc_lex_file 28 27 -1 zbc_parse_pushSTR 65 63 -2 bc_parse_expr_empty_ok 1778 1776 -2 zbc_vm_execute_FILE 55 52 -3 bc_vm_init 678 675 -3 zbc_parse_stmt_allow_NLINE_before 59 55 -4 bc_parse_pushNUM 80 74 -6 bc_parse_pushJUMP_ZERO 27 21 -6 bc_parse_pushJUMP 27 21 -6 bc_vm_run 112 104 -8 bc_parse_pushName 39 31 -8 bc_parse_pushIndex 60 52 -8 zbc_parse_name 468 453 -15 zdc_program_execStr 524 501 -23 zdc_parse_mem 93 70 -23 zbc_program_exec 4003 3967 -36 zdc_parse_expr 518 476 -42 zbc_vm_process 923 878 -45 zbc_lex_next 2158 2070 -88 zbc_parse_stmt_possibly_auto 1560 1451 -109 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 14/20 up/down: 62/-438) Total: -376 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 701 ++++++++++++++++++++++++++++++--------------------------- 1 file changed, 374 insertions(+), 327 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 0fdb2963c..75201f5f0 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -2748,8 +2748,9 @@ static BC_STATUS zbc_num_parse(BcNum *n, const char *val, unsigned base_t) } #define zbc_num_parse(...) (zbc_num_parse(__VA_ARGS__) COMMA_SUCCESS) -static void bc_lex_lineComment(BcLex *l) +static void bc_lex_lineComment(void) { + BcLex *l = &G.prs.l; // Try: echo -n '#foo' | bc size_t i; l->lex = XC_LEX_WHITESPACE; @@ -2759,8 +2760,9 @@ static void bc_lex_lineComment(BcLex *l) l->i = i; } -static void bc_lex_whitespace(BcLex *l) +static void bc_lex_whitespace(void) { + BcLex *l = &G.prs.l; l->lex = XC_LEX_WHITESPACE; for (;;) { char c = l->buf[l->i]; @@ -2772,8 +2774,9 @@ static void bc_lex_whitespace(BcLex *l) } } -static BC_STATUS zbc_lex_number(BcLex *l, char start) +static BC_STATUS zbc_lex_number(char start) { + BcLex *l = &G.prs.l; const char *buf = l->buf + l->i; size_t len, i, ccnt; bool pt; @@ -2842,8 +2845,9 @@ static BC_STATUS zbc_lex_number(BcLex *l, char start) } #define zbc_lex_number(...) (zbc_lex_number(__VA_ARGS__) COMMA_SUCCESS) -static void bc_lex_name(BcLex *l) +static void bc_lex_name(void) { + BcLex *l = &G.prs.l; size_t i; const char *buf; @@ -2872,24 +2876,25 @@ static void bc_lex_name(BcLex *l) //return BC_STATUS_SUCCESS; } -static void bc_lex_init(BcLex *l) +static void bc_lex_init(void) { - bc_char_vec_init(&l->lex_buf); + bc_char_vec_init(&G.prs.l.lex_buf); } -static void bc_lex_free(BcLex *l) +static void bc_lex_free(void) { - bc_vec_free(&l->lex_buf); + bc_vec_free(&G.prs.l.lex_buf); } -static void bc_lex_file(BcLex *l) +static void bc_lex_file(void) { - G.err_line = l->line = 1; - l->newline = false; + G.err_line = G.prs.l.line = 1; + G.prs.l.newline = false; } -static bool bc_lex_more_input(BcLex *l) +static bool bc_lex_more_input(void) { + BcLex *l = &G.prs.l; size_t str; bool comment; @@ -2960,13 +2965,14 @@ static bool bc_lex_more_input(BcLex *l) return l->len != 0; } -IF_BC(static BC_STATUS zbc_lex_token(BcLex *l);) -IF_DC(static BC_STATUS zdc_lex_token(BcLex *l);) +IF_BC(static BC_STATUS zbc_lex_token(void);) +IF_DC(static BC_STATUS zdc_lex_token(void);) #define zbc_lex_token(...) (zbc_lex_token(__VA_ARGS__) COMMA_SUCCESS) #define zdc_lex_token(...) (zdc_lex_token(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zbc_lex_next(BcLex *l) +static BC_STATUS zbc_lex_next(void) { + BcLex *l = &G.prs.l; BcStatus s; l->lex_last = l->lex; @@ -2985,7 +2991,7 @@ static BC_STATUS zbc_lex_next(BcLex *l) l->lex = XC_LEX_EOF; if (!G.prs.input_fp) RETURN_STATUS(BC_STATUS_SUCCESS); - if (!bc_lex_more_input(l)) { + if (!bc_lex_more_input()) { G.prs.input_fp = NULL; RETURN_STATUS(BC_STATUS_SUCCESS); } @@ -2997,9 +3003,9 @@ static BC_STATUS zbc_lex_next(BcLex *l) l->lex_next_at ); if (IS_BC) { - IF_BC(s = zbc_lex_token(l)); + IF_BC(s = zbc_lex_token()); } else { - IF_DC(s = zdc_lex_token(l)); + IF_DC(s = zdc_lex_token()); } } while (!s && l->lex == XC_LEX_WHITESPACE); dbg_lex("l->lex from string:%d", l->lex); @@ -3009,39 +3015,40 @@ static BC_STATUS zbc_lex_next(BcLex *l) #define zbc_lex_next(...) (zbc_lex_next(__VA_ARGS__) COMMA_SUCCESS) #if ENABLE_BC -static BC_STATUS zbc_lex_skip_if_at_NLINE(BcLex *l) +static BC_STATUS zbc_lex_skip_if_at_NLINE(void) { - if (l->lex == XC_LEX_NLINE) - RETURN_STATUS(zbc_lex_next(l)); + if (G.prs.l.lex == XC_LEX_NLINE) + RETURN_STATUS(zbc_lex_next()); RETURN_STATUS(BC_STATUS_SUCCESS); } #define zbc_lex_skip_if_at_NLINE(...) (zbc_lex_skip_if_at_NLINE(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zbc_lex_next_and_skip_NLINE(BcLex *l) +static BC_STATUS zbc_lex_next_and_skip_NLINE(void) { BcStatus s; - s = zbc_lex_next(l); + s = zbc_lex_next(); if (s) RETURN_STATUS(s); // if(cond)stmt is accepted too (but not 2+ newlines) - s = zbc_lex_skip_if_at_NLINE(l); + s = zbc_lex_skip_if_at_NLINE(); RETURN_STATUS(s); } #define zbc_lex_next_and_skip_NLINE(...) (zbc_lex_next_and_skip_NLINE(__VA_ARGS__) COMMA_SUCCESS) #endif -static BC_STATUS zbc_lex_text_init(BcLex *l, const char *text) +static BC_STATUS zbc_lex_text_init(const char *text) { - l->buf = text; - l->i = 0; - l->len = strlen(text); - l->lex = l->lex_last = XC_LEX_INVALID; - RETURN_STATUS(zbc_lex_next(l)); + G.prs.l.buf = text; + G.prs.l.i = 0; + G.prs.l.len = strlen(text); + G.prs.l.lex = G.prs.l.lex_last = XC_LEX_INVALID; + RETURN_STATUS(zbc_lex_next()); } #define zbc_lex_text_init(...) (zbc_lex_text_init(__VA_ARGS__) COMMA_SUCCESS) #if ENABLE_BC -static BC_STATUS zbc_lex_identifier(BcLex *l) +static BC_STATUS zbc_lex_identifier(void) { + BcLex *l = &G.prs.l; BcStatus s; unsigned i; const char *buf = l->buf + l->i - 1; @@ -3070,7 +3077,7 @@ static BC_STATUS zbc_lex_identifier(BcLex *l) RETURN_STATUS(BC_STATUS_SUCCESS); } - bc_lex_name(l); + bc_lex_name(); s = BC_STATUS_SUCCESS; if (l->lex_buf.len > 2) { @@ -3086,8 +3093,9 @@ static BC_STATUS zbc_lex_identifier(BcLex *l) } #define zbc_lex_identifier(...) (zbc_lex_identifier(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zbc_lex_string(BcLex *l) +static BC_STATUS zbc_lex_string(void) { + BcLex *l = &G.prs.l; size_t len, nls, i; l->lex = XC_LEX_STR; @@ -3122,19 +3130,21 @@ static BC_STATUS zbc_lex_string(BcLex *l) } #define zbc_lex_string(...) (zbc_lex_string(__VA_ARGS__) COMMA_SUCCESS) -static void bc_lex_assign(BcLex *l, unsigned with_and_without) +static void bc_lex_assign(unsigned with_and_without) { + BcLex *l = &G.prs.l; if (l->buf[l->i] == '=') { ++l->i; with_and_without >>= 8; // store "with" value } // else store "without" value l->lex = (with_and_without & 0xff); } -#define bc_lex_assign(l, with, without) \ - bc_lex_assign(l, ((with)<<8)|(without)) +#define bc_lex_assign(with, without) \ + bc_lex_assign(((with)<<8)|(without)) -static BC_STATUS zbc_lex_comment(BcLex *l) +static BC_STATUS zbc_lex_comment(void) { + BcLex *l = &G.prs.l; size_t i, nls = 0; const char *buf = l->buf; @@ -3165,8 +3175,9 @@ static BC_STATUS zbc_lex_comment(BcLex *l) #define zbc_lex_comment(...) (zbc_lex_comment(__VA_ARGS__) COMMA_SUCCESS) #undef zbc_lex_token -static BC_STATUS zbc_lex_token(BcLex *l) +static BC_STATUS zbc_lex_token(void) { + BcLex *l = &G.prs.l; BcStatus s = BC_STATUS_SUCCESS; char c = l->buf[l->i++], c2; @@ -3186,25 +3197,25 @@ static BC_STATUS zbc_lex_token(BcLex *l) case '\f': case '\r': case ' ': - bc_lex_whitespace(l); + bc_lex_whitespace(); break; case '!': - bc_lex_assign(l, XC_LEX_OP_REL_NE, BC_LEX_OP_BOOL_NOT); + bc_lex_assign(XC_LEX_OP_REL_NE, BC_LEX_OP_BOOL_NOT); if (l->lex == BC_LEX_OP_BOOL_NOT) { s = zbc_POSIX_does_not_allow_bool_ops_this_is_bad("!"); if (s) RETURN_STATUS(s); } break; case '"': - s = zbc_lex_string(l); + s = zbc_lex_string(); break; case '#': s = zbc_POSIX_does_not_allow("'#' script comments"); if (s) RETURN_STATUS(s); - bc_lex_lineComment(l); + bc_lex_lineComment(); break; case '%': - bc_lex_assign(l, BC_LEX_OP_ASSIGN_MODULUS, XC_LEX_OP_MODULUS); + bc_lex_assign(BC_LEX_OP_ASSIGN_MODULUS, XC_LEX_OP_MODULUS); break; case '&': c2 = l->buf[l->i]; @@ -3223,7 +3234,7 @@ static BC_STATUS zbc_lex_token(BcLex *l) l->lex = (BcLexType)(c - '(' + BC_LEX_LPAREN); break; case '*': - bc_lex_assign(l, BC_LEX_OP_ASSIGN_MULTIPLY, XC_LEX_OP_MULTIPLY); + bc_lex_assign(BC_LEX_OP_ASSIGN_MULTIPLY, XC_LEX_OP_MULTIPLY); break; case '+': c2 = l->buf[l->i]; @@ -3231,7 +3242,7 @@ static BC_STATUS zbc_lex_token(BcLex *l) ++l->i; l->lex = BC_LEX_OP_INC; } else - bc_lex_assign(l, BC_LEX_OP_ASSIGN_PLUS, XC_LEX_OP_PLUS); + bc_lex_assign(BC_LEX_OP_ASSIGN_PLUS, XC_LEX_OP_PLUS); break; case ',': l->lex = BC_LEX_COMMA; @@ -3242,11 +3253,11 @@ static BC_STATUS zbc_lex_token(BcLex *l) ++l->i; l->lex = BC_LEX_OP_DEC; } else - bc_lex_assign(l, BC_LEX_OP_ASSIGN_MINUS, XC_LEX_OP_MINUS); + bc_lex_assign(BC_LEX_OP_ASSIGN_MINUS, XC_LEX_OP_MINUS); break; case '.': if (isdigit(l->buf[l->i])) - s = zbc_lex_number(l, c); + s = zbc_lex_number(c); else { l->lex = BC_LEX_KEY_LAST; s = zbc_POSIX_does_not_allow("a period ('.') as a shortcut for the last result"); @@ -3255,9 +3266,9 @@ static BC_STATUS zbc_lex_token(BcLex *l) case '/': c2 = l->buf[l->i]; if (c2 == '*') - s = zbc_lex_comment(l); + s = zbc_lex_comment(); else - bc_lex_assign(l, BC_LEX_OP_ASSIGN_DIVIDE, XC_LEX_OP_DIVIDE); + bc_lex_assign(BC_LEX_OP_ASSIGN_DIVIDE, XC_LEX_OP_DIVIDE); break; case '0': case '1': @@ -3275,19 +3286,19 @@ static BC_STATUS zbc_lex_token(BcLex *l) case 'D': case 'E': case 'F': - s = zbc_lex_number(l, c); + s = zbc_lex_number(c); break; case ';': l->lex = BC_LEX_SCOLON; break; case '<': - bc_lex_assign(l, XC_LEX_OP_REL_LE, XC_LEX_OP_REL_LT); + bc_lex_assign(XC_LEX_OP_REL_LE, XC_LEX_OP_REL_LT); break; case '=': - bc_lex_assign(l, XC_LEX_OP_REL_EQ, BC_LEX_OP_ASSIGN); + bc_lex_assign(XC_LEX_OP_REL_EQ, BC_LEX_OP_ASSIGN); break; case '>': - bc_lex_assign(l, XC_LEX_OP_REL_GE, XC_LEX_OP_REL_GT); + bc_lex_assign(XC_LEX_OP_REL_GE, XC_LEX_OP_REL_GT); break; case '[': case ']': @@ -3301,7 +3312,7 @@ static BC_STATUS zbc_lex_token(BcLex *l) s = bc_error_bad_character(c); break; case '^': - bc_lex_assign(l, BC_LEX_OP_ASSIGN_POWER, XC_LEX_OP_POWER); + bc_lex_assign(BC_LEX_OP_ASSIGN_POWER, XC_LEX_OP_POWER); break; case 'a': case 'b': @@ -3329,7 +3340,7 @@ static BC_STATUS zbc_lex_token(BcLex *l) case 'x': case 'y': case 'z': - s = zbc_lex_identifier(l); + s = zbc_lex_identifier(); break; case '{': case '}': @@ -3359,12 +3370,13 @@ static BC_STATUS zbc_lex_token(BcLex *l) #endif // ENABLE_BC #if ENABLE_DC -static BC_STATUS zdc_lex_register(BcLex *l) +static BC_STATUS zdc_lex_register(void) { + BcLex *l = &G.prs.l; if (G_exreg && isspace(l->buf[l->i])) { - bc_lex_whitespace(l); // eats whitespace (but not newline) + bc_lex_whitespace(); // eats whitespace (but not newline) l->i++; // bc_lex_name() expects this - bc_lex_name(l); + bc_lex_name(); } else { bc_vec_pop_all(&l->lex_buf); bc_vec_push(&l->lex_buf, &l->buf[l->i++]); @@ -3376,8 +3388,9 @@ static BC_STATUS zdc_lex_register(BcLex *l) } #define zdc_lex_register(...) (zdc_lex_register(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zdc_lex_string(BcLex *l) +static BC_STATUS zdc_lex_string(void) { + BcLex *l = &G.prs.l; size_t depth, nls, i; l->lex = XC_LEX_STR; @@ -3420,8 +3433,9 @@ static BC_STATUS zdc_lex_string(BcLex *l) #define zdc_lex_string(...) (zdc_lex_string(__VA_ARGS__) COMMA_SUCCESS) #undef zdc_lex_token -static BC_STATUS zdc_lex_token(BcLex *l) +static BC_STATUS zdc_lex_token(void) { + BcLex *l = &G.prs.l; static const //BcLexType - should be this type, but narrower type saves size: uint8_t dc_lex_regs[] = { @@ -3437,7 +3451,7 @@ static BC_STATUS zdc_lex_token(BcLex *l) for (i = 0; i < ARRAY_SIZE(dc_lex_regs); ++i) { if (l->lex_last == dc_lex_regs[i]) - RETURN_STATUS(zdc_lex_register(l)); + RETURN_STATUS(zdc_lex_register()); } s = BC_STATUS_SUCCESS; @@ -3471,7 +3485,7 @@ static BC_STATUS zdc_lex_token(BcLex *l) case '\r': case ' ': l->newline = 0; // was (c == '\n') - bc_lex_whitespace(l); + bc_lex_whitespace(); break; case '!': c2 = l->buf[l->i]; @@ -3486,11 +3500,11 @@ static BC_STATUS zdc_lex_token(BcLex *l) ++l->i; break; case '#': - bc_lex_lineComment(l); + bc_lex_lineComment(); break; case '.': if (isdigit(l->buf[l->i])) - s = zbc_lex_number(l, c); + s = zbc_lex_number(c); else s = bc_error_bad_character(c); break; @@ -3510,10 +3524,10 @@ static BC_STATUS zdc_lex_token(BcLex *l) case 'D': case 'E': case 'F': - s = zbc_lex_number(l, c); + s = zbc_lex_number(c); break; case '[': - s = zdc_lex_string(l); + s = zdc_lex_string(); break; default: l->lex = XC_LEX_INVALID; @@ -3526,20 +3540,21 @@ static BC_STATUS zdc_lex_token(BcLex *l) #define zdc_lex_token(...) (zdc_lex_token(__VA_ARGS__) COMMA_SUCCESS) #endif // ENABLE_DC -static void bc_parse_push(BcParse *p, char i) +static void bc_parse_push(char i) { + BcParse *p = &G.prs; dbg_compile("%s:%d pushing bytecode %zd:%d", __func__, __LINE__, p->func->code.len, i); bc_vec_pushByte(&p->func->code, i); } -static void bc_parse_pushName(BcParse *p, char *name) +static void bc_parse_pushName(char *name) { while (*name) - bc_parse_push(p, *name++); - bc_parse_push(p, BC_PARSE_STREND); + bc_parse_push(*name++); + bc_parse_push(BC_PARSE_STREND); } -static void bc_parse_pushIndex(BcParse *p, size_t idx) +static void bc_parse_pushIndex(size_t idx) { size_t mask; unsigned amt; @@ -3553,42 +3568,44 @@ static void bc_parse_pushIndex(BcParse *p, size_t idx) amt--; } while (amt != 0); - bc_parse_push(p, amt); + bc_parse_push(amt); while (idx != 0) { - bc_parse_push(p, (unsigned char)idx); + bc_parse_push((unsigned char)idx); idx >>= 8; } } #if ENABLE_BC -static void bc_parse_pushJUMP(BcParse *p, size_t idx) +static void bc_parse_pushJUMP(size_t idx) { - bc_parse_push(p, BC_INST_JUMP); - bc_parse_pushIndex(p, idx); + bc_parse_push(BC_INST_JUMP); + bc_parse_pushIndex(idx); } -static void bc_parse_pushJUMP_ZERO(BcParse *p, size_t idx) +static void bc_parse_pushJUMP_ZERO(size_t idx) { - bc_parse_push(p, BC_INST_JUMP_ZERO); - bc_parse_pushIndex(p, idx); + bc_parse_push(BC_INST_JUMP_ZERO); + bc_parse_pushIndex(idx); } -static BC_STATUS zbc_parse_pushSTR(BcParse *p) +static BC_STATUS zbc_parse_pushSTR(void) { + BcParse *p = &G.prs; char *str = xstrdup(p->l.lex_buf.v); - bc_parse_push(p, XC_INST_STR); - bc_parse_pushIndex(p, p->func->strs.len); + bc_parse_push(XC_INST_STR); + bc_parse_pushIndex(p->func->strs.len); bc_vec_push(&p->func->strs, &str); - RETURN_STATUS(zbc_lex_next(&p->l)); + RETURN_STATUS(zbc_lex_next()); } #define zbc_parse_pushSTR(...) (zbc_parse_pushSTR(__VA_ARGS__) COMMA_SUCCESS) #endif -static void bc_parse_pushNUM(BcParse *p) +static void bc_parse_pushNUM(void) { + BcParse *p = &G.prs; char *num = xstrdup(p->l.lex_buf.v); #if ENABLE_BC && ENABLE_DC size_t idx = bc_vec_push(IS_BC ? &p->func->consts : &G.prog.consts, &num); @@ -3597,15 +3614,16 @@ static void bc_parse_pushNUM(BcParse *p) #else // DC size_t idx = bc_vec_push(&G.prog.consts, &num); #endif - bc_parse_push(p, XC_INST_NUM); - bc_parse_pushIndex(p, idx); + bc_parse_push(XC_INST_NUM); + bc_parse_pushIndex(idx); } -static BC_STATUS zbc_parse_text_init(BcParse *p, const char *text) +static BC_STATUS zbc_parse_text_init(const char *text) { + BcParse *p = &G.prs; p->func = bc_program_func(p->fidx); - RETURN_STATUS(zbc_lex_text_init(&p->l, text)); + RETURN_STATUS(zbc_lex_text_init(text)); } #define zbc_parse_text_init(...) (zbc_parse_text_init(__VA_ARGS__) COMMA_SUCCESS) @@ -3626,8 +3644,9 @@ static void bc_program_reset(void) // Called when parsing code detects a failure, // resets parsing structures. -static void bc_parse_reset(BcParse *p) +static void bc_parse_reset(void) { + BcParse *p = &G.prs; if (p->fidx != BC_PROG_MAIN) { bc_func_free(p->func); bc_func_init(p->func); @@ -3646,19 +3665,21 @@ static void bc_parse_reset(BcParse *p) bc_program_reset(); } -static void bc_parse_free(BcParse *p) +static void bc_parse_free(void) { + BcParse *p = &G.prs; IF_BC(bc_vec_free(&p->exits);) IF_BC(bc_vec_free(&p->conds);) IF_BC(bc_vec_free(&p->ops);) - bc_lex_free(&p->l); + bc_lex_free(); } -static void bc_parse_create(BcParse *p, size_t fidx) +static void bc_parse_create(size_t fidx) { + BcParse *p = &G.prs; memset(p, 0, sizeof(BcParse)); - bc_lex_init(&p->l); + bc_lex_init(); IF_BC(bc_vec_init(&p->exits, sizeof(size_t), NULL);) IF_BC(bc_vec_init(&p->conds, sizeof(size_t), NULL);) IF_BC(bc_vec_init(&p->ops, sizeof(BcLexType), NULL);) @@ -3714,44 +3735,45 @@ static size_t bc_program_addFunc(char *name) // first in the expr enum. Note: This only works for binary operators. #define BC_TOKEN_2_INST(t) ((char) ((t) - XC_LEX_OP_POWER + XC_INST_POWER)) -static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags); +static BcStatus bc_parse_expr_empty_ok(uint8_t flags); -static BC_STATUS zbc_parse_expr(BcParse *p, uint8_t flags) +static BC_STATUS zbc_parse_expr(uint8_t flags) { BcStatus s; - s = bc_parse_expr_empty_ok(p, flags); + s = bc_parse_expr_empty_ok(flags); if (s == BC_STATUS_PARSE_EMPTY_EXP) RETURN_STATUS(bc_error("empty expression")); RETURN_STATUS(s); } #define zbc_parse_expr(...) (zbc_parse_expr(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zbc_parse_stmt_possibly_auto(BcParse *p, bool auto_allowed); +static BC_STATUS zbc_parse_stmt_possibly_auto(bool auto_allowed); #define zbc_parse_stmt_possibly_auto(...) (zbc_parse_stmt_possibly_auto(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zbc_parse_stmt(BcParse *p) +static BC_STATUS zbc_parse_stmt(void) { - RETURN_STATUS(zbc_parse_stmt_possibly_auto(p, false)); + RETURN_STATUS(zbc_parse_stmt_possibly_auto(false)); } #define zbc_parse_stmt(...) (zbc_parse_stmt(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zbc_parse_stmt_allow_NLINE_before(BcParse *p, const char *after_X) +static BC_STATUS zbc_parse_stmt_allow_NLINE_before(const char *after_X) { + BcParse *p = &G.prs; // "if(cond)stmt" is accepted too, but not 2+ newlines. // Same for "else", "while()", "for()". - BcStatus s = zbc_lex_next_and_skip_NLINE(&p->l); + BcStatus s = zbc_lex_next_and_skip_NLINE(); if (s) RETURN_STATUS(s); if (p->l.lex == XC_LEX_NLINE) RETURN_STATUS(bc_error_fmt("no statement after '%s'", after_X)); - RETURN_STATUS(zbc_parse_stmt(p)); + RETURN_STATUS(zbc_parse_stmt()); } #define zbc_parse_stmt_allow_NLINE_before(...) (zbc_parse_stmt_allow_NLINE_before(__VA_ARGS__) COMMA_SUCCESS) -static void bc_parse_operator(BcParse *p, BcLexType type, size_t start, - size_t *nexprs) +static void bc_parse_operator(BcLexType type, size_t start, size_t *nexprs) { + BcParse *p = &G.prs; char l, r = bc_parse_op_PREC(type - XC_LEX_1st_op); bool left = bc_parse_op_LEFT(type - XC_LEX_1st_op); @@ -3762,7 +3784,7 @@ static void bc_parse_operator(BcParse *p, BcLexType type, size_t start, l = bc_parse_op_PREC(t - XC_LEX_1st_op); if (l >= r && (l != r || !left)) break; - bc_parse_push(p, BC_TOKEN_2_INST(t)); + bc_parse_push(BC_TOKEN_2_INST(t)); bc_vec_pop(&p->ops); *nexprs -= (t != BC_LEX_OP_BOOL_NOT && t != XC_LEX_NEG); } @@ -3770,8 +3792,9 @@ static void bc_parse_operator(BcParse *p, BcLexType type, size_t start, bc_vec_push(&p->ops, &type); } -static BC_STATUS zbc_parse_rightParen(BcParse *p, size_t ops_bgn, size_t *nexs) +static BC_STATUS zbc_parse_rightParen(size_t ops_bgn, size_t *nexs) { + BcParse *p = &G.prs; BcLexType top; if (p->ops.len <= ops_bgn) @@ -3779,7 +3802,7 @@ static BC_STATUS zbc_parse_rightParen(BcParse *p, size_t ops_bgn, size_t *nexs) top = BC_PARSE_TOP_OP(p); while (top != BC_LEX_LPAREN) { - bc_parse_push(p, BC_TOKEN_2_INST(top)); + bc_parse_push(BC_TOKEN_2_INST(top)); bc_vec_pop(&p->ops); *nexs -= (top != BC_LEX_OP_BOOL_NOT && top != XC_LEX_NEG); @@ -3795,21 +3818,22 @@ static BC_STATUS zbc_parse_rightParen(BcParse *p, size_t ops_bgn, size_t *nexs) } #define zbc_parse_rightParen(...) (zbc_parse_rightParen(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zbc_parse_params(BcParse *p, uint8_t flags) +static BC_STATUS zbc_parse_params(uint8_t flags) { + BcParse *p = &G.prs; BcStatus s; size_t nparams; dbg_lex("%s:%d p->l.lex:%d", __func__, __LINE__, p->l.lex); flags = (flags & ~(BC_PARSE_PRINT | BC_PARSE_REL)) | BC_PARSE_ARRAY; - s = zbc_lex_next(&p->l); + s = zbc_lex_next(); if (s) RETURN_STATUS(s); nparams = 0; if (p->l.lex != BC_LEX_RPAREN) { for (;;) { - s = zbc_parse_expr(p, flags); + s = zbc_parse_expr(flags); if (s) RETURN_STATUS(s); nparams++; if (p->l.lex != BC_LEX_COMMA) { @@ -3817,28 +3841,29 @@ static BC_STATUS zbc_parse_params(BcParse *p, uint8_t flags) break; RETURN_STATUS(bc_error_bad_token()); } - s = zbc_lex_next(&p->l); + s = zbc_lex_next(); if (s) RETURN_STATUS(s); } } - bc_parse_push(p, BC_INST_CALL); - bc_parse_pushIndex(p, nparams); + bc_parse_push(BC_INST_CALL); + bc_parse_pushIndex(nparams); RETURN_STATUS(BC_STATUS_SUCCESS); } #define zbc_parse_params(...) (zbc_parse_params(__VA_ARGS__) COMMA_SUCCESS) // Note: takes ownership of 'name' (must be malloced) -static BC_STATUS zbc_parse_call(BcParse *p, char *name, uint8_t flags) +static BC_STATUS zbc_parse_call(char *name, uint8_t flags) { + BcParse *p = &G.prs; BcStatus s; BcId entry, *entry_ptr; size_t idx; entry.name = name; - s = zbc_parse_params(p, flags); + s = zbc_parse_params(flags); if (s) goto err; if (p->l.lex != BC_LEX_RPAREN) { @@ -3856,26 +3881,27 @@ static BC_STATUS zbc_parse_call(BcParse *p, char *name, uint8_t flags) free(name); entry_ptr = bc_vec_item(&G.prog.fn_map, idx); - bc_parse_pushIndex(p, entry_ptr->idx); + bc_parse_pushIndex(entry_ptr->idx); - RETURN_STATUS(zbc_lex_next(&p->l)); + RETURN_STATUS(zbc_lex_next()); err: free(name); RETURN_STATUS(s); } #define zbc_parse_call(...) (zbc_parse_call(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zbc_parse_name(BcParse *p, BcInst *type, uint8_t flags) +static BC_STATUS zbc_parse_name(BcInst *type, uint8_t flags) { + BcParse *p = &G.prs; BcStatus s; char *name; name = xstrdup(p->l.lex_buf.v); - s = zbc_lex_next(&p->l); + s = zbc_lex_next(); if (s) goto err; if (p->l.lex == BC_LEX_LBRACKET) { - s = zbc_lex_next(&p->l); + s = zbc_lex_next(); if (s) goto err; if (p->l.lex == BC_LEX_RBRACKET) { @@ -3887,13 +3913,13 @@ static BC_STATUS zbc_parse_name(BcParse *p, BcInst *type, uint8_t flags) } else { *type = XC_INST_ARRAY_ELEM; flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL); - s = zbc_parse_expr(p, flags); + s = zbc_parse_expr(flags); if (s) goto err; } - s = zbc_lex_next(&p->l); + s = zbc_lex_next(); if (s) goto err; - bc_parse_push(p, *type); - bc_parse_pushName(p, name); + bc_parse_push(*type); + bc_parse_pushName(name); free(name); } else if (p->l.lex == BC_LEX_LPAREN) { if (flags & BC_PARSE_NOCALL) { @@ -3901,11 +3927,11 @@ static BC_STATUS zbc_parse_name(BcParse *p, BcInst *type, uint8_t flags) goto err; } *type = BC_INST_CALL; - s = zbc_parse_call(p, name, flags); + s = zbc_parse_call(name, flags); } else { *type = XC_INST_VAR; - bc_parse_push(p, XC_INST_VAR); - bc_parse_pushName(p, name); + bc_parse_push(XC_INST_VAR); + bc_parse_pushName(name); free(name); } @@ -3916,82 +3942,85 @@ static BC_STATUS zbc_parse_name(BcParse *p, BcInst *type, uint8_t flags) } #define zbc_parse_name(...) (zbc_parse_name(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zbc_parse_read(BcParse *p) +static BC_STATUS zbc_parse_read(void) { + BcParse *p = &G.prs; BcStatus s; - s = zbc_lex_next(&p->l); + s = zbc_lex_next(); if (s) RETURN_STATUS(s); if (p->l.lex != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); - s = zbc_lex_next(&p->l); + s = zbc_lex_next(); if (s) RETURN_STATUS(s); if (p->l.lex != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); - bc_parse_push(p, XC_INST_READ); + bc_parse_push(XC_INST_READ); RETURN_STATUS(s); } #define zbc_parse_read(...) (zbc_parse_read(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zbc_parse_builtin(BcParse *p, BcLexType type, uint8_t flags, - BcInst *prev) +static BC_STATUS zbc_parse_builtin(BcLexType type, uint8_t flags, BcInst *prev) { + BcParse *p = &G.prs; BcStatus s; - s = zbc_lex_next(&p->l); + s = zbc_lex_next(); if (s) RETURN_STATUS(s); if (p->l.lex != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); flags = (flags & ~(BC_PARSE_PRINT | BC_PARSE_REL)) | BC_PARSE_ARRAY; - s = zbc_lex_next(&p->l); + s = zbc_lex_next(); if (s) RETURN_STATUS(s); - s = zbc_parse_expr(p, flags); + s = zbc_parse_expr(flags); if (s) RETURN_STATUS(s); if (p->l.lex != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); *prev = (type == BC_LEX_KEY_LENGTH) ? XC_INST_LENGTH : XC_INST_SQRT; - bc_parse_push(p, *prev); + bc_parse_push(*prev); RETURN_STATUS(s); } #define zbc_parse_builtin(...) (zbc_parse_builtin(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zbc_parse_scale(BcParse *p, BcInst *type, uint8_t flags) +static BC_STATUS zbc_parse_scale(BcInst *type, uint8_t flags) { + BcParse *p = &G.prs; BcStatus s; - s = zbc_lex_next(&p->l); + s = zbc_lex_next(); if (s) RETURN_STATUS(s); if (p->l.lex != BC_LEX_LPAREN) { *type = XC_INST_SCALE; - bc_parse_push(p, XC_INST_SCALE); + bc_parse_push(XC_INST_SCALE); RETURN_STATUS(BC_STATUS_SUCCESS); } *type = XC_INST_SCALE_FUNC; flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL); - s = zbc_lex_next(&p->l); + s = zbc_lex_next(); if (s) RETURN_STATUS(s); - s = zbc_parse_expr(p, flags); + s = zbc_parse_expr(flags); if (s) RETURN_STATUS(s); if (p->l.lex != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); - bc_parse_push(p, XC_INST_SCALE_FUNC); + bc_parse_push(XC_INST_SCALE_FUNC); - RETURN_STATUS(zbc_lex_next(&p->l)); + RETURN_STATUS(zbc_lex_next()); } #define zbc_parse_scale(...) (zbc_parse_scale(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zbc_parse_incdec(BcParse *p, BcInst *prev, bool *paren_expr, - size_t *nexprs, uint8_t flags) +static BC_STATUS zbc_parse_incdec(BcInst *prev, bool *paren_expr, + size_t *nexprs, uint8_t flags) { + BcParse *p = &G.prs; BcStatus s; BcLexType type; char inst; @@ -4002,13 +4031,13 @@ static BC_STATUS zbc_parse_incdec(BcParse *p, BcInst *prev, bool *paren_expr, || etype == XC_INST_IBASE || etype == XC_INST_OBASE ) { *prev = inst = BC_INST_INC_POST + (p->l.lex != BC_LEX_OP_INC); - bc_parse_push(p, inst); - s = zbc_lex_next(&p->l); + bc_parse_push(inst); + s = zbc_lex_next(); } else { *prev = inst = BC_INST_INC_PRE + (p->l.lex != BC_LEX_OP_INC); *paren_expr = true; - s = zbc_lex_next(&p->l); + s = zbc_lex_next(); if (s) RETURN_STATUS(s); type = p->l.lex; @@ -4018,28 +4047,28 @@ static BC_STATUS zbc_parse_incdec(BcParse *p, BcInst *prev, bool *paren_expr, switch (type) { case XC_LEX_NAME: - s = zbc_parse_name(p, prev, flags | BC_PARSE_NOCALL); + s = zbc_parse_name(prev, flags | BC_PARSE_NOCALL); break; case BC_LEX_KEY_IBASE: case BC_LEX_KEY_LAST: case BC_LEX_KEY_OBASE: - bc_parse_push(p, type - BC_LEX_KEY_IBASE + XC_INST_IBASE); - s = zbc_lex_next(&p->l); + bc_parse_push(type - BC_LEX_KEY_IBASE + XC_INST_IBASE); + s = zbc_lex_next(); break; case BC_LEX_KEY_SCALE: - s = zbc_lex_next(&p->l); + s = zbc_lex_next(); if (s) RETURN_STATUS(s); if (p->l.lex == BC_LEX_LPAREN) s = bc_error_bad_token(); else - bc_parse_push(p, XC_INST_SCALE); + bc_parse_push(XC_INST_SCALE); break; default: s = bc_error_bad_token(); break; } - if (!s) bc_parse_push(p, inst); + if (!s) bc_parse_push(inst); } RETURN_STATUS(s); @@ -4064,14 +4093,15 @@ static int ok_in_expr(BcInst p) #define BC_PARSE_LEAF(p, rparen) ((rparen) || ok_in_expr(p)) #endif -static BC_STATUS zbc_parse_minus(BcParse *p, BcInst *prev, size_t ops_bgn, - bool rparen, size_t *nexprs) +static BC_STATUS zbc_parse_minus(BcInst *prev, size_t ops_bgn, + bool rparen, size_t *nexprs) { + BcParse *p = &G.prs; BcStatus s; BcLexType type; BcInst etype = *prev; - s = zbc_lex_next(&p->l); + s = zbc_lex_next(); if (s) RETURN_STATUS(s); type = BC_PARSE_LEAF(etype, rparen) ? XC_LEX_OP_MINUS : XC_LEX_NEG; @@ -4082,28 +4112,29 @@ static BC_STATUS zbc_parse_minus(BcParse *p, BcInst *prev, size_t ops_bgn, if (type != XC_LEX_OP_MINUS) bc_vec_push(&p->ops, &type); else - bc_parse_operator(p, type, ops_bgn, nexprs); + bc_parse_operator(type, ops_bgn, nexprs); RETURN_STATUS(s); } #define zbc_parse_minus(...) (zbc_parse_minus(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zbc_parse_print(BcParse *p) +static BC_STATUS zbc_parse_print(void) { + BcParse *p = &G.prs; BcStatus s; BcLexType type; for (;;) { - s = zbc_lex_next(&p->l); + s = zbc_lex_next(); if (s) RETURN_STATUS(s); type = p->l.lex; if (type == XC_LEX_STR) { - s = zbc_parse_pushSTR(p); + s = zbc_parse_pushSTR(); } else { - s = zbc_parse_expr(p, 0); + s = zbc_parse_expr(0); } if (s) RETURN_STATUS(s); - bc_parse_push(p, XC_INST_PRINT_POP); + bc_parse_push(XC_INST_PRINT_POP); if (p->l.lex != BC_LEX_COMMA) break; } @@ -4112,24 +4143,25 @@ static BC_STATUS zbc_parse_print(BcParse *p) } #define zbc_parse_print(...) (zbc_parse_print(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zbc_parse_return(BcParse *p) +static BC_STATUS zbc_parse_return(void) { + BcParse *p = &G.prs; BcStatus s; BcLexType t; dbg_lex_enter("%s:%d entered", __func__, __LINE__); - s = zbc_lex_next(&p->l); + s = zbc_lex_next(); if (s) RETURN_STATUS(s); t = p->l.lex; if (t == XC_LEX_NLINE || t == BC_LEX_SCOLON) - bc_parse_push(p, BC_INST_RET0); + bc_parse_push(BC_INST_RET0); else { bool paren = (t == BC_LEX_LPAREN); - s = bc_parse_expr_empty_ok(p, 0); + s = bc_parse_expr_empty_ok(0); if (s == BC_STATUS_PARSE_EMPTY_EXP) { - bc_parse_push(p, BC_INST_RET0); - s = zbc_lex_next(&p->l); + bc_parse_push(BC_INST_RET0); + s = zbc_lex_next(); } if (s) RETURN_STATUS(s); @@ -4138,7 +4170,7 @@ static BC_STATUS zbc_parse_return(BcParse *p) if (s) RETURN_STATUS(s); } - bc_parse_push(p, XC_INST_RET); + bc_parse_push(XC_INST_RET); } dbg_lex_done("%s:%d done", __func__, __LINE__); @@ -4146,25 +4178,27 @@ static BC_STATUS zbc_parse_return(BcParse *p) } #define zbc_parse_return(...) (zbc_parse_return(__VA_ARGS__) COMMA_SUCCESS) -static void rewrite_label_to_current(BcParse *p, size_t idx) +static void rewrite_label_to_current(size_t idx) { + BcParse *p = &G.prs; size_t *label = bc_vec_item(&p->func->labels, idx); *label = p->func->code.len; } -static BC_STATUS zbc_parse_if(BcParse *p) +static BC_STATUS zbc_parse_if(void) { + BcParse *p = &G.prs; BcStatus s; size_t ip_idx; dbg_lex_enter("%s:%d entered", __func__, __LINE__); - s = zbc_lex_next(&p->l); + s = zbc_lex_next(); if (s) RETURN_STATUS(s); if (p->l.lex != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); - s = zbc_lex_next(&p->l); + s = zbc_lex_next(); if (s) RETURN_STATUS(s); - s = zbc_parse_expr(p, BC_PARSE_REL); + s = zbc_parse_expr(BC_PARSE_REL); if (s) RETURN_STATUS(s); if (p->l.lex != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); @@ -4172,9 +4206,9 @@ static BC_STATUS zbc_parse_if(BcParse *p) // Pushed value (destination of the jump) is uninitialized, // will be rewritten to be address of "end of if()" or of "else". ip_idx = bc_vec_push(&p->func->labels, &ip_idx); - bc_parse_pushJUMP_ZERO(p, ip_idx); + bc_parse_pushJUMP_ZERO(ip_idx); - s = zbc_parse_stmt_allow_NLINE_before(p, STRING_if); + s = zbc_parse_stmt_allow_NLINE_before(STRING_if); if (s) RETURN_STATUS(s); dbg_lex("%s:%d in if after stmt: p->l.lex:%d", __func__, __LINE__, p->l.lex); @@ -4184,35 +4218,36 @@ static BC_STATUS zbc_parse_if(BcParse *p) // Encode "after then_stmt, jump to end of if()" ip2_idx = bc_vec_push(&p->func->labels, &ip2_idx); dbg_lex("%s:%d after if() then_stmt: BC_INST_JUMP to %zd", __func__, __LINE__, ip2_idx); - bc_parse_pushJUMP(p, ip2_idx); + bc_parse_pushJUMP(ip2_idx); dbg_lex("%s:%d rewriting 'if_zero' label to jump to 'else'-> %zd", __func__, __LINE__, p->func->code.len); - rewrite_label_to_current(p, ip_idx); + rewrite_label_to_current(ip_idx); ip_idx = ip2_idx; - s = zbc_parse_stmt_allow_NLINE_before(p, STRING_else); + s = zbc_parse_stmt_allow_NLINE_before(STRING_else); if (s) RETURN_STATUS(s); } dbg_lex("%s:%d rewriting label to jump after 'if' body-> %zd", __func__, __LINE__, p->func->code.len); - rewrite_label_to_current(p, ip_idx); + rewrite_label_to_current(ip_idx); dbg_lex_done("%s:%d done", __func__, __LINE__); RETURN_STATUS(s); } #define zbc_parse_if(...) (zbc_parse_if(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zbc_parse_while(BcParse *p) +static BC_STATUS zbc_parse_while(void) { + BcParse *p = &G.prs; BcStatus s; size_t cond_idx; size_t ip_idx; - s = zbc_lex_next(&p->l); + s = zbc_lex_next(); if (s) RETURN_STATUS(s); if (p->l.lex != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); - s = zbc_lex_next(&p->l); + s = zbc_lex_next(); if (s) RETURN_STATUS(s); cond_idx = bc_vec_push(&p->func->labels, &p->func->code.len); @@ -4222,20 +4257,20 @@ static BC_STATUS zbc_parse_while(BcParse *p) bc_vec_push(&p->exits, &ip_idx); bc_vec_push(&p->func->labels, &ip_idx); - s = zbc_parse_expr(p, BC_PARSE_REL); + s = zbc_parse_expr(BC_PARSE_REL); if (s) RETURN_STATUS(s); if (p->l.lex != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); - bc_parse_pushJUMP_ZERO(p, ip_idx); + bc_parse_pushJUMP_ZERO(ip_idx); - s = zbc_parse_stmt_allow_NLINE_before(p, STRING_while); + s = zbc_parse_stmt_allow_NLINE_before(STRING_while); if (s) RETURN_STATUS(s); dbg_lex("%s:%d BC_INST_JUMP to %zd", __func__, __LINE__, cond_idx); - bc_parse_pushJUMP(p, cond_idx); + bc_parse_pushJUMP(cond_idx); dbg_lex("%s:%d rewriting label-> %zd", __func__, __LINE__, p->func->code.len); - rewrite_label_to_current(p, ip_idx); + rewrite_label_to_current(ip_idx); bc_vec_pop(&p->exits); bc_vec_pop(&p->conds); @@ -4244,21 +4279,22 @@ static BC_STATUS zbc_parse_while(BcParse *p) } #define zbc_parse_while(...) (zbc_parse_while(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zbc_parse_for(BcParse *p) +static BC_STATUS zbc_parse_for(void) { + BcParse *p = &G.prs; BcStatus s; size_t cond_idx, exit_idx, body_idx, update_idx; dbg_lex("%s:%d p->l.lex:%d", __func__, __LINE__, p->l.lex); - s = zbc_lex_next(&p->l); + s = zbc_lex_next(); if (s) RETURN_STATUS(s); if (p->l.lex != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); - s = zbc_lex_next(&p->l); + s = zbc_lex_next(); if (s) RETURN_STATUS(s); if (p->l.lex != BC_LEX_SCOLON) { - s = zbc_parse_expr(p, 0); - bc_parse_push(p, XC_INST_POP); + s = zbc_parse_expr(0); + bc_parse_push(XC_INST_POP); if (s) RETURN_STATUS(s); } else { s = zbc_POSIX_does_not_allow_empty_X_expression_in_for("init"); @@ -4266,7 +4302,7 @@ static BC_STATUS zbc_parse_for(BcParse *p) } if (p->l.lex != BC_LEX_SCOLON) RETURN_STATUS(bc_error_bad_token()); - s = zbc_lex_next(&p->l); + s = zbc_lex_next(); if (s) RETURN_STATUS(s); cond_idx = bc_vec_push(&p->func->labels, &p->func->code.len); @@ -4275,52 +4311,52 @@ static BC_STATUS zbc_parse_for(BcParse *p) exit_idx = body_idx + 1; if (p->l.lex != BC_LEX_SCOLON) - s = zbc_parse_expr(p, BC_PARSE_REL); + s = zbc_parse_expr(BC_PARSE_REL); else { // Set this for the next call to bc_parse_pushNUM(). // This is safe to set because the current token is a semicolon, // which has no string requirement. bc_vec_string(&p->l.lex_buf, 1, "1"); - bc_parse_pushNUM(p); + bc_parse_pushNUM(); s = zbc_POSIX_does_not_allow_empty_X_expression_in_for("condition"); } if (s) RETURN_STATUS(s); if (p->l.lex != BC_LEX_SCOLON) RETURN_STATUS(bc_error_bad_token()); - s = zbc_lex_next(&p->l); + s = zbc_lex_next(); if (s) RETURN_STATUS(s); - bc_parse_pushJUMP_ZERO(p, exit_idx); - bc_parse_pushJUMP(p, body_idx); + bc_parse_pushJUMP_ZERO(exit_idx); + bc_parse_pushJUMP(body_idx); bc_vec_push(&p->conds, &update_idx); bc_vec_push(&p->func->labels, &p->func->code.len); if (p->l.lex != BC_LEX_RPAREN) { - s = zbc_parse_expr(p, 0); + s = zbc_parse_expr(0); if (s) RETURN_STATUS(s); if (p->l.lex != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); - bc_parse_push(p, XC_INST_POP); + bc_parse_push(XC_INST_POP); } else { s = zbc_POSIX_does_not_allow_empty_X_expression_in_for("update"); if (s) RETURN_STATUS(s); } - bc_parse_pushJUMP(p, cond_idx); + bc_parse_pushJUMP(cond_idx); bc_vec_push(&p->func->labels, &p->func->code.len); bc_vec_push(&p->exits, &exit_idx); bc_vec_push(&p->func->labels, &exit_idx); - s = zbc_parse_stmt_allow_NLINE_before(p, STRING_for); + s = zbc_parse_stmt_allow_NLINE_before(STRING_for); if (s) RETURN_STATUS(s); dbg_lex("%s:%d BC_INST_JUMP to %zd", __func__, __LINE__, update_idx); - bc_parse_pushJUMP(p, update_idx); + bc_parse_pushJUMP(update_idx); dbg_lex("%s:%d rewriting label-> %zd", __func__, __LINE__, p->func->code.len); - rewrite_label_to_current(p, exit_idx); + rewrite_label_to_current(exit_idx); bc_vec_pop(&p->exits); bc_vec_pop(&p->conds); @@ -4329,8 +4365,9 @@ static BC_STATUS zbc_parse_for(BcParse *p) } #define zbc_parse_for(...) (zbc_parse_for(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zbc_parse_break_or_continue(BcParse *p, BcLexType type) +static BC_STATUS zbc_parse_break_or_continue(BcLexType type) { + BcParse *p = &G.prs; size_t i; if (type == BC_LEX_KEY_BREAK) { @@ -4340,9 +4377,9 @@ static BC_STATUS zbc_parse_break_or_continue(BcParse *p, BcLexType type) } else { i = *(size_t*)bc_vec_top(&p->conds); } - bc_parse_pushJUMP(p, i); + bc_parse_pushJUMP(i); - RETURN_STATUS(zbc_lex_next(&p->l)); + RETURN_STATUS(zbc_lex_next()); } #define zbc_parse_break_or_continue(...) (zbc_parse_break_or_continue(__VA_ARGS__) COMMA_SUCCESS) @@ -4367,14 +4404,15 @@ static BC_STATUS zbc_func_insert(BcFunc *f, char *name, bool var) } #define zbc_func_insert(...) (zbc_func_insert(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zbc_parse_funcdef(BcParse *p) +static BC_STATUS zbc_parse_funcdef(void) { + BcParse *p = &G.prs; BcStatus s; bool var, comma = false; char *name; dbg_lex_enter("%s:%d entered", __func__, __LINE__); - s = zbc_lex_next(&p->l); + s = zbc_lex_next(); if (s) RETURN_STATUS(s); if (p->l.lex != XC_LEX_NAME) RETURN_STATUS(bc_error("bad function definition")); @@ -4383,11 +4421,11 @@ static BC_STATUS zbc_parse_funcdef(BcParse *p) p->fidx = bc_program_addFunc(name); p->func = bc_program_func(p->fidx); - s = zbc_lex_next(&p->l); + s = zbc_lex_next(); if (s) RETURN_STATUS(s); if (p->l.lex != BC_LEX_LPAREN) RETURN_STATUS(bc_error("bad function definition")); - s = zbc_lex_next(&p->l); + s = zbc_lex_next(); if (s) RETURN_STATUS(s); while (p->l.lex != BC_LEX_RPAREN) { @@ -4397,13 +4435,13 @@ static BC_STATUS zbc_parse_funcdef(BcParse *p) ++p->func->nparams; name = xstrdup(p->l.lex_buf.v); - s = zbc_lex_next(&p->l); + s = zbc_lex_next(); if (s) goto err; var = p->l.lex != BC_LEX_LBRACKET; if (!var) { - s = zbc_lex_next(&p->l); + s = zbc_lex_next(); if (s) goto err; if (p->l.lex != BC_LEX_RBRACKET) { @@ -4411,13 +4449,13 @@ static BC_STATUS zbc_parse_funcdef(BcParse *p) goto err; } - s = zbc_lex_next(&p->l); + s = zbc_lex_next(); if (s) goto err; } comma = p->l.lex == BC_LEX_COMMA; if (comma) { - s = zbc_lex_next(&p->l); + s = zbc_lex_next(); if (s) goto err; } @@ -4427,7 +4465,7 @@ static BC_STATUS zbc_parse_funcdef(BcParse *p) if (comma) RETURN_STATUS(bc_error("bad function definition")); - s = zbc_lex_next(&p->l); + s = zbc_lex_next(); if (s) RETURN_STATUS(s); if (p->l.lex != BC_LEX_LBRACE) { @@ -4436,18 +4474,18 @@ static BC_STATUS zbc_parse_funcdef(BcParse *p) } // Prevent "define z()" from being interpreted as function with empty stmt as body - s = zbc_lex_skip_if_at_NLINE(&p->l); + s = zbc_lex_skip_if_at_NLINE(); if (s) RETURN_STATUS(s); //GNU bc requires a {} block even if function body has single stmt, enforce this? if (p->l.lex != BC_LEX_LBRACE) RETURN_STATUS(bc_error("function { body } expected")); p->in_funcdef++; // to determine whether "return" stmt is allowed, and such - s = zbc_parse_stmt_possibly_auto(p, true); + s = zbc_parse_stmt_possibly_auto(true); p->in_funcdef--; if (s) RETURN_STATUS(s); - bc_parse_push(p, BC_INST_RET0); + bc_parse_push(BC_INST_RET0); // Subsequent code generation is into main program p->fidx = BC_PROG_MAIN; @@ -4462,13 +4500,14 @@ static BC_STATUS zbc_parse_funcdef(BcParse *p) } #define zbc_parse_funcdef(...) (zbc_parse_funcdef(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zbc_parse_auto(BcParse *p) +static BC_STATUS zbc_parse_auto(void) { + BcParse *p = &G.prs; BcStatus s; char *name; dbg_lex_enter("%s:%d entered", __func__, __LINE__); - s = zbc_lex_next(&p->l); + s = zbc_lex_next(); if (s) RETURN_STATUS(s); for (;;) { @@ -4478,19 +4517,19 @@ static BC_STATUS zbc_parse_auto(BcParse *p) RETURN_STATUS(bc_error("bad 'auto' syntax")); name = xstrdup(p->l.lex_buf.v); - s = zbc_lex_next(&p->l); + s = zbc_lex_next(); if (s) goto err; var = (p->l.lex != BC_LEX_LBRACKET); if (!var) { - s = zbc_lex_next(&p->l); + s = zbc_lex_next(); if (s) goto err; if (p->l.lex != BC_LEX_RBRACKET) { s = bc_error("bad 'auto' syntax"); goto err; } - s = zbc_lex_next(&p->l); + s = zbc_lex_next(); if (s) goto err; } @@ -4505,7 +4544,7 @@ static BC_STATUS zbc_parse_auto(BcParse *p) } if (p->l.lex != BC_LEX_COMMA) RETURN_STATUS(bc_error("bad 'auto' syntax")); - s = zbc_lex_next(&p->l); // skip comma + s = zbc_lex_next(); // skip comma if (s) RETURN_STATUS(s); } @@ -4519,38 +4558,39 @@ static BC_STATUS zbc_parse_auto(BcParse *p) #define zbc_parse_auto(...) (zbc_parse_auto(__VA_ARGS__) COMMA_SUCCESS) #undef zbc_parse_stmt_possibly_auto -static BC_STATUS zbc_parse_stmt_possibly_auto(BcParse *p, bool auto_allowed) +static BC_STATUS zbc_parse_stmt_possibly_auto(bool auto_allowed) { + BcParse *p = &G.prs; BcStatus s = BC_STATUS_SUCCESS; dbg_lex_enter("%s:%d entered, p->l.lex:%d", __func__, __LINE__, p->l.lex); if (p->l.lex == XC_LEX_NLINE) { dbg_lex_done("%s:%d done (seen XC_LEX_NLINE)", __func__, __LINE__); - RETURN_STATUS(zbc_lex_next(&p->l)); + RETURN_STATUS(zbc_lex_next()); } if (p->l.lex == BC_LEX_SCOLON) { dbg_lex_done("%s:%d done (seen BC_LEX_SCOLON)", __func__, __LINE__); - RETURN_STATUS(zbc_lex_next(&p->l)); + RETURN_STATUS(zbc_lex_next()); } if (p->l.lex == BC_LEX_LBRACE) { dbg_lex("%s:%d BC_LEX_LBRACE: (auto_allowed:%d)", __func__, __LINE__, auto_allowed); do { - s = zbc_lex_next(&p->l); + s = zbc_lex_next(); if (s) RETURN_STATUS(s); } while (p->l.lex == XC_LEX_NLINE); if (auto_allowed && p->l.lex == BC_LEX_KEY_AUTO) { dbg_lex("%s:%d calling zbc_parse_auto()", __func__, __LINE__); - s = zbc_parse_auto(p); + s = zbc_parse_auto(); if (s) RETURN_STATUS(s); } while (p->l.lex != BC_LEX_RBRACE) { dbg_lex("%s:%d block parsing loop", __func__, __LINE__); - s = zbc_parse_stmt(p); + s = zbc_parse_stmt(); if (s) RETURN_STATUS(s); } - s = zbc_lex_next(&p->l); + s = zbc_lex_next(); dbg_lex_done("%s:%d done (seen BC_LEX_RBRACE)", __func__, __LINE__); RETURN_STATUS(s); } @@ -4571,25 +4611,25 @@ static BC_STATUS zbc_parse_stmt_possibly_auto(BcParse *p, bool auto_allowed) case BC_LEX_KEY_READ: case BC_LEX_KEY_SCALE: case BC_LEX_KEY_SQRT: - s = zbc_parse_expr(p, BC_PARSE_PRINT); + s = zbc_parse_expr(BC_PARSE_PRINT); break; case XC_LEX_STR: - s = zbc_parse_pushSTR(p); - bc_parse_push(p, XC_INST_PRINT_STR); + s = zbc_parse_pushSTR(); + bc_parse_push(XC_INST_PRINT_STR); break; case BC_LEX_KEY_BREAK: case BC_LEX_KEY_CONTINUE: - s = zbc_parse_break_or_continue(p, p->l.lex); + s = zbc_parse_break_or_continue(p->l.lex); break; case BC_LEX_KEY_FOR: - s = zbc_parse_for(p); + s = zbc_parse_for(); break; case BC_LEX_KEY_HALT: - bc_parse_push(p, BC_INST_HALT); - s = zbc_lex_next(&p->l); + bc_parse_push(BC_INST_HALT); + s = zbc_lex_next(); break; case BC_LEX_KEY_IF: - s = zbc_parse_if(p); + s = zbc_parse_if(); break; case BC_LEX_KEY_LIMITS: // "limits" is a compile-time command, @@ -4604,10 +4644,10 @@ static BC_STATUS zbc_parse_stmt_possibly_auto(BcParse *p, bool auto_allowed) "MAX Exponent = "BC_MAX_EXP_STR "\n" "Number of vars = "BC_MAX_VARS_STR "\n" ); - s = zbc_lex_next(&p->l); + s = zbc_lex_next(); break; case BC_LEX_KEY_PRINT: - s = zbc_parse_print(p); + s = zbc_parse_print(); break; case BC_LEX_KEY_QUIT: // "quit" is a compile-time command. For example, @@ -4617,10 +4657,10 @@ static BC_STATUS zbc_parse_stmt_possibly_auto(BcParse *p, bool auto_allowed) case BC_LEX_KEY_RETURN: if (!p->in_funcdef) RETURN_STATUS(bc_error("'return' not in a function")); - s = zbc_parse_return(p); + s = zbc_parse_return(); break; case BC_LEX_KEY_WHILE: - s = zbc_parse_while(p); + s = zbc_parse_while(); break; default: s = bc_error_bad_token(); @@ -4632,8 +4672,9 @@ static BC_STATUS zbc_parse_stmt_possibly_auto(BcParse *p, bool auto_allowed) } #define zbc_parse_stmt_possibly_auto(...) (zbc_parse_stmt_possibly_auto(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zbc_parse_stmt_or_funcdef(BcParse *p) +static BC_STATUS zbc_parse_stmt_or_funcdef(void) { + BcParse *p = &G.prs; BcStatus s; dbg_lex_enter("%s:%d entered", __func__, __LINE__); @@ -4641,10 +4682,10 @@ static BC_STATUS zbc_parse_stmt_or_funcdef(BcParse *p) s = bc_error("end of file"); else if (p->l.lex == BC_LEX_KEY_DEFINE) { dbg_lex("%s:%d p->l.lex:BC_LEX_KEY_DEFINE", __func__, __LINE__); - s = zbc_parse_funcdef(p); + s = zbc_parse_funcdef(); } else { dbg_lex("%s:%d p->l.lex:%d (not BC_LEX_KEY_DEFINE)", __func__, __LINE__, p->l.lex); - s = zbc_parse_stmt(p); + s = zbc_parse_stmt(); } dbg_lex_done("%s:%d done", __func__, __LINE__); @@ -4653,8 +4694,9 @@ static BC_STATUS zbc_parse_stmt_or_funcdef(BcParse *p) #define zbc_parse_stmt_or_funcdef(...) (zbc_parse_stmt_or_funcdef(__VA_ARGS__) COMMA_SUCCESS) // This is not a "z" function: can also return BC_STATUS_PARSE_EMPTY_EXP -static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) +static BcStatus bc_parse_expr_empty_ok(uint8_t flags) { + BcParse *p = &G.prs; BcInst prev = XC_INST_PRINT; size_t nexprs = 0, ops_bgn = p->ops.len; unsigned nparens, nrelops; @@ -4680,12 +4722,12 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) switch (t) { case BC_LEX_OP_INC: case BC_LEX_OP_DEC: - s = zbc_parse_incdec(p, &prev, &paren_expr, &nexprs, flags); + s = zbc_parse_incdec(&prev, &paren_expr, &nexprs, flags); rprn = bin_last = false; //get_token = false; - already is break; case XC_LEX_OP_MINUS: - s = zbc_parse_minus(p, &prev, ops_bgn, rprn, &nexprs); + s = zbc_parse_minus(&prev, ops_bgn, rprn, &nexprs); rprn = false; //get_token = false; - already is bin_last = (prev == XC_INST_MINUS); @@ -4728,8 +4770,8 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) } nrelops += (t >= XC_LEX_OP_REL_EQ && t <= XC_LEX_OP_REL_GT); prev = BC_TOKEN_2_INST(t); - bc_parse_operator(p, t, ops_bgn, &nexprs); - s = zbc_lex_next(&p->l); + bc_parse_operator(t, ops_bgn, &nexprs); + s = zbc_lex_next(); rprn = false; //get_token = false; - already is bin_last = (t != BC_LEX_OP_BOOL_NOT); @@ -4753,7 +4795,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) dbg_lex_done("%s:%d done (returning EMPTY_EXP)", __func__, __LINE__); return BC_STATUS_PARSE_EMPTY_EXP; } - s = zbc_parse_rightParen(p, ops_bgn, &nexprs); + s = zbc_parse_rightParen(ops_bgn, &nexprs); nparens--; get_token = true; paren_expr = rprn = true; @@ -4762,7 +4804,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) case XC_LEX_NAME: if (BC_PARSE_LEAF(prev, rprn)) return bc_error_bad_expression(); - s = zbc_parse_name(p, &prev, flags & ~BC_PARSE_NOCALL); + s = zbc_parse_name(&prev, flags & ~BC_PARSE_NOCALL); paren_expr = true; rprn = bin_last = false; //get_token = false; - already is @@ -4771,7 +4813,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) case XC_LEX_NUMBER: if (BC_PARSE_LEAF(prev, rprn)) return bc_error_bad_expression(); - bc_parse_pushNUM(p); + bc_parse_pushNUM(); prev = XC_INST_NUM; get_token = true; paren_expr = true; @@ -4784,7 +4826,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) if (BC_PARSE_LEAF(prev, rprn)) return bc_error_bad_expression(); prev = (char) (t - BC_LEX_KEY_IBASE + XC_INST_IBASE); - bc_parse_push(p, (char) prev); + bc_parse_push((char) prev); get_token = true; paren_expr = true; rprn = bin_last = false; @@ -4794,7 +4836,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) case BC_LEX_KEY_SQRT: if (BC_PARSE_LEAF(prev, rprn)) return bc_error_bad_expression(); - s = zbc_parse_builtin(p, t, flags, &prev); + s = zbc_parse_builtin(t, flags, &prev); get_token = true; paren_expr = true; rprn = bin_last = false; @@ -4803,7 +4845,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) case BC_LEX_KEY_READ: if (BC_PARSE_LEAF(prev, rprn)) return bc_error_bad_expression(); - s = zbc_parse_read(p); + s = zbc_parse_read(); prev = XC_INST_READ; get_token = true; paren_expr = true; @@ -4813,7 +4855,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) case BC_LEX_KEY_SCALE: if (BC_PARSE_LEAF(prev, rprn)) return bc_error_bad_expression(); - s = zbc_parse_scale(p, &prev, flags); + s = zbc_parse_scale(&prev, flags); prev = XC_INST_SCALE; //get_token = false; - already is paren_expr = true; @@ -4827,7 +4869,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) if (s || G_interrupt) // error, or ^C: stop parsing return BC_STATUS_FAILURE; if (get_token) { - s = zbc_lex_next(&p->l); + s = zbc_lex_next(); if (s) return s; } } @@ -4840,7 +4882,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) if (top == BC_LEX_LPAREN || top == BC_LEX_RPAREN) return bc_error_bad_expression(); - bc_parse_push(p, BC_TOKEN_2_INST(top)); + bc_parse_push(BC_TOKEN_2_INST(top)); nexprs -= (top != BC_LEX_OP_BOOL_NOT && top != XC_LEX_NEG); bc_vec_pop(&p->ops); @@ -4861,8 +4903,8 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) if (flags & BC_PARSE_PRINT) { if (paren_first || !assign) - bc_parse_push(p, XC_INST_PRINT); - bc_parse_push(p, XC_INST_POP); + bc_parse_push(XC_INST_PRINT); + bc_parse_push(XC_INST_POP); } dbg_lex_done("%s:%d done", __func__, __LINE__); @@ -4873,30 +4915,32 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) #if ENABLE_DC -static BC_STATUS zdc_parse_register(BcParse *p) +static BC_STATUS zdc_parse_register(void) { + BcParse *p = &G.prs; BcStatus s; - s = zbc_lex_next(&p->l); + s = zbc_lex_next(); if (s) RETURN_STATUS(s); if (p->l.lex != XC_LEX_NAME) RETURN_STATUS(bc_error_bad_token()); - bc_parse_pushName(p, p->l.lex_buf.v); + bc_parse_pushName(p->l.lex_buf.v); RETURN_STATUS(s); } #define zdc_parse_register(...) (zdc_parse_register(__VA_ARGS__) COMMA_SUCCESS) -static void dc_parse_string(BcParse *p) +static void dc_parse_string(void) { + BcParse *p = &G.prs; char *str; size_t len = G.prog.strs.len; dbg_lex_enter("%s:%d entered", __func__, __LINE__); str = xstrdup(p->l.lex_buf.v); - bc_parse_push(p, XC_INST_STR); - bc_parse_pushIndex(p, len); + bc_parse_push(XC_INST_STR); + bc_parse_pushIndex(len); bc_vec_push(&G.prog.strs, &str); // Explanation needed here @@ -4906,55 +4950,56 @@ static void dc_parse_string(BcParse *p) dbg_lex_done("%s:%d done", __func__, __LINE__); } -static BC_STATUS zdc_parse_mem(BcParse *p, uint8_t inst, bool name, bool store) +static BC_STATUS zdc_parse_mem(uint8_t inst, bool name, bool store) { BcStatus s; - bc_parse_push(p, inst); + bc_parse_push(inst); if (name) { - s = zdc_parse_register(p); + s = zdc_parse_register(); if (s) RETURN_STATUS(s); } if (store) { - bc_parse_push(p, DC_INST_SWAP); - bc_parse_push(p, XC_INST_ASSIGN); - bc_parse_push(p, XC_INST_POP); + bc_parse_push(DC_INST_SWAP); + bc_parse_push(XC_INST_ASSIGN); + bc_parse_push(XC_INST_POP); } RETURN_STATUS(BC_STATUS_SUCCESS); } #define zdc_parse_mem(...) (zdc_parse_mem(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zdc_parse_cond(BcParse *p, uint8_t inst) +static BC_STATUS zdc_parse_cond(uint8_t inst) { + BcParse *p = &G.prs; BcStatus s; - bc_parse_push(p, inst); - bc_parse_push(p, DC_INST_EXEC_COND); + bc_parse_push(inst); + bc_parse_push(DC_INST_EXEC_COND); - s = zdc_parse_register(p); + s = zdc_parse_register(); if (s) RETURN_STATUS(s); - s = zbc_lex_next(&p->l); + s = zbc_lex_next(); if (s) RETURN_STATUS(s); // Note that 'else' part can not be on the next line: // echo -e '[1p]sa [2p]sb 2 1>a eb' | dc - OK, prints "2" // echo -e '[1p]sa [2p]sb 2 1>a\neb' | dc - parse error if (p->l.lex == DC_LEX_ELSE) { - s = zdc_parse_register(p); + s = zdc_parse_register(); if (s) RETURN_STATUS(s); - s = zbc_lex_next(&p->l); + s = zbc_lex_next(); } else { - bc_parse_push(p, BC_PARSE_STREND); + bc_parse_push(BC_PARSE_STREND); } RETURN_STATUS(s); } #define zdc_parse_cond(...) (zdc_parse_cond(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t) +static BC_STATUS zdc_parse_token(BcLexType t) { BcStatus s; uint8_t inst; @@ -4971,88 +5016,90 @@ static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t) case XC_LEX_OP_REL_LT: case XC_LEX_OP_REL_GT: dbg_lex("%s:%d LEX_OP_REL_xyz", __func__, __LINE__); - s = zdc_parse_cond(p, t - XC_LEX_OP_REL_EQ + XC_INST_REL_EQ); + s = zdc_parse_cond(t - XC_LEX_OP_REL_EQ + XC_INST_REL_EQ); get_token = false; break; case DC_LEX_SCOLON: case DC_LEX_COLON: dbg_lex("%s:%d LEX_[S]COLON", __func__, __LINE__); - s = zdc_parse_mem(p, XC_INST_ARRAY_ELEM, true, t == DC_LEX_COLON); + s = zdc_parse_mem(XC_INST_ARRAY_ELEM, true, t == DC_LEX_COLON); break; case XC_LEX_STR: dbg_lex("%s:%d LEX_STR", __func__, __LINE__); - dc_parse_string(p); + dc_parse_string(); break; case XC_LEX_NEG: dbg_lex("%s:%d LEX_NEG", __func__, __LINE__); - s = zbc_lex_next(&p->l); + s = zbc_lex_next(); if (s) RETURN_STATUS(s); - if (p->l.lex != XC_LEX_NUMBER) + if (G.prs.l.lex != XC_LEX_NUMBER) RETURN_STATUS(bc_error_bad_token()); - bc_parse_pushNUM(p); - bc_parse_push(p, XC_INST_NEG); + bc_parse_pushNUM(); + bc_parse_push(XC_INST_NEG); break; case XC_LEX_NUMBER: dbg_lex("%s:%d LEX_NUMBER", __func__, __LINE__); - bc_parse_pushNUM(p); + bc_parse_pushNUM(); break; case DC_LEX_READ: dbg_lex("%s:%d LEX_KEY_READ", __func__, __LINE__); - bc_parse_push(p, XC_INST_READ); + bc_parse_push(XC_INST_READ); break; case DC_LEX_OP_ASSIGN: case DC_LEX_STORE_PUSH: dbg_lex("%s:%d LEX_OP_ASSIGN/STORE_PUSH", __func__, __LINE__); assign = (t == DC_LEX_OP_ASSIGN); inst = assign ? XC_INST_VAR : DC_INST_PUSH_TO_VAR; - s = zdc_parse_mem(p, inst, true, assign); + s = zdc_parse_mem(inst, true, assign); break; case DC_LEX_LOAD: case DC_LEX_LOAD_POP: dbg_lex("%s:%d LEX_OP_LOAD[_POP]", __func__, __LINE__); inst = t == DC_LEX_LOAD_POP ? DC_INST_PUSH_VAR : DC_INST_LOAD; - s = zdc_parse_mem(p, inst, true, false); + s = zdc_parse_mem(inst, true, false); break; case DC_LEX_STORE_IBASE: case DC_LEX_STORE_SCALE: case DC_LEX_STORE_OBASE: dbg_lex("%s:%d LEX_OP_STORE_I/OBASE/SCALE", __func__, __LINE__); inst = t - DC_LEX_STORE_IBASE + XC_INST_IBASE; - s = zdc_parse_mem(p, inst, false, true); + s = zdc_parse_mem(inst, false, true); break; default: dbg_lex_done("%s:%d done (bad token)", __func__, __LINE__); RETURN_STATUS(bc_error_bad_token()); } - if (!s && get_token) s = zbc_lex_next(&p->l); + if (!s && get_token) s = zbc_lex_next(); dbg_lex_done("%s:%d done", __func__, __LINE__); RETURN_STATUS(s); } #define zdc_parse_token(...) (zdc_parse_token(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zdc_parse_expr(BcParse *p) +static BC_STATUS zdc_parse_expr(void) { + BcParse *p = &G.prs; int i; i = (int)p->l.lex - (int)XC_LEX_OP_POWER; if (i >= 0) { BcInst inst = dc_LEX_to_INST[i]; if (inst != DC_INST_INVALID) { - bc_parse_push(p, inst); - RETURN_STATUS(zbc_lex_next(&p->l)); + bc_parse_push(inst); + RETURN_STATUS(zbc_lex_next()); } } - RETURN_STATUS(zdc_parse_token(p, p->l.lex)); + RETURN_STATUS(zdc_parse_token(p->l.lex)); } #define zdc_parse_expr(...) (zdc_parse_expr(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zdc_parse_exprs_until_eof(BcParse *p) +static BC_STATUS zdc_parse_exprs_until_eof(void) { + BcParse *p = &G.prs; dbg_lex_enter("%s:%d entered, p->l.lex:%d", __func__, __LINE__, p->l.lex); while (p->l.lex != XC_LEX_EOF) { - BcStatus s = zdc_parse_expr(p); + BcStatus s = zdc_parse_expr(); if (s) RETURN_STATUS(s); } @@ -5269,15 +5316,15 @@ static BC_STATUS zbc_program_read(void) bc_vec_pop_all(&f->code); sv_parse = G.prs; // struct copy - bc_parse_create(&G.prs, BC_PROG_READ); + bc_parse_create(BC_PROG_READ); //bc_lex_file(&G.prs.l); - not needed, error line info is not printed for read() - s = zbc_parse_text_init(&G.prs, buf.v); + s = zbc_parse_text_init(buf.v); if (s) goto exec_err; if (IS_BC) { - IF_BC(s = zbc_parse_expr(&G.prs, 0)); + IF_BC(s = zbc_parse_expr(0)); } else { - IF_DC(s = zdc_parse_exprs_until_eof(&G.prs)); + IF_DC(s = zdc_parse_exprs_until_eof()); } if (s) goto exec_err; @@ -5290,11 +5337,11 @@ static BC_STATUS zbc_program_read(void) ip.inst_idx = 0; IF_BC(ip.results_len_before_call = G.prog.results.len;) - bc_parse_push(&G.prs, XC_INST_RET); + bc_parse_push(XC_INST_RET); bc_vec_push(&G.prog.exestack, &ip); exec_err: - bc_parse_free(&G.prs); + bc_parse_free(); G.prs = sv_parse; // struct copy bc_vec_free(&buf); RETURN_STATUS(s); @@ -6404,17 +6451,17 @@ static BC_STATUS zdc_program_execStr(char *code, size_t *bgn, bool cond) char *str; sv_parse = G.prs; // struct copy - bc_parse_create(&G.prs, fidx); + bc_parse_create(fidx); str = *bc_program_str(sidx); - s = zbc_parse_text_init(&G.prs, str); + s = zbc_parse_text_init(str); if (s) goto err; - s = zdc_parse_exprs_until_eof(&G.prs); + s = zdc_parse_exprs_until_eof(); if (s) goto err; - bc_parse_push(&G.prs, DC_INST_POP_EXEC); + bc_parse_push(DC_INST_POP_EXEC); if (G.prs.l.lex != XC_LEX_EOF) s = bc_error_bad_expression(); - bc_parse_free(&G.prs); + bc_parse_free(); G.prs = sv_parse; // struct copy if (s) { err: @@ -6745,7 +6792,7 @@ static BC_STATUS zbc_vm_process(const char *text) BcStatus s; dbg_lex_enter("%s:%d entered", __func__, __LINE__); - s = zbc_parse_text_init(&G.prs, text); // does the first zbc_lex_next() + s = zbc_parse_text_init(text); // does the first zbc_lex_next() if (s) RETURN_STATUS(s); IF_BC(check_eof:) @@ -6759,12 +6806,12 @@ static BC_STATUS zbc_vm_process(const char *text) if (G.prs.l.lex == BC_LEX_SCOLON || G.prs.l.lex == XC_LEX_NLINE ) { - s = zbc_lex_next(&G.prs.l); + s = zbc_lex_next(); if (s) goto err; goto check_eof; } - s = zbc_parse_stmt_or_funcdef(&G.prs); + s = zbc_parse_stmt_or_funcdef(); if (s) goto err; // Check that next token is a correct stmt delimiter - @@ -6790,17 +6837,17 @@ static BC_STATUS zbc_vm_process(const char *text) // Most of dc parsing assumes all whitespace, // including '\n', is eaten. while (G.prs.l.lex == XC_LEX_NLINE) { - s = zbc_lex_next(&G.prs.l); + s = zbc_lex_next(); if (s) goto err; if (G.prs.l.lex == XC_LEX_EOF) goto done; } - s = zdc_parse_expr(&G.prs); + s = zdc_parse_expr(); #endif } if (s || G_interrupt) { err: - bc_parse_reset(&G.prs); // includes bc_program_reset() + bc_parse_reset(); // includes bc_program_reset() RETURN_STATUS(BC_STATUS_FAILURE); } @@ -6872,7 +6919,7 @@ static BC_STATUS zbc_vm_execute_FILE(FILE *fp, const char *filename) G.prs.filename = filename; G.prs.input_fp = fp; - bc_lex_file(&G.prs.l); + bc_lex_file(); do { s = zbc_vm_process(""); @@ -7153,7 +7200,7 @@ static BC_STATUS zbc_vm_exec(void) // We know that internal library is not buggy, // thus error checking is normally disabled. # define DEBUG_LIB 0 - bc_lex_file(&G.prs.l); + bc_lex_file(); s = zbc_vm_process(bc_lib); if (DEBUG_LIB && s) RETURN_STATUS(s); } @@ -7202,7 +7249,7 @@ static void bc_vm_free(void) { bc_vec_free(&G.files); bc_program_free(); - bc_parse_free(&G.prs); + bc_parse_free(); free(G.env_args); } #endif @@ -7266,7 +7313,7 @@ static int bc_vm_init(const char *env_len) bc_vec_init(&G.files, sizeof(char *), NULL); IF_BC(if (IS_BC) bc_vm_envArgs();) bc_program_init(); - bc_parse_create(&G.prs, BC_PROG_MAIN); + bc_parse_create(BC_PROG_MAIN); //TODO: in GNU bc, the check is (isatty(0) && isatty(1)), //-i option unconditionally enables this regardless of isatty(): -- cgit v1.2.3-55-g6feb From 8fac1c77401478855fd0ac1a7fa64c371bd735cb Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 25 Dec 2018 20:50:41 +0100 Subject: dc: add two tests Signed-off-by: Denys Vlasenko --- testsuite/dc.tests | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/testsuite/dc.tests b/testsuite/dc.tests index cb2dcbc23..2756608f7 100755 --- a/testsuite/dc.tests +++ b/testsuite/dc.tests @@ -56,6 +56,16 @@ testing "dc '>aeb' (conditional execute string with else)" \ "2\n9\n" \ "" "[1p]sa [2p]sb 2 1>aeb\n9p" +testing "dc space can be a register" \ + "dc" \ + "2\n9\n" \ + "" "[2p]s \n[3p]\nl x\n9p" + +testing "dc newline can be a register" \ + "dc" \ + "2\n9\n" \ + "" "[2p]s\n[3p]l\nx\n9p" + for f in dc_*.dc; do r="`basename "$f" .dc`_results.txt" test -f "$r" || continue -- cgit v1.2.3-55-g6feb From fa495ce4988f978dc2c716dba364e90e76cee844 Mon Sep 17 00:00:00 2001 From: Gavin Howard Date: Tue, 18 Dec 2018 10:03:14 -0700 Subject: bc: make it clear that the code is adapted Signed-off-by: Gavin Howard Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 75201f5f0..3e34d9e83 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1,7 +1,8 @@ /* vi: set sw=4 ts=4: */ /* * Licensed under GPLv2 or later, see file LICENSE in this source tree. - * Copyright (c) 2018 Gavin D. Howard and contributors. + * Adapted from https://github.com/gavinhoward/bc + * Original code copyright (c) 2018 Gavin D. Howard and contributors. */ //config:config BC //config: bool "bc (45 kb; 49 kb when combined with dc)" @@ -6950,7 +6951,8 @@ static BC_STATUS zbc_vm_file(const char *file) static void bc_vm_info(void) { printf("%s "BB_VER"\n" - "Copyright (c) 2018 Gavin D. Howard and contributors\n" + "Adapted from https://github.com/gavinhoward/bc\n" + "Original code (c) 2018 Gavin D. Howard and contributors\n" , applet_name); } -- cgit v1.2.3-55-g6feb From 3f8752c33f29d4cb4cc18fbff1f0da555f04c3ce Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 25 Dec 2018 21:28:25 +0100 Subject: bc: shorten error messages Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 3e34d9e83..8fa312a2b 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1029,12 +1029,12 @@ static BC_STATUS zbc_POSIX_does_not_allow(const char *msg) #define zbc_POSIX_does_not_allow(...) (zbc_POSIX_does_not_allow(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_POSIX_does_not_allow_bool_ops_this_is_bad(const char *msg) { - RETURN_STATUS(zbc_posix_error_fmt("%s%s %s", "POSIX does not allow ", "boolean operators; the following is bad:", msg)); + RETURN_STATUS(zbc_posix_error_fmt("%s%s %s", "POSIX does not allow ", "boolean operators; this is bad:", msg)); } #define zbc_POSIX_does_not_allow_bool_ops_this_is_bad(...) (zbc_POSIX_does_not_allow_bool_ops_this_is_bad(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_POSIX_does_not_allow_empty_X_expression_in_for(const char *msg) { - RETURN_STATUS(zbc_posix_error_fmt("%san empty %s expression in a for loop", "POSIX does not allow ", msg)); + RETURN_STATUS(zbc_posix_error_fmt("%san empty %s expression in 'for()'", "POSIX does not allow ", msg)); } #define zbc_POSIX_does_not_allow_empty_X_expression_in_for(...) (zbc_POSIX_does_not_allow_empty_X_expression_in_for(__VA_ARGS__) COMMA_SUCCESS) #endif @@ -3084,10 +3084,10 @@ static BC_STATUS zbc_lex_identifier(void) if (l->lex_buf.len > 2) { // Prevent this: // >>> qwe=1 - // bc: POSIX only allows one character names; the following is bad: 'qwe=1 + // bc: POSIX only allows one character names; this is bad: 'qwe=1 // ' unsigned len = strchrnul(buf, '\n') - buf; - s = zbc_posix_error_fmt("POSIX only allows one character names; the following is bad: '%.*s'", len, buf); + s = zbc_posix_error_fmt("POSIX only allows one character names; this is bad: '%.*s'", len, buf); } RETURN_STATUS(s); @@ -3107,7 +3107,7 @@ static BC_STATUS zbc_lex_string(void) char c = l->buf[i]; if (c == '\0') { l->i = i; - RETURN_STATUS(bc_error("string end could not be found")); + RETURN_STATUS(bc_error("unterminated string")); } if (c == '"') break; @@ -3162,7 +3162,7 @@ static BC_STATUS zbc_lex_comment(void) } if (c == '\0') { l->i = i; - RETURN_STATUS(bc_error("comment end could not be found")); + RETURN_STATUS(bc_error("unterminated comment")); } nls += (c == '\n'); } @@ -3261,7 +3261,7 @@ static BC_STATUS zbc_lex_token(void) s = zbc_lex_number(c); else { l->lex = BC_LEX_KEY_LAST; - s = zbc_POSIX_does_not_allow("a period ('.') as a shortcut for the last result"); + s = zbc_POSIX_does_not_allow("'.' as 'last'"); } break; case '/': @@ -4393,7 +4393,7 @@ static BC_STATUS zbc_func_insert(BcFunc *f, char *name, bool var) autoid = (void*)f->autos.v; for (i = 0; i < f->autos.len; i++, autoid++) { if (strcmp(name, autoid->name) == 0) - RETURN_STATUS(bc_error("function parameter or auto var has the same name as another")); + RETURN_STATUS(bc_error("duplicate function parameter or auto name")); } a.idx = var; -- cgit v1.2.3-55-g6feb From 0b0e8d0509bdd45aa600d3ea2bf9043630809cd2 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 25 Dec 2018 21:44:10 +0100 Subject: bc: rename some members and macros, no code changes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 258 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 129 insertions(+), 129 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 8fa312a2b..7a6278cfc 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -518,31 +518,31 @@ typedef enum BcLexType { struct BcLexKeyword { char name8[8]; }; -#define BC_LEX_KW_ENTRY(a, b) \ +#define LEX_KW_ENTRY(a, b) \ { .name8 = a /*, .posix = b */ } static const struct BcLexKeyword bc_lex_kws[20] = { - BC_LEX_KW_ENTRY("auto" , 1), // 0 - BC_LEX_KW_ENTRY("break" , 1), // 1 - BC_LEX_KW_ENTRY("continue", 0), // 2 note: this one has no terminating NUL - BC_LEX_KW_ENTRY("define" , 1), // 3 - BC_LEX_KW_ENTRY("else" , 0), // 4 - BC_LEX_KW_ENTRY("for" , 1), // 5 - BC_LEX_KW_ENTRY("halt" , 0), // 6 - BC_LEX_KW_ENTRY("ibase" , 1), // 7 - BC_LEX_KW_ENTRY("obase" , 1), // 8 - BC_LEX_KW_ENTRY("if" , 1), // 9 - BC_LEX_KW_ENTRY("last" , 0), // 10 - BC_LEX_KW_ENTRY("length" , 1), // 11 - BC_LEX_KW_ENTRY("limits" , 0), // 12 - BC_LEX_KW_ENTRY("print" , 0), // 13 - BC_LEX_KW_ENTRY("quit" , 1), // 14 - BC_LEX_KW_ENTRY("read" , 0), // 15 - BC_LEX_KW_ENTRY("return" , 1), // 16 - BC_LEX_KW_ENTRY("scale" , 1), // 17 - BC_LEX_KW_ENTRY("sqrt" , 1), // 18 - BC_LEX_KW_ENTRY("while" , 1), // 19 + LEX_KW_ENTRY("auto" , 1), // 0 + LEX_KW_ENTRY("break" , 1), // 1 + LEX_KW_ENTRY("continue", 0), // 2 note: this one has no terminating NUL + LEX_KW_ENTRY("define" , 1), // 3 + LEX_KW_ENTRY("else" , 0), // 4 + LEX_KW_ENTRY("for" , 1), // 5 + LEX_KW_ENTRY("halt" , 0), // 6 + LEX_KW_ENTRY("ibase" , 1), // 7 + LEX_KW_ENTRY("obase" , 1), // 8 + LEX_KW_ENTRY("if" , 1), // 9 + LEX_KW_ENTRY("last" , 0), // 10 + LEX_KW_ENTRY("length" , 1), // 11 + LEX_KW_ENTRY("limits" , 0), // 12 + LEX_KW_ENTRY("print" , 0), // 13 + LEX_KW_ENTRY("quit" , 1), // 14 + LEX_KW_ENTRY("read" , 0), // 15 + LEX_KW_ENTRY("return" , 1), // 16 + LEX_KW_ENTRY("scale" , 1), // 17 + LEX_KW_ENTRY("sqrt" , 1), // 18 + LEX_KW_ENTRY("while" , 1), // 19 }; -#undef BC_LEX_KW_ENTRY +#undef LEX_KW_ENTRY #define STRING_else (bc_lex_kws[4].name8) #define STRING_for (bc_lex_kws[5].name8) #define STRING_if (bc_lex_kws[9].name8) @@ -570,7 +570,7 @@ enum { | (1 << 18) // 18 | (1 << 19) // 19 }; -#define bc_lex_kws_POSIX(i) ((1 << (i)) & POSIX_KWORD_MASK) +#define keyword_is_POSIX(i) ((1 << (i)) & POSIX_KWORD_MASK) // This is a bit array that corresponds to token types. An entry is // true if the token is valid in an expression, false otherwise. @@ -711,15 +711,15 @@ dc_LEX_to_INST[] = { // starts at XC_LEX_OP_POWER // corresponding XC/DC_L #endif // ENABLE_DC typedef struct BcLex { - const char *buf; + const char *lex_inbuf; const char *lex_next_at; // last lex_next() was called at this string - size_t i; - size_t line; - size_t len; - bool newline; + size_t lex_i; + size_t lex_line; + size_t lex_len; + bool lex_newline; smallint lex; // was BcLexType smallint lex_last; // was BcLexType - BcVec lex_buf; + BcVec lex_strnumbuf; } BcLex; #define BC_PARSE_STREND (0xff) @@ -2755,10 +2755,10 @@ static void bc_lex_lineComment(void) // Try: echo -n '#foo' | bc size_t i; l->lex = XC_LEX_WHITESPACE; - i = l->i; - while (i < l->len && l->buf[i] != '\n') + i = l->lex_i; + while (i < l->lex_len && l->lex_inbuf[i] != '\n') i++; - l->i = i; + l->lex_i = i; } static void bc_lex_whitespace(void) @@ -2766,19 +2766,19 @@ static void bc_lex_whitespace(void) BcLex *l = &G.prs.l; l->lex = XC_LEX_WHITESPACE; for (;;) { - char c = l->buf[l->i]; + char c = l->lex_inbuf[l->lex_i]; if (c == '\n') // this is XC_LEX_NLINE, not XC_LEX_WHITESPACE break; if (!isspace(c)) break; - l->i++; + l->lex_i++; } } static BC_STATUS zbc_lex_number(char start) { BcLex *l = &G.prs.l; - const char *buf = l->buf + l->i; + const char *buf = l->lex_inbuf + l->lex_i; size_t len, i, ccnt; bool pt; @@ -2808,7 +2808,7 @@ static BC_STATUS zbc_lex_number(char start) //ccnt is the number of chars in the number string, excluding possible //trailing "[\].[\]" (with any number of \ repetitions). //i is buf[i] index of the first not-yet-parsed char after that. - l->i += i; + l->lex_i += i; // This might overestimate the size, if there are "\"'s // in the number. Subtracting number_of_backslashes*2 correctly @@ -2823,9 +2823,9 @@ static BC_STATUS zbc_lex_number(char start) RETURN_STATUS(bc_error("number too long: must be [1,"BC_MAX_NUM_STR"]")); } - bc_vec_pop_all(&l->lex_buf); - bc_vec_expand(&l->lex_buf, 1 + len); - bc_vec_push(&l->lex_buf, &start); + bc_vec_pop_all(&l->lex_strnumbuf); + bc_vec_expand(&l->lex_strnumbuf, 1 + len); + bc_vec_push(&l->lex_strnumbuf, &start); while (ccnt != 0) { // If we have hit a backslash, skip it. We don't have @@ -2835,12 +2835,12 @@ static BC_STATUS zbc_lex_number(char start) ccnt -= 2; continue; } - bc_vec_push(&l->lex_buf, buf); + bc_vec_push(&l->lex_strnumbuf, buf); buf++; ccnt--; } - bc_vec_pushZeroByte(&l->lex_buf); + bc_vec_pushZeroByte(&l->lex_strnumbuf); RETURN_STATUS(BC_STATUS_SUCCESS); } @@ -2855,7 +2855,7 @@ static void bc_lex_name(void) l->lex = XC_LEX_NAME; i = 0; - buf = l->buf + l->i - 1; + buf = l->lex_inbuf + l->lex_i - 1; for (;;) { char c = buf[i]; if ((c < 'a' || c > 'z') && !isdigit(c) && c != '_') break; @@ -2869,28 +2869,28 @@ static void bc_lex_name(void) return bc_error("name too long: must be [1,"BC_MAX_STRING_STR"]"); } #endif - bc_vec_string(&l->lex_buf, i, buf); + bc_vec_string(&l->lex_strnumbuf, i, buf); // Increment the index. We minus 1 because it has already been incremented. - l->i += i - 1; + l->lex_i += i - 1; //return BC_STATUS_SUCCESS; } static void bc_lex_init(void) { - bc_char_vec_init(&G.prs.l.lex_buf); + bc_char_vec_init(&G.prs.l.lex_strnumbuf); } static void bc_lex_free(void) { - bc_vec_free(&G.prs.l.lex_buf); + bc_vec_free(&G.prs.l.lex_strnumbuf); } static void bc_lex_file(void) { - G.err_line = G.prs.l.line = 1; - G.prs.l.newline = false; + G.err_line = G.prs.l.lex_line = 1; + G.prs.l.lex_newline = false; } static bool bc_lex_more_input(void) @@ -2958,12 +2958,12 @@ static bool bc_lex_more_input(void) break; } - l->buf = G.input_buffer.v; - l->i = 0; + l->lex_inbuf = G.input_buffer.v; + l->lex_i = 0; // bb_error_msg("G.input_buffer.len:%d '%s'", G.input_buffer.len, G.input_buffer.v); - l->len = G.input_buffer.len - 1; // do not include NUL + l->lex_len = G.input_buffer.len - 1; // do not include NUL - return l->len != 0; + return l->lex_len != 0; } IF_BC(static BC_STATUS zbc_lex_token(void);) @@ -2979,16 +2979,16 @@ static BC_STATUS zbc_lex_next(void) l->lex_last = l->lex; if (l->lex_last == XC_LEX_EOF) RETURN_STATUS(bc_error("end of file")); - l->line += l->newline; - G.err_line = l->line; - l->newline = false; + l->lex_line += l->lex_newline; + G.err_line = l->lex_line; + l->lex_newline = false; // Loop until failure or we don't have whitespace. This // is so the parser doesn't get inundated with whitespace. // Comments are also XC_LEX_WHITESPACE tokens and eaten here. s = BC_STATUS_SUCCESS; do { - if (l->i == l->len) { + if (l->lex_i == l->lex_len) { l->lex = XC_LEX_EOF; if (!G.prs.input_fp) RETURN_STATUS(BC_STATUS_SUCCESS); @@ -2996,9 +2996,9 @@ static BC_STATUS zbc_lex_next(void) G.prs.input_fp = NULL; RETURN_STATUS(BC_STATUS_SUCCESS); } - // here it's guaranteed that l->i is below l->len + // here it's guaranteed that l->lex_i is below l->lex_len } - l->lex_next_at = l->buf + l->i; + l->lex_next_at = l->lex_inbuf + l->lex_i; dbg_lex("next string to parse:'%.*s'", (int)(strchrnul(l->lex_next_at, '\n') - l->lex_next_at), l->lex_next_at @@ -3038,9 +3038,9 @@ static BC_STATUS zbc_lex_next_and_skip_NLINE(void) static BC_STATUS zbc_lex_text_init(const char *text) { - G.prs.l.buf = text; - G.prs.l.i = 0; - G.prs.l.len = strlen(text); + G.prs.l.lex_inbuf = text; + G.prs.l.lex_i = 0; + G.prs.l.lex_len = strlen(text); G.prs.l.lex = G.prs.l.lex_last = XC_LEX_INVALID; RETURN_STATUS(zbc_lex_next()); } @@ -3052,7 +3052,7 @@ static BC_STATUS zbc_lex_identifier(void) BcLex *l = &G.prs.l; BcStatus s; unsigned i; - const char *buf = l->buf + l->i - 1; + const char *buf = l->lex_inbuf + l->lex_i - 1; for (i = 0; i < ARRAY_SIZE(bc_lex_kws); ++i) { const char *keyword8 = bc_lex_kws[i].name8; @@ -3068,20 +3068,20 @@ static BC_STATUS zbc_lex_identifier(void) if (isalnum(buf[j]) || buf[j]=='_') continue; // "ifz" does not match "if" keyword, "if." does l->lex = BC_LEX_KEY_1st_keyword + i; - if (!bc_lex_kws_POSIX(i)) { + if (!keyword_is_POSIX(i)) { s = zbc_posix_error_fmt("%sthe '%.8s' keyword", "POSIX does not allow ", bc_lex_kws[i].name8); if (s) RETURN_STATUS(s); } // We minus 1 because the index has already been incremented. - l->i += j - 1; + l->lex_i += j - 1; RETURN_STATUS(BC_STATUS_SUCCESS); } bc_lex_name(); s = BC_STATUS_SUCCESS; - if (l->lex_buf.len > 2) { + if (l->lex_strnumbuf.len > 2) { // Prevent this: // >>> qwe=1 // bc: POSIX only allows one character names; this is bad: 'qwe=1 @@ -3102,11 +3102,11 @@ static BC_STATUS zbc_lex_string(void) l->lex = XC_LEX_STR; nls = 0; - i = l->i; + i = l->lex_i; for (;;) { - char c = l->buf[i]; + char c = l->lex_inbuf[i]; if (c == '\0') { - l->i = i; + l->lex_i = i; RETURN_STATUS(bc_error("unterminated string")); } if (c == '"') @@ -3115,17 +3115,17 @@ static BC_STATUS zbc_lex_string(void) i++; } - len = i - l->i; + len = i - l->lex_i; // This check makes sense only if size_t is (much) larger than BC_MAX_STRING. if (SIZE_MAX > (BC_MAX_STRING | 0xff)) { if (len > BC_MAX_STRING) RETURN_STATUS(bc_error("string too long: must be [1,"BC_MAX_STRING_STR"]")); } - bc_vec_string(&l->lex_buf, len, l->buf + l->i); + bc_vec_string(&l->lex_strnumbuf, len, l->lex_inbuf + l->lex_i); - l->i = i + 1; - l->line += nls; - G.err_line = l->line; + l->lex_i = i + 1; + l->lex_line += nls; + G.err_line = l->lex_line; RETURN_STATUS(BC_STATUS_SUCCESS); } @@ -3134,8 +3134,8 @@ static BC_STATUS zbc_lex_string(void) static void bc_lex_assign(unsigned with_and_without) { BcLex *l = &G.prs.l; - if (l->buf[l->i] == '=') { - ++l->i; + if (l->lex_inbuf[l->lex_i] == '=') { + l->lex_i++; with_and_without >>= 8; // store "with" value } // else store "without" value l->lex = (with_and_without & 0xff); @@ -3147,10 +3147,10 @@ static BC_STATUS zbc_lex_comment(void) { BcLex *l = &G.prs.l; size_t i, nls = 0; - const char *buf = l->buf; + const char *buf = l->lex_inbuf; l->lex = XC_LEX_WHITESPACE; - i = l->i; /* here buf[l->i] is the '*' of opening comment delimiter */ + i = l->lex_i; /* here buf[l->lex_i] is the '*' of opening comment delimiter */ for (;;) { char c = buf[++i]; check_star: @@ -3161,15 +3161,15 @@ static BC_STATUS zbc_lex_comment(void) goto check_star; } if (c == '\0') { - l->i = i; + l->lex_i = i; RETURN_STATUS(bc_error("unterminated comment")); } nls += (c == '\n'); } - l->i = i + 1; - l->line += nls; - G.err_line = l->line; + l->lex_i = i + 1; + l->lex_line += nls; + G.err_line = l->lex_line; RETURN_STATUS(BC_STATUS_SUCCESS); } @@ -3180,18 +3180,18 @@ static BC_STATUS zbc_lex_token(void) { BcLex *l = &G.prs.l; BcStatus s = BC_STATUS_SUCCESS; - char c = l->buf[l->i++], c2; + char c = l->lex_inbuf[l->lex_i++], c2; // This is the workhorse of the lexer. switch (c) { // case '\0': // probably never reached -// l->i--; +// l->lex_i--; // l->lex = XC_LEX_EOF; -// l->newline = true; +// l->lex_newline = true; // break; case '\n': l->lex = XC_LEX_NLINE; - l->newline = true; + l->lex_newline = true; break; case '\t': case '\v': @@ -3219,11 +3219,11 @@ static BC_STATUS zbc_lex_token(void) bc_lex_assign(BC_LEX_OP_ASSIGN_MODULUS, XC_LEX_OP_MODULUS); break; case '&': - c2 = l->buf[l->i]; + c2 = l->lex_inbuf[l->lex_i]; if (c2 == '&') { s = zbc_POSIX_does_not_allow_bool_ops_this_is_bad("&&"); if (s) RETURN_STATUS(s); - ++l->i; + l->lex_i++; l->lex = BC_LEX_OP_BOOL_AND; } else { l->lex = XC_LEX_INVALID; @@ -3238,9 +3238,9 @@ static BC_STATUS zbc_lex_token(void) bc_lex_assign(BC_LEX_OP_ASSIGN_MULTIPLY, XC_LEX_OP_MULTIPLY); break; case '+': - c2 = l->buf[l->i]; + c2 = l->lex_inbuf[l->lex_i]; if (c2 == '+') { - ++l->i; + l->lex_i++; l->lex = BC_LEX_OP_INC; } else bc_lex_assign(BC_LEX_OP_ASSIGN_PLUS, XC_LEX_OP_PLUS); @@ -3249,15 +3249,15 @@ static BC_STATUS zbc_lex_token(void) l->lex = BC_LEX_COMMA; break; case '-': - c2 = l->buf[l->i]; + c2 = l->lex_inbuf[l->lex_i]; if (c2 == '-') { - ++l->i; + l->lex_i++; l->lex = BC_LEX_OP_DEC; } else bc_lex_assign(BC_LEX_OP_ASSIGN_MINUS, XC_LEX_OP_MINUS); break; case '.': - if (isdigit(l->buf[l->i])) + if (isdigit(l->lex_inbuf[l->lex_i])) s = zbc_lex_number(c); else { l->lex = BC_LEX_KEY_LAST; @@ -3265,7 +3265,7 @@ static BC_STATUS zbc_lex_token(void) } break; case '/': - c2 = l->buf[l->i]; + c2 = l->lex_inbuf[l->lex_i]; if (c2 == '*') s = zbc_lex_comment(); else @@ -3306,9 +3306,9 @@ static BC_STATUS zbc_lex_token(void) l->lex = (BcLexType)(c - '[' + BC_LEX_LBRACKET); break; case '\\': - if (l->buf[l->i] == '\n') { + if (l->lex_inbuf[l->lex_i] == '\n') { l->lex = XC_LEX_WHITESPACE; - ++l->i; + l->lex_i++; } else s = bc_error_bad_character(c); break; @@ -3348,11 +3348,11 @@ static BC_STATUS zbc_lex_token(void) l->lex = (BcLexType)(c - '{' + BC_LEX_LBRACE); break; case '|': - c2 = l->buf[l->i]; + c2 = l->lex_inbuf[l->lex_i]; if (c2 == '|') { s = zbc_POSIX_does_not_allow_bool_ops_this_is_bad("||"); if (s) RETURN_STATUS(s); - ++l->i; + l->lex_i++; l->lex = BC_LEX_OP_BOOL_OR; } else { l->lex = XC_LEX_INVALID; @@ -3374,14 +3374,14 @@ static BC_STATUS zbc_lex_token(void) static BC_STATUS zdc_lex_register(void) { BcLex *l = &G.prs.l; - if (G_exreg && isspace(l->buf[l->i])) { + if (G_exreg && isspace(l->lex_inbuf[l->lex_i])) { bc_lex_whitespace(); // eats whitespace (but not newline) - l->i++; // bc_lex_name() expects this + l->lex_i++; // bc_lex_name() expects this bc_lex_name(); } else { - bc_vec_pop_all(&l->lex_buf); - bc_vec_push(&l->lex_buf, &l->buf[l->i++]); - bc_vec_pushZeroByte(&l->lex_buf); + bc_vec_pop_all(&l->lex_strnumbuf); + bc_vec_push(&l->lex_strnumbuf, &l->lex_inbuf[l->lex_i++]); + bc_vec_pushZeroByte(&l->lex_strnumbuf); l->lex = XC_LEX_NAME; } @@ -3395,39 +3395,39 @@ static BC_STATUS zdc_lex_string(void) size_t depth, nls, i; l->lex = XC_LEX_STR; - bc_vec_pop_all(&l->lex_buf); + bc_vec_pop_all(&l->lex_strnumbuf); nls = 0; depth = 1; - i = l->i; + i = l->lex_i; for (;;) { - char c = l->buf[i]; + char c = l->lex_inbuf[i]; if (c == '\0') { - l->i = i; + l->lex_i = i; RETURN_STATUS(bc_error("string end could not be found")); } nls += (c == '\n'); - if (i == l->i || l->buf[i - 1] != '\\') { + if (i == l->lex_i || l->lex_inbuf[i - 1] != '\\') { if (c == '[') depth++; if (c == ']') if (--depth == 0) break; } - bc_vec_push(&l->lex_buf, &l->buf[i]); + bc_vec_push(&l->lex_strnumbuf, &l->lex_inbuf[i]); i++; } i++; - bc_vec_pushZeroByte(&l->lex_buf); + bc_vec_pushZeroByte(&l->lex_strnumbuf); // This check makes sense only if size_t is (much) larger than BC_MAX_STRING. if (SIZE_MAX > (BC_MAX_STRING | 0xff)) { - if (i - l->i > BC_MAX_STRING) + if (i - l->lex_i > BC_MAX_STRING) RETURN_STATUS(bc_error("string too long: must be [1,"BC_MAX_STRING_STR"]")); } - l->i = i; - l->line += nls; - G.err_line = l->line; + l->lex_i = i; + l->lex_line += nls; + G.err_line = l->lex_line; RETURN_STATUS(BC_STATUS_SUCCESS); } @@ -3456,7 +3456,7 @@ static BC_STATUS zdc_lex_token(void) } s = BC_STATUS_SUCCESS; - c = l->buf[l->i++]; + c = l->lex_inbuf[l->lex_i++]; if (c >= '%' && c <= '~' && (l->lex = dc_char_to_LEX[c - '%']) != XC_LEX_INVALID ) { @@ -3478,18 +3478,18 @@ static BC_STATUS zdc_lex_token(void) // IOW: typing "1p" should print "1" _at once_, // not after some more input. l->lex = XC_LEX_NLINE; - l->newline = true; + l->lex_newline = true; break; case '\t': case '\v': case '\f': case '\r': case ' ': - l->newline = 0; // was (c == '\n') + l->lex_newline = 0; // was (c == '\n') bc_lex_whitespace(); break; case '!': - c2 = l->buf[l->i]; + c2 = l->lex_inbuf[l->lex_i]; if (c2 == '=') l->lex = XC_LEX_OP_REL_NE; else if (c2 == '<') @@ -3498,13 +3498,13 @@ static BC_STATUS zdc_lex_token(void) l->lex = XC_LEX_OP_REL_GE; else RETURN_STATUS(bc_error_bad_character(c)); - ++l->i; + l->lex_i++; break; case '#': bc_lex_lineComment(); break; case '.': - if (isdigit(l->buf[l->i])) + if (isdigit(l->lex_inbuf[l->lex_i])) s = zbc_lex_number(c); else s = bc_error_bad_character(c); @@ -3593,7 +3593,7 @@ static void bc_parse_pushJUMP_ZERO(size_t idx) static BC_STATUS zbc_parse_pushSTR(void) { BcParse *p = &G.prs; - char *str = xstrdup(p->l.lex_buf.v); + char *str = xstrdup(p->l.lex_strnumbuf.v); bc_parse_push(XC_INST_STR); bc_parse_pushIndex(p->func->strs.len); @@ -3607,7 +3607,7 @@ static BC_STATUS zbc_parse_pushSTR(void) static void bc_parse_pushNUM(void) { BcParse *p = &G.prs; - char *num = xstrdup(p->l.lex_buf.v); + char *num = xstrdup(p->l.lex_strnumbuf.v); #if ENABLE_BC && ENABLE_DC size_t idx = bc_vec_push(IS_BC ? &p->func->consts : &G.prog.consts, &num); #elif ENABLE_BC @@ -3656,7 +3656,7 @@ static void bc_parse_reset(void) p->func = bc_program_func_BC_PROG_MAIN(); } - p->l.i = p->l.len; + p->l.lex_i = p->l.lex_len; p->l.lex = XC_LEX_EOF; IF_BC(bc_vec_pop_all(&p->exits);) @@ -3897,7 +3897,7 @@ static BC_STATUS zbc_parse_name(BcInst *type, uint8_t flags) BcStatus s; char *name; - name = xstrdup(p->l.lex_buf.v); + name = xstrdup(p->l.lex_strnumbuf.v); s = zbc_lex_next(); if (s) goto err; @@ -4317,7 +4317,7 @@ static BC_STATUS zbc_parse_for(void) // Set this for the next call to bc_parse_pushNUM(). // This is safe to set because the current token is a semicolon, // which has no string requirement. - bc_vec_string(&p->l.lex_buf, 1, "1"); + bc_vec_string(&p->l.lex_strnumbuf, 1, "1"); bc_parse_pushNUM(); s = zbc_POSIX_does_not_allow_empty_X_expression_in_for("condition"); } @@ -4418,7 +4418,7 @@ static BC_STATUS zbc_parse_funcdef(void) if (p->l.lex != XC_LEX_NAME) RETURN_STATUS(bc_error("bad function definition")); - name = xstrdup(p->l.lex_buf.v); + name = xstrdup(p->l.lex_strnumbuf.v); p->fidx = bc_program_addFunc(name); p->func = bc_program_func(p->fidx); @@ -4435,7 +4435,7 @@ static BC_STATUS zbc_parse_funcdef(void) ++p->func->nparams; - name = xstrdup(p->l.lex_buf.v); + name = xstrdup(p->l.lex_strnumbuf.v); s = zbc_lex_next(); if (s) goto err; @@ -4517,7 +4517,7 @@ static BC_STATUS zbc_parse_auto(void) if (p->l.lex != XC_LEX_NAME) RETURN_STATUS(bc_error("bad 'auto' syntax")); - name = xstrdup(p->l.lex_buf.v); + name = xstrdup(p->l.lex_strnumbuf.v); s = zbc_lex_next(); if (s) goto err; @@ -4925,7 +4925,7 @@ static BC_STATUS zdc_parse_register(void) if (s) RETURN_STATUS(s); if (p->l.lex != XC_LEX_NAME) RETURN_STATUS(bc_error_bad_token()); - bc_parse_pushName(p->l.lex_buf.v); + bc_parse_pushName(p->l.lex_strnumbuf.v); RETURN_STATUS(s); } @@ -4939,7 +4939,7 @@ static void dc_parse_string(void) dbg_lex_enter("%s:%d entered", __func__, __LINE__); - str = xstrdup(p->l.lex_buf.v); + str = xstrdup(p->l.lex_strnumbuf.v); bc_parse_push(XC_INST_STR); bc_parse_pushIndex(len); bc_vec_push(&G.prog.strs, &str); -- cgit v1.2.3-55-g6feb From 6e6182342ef59c47972a49543cd8b15dc4f28f6d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 25 Dec 2018 22:20:14 +0100 Subject: bc: move BcLex::lex member to be the first in struct globals function old new delta zbc_program_exec 3967 4003 +36 zdc_program_execStr 501 520 +19 zbc_posix_error_fmt 58 62 +4 bc_vm_init 675 679 +4 bc_read_line 407 411 +4 bc_error_fmt 36 40 +4 zdc_parse_register 45 44 -1 zdc_parse_exprs_until_eof 28 27 -1 zbc_parse_text_init 56 55 -1 zbc_parse_stmt_allow_NLINE_before 55 54 -1 zbc_lex_skip_if_at_NLINE 19 18 -1 zbc_lex_number 178 177 -1 bc_parse_create 97 96 -1 bc_lex_whitespace 43 42 -1 bc_lex_name 71 70 -1 bc_lex_lineComment 38 37 -1 bc_lex_assign 35 34 -1 zdc_parse_expr 476 473 -3 bc_verror_msg 93 90 -3 bc_lex_file 27 24 -3 zbc_parse_name 453 448 -5 bc_parse_expr_empty_ok 1776 1764 -12 zbc_vm_process 878 865 -13 zbc_parse_stmt_possibly_auto 1451 1425 -26 zbc_lex_next 2075 2039 -36 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 6/19 up/down: 71/-112) Total: -41 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 130 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 65 insertions(+), 65 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 7a6278cfc..44d4976cc 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -711,40 +711,29 @@ dc_LEX_to_INST[] = { // starts at XC_LEX_OP_POWER // corresponding XC/DC_L #endif // ENABLE_DC typedef struct BcLex { - const char *lex_inbuf; - const char *lex_next_at; // last lex_next() was called at this string + smallint lex; // was BcLexType // first member is most used + smallint lex_last; // was BcLexType + bool lex_newline; size_t lex_i; size_t lex_line; size_t lex_len; - bool lex_newline; - smallint lex; // was BcLexType - smallint lex_last; // was BcLexType + const char *lex_inbuf; + const char *lex_next_at; // last lex_next() was called at this string BcVec lex_strnumbuf; } BcLex; -#define BC_PARSE_STREND (0xff) - -#if ENABLE_BC -# define BC_PARSE_REL (1 << 0) -# define BC_PARSE_PRINT (1 << 1) -# define BC_PARSE_ARRAY (1 << 2) -# define BC_PARSE_NOCALL (1 << 3) -#endif - typedef struct BcParse { - BcLex l; - - IF_BC(BcVec exits;) - IF_BC(BcVec conds;) - IF_BC(BcVec ops;) + BcLex l; // first member is most used const char *filename; FILE *input_fp; BcFunc *func; size_t fidx; - IF_BC(size_t in_funcdef;) + IF_BC(BcVec exits;) + IF_BC(BcVec conds;) + IF_BC(BcVec ops;) } BcParse; typedef struct BcProgram { @@ -775,6 +764,62 @@ typedef struct BcProgram { IF_BC(BcNum last;) } BcProgram; +struct globals { + BcParse prs; // first member is most used + + // For error messages. Can be set to current parsed line, + // or [TODO] to current executing line (can be before last parsed one) + unsigned err_line; + + BcVec input_buffer; + + IF_FEATURE_BC_SIGNALS(smallint ttyin;) + IF_FEATURE_CLEAN_UP(smallint exiting;) + + BcProgram prog; + + BcVec files; + + char *env_args; + +#if ENABLE_FEATURE_EDITING + line_input_t *line_input_state; +#endif +} FIX_ALIASING; +#define G (*ptr_to_globals) +#define INIT_G() do { \ + SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ +} while (0) +#define FREE_G() do { \ + FREE_PTR_TO_GLOBALS(); \ +} while (0) +#define G_posix (ENABLE_BC && (option_mask32 & BC_FLAG_S)) +#define G_warn (ENABLE_BC && (option_mask32 & BC_FLAG_W)) +#define G_exreg (ENABLE_DC && (option_mask32 & DC_FLAG_X)) +#if ENABLE_FEATURE_BC_SIGNALS +# define G_interrupt bb_got_signal +# define G_ttyin G.ttyin +#else +# define G_interrupt 0 +# define G_ttyin 0 +#endif +#if ENABLE_FEATURE_CLEAN_UP +# define G_exiting G.exiting +#else +# define G_exiting 0 +#endif +#define IS_BC (ENABLE_BC && (!ENABLE_DC || applet_name[0] == 'b')) +#define IS_DC (ENABLE_DC && (!ENABLE_BC || applet_name[0] != 'b')) + +#define BC_PARSE_STREND (0xff) + +#if ENABLE_BC +# define BC_PARSE_REL (1 << 0) +# define BC_PARSE_PRINT (1 << 1) +# define BC_PARSE_ARRAY (1 << 2) +# define BC_PARSE_NOCALL (1 << 3) +#endif + #define BC_PROG_MAIN (0) #define BC_PROG_READ (1) #if ENABLE_DC @@ -830,51 +875,6 @@ typedef struct BcProgram { #endif #define BC_MAX_NUM_STR BC_MAX_STRING_STR -struct globals { - IF_FEATURE_BC_SIGNALS(smallint ttyin;) - IF_FEATURE_CLEAN_UP(smallint exiting;) - - BcParse prs; - BcProgram prog; - - // For error messages. Can be set to current parsed line, - // or [TODO] to current executing line (can be before last parsed one) - unsigned err_line; - - BcVec files; - BcVec input_buffer; - - char *env_args; - -#if ENABLE_FEATURE_EDITING - line_input_t *line_input_state; -#endif -} FIX_ALIASING; -#define G (*ptr_to_globals) -#define INIT_G() do { \ - SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ -} while (0) -#define FREE_G() do { \ - FREE_PTR_TO_GLOBALS(); \ -} while (0) -#define G_posix (ENABLE_BC && (option_mask32 & BC_FLAG_S)) -#define G_warn (ENABLE_BC && (option_mask32 & BC_FLAG_W)) -#define G_exreg (ENABLE_DC && (option_mask32 & DC_FLAG_X)) -#if ENABLE_FEATURE_BC_SIGNALS -# define G_interrupt bb_got_signal -# define G_ttyin G.ttyin -#else -# define G_interrupt 0 -# define G_ttyin 0 -#endif -#if ENABLE_FEATURE_CLEAN_UP -# define G_exiting G.exiting -#else -# define G_exiting 0 -#endif -#define IS_BC (ENABLE_BC && (!ENABLE_DC || applet_name[0] == 'b')) -#define IS_DC (ENABLE_DC && (!ENABLE_BC || applet_name[0] != 'b')) - // In configurations where errors abort instead of propagating error // return code up the call chain, functions returning BC_STATUS // actually don't return anything, they always succeed and return "void". -- cgit v1.2.3-55-g6feb From ecb62edd478e8ae2b1a5f3d122e316345909a805 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 25 Dec 2018 22:32:41 +0100 Subject: bc: fold struct BcLex into BcParse Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 529 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 262 insertions(+), 267 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 44d4976cc..61fb24304 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -710,7 +710,7 @@ dc_LEX_to_INST[] = { // starts at XC_LEX_OP_POWER // corresponding XC/DC_L }; #endif // ENABLE_DC -typedef struct BcLex { +typedef struct BcParse { smallint lex; // was BcLexType // first member is most used smallint lex_last; // was BcLexType bool lex_newline; @@ -719,14 +719,9 @@ typedef struct BcLex { size_t lex_len; const char *lex_inbuf; const char *lex_next_at; // last lex_next() was called at this string + const char *lex_filename; + FILE *lex_input_fp; BcVec lex_strnumbuf; -} BcLex; - -typedef struct BcParse { - BcLex l; // first member is most used - - const char *filename; - FILE *input_fp; BcFunc *func; size_t fidx; @@ -937,12 +932,12 @@ static void quit(void) static void bc_verror_msg(const char *fmt, va_list p) { const char *sv = sv; // for compiler - if (G.prs.filename) { + if (G.prs.lex_filename) { sv = applet_name; - applet_name = xasprintf("%s: %s:%u", applet_name, G.prs.filename, G.err_line); + applet_name = xasprintf("%s: %s:%u", applet_name, G.prs.lex_filename, G.err_line); } bb_verror_msg(fmt, p, NULL); - if (G.prs.filename) { + if (G.prs.lex_filename) { free((char*)applet_name); applet_name = sv; } @@ -2582,12 +2577,12 @@ static void bc_read_line(BcVec *vec, FILE *fp) if (bad_chars) { // Bad chars on this line - if (!G.prs.filename) { // stdin + if (!G.prs.lex_filename) { // stdin // ignore entire line, get another one vec->len = len; goto again; } - bb_perror_msg_and_die("file '%s' is not text", G.prs.filename); + bb_perror_msg_and_die("file '%s' is not text", G.prs.lex_filename); } bc_vec_pushZeroByte(vec); } @@ -2751,39 +2746,39 @@ static BC_STATUS zbc_num_parse(BcNum *n, const char *val, unsigned base_t) static void bc_lex_lineComment(void) { - BcLex *l = &G.prs.l; + BcParse *p = &G.prs; // Try: echo -n '#foo' | bc size_t i; - l->lex = XC_LEX_WHITESPACE; - i = l->lex_i; - while (i < l->lex_len && l->lex_inbuf[i] != '\n') + p->lex = XC_LEX_WHITESPACE; + i = p->lex_i; + while (i < p->lex_len && p->lex_inbuf[i] != '\n') i++; - l->lex_i = i; + p->lex_i = i; } static void bc_lex_whitespace(void) { - BcLex *l = &G.prs.l; - l->lex = XC_LEX_WHITESPACE; + BcParse *p = &G.prs; + p->lex = XC_LEX_WHITESPACE; for (;;) { - char c = l->lex_inbuf[l->lex_i]; + char c = p->lex_inbuf[p->lex_i]; if (c == '\n') // this is XC_LEX_NLINE, not XC_LEX_WHITESPACE break; if (!isspace(c)) break; - l->lex_i++; + p->lex_i++; } } static BC_STATUS zbc_lex_number(char start) { - BcLex *l = &G.prs.l; - const char *buf = l->lex_inbuf + l->lex_i; + BcParse *p = &G.prs; + const char *buf = p->lex_inbuf + p->lex_i; size_t len, i, ccnt; bool pt; pt = (start == '.'); - l->lex = XC_LEX_NUMBER; + p->lex = XC_LEX_NUMBER; ccnt = i = 0; for (;;) { char c = buf[i]; @@ -2808,7 +2803,7 @@ static BC_STATUS zbc_lex_number(char start) //ccnt is the number of chars in the number string, excluding possible //trailing "[\].[\]" (with any number of \ repetitions). //i is buf[i] index of the first not-yet-parsed char after that. - l->lex_i += i; + p->lex_i += i; // This might overestimate the size, if there are "\"'s // in the number. Subtracting number_of_backslashes*2 correctly @@ -2823,9 +2818,9 @@ static BC_STATUS zbc_lex_number(char start) RETURN_STATUS(bc_error("number too long: must be [1,"BC_MAX_NUM_STR"]")); } - bc_vec_pop_all(&l->lex_strnumbuf); - bc_vec_expand(&l->lex_strnumbuf, 1 + len); - bc_vec_push(&l->lex_strnumbuf, &start); + bc_vec_pop_all(&p->lex_strnumbuf); + bc_vec_expand(&p->lex_strnumbuf, 1 + len); + bc_vec_push(&p->lex_strnumbuf, &start); while (ccnt != 0) { // If we have hit a backslash, skip it. We don't have @@ -2835,12 +2830,12 @@ static BC_STATUS zbc_lex_number(char start) ccnt -= 2; continue; } - bc_vec_push(&l->lex_strnumbuf, buf); + bc_vec_push(&p->lex_strnumbuf, buf); buf++; ccnt--; } - bc_vec_pushZeroByte(&l->lex_strnumbuf); + bc_vec_pushZeroByte(&p->lex_strnumbuf); RETURN_STATUS(BC_STATUS_SUCCESS); } @@ -2848,14 +2843,14 @@ static BC_STATUS zbc_lex_number(char start) static void bc_lex_name(void) { - BcLex *l = &G.prs.l; + BcParse *p = &G.prs; size_t i; const char *buf; - l->lex = XC_LEX_NAME; + p->lex = XC_LEX_NAME; i = 0; - buf = l->lex_inbuf + l->lex_i - 1; + buf = p->lex_inbuf + p->lex_i - 1; for (;;) { char c = buf[i]; if ((c < 'a' || c > 'z') && !isdigit(c) && c != '_') break; @@ -2869,33 +2864,33 @@ static void bc_lex_name(void) return bc_error("name too long: must be [1,"BC_MAX_STRING_STR"]"); } #endif - bc_vec_string(&l->lex_strnumbuf, i, buf); + bc_vec_string(&p->lex_strnumbuf, i, buf); // Increment the index. We minus 1 because it has already been incremented. - l->lex_i += i - 1; + p->lex_i += i - 1; //return BC_STATUS_SUCCESS; } static void bc_lex_init(void) { - bc_char_vec_init(&G.prs.l.lex_strnumbuf); + bc_char_vec_init(&G.prs.lex_strnumbuf); } static void bc_lex_free(void) { - bc_vec_free(&G.prs.l.lex_strnumbuf); + bc_vec_free(&G.prs.lex_strnumbuf); } static void bc_lex_file(void) { - G.err_line = G.prs.l.lex_line = 1; - G.prs.l.lex_newline = false; + G.err_line = G.prs.lex_line = 1; + G.prs.lex_newline = false; } static bool bc_lex_more_input(void) { - BcLex *l = &G.prs.l; + BcParse *p = &G.prs; size_t str; bool comment; @@ -2911,7 +2906,7 @@ static bool bc_lex_more_input(void) size_t prevlen = G.input_buffer.len; char *string; - bc_read_line(&G.input_buffer, G.prs.input_fp); + bc_read_line(&G.input_buffer, G.prs.lex_input_fp); // No more input means EOF if (G.input_buffer.len <= prevlen + 1) // (we expect +1 for NUL byte) break; @@ -2958,12 +2953,12 @@ static bool bc_lex_more_input(void) break; } - l->lex_inbuf = G.input_buffer.v; - l->lex_i = 0; + p->lex_inbuf = G.input_buffer.v; + p->lex_i = 0; // bb_error_msg("G.input_buffer.len:%d '%s'", G.input_buffer.len, G.input_buffer.v); - l->lex_len = G.input_buffer.len - 1; // do not include NUL + p->lex_len = G.input_buffer.len - 1; // do not include NUL - return l->lex_len != 0; + return p->lex_len != 0; } IF_BC(static BC_STATUS zbc_lex_token(void);) @@ -2973,43 +2968,43 @@ IF_DC(static BC_STATUS zdc_lex_token(void);) static BC_STATUS zbc_lex_next(void) { - BcLex *l = &G.prs.l; + BcParse *p = &G.prs; BcStatus s; - l->lex_last = l->lex; - if (l->lex_last == XC_LEX_EOF) RETURN_STATUS(bc_error("end of file")); + p->lex_last = p->lex; + if (p->lex_last == XC_LEX_EOF) RETURN_STATUS(bc_error("end of file")); - l->lex_line += l->lex_newline; - G.err_line = l->lex_line; - l->lex_newline = false; + p->lex_line += p->lex_newline; + G.err_line = p->lex_line; + p->lex_newline = false; // Loop until failure or we don't have whitespace. This // is so the parser doesn't get inundated with whitespace. // Comments are also XC_LEX_WHITESPACE tokens and eaten here. s = BC_STATUS_SUCCESS; do { - if (l->lex_i == l->lex_len) { - l->lex = XC_LEX_EOF; - if (!G.prs.input_fp) + if (p->lex_i == p->lex_len) { + p->lex = XC_LEX_EOF; + if (!G.prs.lex_input_fp) RETURN_STATUS(BC_STATUS_SUCCESS); if (!bc_lex_more_input()) { - G.prs.input_fp = NULL; + G.prs.lex_input_fp = NULL; RETURN_STATUS(BC_STATUS_SUCCESS); } - // here it's guaranteed that l->lex_i is below l->lex_len + // here it's guaranteed that p->lex_i is below p->lex_len } - l->lex_next_at = l->lex_inbuf + l->lex_i; + p->lex_next_at = p->lex_inbuf + p->lex_i; dbg_lex("next string to parse:'%.*s'", - (int)(strchrnul(l->lex_next_at, '\n') - l->lex_next_at), - l->lex_next_at + (int)(strchrnul(p->lex_next_at, '\n') - p->lex_next_at), + p->lex_next_at ); if (IS_BC) { IF_BC(s = zbc_lex_token()); } else { IF_DC(s = zdc_lex_token()); } - } while (!s && l->lex == XC_LEX_WHITESPACE); - dbg_lex("l->lex from string:%d", l->lex); + } while (!s && p->lex == XC_LEX_WHITESPACE); + dbg_lex("p->lex from string:%d", p->lex); RETURN_STATUS(s); } @@ -3018,7 +3013,7 @@ static BC_STATUS zbc_lex_next(void) #if ENABLE_BC static BC_STATUS zbc_lex_skip_if_at_NLINE(void) { - if (G.prs.l.lex == XC_LEX_NLINE) + if (G.prs.lex == XC_LEX_NLINE) RETURN_STATUS(zbc_lex_next()); RETURN_STATUS(BC_STATUS_SUCCESS); } @@ -3038,10 +3033,10 @@ static BC_STATUS zbc_lex_next_and_skip_NLINE(void) static BC_STATUS zbc_lex_text_init(const char *text) { - G.prs.l.lex_inbuf = text; - G.prs.l.lex_i = 0; - G.prs.l.lex_len = strlen(text); - G.prs.l.lex = G.prs.l.lex_last = XC_LEX_INVALID; + G.prs.lex_inbuf = text; + G.prs.lex_i = 0; + G.prs.lex_len = strlen(text); + G.prs.lex = G.prs.lex_last = XC_LEX_INVALID; RETURN_STATUS(zbc_lex_next()); } #define zbc_lex_text_init(...) (zbc_lex_text_init(__VA_ARGS__) COMMA_SUCCESS) @@ -3049,10 +3044,10 @@ static BC_STATUS zbc_lex_text_init(const char *text) #if ENABLE_BC static BC_STATUS zbc_lex_identifier(void) { - BcLex *l = &G.prs.l; + BcParse *p = &G.prs; BcStatus s; unsigned i; - const char *buf = l->lex_inbuf + l->lex_i - 1; + const char *buf = p->lex_inbuf + p->lex_i - 1; for (i = 0; i < ARRAY_SIZE(bc_lex_kws); ++i) { const char *keyword8 = bc_lex_kws[i].name8; @@ -3067,21 +3062,21 @@ static BC_STATUS zbc_lex_identifier(void) // buf starts with keyword bc_lex_kws[i] if (isalnum(buf[j]) || buf[j]=='_') continue; // "ifz" does not match "if" keyword, "if." does - l->lex = BC_LEX_KEY_1st_keyword + i; + p->lex = BC_LEX_KEY_1st_keyword + i; if (!keyword_is_POSIX(i)) { s = zbc_posix_error_fmt("%sthe '%.8s' keyword", "POSIX does not allow ", bc_lex_kws[i].name8); if (s) RETURN_STATUS(s); } // We minus 1 because the index has already been incremented. - l->lex_i += j - 1; + p->lex_i += j - 1; RETURN_STATUS(BC_STATUS_SUCCESS); } bc_lex_name(); s = BC_STATUS_SUCCESS; - if (l->lex_strnumbuf.len > 2) { + if (p->lex_strnumbuf.len > 2) { // Prevent this: // >>> qwe=1 // bc: POSIX only allows one character names; this is bad: 'qwe=1 @@ -3096,17 +3091,17 @@ static BC_STATUS zbc_lex_identifier(void) static BC_STATUS zbc_lex_string(void) { - BcLex *l = &G.prs.l; + BcParse *p = &G.prs; size_t len, nls, i; - l->lex = XC_LEX_STR; + p->lex = XC_LEX_STR; nls = 0; - i = l->lex_i; + i = p->lex_i; for (;;) { - char c = l->lex_inbuf[i]; + char c = p->lex_inbuf[i]; if (c == '\0') { - l->lex_i = i; + p->lex_i = i; RETURN_STATUS(bc_error("unterminated string")); } if (c == '"') @@ -3115,17 +3110,17 @@ static BC_STATUS zbc_lex_string(void) i++; } - len = i - l->lex_i; + len = i - p->lex_i; // This check makes sense only if size_t is (much) larger than BC_MAX_STRING. if (SIZE_MAX > (BC_MAX_STRING | 0xff)) { if (len > BC_MAX_STRING) RETURN_STATUS(bc_error("string too long: must be [1,"BC_MAX_STRING_STR"]")); } - bc_vec_string(&l->lex_strnumbuf, len, l->lex_inbuf + l->lex_i); + bc_vec_string(&p->lex_strnumbuf, len, p->lex_inbuf + p->lex_i); - l->lex_i = i + 1; - l->lex_line += nls; - G.err_line = l->lex_line; + p->lex_i = i + 1; + p->lex_line += nls; + G.err_line = p->lex_line; RETURN_STATUS(BC_STATUS_SUCCESS); } @@ -3133,24 +3128,24 @@ static BC_STATUS zbc_lex_string(void) static void bc_lex_assign(unsigned with_and_without) { - BcLex *l = &G.prs.l; - if (l->lex_inbuf[l->lex_i] == '=') { - l->lex_i++; + BcParse *p = &G.prs; + if (p->lex_inbuf[p->lex_i] == '=') { + p->lex_i++; with_and_without >>= 8; // store "with" value } // else store "without" value - l->lex = (with_and_without & 0xff); + p->lex = (with_and_without & 0xff); } #define bc_lex_assign(with, without) \ bc_lex_assign(((with)<<8)|(without)) static BC_STATUS zbc_lex_comment(void) { - BcLex *l = &G.prs.l; + BcParse *p = &G.prs; size_t i, nls = 0; - const char *buf = l->lex_inbuf; + const char *buf = p->lex_inbuf; - l->lex = XC_LEX_WHITESPACE; - i = l->lex_i; /* here buf[l->lex_i] is the '*' of opening comment delimiter */ + p->lex = XC_LEX_WHITESPACE; + i = p->lex_i; /* here buf[p->lex_i] is the '*' of opening comment delimiter */ for (;;) { char c = buf[++i]; check_star: @@ -3161,15 +3156,15 @@ static BC_STATUS zbc_lex_comment(void) goto check_star; } if (c == '\0') { - l->lex_i = i; + p->lex_i = i; RETURN_STATUS(bc_error("unterminated comment")); } nls += (c == '\n'); } - l->lex_i = i + 1; - l->lex_line += nls; - G.err_line = l->lex_line; + p->lex_i = i + 1; + p->lex_line += nls; + G.err_line = p->lex_line; RETURN_STATUS(BC_STATUS_SUCCESS); } @@ -3178,20 +3173,20 @@ static BC_STATUS zbc_lex_comment(void) #undef zbc_lex_token static BC_STATUS zbc_lex_token(void) { - BcLex *l = &G.prs.l; + BcParse *p = &G.prs; BcStatus s = BC_STATUS_SUCCESS; - char c = l->lex_inbuf[l->lex_i++], c2; + char c = p->lex_inbuf[p->lex_i++], c2; // This is the workhorse of the lexer. switch (c) { // case '\0': // probably never reached -// l->lex_i--; -// l->lex = XC_LEX_EOF; -// l->lex_newline = true; +// p->lex_i--; +// p->lex = XC_LEX_EOF; +// p->lex_newline = true; // break; case '\n': - l->lex = XC_LEX_NLINE; - l->lex_newline = true; + p->lex = XC_LEX_NLINE; + p->lex_newline = true; break; case '\t': case '\v': @@ -3202,7 +3197,7 @@ static BC_STATUS zbc_lex_token(void) break; case '!': bc_lex_assign(XC_LEX_OP_REL_NE, BC_LEX_OP_BOOL_NOT); - if (l->lex == BC_LEX_OP_BOOL_NOT) { + if (p->lex == BC_LEX_OP_BOOL_NOT) { s = zbc_POSIX_does_not_allow_bool_ops_this_is_bad("!"); if (s) RETURN_STATUS(s); } @@ -3219,53 +3214,53 @@ static BC_STATUS zbc_lex_token(void) bc_lex_assign(BC_LEX_OP_ASSIGN_MODULUS, XC_LEX_OP_MODULUS); break; case '&': - c2 = l->lex_inbuf[l->lex_i]; + c2 = p->lex_inbuf[p->lex_i]; if (c2 == '&') { s = zbc_POSIX_does_not_allow_bool_ops_this_is_bad("&&"); if (s) RETURN_STATUS(s); - l->lex_i++; - l->lex = BC_LEX_OP_BOOL_AND; + p->lex_i++; + p->lex = BC_LEX_OP_BOOL_AND; } else { - l->lex = XC_LEX_INVALID; + p->lex = XC_LEX_INVALID; s = bc_error_bad_character('&'); } break; case '(': case ')': - l->lex = (BcLexType)(c - '(' + BC_LEX_LPAREN); + p->lex = (BcLexType)(c - '(' + BC_LEX_LPAREN); break; case '*': bc_lex_assign(BC_LEX_OP_ASSIGN_MULTIPLY, XC_LEX_OP_MULTIPLY); break; case '+': - c2 = l->lex_inbuf[l->lex_i]; + c2 = p->lex_inbuf[p->lex_i]; if (c2 == '+') { - l->lex_i++; - l->lex = BC_LEX_OP_INC; + p->lex_i++; + p->lex = BC_LEX_OP_INC; } else bc_lex_assign(BC_LEX_OP_ASSIGN_PLUS, XC_LEX_OP_PLUS); break; case ',': - l->lex = BC_LEX_COMMA; + p->lex = BC_LEX_COMMA; break; case '-': - c2 = l->lex_inbuf[l->lex_i]; + c2 = p->lex_inbuf[p->lex_i]; if (c2 == '-') { - l->lex_i++; - l->lex = BC_LEX_OP_DEC; + p->lex_i++; + p->lex = BC_LEX_OP_DEC; } else bc_lex_assign(BC_LEX_OP_ASSIGN_MINUS, XC_LEX_OP_MINUS); break; case '.': - if (isdigit(l->lex_inbuf[l->lex_i])) + if (isdigit(p->lex_inbuf[p->lex_i])) s = zbc_lex_number(c); else { - l->lex = BC_LEX_KEY_LAST; + p->lex = BC_LEX_KEY_LAST; s = zbc_POSIX_does_not_allow("'.' as 'last'"); } break; case '/': - c2 = l->lex_inbuf[l->lex_i]; + c2 = p->lex_inbuf[p->lex_i]; if (c2 == '*') s = zbc_lex_comment(); else @@ -3290,7 +3285,7 @@ static BC_STATUS zbc_lex_token(void) s = zbc_lex_number(c); break; case ';': - l->lex = BC_LEX_SCOLON; + p->lex = BC_LEX_SCOLON; break; case '<': bc_lex_assign(XC_LEX_OP_REL_LE, XC_LEX_OP_REL_LT); @@ -3303,12 +3298,12 @@ static BC_STATUS zbc_lex_token(void) break; case '[': case ']': - l->lex = (BcLexType)(c - '[' + BC_LEX_LBRACKET); + p->lex = (BcLexType)(c - '[' + BC_LEX_LBRACKET); break; case '\\': - if (l->lex_inbuf[l->lex_i] == '\n') { - l->lex = XC_LEX_WHITESPACE; - l->lex_i++; + if (p->lex_inbuf[p->lex_i] == '\n') { + p->lex = XC_LEX_WHITESPACE; + p->lex_i++; } else s = bc_error_bad_character(c); break; @@ -3345,22 +3340,22 @@ static BC_STATUS zbc_lex_token(void) break; case '{': case '}': - l->lex = (BcLexType)(c - '{' + BC_LEX_LBRACE); + p->lex = (BcLexType)(c - '{' + BC_LEX_LBRACE); break; case '|': - c2 = l->lex_inbuf[l->lex_i]; + c2 = p->lex_inbuf[p->lex_i]; if (c2 == '|') { s = zbc_POSIX_does_not_allow_bool_ops_this_is_bad("||"); if (s) RETURN_STATUS(s); - l->lex_i++; - l->lex = BC_LEX_OP_BOOL_OR; + p->lex_i++; + p->lex = BC_LEX_OP_BOOL_OR; } else { - l->lex = XC_LEX_INVALID; + p->lex = XC_LEX_INVALID; s = bc_error_bad_character(c); } break; default: - l->lex = XC_LEX_INVALID; + p->lex = XC_LEX_INVALID; s = bc_error_bad_character(c); break; } @@ -3373,16 +3368,16 @@ static BC_STATUS zbc_lex_token(void) #if ENABLE_DC static BC_STATUS zdc_lex_register(void) { - BcLex *l = &G.prs.l; - if (G_exreg && isspace(l->lex_inbuf[l->lex_i])) { + BcParse *p = &G.prs; + if (G_exreg && isspace(p->lex_inbuf[p->lex_i])) { bc_lex_whitespace(); // eats whitespace (but not newline) - l->lex_i++; // bc_lex_name() expects this + p->lex_i++; // bc_lex_name() expects this bc_lex_name(); } else { - bc_vec_pop_all(&l->lex_strnumbuf); - bc_vec_push(&l->lex_strnumbuf, &l->lex_inbuf[l->lex_i++]); - bc_vec_pushZeroByte(&l->lex_strnumbuf); - l->lex = XC_LEX_NAME; + bc_vec_pop_all(&p->lex_strnumbuf); + bc_vec_push(&p->lex_strnumbuf, &p->lex_inbuf[p->lex_i++]); + bc_vec_pushZeroByte(&p->lex_strnumbuf); + p->lex = XC_LEX_NAME; } RETURN_STATUS(BC_STATUS_SUCCESS); @@ -3391,43 +3386,43 @@ static BC_STATUS zdc_lex_register(void) static BC_STATUS zdc_lex_string(void) { - BcLex *l = &G.prs.l; + BcParse *p = &G.prs; size_t depth, nls, i; - l->lex = XC_LEX_STR; - bc_vec_pop_all(&l->lex_strnumbuf); + p->lex = XC_LEX_STR; + bc_vec_pop_all(&p->lex_strnumbuf); nls = 0; depth = 1; - i = l->lex_i; + i = p->lex_i; for (;;) { - char c = l->lex_inbuf[i]; + char c = p->lex_inbuf[i]; if (c == '\0') { - l->lex_i = i; + p->lex_i = i; RETURN_STATUS(bc_error("string end could not be found")); } nls += (c == '\n'); - if (i == l->lex_i || l->lex_inbuf[i - 1] != '\\') { + if (i == p->lex_i || p->lex_inbuf[i - 1] != '\\') { if (c == '[') depth++; if (c == ']') if (--depth == 0) break; } - bc_vec_push(&l->lex_strnumbuf, &l->lex_inbuf[i]); + bc_vec_push(&p->lex_strnumbuf, &p->lex_inbuf[i]); i++; } i++; - bc_vec_pushZeroByte(&l->lex_strnumbuf); + bc_vec_pushZeroByte(&p->lex_strnumbuf); // This check makes sense only if size_t is (much) larger than BC_MAX_STRING. if (SIZE_MAX > (BC_MAX_STRING | 0xff)) { - if (i - l->lex_i > BC_MAX_STRING) + if (i - p->lex_i > BC_MAX_STRING) RETURN_STATUS(bc_error("string too long: must be [1,"BC_MAX_STRING_STR"]")); } - l->lex_i = i; - l->lex_line += nls; - G.err_line = l->lex_line; + p->lex_i = i; + p->lex_line += nls; + G.err_line = p->lex_line; RETURN_STATUS(BC_STATUS_SUCCESS); } @@ -3436,7 +3431,7 @@ static BC_STATUS zdc_lex_string(void) #undef zdc_lex_token static BC_STATUS zdc_lex_token(void) { - BcLex *l = &G.prs.l; + BcParse *p = &G.prs; static const //BcLexType - should be this type, but narrower type saves size: uint8_t dc_lex_regs[] = { @@ -3451,14 +3446,14 @@ static BC_STATUS zdc_lex_token(void) size_t i; for (i = 0; i < ARRAY_SIZE(dc_lex_regs); ++i) { - if (l->lex_last == dc_lex_regs[i]) + if (p->lex_last == dc_lex_regs[i]) RETURN_STATUS(zdc_lex_register()); } s = BC_STATUS_SUCCESS; - c = l->lex_inbuf[l->lex_i++]; + c = p->lex_inbuf[p->lex_i++]; if (c >= '%' && c <= '~' - && (l->lex = dc_char_to_LEX[c - '%']) != XC_LEX_INVALID + && (p->lex = dc_char_to_LEX[c - '%']) != XC_LEX_INVALID ) { RETURN_STATUS(s); } @@ -3466,7 +3461,7 @@ static BC_STATUS zdc_lex_token(void) // This is the workhorse of the lexer. switch (c) { // case '\0': // probably never reached -// l->lex = XC_LEX_EOF; +// p->lex = XC_LEX_EOF; // break; case '\n': // '\n' is XC_LEX_NLINE, not XC_LEX_WHITESPACE @@ -3477,34 +3472,34 @@ static BC_STATUS zdc_lex_token(void) // commands are not executed on pressing ). // IOW: typing "1p" should print "1" _at once_, // not after some more input. - l->lex = XC_LEX_NLINE; - l->lex_newline = true; + p->lex = XC_LEX_NLINE; + p->lex_newline = true; break; case '\t': case '\v': case '\f': case '\r': case ' ': - l->lex_newline = 0; // was (c == '\n') + p->lex_newline = 0; // was (c == '\n') bc_lex_whitespace(); break; case '!': - c2 = l->lex_inbuf[l->lex_i]; + c2 = p->lex_inbuf[p->lex_i]; if (c2 == '=') - l->lex = XC_LEX_OP_REL_NE; + p->lex = XC_LEX_OP_REL_NE; else if (c2 == '<') - l->lex = XC_LEX_OP_REL_LE; + p->lex = XC_LEX_OP_REL_LE; else if (c2 == '>') - l->lex = XC_LEX_OP_REL_GE; + p->lex = XC_LEX_OP_REL_GE; else RETURN_STATUS(bc_error_bad_character(c)); - l->lex_i++; + p->lex_i++; break; case '#': bc_lex_lineComment(); break; case '.': - if (isdigit(l->lex_inbuf[l->lex_i])) + if (isdigit(p->lex_inbuf[p->lex_i])) s = zbc_lex_number(c); else s = bc_error_bad_character(c); @@ -3531,7 +3526,7 @@ static BC_STATUS zdc_lex_token(void) s = zdc_lex_string(); break; default: - l->lex = XC_LEX_INVALID; + p->lex = XC_LEX_INVALID; s = bc_error_bad_character(c); break; } @@ -3593,7 +3588,7 @@ static void bc_parse_pushJUMP_ZERO(size_t idx) static BC_STATUS zbc_parse_pushSTR(void) { BcParse *p = &G.prs; - char *str = xstrdup(p->l.lex_strnumbuf.v); + char *str = xstrdup(p->lex_strnumbuf.v); bc_parse_push(XC_INST_STR); bc_parse_pushIndex(p->func->strs.len); @@ -3607,7 +3602,7 @@ static BC_STATUS zbc_parse_pushSTR(void) static void bc_parse_pushNUM(void) { BcParse *p = &G.prs; - char *num = xstrdup(p->l.lex_strnumbuf.v); + char *num = xstrdup(p->lex_strnumbuf.v); #if ENABLE_BC && ENABLE_DC size_t idx = bc_vec_push(IS_BC ? &p->func->consts : &G.prog.consts, &num); #elif ENABLE_BC @@ -3656,8 +3651,8 @@ static void bc_parse_reset(void) p->func = bc_program_func_BC_PROG_MAIN(); } - p->l.lex_i = p->l.lex_len; - p->l.lex = XC_LEX_EOF; + p->lex_i = p->lex_len; + p->lex = XC_LEX_EOF; IF_BC(bc_vec_pop_all(&p->exits);) IF_BC(bc_vec_pop_all(&p->conds);) @@ -3765,7 +3760,7 @@ static BC_STATUS zbc_parse_stmt_allow_NLINE_before(const char *after_X) // Same for "else", "while()", "for()". BcStatus s = zbc_lex_next_and_skip_NLINE(); if (s) RETURN_STATUS(s); - if (p->l.lex == XC_LEX_NLINE) + if (p->lex == XC_LEX_NLINE) RETURN_STATUS(bc_error_fmt("no statement after '%s'", after_X)); RETURN_STATUS(zbc_parse_stmt()); @@ -3825,20 +3820,20 @@ static BC_STATUS zbc_parse_params(uint8_t flags) BcStatus s; size_t nparams; - dbg_lex("%s:%d p->l.lex:%d", __func__, __LINE__, p->l.lex); + dbg_lex("%s:%d p->lex:%d", __func__, __LINE__, p->lex); flags = (flags & ~(BC_PARSE_PRINT | BC_PARSE_REL)) | BC_PARSE_ARRAY; s = zbc_lex_next(); if (s) RETURN_STATUS(s); nparams = 0; - if (p->l.lex != BC_LEX_RPAREN) { + if (p->lex != BC_LEX_RPAREN) { for (;;) { s = zbc_parse_expr(flags); if (s) RETURN_STATUS(s); nparams++; - if (p->l.lex != BC_LEX_COMMA) { - if (p->l.lex == BC_LEX_RPAREN) + if (p->lex != BC_LEX_COMMA) { + if (p->lex == BC_LEX_RPAREN) break; RETURN_STATUS(bc_error_bad_token()); } @@ -3867,7 +3862,7 @@ static BC_STATUS zbc_parse_call(char *name, uint8_t flags) s = zbc_parse_params(flags); if (s) goto err; - if (p->l.lex != BC_LEX_RPAREN) { + if (p->lex != BC_LEX_RPAREN) { s = bc_error_bad_token(); goto err; } @@ -3897,15 +3892,15 @@ static BC_STATUS zbc_parse_name(BcInst *type, uint8_t flags) BcStatus s; char *name; - name = xstrdup(p->l.lex_strnumbuf.v); + name = xstrdup(p->lex_strnumbuf.v); s = zbc_lex_next(); if (s) goto err; - if (p->l.lex == BC_LEX_LBRACKET) { + if (p->lex == BC_LEX_LBRACKET) { s = zbc_lex_next(); if (s) goto err; - if (p->l.lex == BC_LEX_RBRACKET) { + if (p->lex == BC_LEX_RBRACKET) { if (!(flags & BC_PARSE_ARRAY)) { s = bc_error_bad_expression(); goto err; @@ -3922,7 +3917,7 @@ static BC_STATUS zbc_parse_name(BcInst *type, uint8_t flags) bc_parse_push(*type); bc_parse_pushName(name); free(name); - } else if (p->l.lex == BC_LEX_LPAREN) { + } else if (p->lex == BC_LEX_LPAREN) { if (flags & BC_PARSE_NOCALL) { s = bc_error_bad_token(); goto err; @@ -3950,11 +3945,11 @@ static BC_STATUS zbc_parse_read(void) s = zbc_lex_next(); if (s) RETURN_STATUS(s); - if (p->l.lex != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); + if (p->lex != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); s = zbc_lex_next(); if (s) RETURN_STATUS(s); - if (p->l.lex != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); + if (p->lex != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); bc_parse_push(XC_INST_READ); @@ -3969,7 +3964,7 @@ static BC_STATUS zbc_parse_builtin(BcLexType type, uint8_t flags, BcInst *prev) s = zbc_lex_next(); if (s) RETURN_STATUS(s); - if (p->l.lex != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); + if (p->lex != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); flags = (flags & ~(BC_PARSE_PRINT | BC_PARSE_REL)) | BC_PARSE_ARRAY; @@ -3979,7 +3974,7 @@ static BC_STATUS zbc_parse_builtin(BcLexType type, uint8_t flags, BcInst *prev) s = zbc_parse_expr(flags); if (s) RETURN_STATUS(s); - if (p->l.lex != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); + if (p->lex != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); *prev = (type == BC_LEX_KEY_LENGTH) ? XC_INST_LENGTH : XC_INST_SQRT; bc_parse_push(*prev); @@ -3996,7 +3991,7 @@ static BC_STATUS zbc_parse_scale(BcInst *type, uint8_t flags) s = zbc_lex_next(); if (s) RETURN_STATUS(s); - if (p->l.lex != BC_LEX_LPAREN) { + if (p->lex != BC_LEX_LPAREN) { *type = XC_INST_SCALE; bc_parse_push(XC_INST_SCALE); RETURN_STATUS(BC_STATUS_SUCCESS); @@ -4010,7 +4005,7 @@ static BC_STATUS zbc_parse_scale(BcInst *type, uint8_t flags) s = zbc_parse_expr(flags); if (s) RETURN_STATUS(s); - if (p->l.lex != BC_LEX_RPAREN) + if (p->lex != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); bc_parse_push(XC_INST_SCALE_FUNC); @@ -4031,16 +4026,16 @@ static BC_STATUS zbc_parse_incdec(BcInst *prev, bool *paren_expr, || etype == XC_INST_SCALE || etype == BC_INST_LAST || etype == XC_INST_IBASE || etype == XC_INST_OBASE ) { - *prev = inst = BC_INST_INC_POST + (p->l.lex != BC_LEX_OP_INC); + *prev = inst = BC_INST_INC_POST + (p->lex != BC_LEX_OP_INC); bc_parse_push(inst); s = zbc_lex_next(); } else { - *prev = inst = BC_INST_INC_PRE + (p->l.lex != BC_LEX_OP_INC); + *prev = inst = BC_INST_INC_PRE + (p->lex != BC_LEX_OP_INC); *paren_expr = true; s = zbc_lex_next(); if (s) RETURN_STATUS(s); - type = p->l.lex; + type = p->lex; // Because we parse the next part of the expression // right here, we need to increment this. @@ -4059,7 +4054,7 @@ static BC_STATUS zbc_parse_incdec(BcInst *prev, bool *paren_expr, case BC_LEX_KEY_SCALE: s = zbc_lex_next(); if (s) RETURN_STATUS(s); - if (p->l.lex == BC_LEX_LPAREN) + if (p->lex == BC_LEX_LPAREN) s = bc_error_bad_token(); else bc_parse_push(XC_INST_SCALE); @@ -4128,7 +4123,7 @@ static BC_STATUS zbc_parse_print(void) for (;;) { s = zbc_lex_next(); if (s) RETURN_STATUS(s); - type = p->l.lex; + type = p->lex; if (type == XC_LEX_STR) { s = zbc_parse_pushSTR(); } else { @@ -4136,7 +4131,7 @@ static BC_STATUS zbc_parse_print(void) } if (s) RETURN_STATUS(s); bc_parse_push(XC_INST_PRINT_POP); - if (p->l.lex != BC_LEX_COMMA) + if (p->lex != BC_LEX_COMMA) break; } @@ -4154,7 +4149,7 @@ static BC_STATUS zbc_parse_return(void) s = zbc_lex_next(); if (s) RETURN_STATUS(s); - t = p->l.lex; + t = p->lex; if (t == XC_LEX_NLINE || t == BC_LEX_SCOLON) bc_parse_push(BC_INST_RET0); else { @@ -4166,7 +4161,7 @@ static BC_STATUS zbc_parse_return(void) } if (s) RETURN_STATUS(s); - if (!paren || p->l.lex_last != BC_LEX_RPAREN) { + if (!paren || p->lex_last != BC_LEX_RPAREN) { s = zbc_POSIX_requires("parentheses around return expressions"); if (s) RETURN_STATUS(s); } @@ -4195,13 +4190,13 @@ static BC_STATUS zbc_parse_if(void) dbg_lex_enter("%s:%d entered", __func__, __LINE__); s = zbc_lex_next(); if (s) RETURN_STATUS(s); - if (p->l.lex != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); + if (p->lex != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); s = zbc_lex_next(); if (s) RETURN_STATUS(s); s = zbc_parse_expr(BC_PARSE_REL); if (s) RETURN_STATUS(s); - if (p->l.lex != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); + if (p->lex != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); // Encode "if zero, jump to ..." // Pushed value (destination of the jump) is uninitialized, @@ -4212,8 +4207,8 @@ static BC_STATUS zbc_parse_if(void) s = zbc_parse_stmt_allow_NLINE_before(STRING_if); if (s) RETURN_STATUS(s); - dbg_lex("%s:%d in if after stmt: p->l.lex:%d", __func__, __LINE__, p->l.lex); - if (p->l.lex == BC_LEX_KEY_ELSE) { + dbg_lex("%s:%d in if after stmt: p->lex:%d", __func__, __LINE__, p->lex); + if (p->lex == BC_LEX_KEY_ELSE) { size_t ip2_idx; // Encode "after then_stmt, jump to end of if()" @@ -4247,7 +4242,7 @@ static BC_STATUS zbc_parse_while(void) s = zbc_lex_next(); if (s) RETURN_STATUS(s); - if (p->l.lex != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); + if (p->lex != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); s = zbc_lex_next(); if (s) RETURN_STATUS(s); @@ -4260,7 +4255,7 @@ static BC_STATUS zbc_parse_while(void) s = zbc_parse_expr(BC_PARSE_REL); if (s) RETURN_STATUS(s); - if (p->l.lex != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); + if (p->lex != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); bc_parse_pushJUMP_ZERO(ip_idx); @@ -4286,14 +4281,14 @@ static BC_STATUS zbc_parse_for(void) BcStatus s; size_t cond_idx, exit_idx, body_idx, update_idx; - dbg_lex("%s:%d p->l.lex:%d", __func__, __LINE__, p->l.lex); + dbg_lex("%s:%d p->lex:%d", __func__, __LINE__, p->lex); s = zbc_lex_next(); if (s) RETURN_STATUS(s); - if (p->l.lex != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); + if (p->lex != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); s = zbc_lex_next(); if (s) RETURN_STATUS(s); - if (p->l.lex != BC_LEX_SCOLON) { + if (p->lex != BC_LEX_SCOLON) { s = zbc_parse_expr(0); bc_parse_push(XC_INST_POP); if (s) RETURN_STATUS(s); @@ -4302,7 +4297,7 @@ static BC_STATUS zbc_parse_for(void) if (s) RETURN_STATUS(s); } - if (p->l.lex != BC_LEX_SCOLON) RETURN_STATUS(bc_error_bad_token()); + if (p->lex != BC_LEX_SCOLON) RETURN_STATUS(bc_error_bad_token()); s = zbc_lex_next(); if (s) RETURN_STATUS(s); @@ -4311,19 +4306,19 @@ static BC_STATUS zbc_parse_for(void) body_idx = update_idx + 1; exit_idx = body_idx + 1; - if (p->l.lex != BC_LEX_SCOLON) + if (p->lex != BC_LEX_SCOLON) s = zbc_parse_expr(BC_PARSE_REL); else { // Set this for the next call to bc_parse_pushNUM(). // This is safe to set because the current token is a semicolon, // which has no string requirement. - bc_vec_string(&p->l.lex_strnumbuf, 1, "1"); + bc_vec_string(&p->lex_strnumbuf, 1, "1"); bc_parse_pushNUM(); s = zbc_POSIX_does_not_allow_empty_X_expression_in_for("condition"); } if (s) RETURN_STATUS(s); - if (p->l.lex != BC_LEX_SCOLON) RETURN_STATUS(bc_error_bad_token()); + if (p->lex != BC_LEX_SCOLON) RETURN_STATUS(bc_error_bad_token()); s = zbc_lex_next(); if (s) RETURN_STATUS(s); @@ -4334,10 +4329,10 @@ static BC_STATUS zbc_parse_for(void) bc_vec_push(&p->conds, &update_idx); bc_vec_push(&p->func->labels, &p->func->code.len); - if (p->l.lex != BC_LEX_RPAREN) { + if (p->lex != BC_LEX_RPAREN) { s = zbc_parse_expr(0); if (s) RETURN_STATUS(s); - if (p->l.lex != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); + if (p->lex != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); bc_parse_push(XC_INST_POP); } else { s = zbc_POSIX_does_not_allow_empty_X_expression_in_for("update"); @@ -4415,37 +4410,37 @@ static BC_STATUS zbc_parse_funcdef(void) dbg_lex_enter("%s:%d entered", __func__, __LINE__); s = zbc_lex_next(); if (s) RETURN_STATUS(s); - if (p->l.lex != XC_LEX_NAME) + if (p->lex != XC_LEX_NAME) RETURN_STATUS(bc_error("bad function definition")); - name = xstrdup(p->l.lex_strnumbuf.v); + name = xstrdup(p->lex_strnumbuf.v); p->fidx = bc_program_addFunc(name); p->func = bc_program_func(p->fidx); s = zbc_lex_next(); if (s) RETURN_STATUS(s); - if (p->l.lex != BC_LEX_LPAREN) + if (p->lex != BC_LEX_LPAREN) RETURN_STATUS(bc_error("bad function definition")); s = zbc_lex_next(); if (s) RETURN_STATUS(s); - while (p->l.lex != BC_LEX_RPAREN) { - if (p->l.lex != XC_LEX_NAME) + while (p->lex != BC_LEX_RPAREN) { + if (p->lex != XC_LEX_NAME) RETURN_STATUS(bc_error("bad function definition")); ++p->func->nparams; - name = xstrdup(p->l.lex_strnumbuf.v); + name = xstrdup(p->lex_strnumbuf.v); s = zbc_lex_next(); if (s) goto err; - var = p->l.lex != BC_LEX_LBRACKET; + var = p->lex != BC_LEX_LBRACKET; if (!var) { s = zbc_lex_next(); if (s) goto err; - if (p->l.lex != BC_LEX_RBRACKET) { + if (p->lex != BC_LEX_RBRACKET) { s = bc_error("bad function definition"); goto err; } @@ -4454,7 +4449,7 @@ static BC_STATUS zbc_parse_funcdef(void) if (s) goto err; } - comma = p->l.lex == BC_LEX_COMMA; + comma = p->lex == BC_LEX_COMMA; if (comma) { s = zbc_lex_next(); if (s) goto err; @@ -4469,7 +4464,7 @@ static BC_STATUS zbc_parse_funcdef(void) s = zbc_lex_next(); if (s) RETURN_STATUS(s); - if (p->l.lex != BC_LEX_LBRACE) { + if (p->lex != BC_LEX_LBRACE) { s = zbc_POSIX_requires("the left brace be on the same line as the function header"); if (s) RETURN_STATUS(s); } @@ -4478,7 +4473,7 @@ static BC_STATUS zbc_parse_funcdef(void) s = zbc_lex_skip_if_at_NLINE(); if (s) RETURN_STATUS(s); //GNU bc requires a {} block even if function body has single stmt, enforce this? - if (p->l.lex != BC_LEX_LBRACE) + if (p->lex != BC_LEX_LBRACE) RETURN_STATUS(bc_error("function { body } expected")); p->in_funcdef++; // to determine whether "return" stmt is allowed, and such @@ -4514,19 +4509,19 @@ static BC_STATUS zbc_parse_auto(void) for (;;) { bool var; - if (p->l.lex != XC_LEX_NAME) + if (p->lex != XC_LEX_NAME) RETURN_STATUS(bc_error("bad 'auto' syntax")); - name = xstrdup(p->l.lex_strnumbuf.v); + name = xstrdup(p->lex_strnumbuf.v); s = zbc_lex_next(); if (s) goto err; - var = (p->l.lex != BC_LEX_LBRACKET); + var = (p->lex != BC_LEX_LBRACKET); if (!var) { s = zbc_lex_next(); if (s) goto err; - if (p->l.lex != BC_LEX_RBRACKET) { + if (p->lex != BC_LEX_RBRACKET) { s = bc_error("bad 'auto' syntax"); goto err; } @@ -4537,13 +4532,13 @@ static BC_STATUS zbc_parse_auto(void) s = zbc_func_insert(p->func, name, var); if (s) goto err; - if (p->l.lex == XC_LEX_NLINE - || p->l.lex == BC_LEX_SCOLON - //|| p->l.lex == BC_LEX_RBRACE // allow "define f() {auto a}" + if (p->lex == XC_LEX_NLINE + || p->lex == BC_LEX_SCOLON + //|| p->lex == BC_LEX_RBRACE // allow "define f() {auto a}" ) { break; } - if (p->l.lex != BC_LEX_COMMA) + if (p->lex != BC_LEX_COMMA) RETURN_STATUS(bc_error("bad 'auto' syntax")); s = zbc_lex_next(); // skip comma if (s) RETURN_STATUS(s); @@ -4564,29 +4559,29 @@ static BC_STATUS zbc_parse_stmt_possibly_auto(bool auto_allowed) BcParse *p = &G.prs; BcStatus s = BC_STATUS_SUCCESS; - dbg_lex_enter("%s:%d entered, p->l.lex:%d", __func__, __LINE__, p->l.lex); + dbg_lex_enter("%s:%d entered, p->lex:%d", __func__, __LINE__, p->lex); - if (p->l.lex == XC_LEX_NLINE) { + if (p->lex == XC_LEX_NLINE) { dbg_lex_done("%s:%d done (seen XC_LEX_NLINE)", __func__, __LINE__); RETURN_STATUS(zbc_lex_next()); } - if (p->l.lex == BC_LEX_SCOLON) { + if (p->lex == BC_LEX_SCOLON) { dbg_lex_done("%s:%d done (seen BC_LEX_SCOLON)", __func__, __LINE__); RETURN_STATUS(zbc_lex_next()); } - if (p->l.lex == BC_LEX_LBRACE) { + if (p->lex == BC_LEX_LBRACE) { dbg_lex("%s:%d BC_LEX_LBRACE: (auto_allowed:%d)", __func__, __LINE__, auto_allowed); do { s = zbc_lex_next(); if (s) RETURN_STATUS(s); - } while (p->l.lex == XC_LEX_NLINE); - if (auto_allowed && p->l.lex == BC_LEX_KEY_AUTO) { + } while (p->lex == XC_LEX_NLINE); + if (auto_allowed && p->lex == BC_LEX_KEY_AUTO) { dbg_lex("%s:%d calling zbc_parse_auto()", __func__, __LINE__); s = zbc_parse_auto(); if (s) RETURN_STATUS(s); } - while (p->l.lex != BC_LEX_RBRACE) { + while (p->lex != BC_LEX_RBRACE) { dbg_lex("%s:%d block parsing loop", __func__, __LINE__); s = zbc_parse_stmt(); if (s) RETURN_STATUS(s); @@ -4596,8 +4591,8 @@ static BC_STATUS zbc_parse_stmt_possibly_auto(bool auto_allowed) RETURN_STATUS(s); } - dbg_lex("%s:%d p->l.lex:%d", __func__, __LINE__, p->l.lex); - switch (p->l.lex) { + dbg_lex("%s:%d p->lex:%d", __func__, __LINE__, p->lex); + switch (p->lex) { case XC_LEX_OP_MINUS: case BC_LEX_OP_INC: case BC_LEX_OP_DEC: @@ -4620,7 +4615,7 @@ static BC_STATUS zbc_parse_stmt_possibly_auto(bool auto_allowed) break; case BC_LEX_KEY_BREAK: case BC_LEX_KEY_CONTINUE: - s = zbc_parse_break_or_continue(p->l.lex); + s = zbc_parse_break_or_continue(p->lex); break; case BC_LEX_KEY_FOR: s = zbc_parse_for(); @@ -4679,13 +4674,13 @@ static BC_STATUS zbc_parse_stmt_or_funcdef(void) BcStatus s; dbg_lex_enter("%s:%d entered", __func__, __LINE__); - if (p->l.lex == XC_LEX_EOF) + if (p->lex == XC_LEX_EOF) s = bc_error("end of file"); - else if (p->l.lex == BC_LEX_KEY_DEFINE) { - dbg_lex("%s:%d p->l.lex:BC_LEX_KEY_DEFINE", __func__, __LINE__); + else if (p->lex == BC_LEX_KEY_DEFINE) { + dbg_lex("%s:%d p->lex:BC_LEX_KEY_DEFINE", __func__, __LINE__); s = zbc_parse_funcdef(); } else { - dbg_lex("%s:%d p->l.lex:%d (not BC_LEX_KEY_DEFINE)", __func__, __LINE__, p->l.lex); + dbg_lex("%s:%d p->lex:%d (not BC_LEX_KEY_DEFINE)", __func__, __LINE__, p->lex); s = zbc_parse_stmt(); } @@ -4704,7 +4699,7 @@ static BcStatus bc_parse_expr_empty_ok(uint8_t flags) bool paren_first, paren_expr, rprn, assign, bin_last; dbg_lex_enter("%s:%d entered", __func__, __LINE__); - paren_first = (p->l.lex == BC_LEX_LPAREN); + paren_first = (p->lex == BC_LEX_LPAREN); nparens = nrelops = 0; paren_expr = rprn = assign = false; bin_last = true; @@ -4712,7 +4707,7 @@ static BcStatus bc_parse_expr_empty_ok(uint8_t flags) for (;;) { bool get_token; BcStatus s; - BcLexType t = p->l.lex; + BcLexType t = p->lex; if (!lex_allowed_in_bc_expr(t)) break; @@ -4923,9 +4918,9 @@ static BC_STATUS zdc_parse_register(void) s = zbc_lex_next(); if (s) RETURN_STATUS(s); - if (p->l.lex != XC_LEX_NAME) RETURN_STATUS(bc_error_bad_token()); + if (p->lex != XC_LEX_NAME) RETURN_STATUS(bc_error_bad_token()); - bc_parse_pushName(p->l.lex_strnumbuf.v); + bc_parse_pushName(p->lex_strnumbuf.v); RETURN_STATUS(s); } @@ -4939,7 +4934,7 @@ static void dc_parse_string(void) dbg_lex_enter("%s:%d entered", __func__, __LINE__); - str = xstrdup(p->l.lex_strnumbuf.v); + str = xstrdup(p->lex_strnumbuf.v); bc_parse_push(XC_INST_STR); bc_parse_pushIndex(len); bc_vec_push(&G.prog.strs, &str); @@ -4988,7 +4983,7 @@ static BC_STATUS zdc_parse_cond(uint8_t inst) // Note that 'else' part can not be on the next line: // echo -e '[1p]sa [2p]sb 2 1>a eb' | dc - OK, prints "2" // echo -e '[1p]sa [2p]sb 2 1>a\neb' | dc - parse error - if (p->l.lex == DC_LEX_ELSE) { + if (p->lex == DC_LEX_ELSE) { s = zdc_parse_register(); if (s) RETURN_STATUS(s); s = zbc_lex_next(); @@ -5033,7 +5028,7 @@ static BC_STATUS zdc_parse_token(BcLexType t) dbg_lex("%s:%d LEX_NEG", __func__, __LINE__); s = zbc_lex_next(); if (s) RETURN_STATUS(s); - if (G.prs.l.lex != XC_LEX_NUMBER) + if (G.prs.lex != XC_LEX_NUMBER) RETURN_STATUS(bc_error_bad_token()); bc_parse_pushNUM(); bc_parse_push(XC_INST_NEG); @@ -5083,7 +5078,7 @@ static BC_STATUS zdc_parse_expr(void) BcParse *p = &G.prs; int i; - i = (int)p->l.lex - (int)XC_LEX_OP_POWER; + i = (int)p->lex - (int)XC_LEX_OP_POWER; if (i >= 0) { BcInst inst = dc_LEX_to_INST[i]; if (inst != DC_INST_INVALID) { @@ -5091,15 +5086,15 @@ static BC_STATUS zdc_parse_expr(void) RETURN_STATUS(zbc_lex_next()); } } - RETURN_STATUS(zdc_parse_token(p->l.lex)); + RETURN_STATUS(zdc_parse_token(p->lex)); } #define zdc_parse_expr(...) (zdc_parse_expr(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zdc_parse_exprs_until_eof(void) { BcParse *p = &G.prs; - dbg_lex_enter("%s:%d entered, p->l.lex:%d", __func__, __LINE__, p->l.lex); - while (p->l.lex != XC_LEX_EOF) { + dbg_lex_enter("%s:%d entered, p->lex:%d", __func__, __LINE__, p->lex); + while (p->lex != XC_LEX_EOF) { BcStatus s = zdc_parse_expr(); if (s) RETURN_STATUS(s); } @@ -5329,7 +5324,7 @@ static BC_STATUS zbc_program_read(void) } if (s) goto exec_err; - if (G.prs.l.lex != XC_LEX_NLINE && G.prs.l.lex != XC_LEX_EOF) { + if (G.prs.lex != XC_LEX_NLINE && G.prs.lex != XC_LEX_EOF) { s = bc_error("bad read() expression"); goto exec_err; } @@ -6460,7 +6455,7 @@ static BC_STATUS zdc_program_execStr(char *code, size_t *bgn, bool cond) s = zdc_parse_exprs_until_eof(); if (s) goto err; bc_parse_push(DC_INST_POP_EXEC); - if (G.prs.l.lex != XC_LEX_EOF) + if (G.prs.lex != XC_LEX_EOF) s = bc_error_bad_expression(); bc_parse_free(); G.prs = sv_parse; // struct copy @@ -6797,15 +6792,15 @@ static BC_STATUS zbc_vm_process(const char *text) if (s) RETURN_STATUS(s); IF_BC(check_eof:) - while (G.prs.l.lex != XC_LEX_EOF) { + while (G.prs.lex != XC_LEX_EOF) { BcInstPtr *ip; BcFunc *f; - dbg_lex("%s:%d G.prs.l.lex:%d, parsing...", __func__, __LINE__, G.prs.l.lex); + dbg_lex("%s:%d G.prs.lex:%d, parsing...", __func__, __LINE__, G.prs.lex); if (IS_BC) { #if ENABLE_BC - if (G.prs.l.lex == BC_LEX_SCOLON - || G.prs.l.lex == XC_LEX_NLINE + if (G.prs.lex == BC_LEX_SCOLON + || G.prs.lex == XC_LEX_NLINE ) { s = zbc_lex_next(); if (s) goto err; @@ -6817,13 +6812,13 @@ static BC_STATUS zbc_vm_process(const char *text) // Check that next token is a correct stmt delimiter - // disallows "print 1 print 2" and such. - if (G.prs.l.lex != BC_LEX_SCOLON - && G.prs.l.lex != XC_LEX_NLINE - && G.prs.l.lex != XC_LEX_EOF + if (G.prs.lex != BC_LEX_SCOLON + && G.prs.lex != XC_LEX_NLINE + && G.prs.lex != XC_LEX_EOF ) { const char *err_at; //TODO: commonalize for other parse errors: - err_at = G.prs.l.lex_next_at ? G.prs.l.lex_next_at : "UNKNOWN"; + err_at = G.prs.lex_next_at ? G.prs.lex_next_at : "UNKNOWN"; bc_error_fmt("bad statement terminator at '%.*s'", (int)(strchrnul(err_at, '\n') - err_at), err_at @@ -6837,10 +6832,10 @@ static BC_STATUS zbc_vm_process(const char *text) #if ENABLE_DC // Most of dc parsing assumes all whitespace, // including '\n', is eaten. - while (G.prs.l.lex == XC_LEX_NLINE) { + while (G.prs.lex == XC_LEX_NLINE) { s = zbc_lex_next(); if (s) goto err; - if (G.prs.l.lex == XC_LEX_EOF) + if (G.prs.lex == XC_LEX_EOF) goto done; } s = zdc_parse_expr(); @@ -6914,12 +6909,12 @@ static BC_STATUS zbc_vm_process(const char *text) static BC_STATUS zbc_vm_execute_FILE(FILE *fp, const char *filename) { // So far bc/dc have no way to include a file from another file, - // therefore we know G.prs.filename == NULL on entry + // therefore we know G.prs.lex_filename == NULL on entry //const char *sv_file; BcStatus s; - G.prs.filename = filename; - G.prs.input_fp = fp; + G.prs.lex_filename = filename; + G.prs.lex_input_fp = fp; bc_lex_file(); do { @@ -6928,8 +6923,8 @@ static BC_STATUS zbc_vm_execute_FILE(FILE *fp, const char *filename) // Example: start interactive bc and enter "return". // It should say "'return' not in a function" // but should not exit. - } while (G.prs.input_fp == stdin); - G.prs.filename = NULL; + } while (G.prs.lex_input_fp == stdin); + G.prs.lex_filename = NULL; RETURN_STATUS(s); } #define zbc_vm_execute_FILE(...) (zbc_vm_execute_FILE(__VA_ARGS__) COMMA_SUCCESS) -- cgit v1.2.3-55-g6feb From c192b0442b0b3f50d4fbb34322e07f0ff3c5aecd Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 25 Dec 2018 23:15:59 +0100 Subject: bc: simplify input pointer manipulation while lexing function old new delta bc_lex_name 70 68 -2 zbc_lex_number 177 174 -3 bc_vm_init 679 676 -3 bc_lex_whitespace 42 39 -3 zbc_parse_text_init 55 51 -4 bc_lex_lineComment 37 29 -8 bc_lex_assign 34 26 -8 zbc_lex_next 2039 1965 -74 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/8 up/down: 0/-105) Total: -105 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 115 +++++++++++++++++++++++++++------------------------------ 1 file changed, 55 insertions(+), 60 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 61fb24304..809b4bfc4 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -714,10 +714,9 @@ typedef struct BcParse { smallint lex; // was BcLexType // first member is most used smallint lex_last; // was BcLexType bool lex_newline; - size_t lex_i; size_t lex_line; - size_t lex_len; const char *lex_inbuf; + const char *lex_end; const char *lex_next_at; // last lex_next() was called at this string const char *lex_filename; FILE *lex_input_fp; @@ -2748,12 +2747,9 @@ static void bc_lex_lineComment(void) { BcParse *p = &G.prs; // Try: echo -n '#foo' | bc - size_t i; p->lex = XC_LEX_WHITESPACE; - i = p->lex_i; - while (i < p->lex_len && p->lex_inbuf[i] != '\n') - i++; - p->lex_i = i; + while (p->lex_inbuf < p->lex_end && *p->lex_inbuf != '\n') + p->lex_inbuf++; } static void bc_lex_whitespace(void) @@ -2761,19 +2757,19 @@ static void bc_lex_whitespace(void) BcParse *p = &G.prs; p->lex = XC_LEX_WHITESPACE; for (;;) { - char c = p->lex_inbuf[p->lex_i]; + char c = *p->lex_inbuf; if (c == '\n') // this is XC_LEX_NLINE, not XC_LEX_WHITESPACE break; if (!isspace(c)) break; - p->lex_i++; + p->lex_inbuf++; } } static BC_STATUS zbc_lex_number(char start) { BcParse *p = &G.prs; - const char *buf = p->lex_inbuf + p->lex_i; + const char *buf = p->lex_inbuf; size_t len, i, ccnt; bool pt; @@ -2803,7 +2799,7 @@ static BC_STATUS zbc_lex_number(char start) //ccnt is the number of chars in the number string, excluding possible //trailing "[\].[\]" (with any number of \ repetitions). //i is buf[i] index of the first not-yet-parsed char after that. - p->lex_i += i; + p->lex_inbuf += i; // This might overestimate the size, if there are "\"'s // in the number. Subtracting number_of_backslashes*2 correctly @@ -2850,7 +2846,7 @@ static void bc_lex_name(void) p->lex = XC_LEX_NAME; i = 0; - buf = p->lex_inbuf + p->lex_i - 1; + buf = p->lex_inbuf - 1; for (;;) { char c = buf[i]; if ((c < 'a' || c > 'z') && !isdigit(c) && c != '_') break; @@ -2867,7 +2863,7 @@ static void bc_lex_name(void) bc_vec_string(&p->lex_strnumbuf, i, buf); // Increment the index. We minus 1 because it has already been incremented. - p->lex_i += i - 1; + p->lex_inbuf += i - 1; //return BC_STATUS_SUCCESS; } @@ -2954,11 +2950,10 @@ static bool bc_lex_more_input(void) } p->lex_inbuf = G.input_buffer.v; - p->lex_i = 0; // bb_error_msg("G.input_buffer.len:%d '%s'", G.input_buffer.len, G.input_buffer.v); - p->lex_len = G.input_buffer.len - 1; // do not include NUL + p->lex_end = p->lex_inbuf + G.input_buffer.len - 1; // do not include NUL - return p->lex_len != 0; + return G.input_buffer.len > 1; } IF_BC(static BC_STATUS zbc_lex_token(void);) @@ -2983,7 +2978,7 @@ static BC_STATUS zbc_lex_next(void) // Comments are also XC_LEX_WHITESPACE tokens and eaten here. s = BC_STATUS_SUCCESS; do { - if (p->lex_i == p->lex_len) { + if (p->lex_inbuf == p->lex_end) { p->lex = XC_LEX_EOF; if (!G.prs.lex_input_fp) RETURN_STATUS(BC_STATUS_SUCCESS); @@ -2991,9 +2986,9 @@ static BC_STATUS zbc_lex_next(void) G.prs.lex_input_fp = NULL; RETURN_STATUS(BC_STATUS_SUCCESS); } - // here it's guaranteed that p->lex_i is below p->lex_len + // here it's guaranteed that p->lex_ibuf is below p->lex_end } - p->lex_next_at = p->lex_inbuf + p->lex_i; + p->lex_next_at = p->lex_inbuf; dbg_lex("next string to parse:'%.*s'", (int)(strchrnul(p->lex_next_at, '\n') - p->lex_next_at), p->lex_next_at @@ -3034,8 +3029,7 @@ static BC_STATUS zbc_lex_next_and_skip_NLINE(void) static BC_STATUS zbc_lex_text_init(const char *text) { G.prs.lex_inbuf = text; - G.prs.lex_i = 0; - G.prs.lex_len = strlen(text); + G.prs.lex_end = text + strlen(text); G.prs.lex = G.prs.lex_last = XC_LEX_INVALID; RETURN_STATUS(zbc_lex_next()); } @@ -3047,7 +3041,7 @@ static BC_STATUS zbc_lex_identifier(void) BcParse *p = &G.prs; BcStatus s; unsigned i; - const char *buf = p->lex_inbuf + p->lex_i - 1; + const char *buf = p->lex_inbuf - 1; for (i = 0; i < ARRAY_SIZE(bc_lex_kws); ++i) { const char *keyword8 = bc_lex_kws[i].name8; @@ -3069,7 +3063,7 @@ static BC_STATUS zbc_lex_identifier(void) } // We minus 1 because the index has already been incremented. - p->lex_i += j - 1; + p->lex_inbuf += j - 1; RETURN_STATUS(BC_STATUS_SUCCESS); } @@ -3097,11 +3091,11 @@ static BC_STATUS zbc_lex_string(void) p->lex = XC_LEX_STR; nls = 0; - i = p->lex_i; + i = 0; for (;;) { char c = p->lex_inbuf[i]; if (c == '\0') { - p->lex_i = i; + p->lex_inbuf += i; RETURN_STATUS(bc_error("unterminated string")); } if (c == '"') @@ -3110,15 +3104,15 @@ static BC_STATUS zbc_lex_string(void) i++; } - len = i - p->lex_i; + len = i; // This check makes sense only if size_t is (much) larger than BC_MAX_STRING. if (SIZE_MAX > (BC_MAX_STRING | 0xff)) { if (len > BC_MAX_STRING) RETURN_STATUS(bc_error("string too long: must be [1,"BC_MAX_STRING_STR"]")); } - bc_vec_string(&p->lex_strnumbuf, len, p->lex_inbuf + p->lex_i); + bc_vec_string(&p->lex_strnumbuf, len, p->lex_inbuf); - p->lex_i = i + 1; + p->lex_inbuf += i + 1; p->lex_line += nls; G.err_line = p->lex_line; @@ -3129,8 +3123,8 @@ static BC_STATUS zbc_lex_string(void) static void bc_lex_assign(unsigned with_and_without) { BcParse *p = &G.prs; - if (p->lex_inbuf[p->lex_i] == '=') { - p->lex_i++; + if (*p->lex_inbuf == '=') { + p->lex_inbuf++; with_and_without >>= 8; // store "with" value } // else store "without" value p->lex = (with_and_without & 0xff); @@ -3145,7 +3139,7 @@ static BC_STATUS zbc_lex_comment(void) const char *buf = p->lex_inbuf; p->lex = XC_LEX_WHITESPACE; - i = p->lex_i; /* here buf[p->lex_i] is the '*' of opening comment delimiter */ + i = 0; /* here lex_inbuf[0] is the '*' of opening comment delimiter */ for (;;) { char c = buf[++i]; check_star: @@ -3156,13 +3150,13 @@ static BC_STATUS zbc_lex_comment(void) goto check_star; } if (c == '\0') { - p->lex_i = i; + p->lex_inbuf += i; RETURN_STATUS(bc_error("unterminated comment")); } nls += (c == '\n'); } - p->lex_i = i + 1; + p->lex_inbuf += i + 1; p->lex_line += nls; G.err_line = p->lex_line; @@ -3175,12 +3169,13 @@ static BC_STATUS zbc_lex_token(void) { BcParse *p = &G.prs; BcStatus s = BC_STATUS_SUCCESS; - char c = p->lex_inbuf[p->lex_i++], c2; + char c = *p->lex_inbuf++; + char c2; // This is the workhorse of the lexer. switch (c) { // case '\0': // probably never reached -// p->lex_i--; +// p->lex_inbuf--; // p->lex = XC_LEX_EOF; // p->lex_newline = true; // break; @@ -3214,11 +3209,11 @@ static BC_STATUS zbc_lex_token(void) bc_lex_assign(BC_LEX_OP_ASSIGN_MODULUS, XC_LEX_OP_MODULUS); break; case '&': - c2 = p->lex_inbuf[p->lex_i]; + c2 = *p->lex_inbuf; if (c2 == '&') { s = zbc_POSIX_does_not_allow_bool_ops_this_is_bad("&&"); if (s) RETURN_STATUS(s); - p->lex_i++; + p->lex_inbuf++; p->lex = BC_LEX_OP_BOOL_AND; } else { p->lex = XC_LEX_INVALID; @@ -3233,9 +3228,9 @@ static BC_STATUS zbc_lex_token(void) bc_lex_assign(BC_LEX_OP_ASSIGN_MULTIPLY, XC_LEX_OP_MULTIPLY); break; case '+': - c2 = p->lex_inbuf[p->lex_i]; + c2 = *p->lex_inbuf; if (c2 == '+') { - p->lex_i++; + p->lex_inbuf++; p->lex = BC_LEX_OP_INC; } else bc_lex_assign(BC_LEX_OP_ASSIGN_PLUS, XC_LEX_OP_PLUS); @@ -3244,15 +3239,15 @@ static BC_STATUS zbc_lex_token(void) p->lex = BC_LEX_COMMA; break; case '-': - c2 = p->lex_inbuf[p->lex_i]; + c2 = *p->lex_inbuf; if (c2 == '-') { - p->lex_i++; + p->lex_inbuf++; p->lex = BC_LEX_OP_DEC; } else bc_lex_assign(BC_LEX_OP_ASSIGN_MINUS, XC_LEX_OP_MINUS); break; case '.': - if (isdigit(p->lex_inbuf[p->lex_i])) + if (isdigit(*p->lex_inbuf)) s = zbc_lex_number(c); else { p->lex = BC_LEX_KEY_LAST; @@ -3260,7 +3255,7 @@ static BC_STATUS zbc_lex_token(void) } break; case '/': - c2 = p->lex_inbuf[p->lex_i]; + c2 = *p->lex_inbuf; if (c2 == '*') s = zbc_lex_comment(); else @@ -3301,9 +3296,9 @@ static BC_STATUS zbc_lex_token(void) p->lex = (BcLexType)(c - '[' + BC_LEX_LBRACKET); break; case '\\': - if (p->lex_inbuf[p->lex_i] == '\n') { + if (*p->lex_inbuf == '\n') { p->lex = XC_LEX_WHITESPACE; - p->lex_i++; + p->lex_inbuf++; } else s = bc_error_bad_character(c); break; @@ -3343,11 +3338,11 @@ static BC_STATUS zbc_lex_token(void) p->lex = (BcLexType)(c - '{' + BC_LEX_LBRACE); break; case '|': - c2 = p->lex_inbuf[p->lex_i]; + c2 = *p->lex_inbuf; if (c2 == '|') { s = zbc_POSIX_does_not_allow_bool_ops_this_is_bad("||"); if (s) RETURN_STATUS(s); - p->lex_i++; + p->lex_inbuf++; p->lex = BC_LEX_OP_BOOL_OR; } else { p->lex = XC_LEX_INVALID; @@ -3369,13 +3364,13 @@ static BC_STATUS zbc_lex_token(void) static BC_STATUS zdc_lex_register(void) { BcParse *p = &G.prs; - if (G_exreg && isspace(p->lex_inbuf[p->lex_i])) { + if (G_exreg && isspace(*p->lex_inbuf)) { bc_lex_whitespace(); // eats whitespace (but not newline) - p->lex_i++; // bc_lex_name() expects this + p->lex_inbuf++; // bc_lex_name() expects this bc_lex_name(); } else { bc_vec_pop_all(&p->lex_strnumbuf); - bc_vec_push(&p->lex_strnumbuf, &p->lex_inbuf[p->lex_i++]); + bc_vec_push(&p->lex_strnumbuf, p->lex_inbuf++); bc_vec_pushZeroByte(&p->lex_strnumbuf); p->lex = XC_LEX_NAME; } @@ -3394,15 +3389,15 @@ static BC_STATUS zdc_lex_string(void) nls = 0; depth = 1; - i = p->lex_i; + i = 0; for (;;) { char c = p->lex_inbuf[i]; if (c == '\0') { - p->lex_i = i; + p->lex_inbuf += i; RETURN_STATUS(bc_error("string end could not be found")); } nls += (c == '\n'); - if (i == p->lex_i || p->lex_inbuf[i - 1] != '\\') { + if (i == 0 || p->lex_inbuf[i - 1] != '\\') { if (c == '[') depth++; if (c == ']') if (--depth == 0) @@ -3416,11 +3411,11 @@ static BC_STATUS zdc_lex_string(void) bc_vec_pushZeroByte(&p->lex_strnumbuf); // This check makes sense only if size_t is (much) larger than BC_MAX_STRING. if (SIZE_MAX > (BC_MAX_STRING | 0xff)) { - if (i - p->lex_i > BC_MAX_STRING) + if (i > BC_MAX_STRING) RETURN_STATUS(bc_error("string too long: must be [1,"BC_MAX_STRING_STR"]")); } - p->lex_i = i; + p->lex_inbuf += i; p->lex_line += nls; G.err_line = p->lex_line; @@ -3451,7 +3446,7 @@ static BC_STATUS zdc_lex_token(void) } s = BC_STATUS_SUCCESS; - c = p->lex_inbuf[p->lex_i++]; + c = *p->lex_inbuf++; if (c >= '%' && c <= '~' && (p->lex = dc_char_to_LEX[c - '%']) != XC_LEX_INVALID ) { @@ -3484,7 +3479,7 @@ static BC_STATUS zdc_lex_token(void) bc_lex_whitespace(); break; case '!': - c2 = p->lex_inbuf[p->lex_i]; + c2 = *p->lex_inbuf; if (c2 == '=') p->lex = XC_LEX_OP_REL_NE; else if (c2 == '<') @@ -3493,13 +3488,13 @@ static BC_STATUS zdc_lex_token(void) p->lex = XC_LEX_OP_REL_GE; else RETURN_STATUS(bc_error_bad_character(c)); - p->lex_i++; + p->lex_inbuf++; break; case '#': bc_lex_lineComment(); break; case '.': - if (isdigit(p->lex_inbuf[p->lex_i])) + if (isdigit(*p->lex_inbuf)) s = zbc_lex_number(c); else s = bc_error_bad_character(c); @@ -3651,7 +3646,7 @@ static void bc_parse_reset(void) p->func = bc_program_func_BC_PROG_MAIN(); } - p->lex_i = p->lex_len; + p->lex_inbuf = p->lex_end; p->lex = XC_LEX_EOF; IF_BC(bc_vec_pop_all(&p->exits);) -- cgit v1.2.3-55-g6feb From 94576d2b972b3bd136fbe8057c95690ae36ea8c9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 25 Dec 2018 23:45:57 +0100 Subject: bc: fix interactive handling of comments in strings and quotes in comments function old new delta zbc_lex_next 1965 1979 +14 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 36 ++++++++++++++++++++---------------- testsuite/bc.tests | 16 ++++++++++++++-- 2 files changed, 34 insertions(+), 18 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 809b4bfc4..9d04ddea3 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -2910,25 +2910,29 @@ static bool bc_lex_more_input(void) string = G.input_buffer.v + prevlen; while (*string) { char c = *string; - if (string == G.input_buffer.v || string[-1] != '\\') { - if (IS_BC) - str ^= (c == '"'); - else { - if (c == ']') - str -= 1; - else if (c == '[') - str += 1; + if (!comment) { + if (string == G.input_buffer.v || string[-1] != '\\') { + if (IS_BC) + str ^= (c == '"'); + else { + if (c == ']') + str -= 1; + else if (c == '[') + str += 1; + } } } string++; - if (c == '/' && *string == '*') { - comment = true; - string++; - continue; - } - if (c == '*' && *string == '/') { - comment = false; - string++; + if (!str) { + if (c == '/' && *string == '*') { + comment = true; + string++; + continue; + } + if (c == '*' && *string == '/') { + comment = false; + string++; + } } } if (str != 0 || comment) { diff --git a/testsuite/bc.tests b/testsuite/bc.tests index 42fe83013..3fbb49996 100755 --- a/testsuite/bc.tests +++ b/testsuite/bc.tests @@ -6,16 +6,28 @@ # testing "test name" "command" "expected result" "file input" "stdin" -testing "bc comment 1" \ +testing "bc comment" \ "bc" \ "3\n" \ "" "1 /* comment */ + 2" -testing "bc comment 2: /*/ is not a closed comment" \ +testing "bc /*/ is not a closed comment" \ "bc" \ "4\n" \ "" "1 /*/ + 2 */ + 3" +# this needs interactive testing +testing "bc comment with \"" \ + "bc" \ + "3\n" \ + "" "1 /* \" */ + 2" + +# this needs interactive testing +testing "bc \"string/*\" is not a comment" \ + "bc" \ + "string/*9\n" \ + "" "\"string/*\";9" + testing "bc comment 3: unterminated #comment" \ "bc" \ "" \ -- cgit v1.2.3-55-g6feb From 63ad7993845fbf59264e22295ae9c06250832119 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 26 Dec 2018 12:23:05 +0100 Subject: bc: fix handling of comment/string interactions while buffering input function old new delta zbc_lex_next 1965 1982 +17 zbc_num_divmod 150 156 +6 bc_read_line 411 394 -17 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/1 up/down: 23/-17) Total: 6 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 112 +++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 74 insertions(+), 38 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 9d04ddea3..f4e499f13 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -1147,23 +1147,6 @@ static void bc_vec_string(BcVec *v, size_t len, const char *str) bc_vec_pushZeroByte(v); } -#if ENABLE_FEATURE_BC_SIGNALS && ENABLE_FEATURE_EDITING -static void bc_vec_concat(BcVec *v, const char *str) -{ - size_t len, slen; - - if (v->len == 0) bc_vec_pushZeroByte(v); - - slen = strlen(str); - len = v->len + slen; - - if (v->cap < len) bc_vec_grow(v, slen); - strcpy(v->v + v->len - 1, str); - - v->len = len; -} -#endif - static void *bc_vec_item(const BcVec *v, size_t idx) { return v->v + v->size * idx; @@ -2491,6 +2474,21 @@ static FAST_FUNC void bc_result_free(void *result) } } +#if ENABLE_FEATURE_BC_SIGNALS && ENABLE_FEATURE_EDITING +static void bc_vec_concat(BcVec *v, const char *str) +{ + size_t len, slen; + + slen = strlen(str); + len = v->len + slen + 1; + + if (v->cap < len) bc_vec_grow(v, slen); + strcpy(v->v + v->len, str); + + v->len = len; +} +#endif + static int bad_input_byte(char c) { if ((c < ' ' && c != '\t' && c != '\r' && c != '\n') // also allow '\v' '\f'? @@ -2887,7 +2885,7 @@ static void bc_lex_file(void) static bool bc_lex_more_input(void) { BcParse *p = &G.prs; - size_t str; + unsigned str; // bool for bc, string nest count for dc bool comment; bc_vec_pop_all(&G.input_buffer); @@ -2896,8 +2894,23 @@ static bool bc_lex_more_input(void) // with a backslash to the parser. The reason for that is because the parser // treats a backslash+newline combo as whitespace, per the bc spec. In that // case, and for strings and comments, the parser will expect more stuff. - comment = false; + // + // bc cases to test interactively: + // 1 #comment\ - prints "1" at once (comment is not continued) + // 1 #comment/* - prints "1" at once + // 1 #comment" - prints "1" at once + // 1\#comment - error at once (\ is not a line continuation) + // 1 + /*"*/2 - prints "3" at once + // 1 + /*#*/2 - prints "3" at once + // "str\" - prints "str\" at once + // "str#" - prints "str#" at once + // "str/*" - prints "str/*" at once + // "str#\ - waits for second line + // end" - ...prints "str#\end" +//This is way too complex, we duplicate comment/string logic of lexer +//TODO: switch to char-by-char input like hush does it str = 0; + comment = false; // stays always false for dc for (;;) { size_t prevlen = G.input_buffer.len; char *string; @@ -2909,39 +2922,61 @@ static bool bc_lex_more_input(void) string = G.input_buffer.v + prevlen; while (*string) { - char c = *string; - if (!comment) { - if (string == G.input_buffer.v || string[-1] != '\\') { - if (IS_BC) - str ^= (c == '"'); - else { - if (c == ']') - str -= 1; - else if (c == '[') - str += 1; - } + char c = *string++; +#if ENABLE_BC + if (comment) { + // We are in /**/ comment, exit only on "*/" + if (c == '*' && *string == '/') { + comment = false; + string++; } + continue; } - string++; - if (!str) { +#endif + // We are not in /**/ comment + if (str) { + // We are in "string" (bc) or [string] (dc) + if (IS_BC) { + // bc strings have no escapes: \\ is not special, + // \n is not, \" is not, \ is not. + str = (c != '"'); // clear flag when " is seen + } else { + // dc strings have no escapes as well, can nest + if (c == ']') + str--; + if (c == '[') + str++; + } + continue; + } + // We are not in a string or /**/ comment + + // Is it a #comment? Return the string (can't have continuation) + if (c == '#') + goto return_string; +#if ENABLE_BC + if (IS_BC) { + // bc: is it a start of /**/ comment or string? if (c == '/' && *string == '*') { comment = true; string++; continue; } - if (c == '*' && *string == '/') { - comment = false; - string++; - } + str = (c == '"'); // set flag if " is seen + continue; } - } +#endif + // dc: is it a start of string? + str = (c == '['); + } // end of "check all chars in string" loop + if (str != 0 || comment) { G.input_buffer.len--; // backstep over the trailing NUL byte continue; } // Check for backslash+newline. - // we do not check that last char is '\n' - + // We do not check that last char is '\n' - // if it is not, then it's EOF, and looping back // to bc_read_line() will detect it: string -= 2; @@ -2952,6 +2987,7 @@ static bool bc_lex_more_input(void) break; } + return_string: p->lex_inbuf = G.input_buffer.v; // bb_error_msg("G.input_buffer.len:%d '%s'", G.input_buffer.len, G.input_buffer.v); -- cgit v1.2.3-55-g6feb From 7d32e25bf33c98af6878715907ebbf297ef3d64a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 26 Dec 2018 18:32:43 +0100 Subject: bc: prepare for char-by-char input handling function old new delta peek_inbuf - 292 +292 parse_lex_by_checking_eq_sign - 26 +26 eat_inbuf - 22 +22 zbc_vm_execute_FILE 52 61 +9 bc_lex_lineComment 29 30 +1 zbc_lex_number 174 172 -2 bc_vm_run 104 99 -5 zbc_num_divmod 156 150 -6 bc_lex_file 24 - -24 bc_lex_assign 26 - -26 zbc_lex_next 1982 1587 -395 ------------------------------------------------------------------------------ (add/remove: 3/2 grow/shrink: 2/4 up/down: 350/-458) Total: -108 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 443 +++++++++++++++++++-------------------- testsuite/dc_strings_results.txt | 8 +- 2 files changed, 214 insertions(+), 237 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index f4e499f13..5789869a7 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -713,7 +713,6 @@ dc_LEX_to_INST[] = { // starts at XC_LEX_OP_POWER // corresponding XC/DC_L typedef struct BcParse { smallint lex; // was BcLexType // first member is most used smallint lex_last; // was BcLexType - bool lex_newline; size_t lex_line; const char *lex_inbuf; const char *lex_end; @@ -2741,147 +2740,6 @@ static BC_STATUS zbc_num_parse(BcNum *n, const char *val, unsigned base_t) } #define zbc_num_parse(...) (zbc_num_parse(__VA_ARGS__) COMMA_SUCCESS) -static void bc_lex_lineComment(void) -{ - BcParse *p = &G.prs; - // Try: echo -n '#foo' | bc - p->lex = XC_LEX_WHITESPACE; - while (p->lex_inbuf < p->lex_end && *p->lex_inbuf != '\n') - p->lex_inbuf++; -} - -static void bc_lex_whitespace(void) -{ - BcParse *p = &G.prs; - p->lex = XC_LEX_WHITESPACE; - for (;;) { - char c = *p->lex_inbuf; - if (c == '\n') // this is XC_LEX_NLINE, not XC_LEX_WHITESPACE - break; - if (!isspace(c)) - break; - p->lex_inbuf++; - } -} - -static BC_STATUS zbc_lex_number(char start) -{ - BcParse *p = &G.prs; - const char *buf = p->lex_inbuf; - size_t len, i, ccnt; - bool pt; - - pt = (start == '.'); - p->lex = XC_LEX_NUMBER; - ccnt = i = 0; - for (;;) { - char c = buf[i]; - if (c == '\0') - break; - if (c == '\\' && buf[i + 1] == '\n') { - i += 2; - //number_of_backslashes++ - see comment below - continue; - } - if (!isdigit(c) && (c < 'A' || c > 'F')) { - if (c != '.') break; - // if '.' was already seen, stop on second one: - if (pt) break; - pt = true; - } - // buf[i] is one of "0-9A-F." - i++; - if (c != '.') - ccnt = i; - } - //ccnt is the number of chars in the number string, excluding possible - //trailing "[\].[\]" (with any number of \ repetitions). - //i is buf[i] index of the first not-yet-parsed char after that. - p->lex_inbuf += i; - - // This might overestimate the size, if there are "\"'s - // in the number. Subtracting number_of_backslashes*2 correctly - // is not that easy: consider that in the case of "NNN.\" - // loop above will count "\" before it realizes it is not - // in fact *inside* the number: - len = ccnt + 1; // +1 byte for NUL termination - - // This check makes sense only if size_t is (much) larger than BC_MAX_NUM. - if (SIZE_MAX > (BC_MAX_NUM | 0xff)) { - if (len > BC_MAX_NUM) - RETURN_STATUS(bc_error("number too long: must be [1,"BC_MAX_NUM_STR"]")); - } - - bc_vec_pop_all(&p->lex_strnumbuf); - bc_vec_expand(&p->lex_strnumbuf, 1 + len); - bc_vec_push(&p->lex_strnumbuf, &start); - - while (ccnt != 0) { - // If we have hit a backslash, skip it. We don't have - // to check for a newline because it's guaranteed. - if (*buf == '\\') { - buf += 2; - ccnt -= 2; - continue; - } - bc_vec_push(&p->lex_strnumbuf, buf); - buf++; - ccnt--; - } - - bc_vec_pushZeroByte(&p->lex_strnumbuf); - - RETURN_STATUS(BC_STATUS_SUCCESS); -} -#define zbc_lex_number(...) (zbc_lex_number(__VA_ARGS__) COMMA_SUCCESS) - -static void bc_lex_name(void) -{ - BcParse *p = &G.prs; - size_t i; - const char *buf; - - p->lex = XC_LEX_NAME; - - i = 0; - buf = p->lex_inbuf - 1; - for (;;) { - char c = buf[i]; - if ((c < 'a' || c > 'z') && !isdigit(c) && c != '_') break; - i++; - } - -#if 0 // We do not protect against people with gigabyte-long names - // This check makes sense only if size_t is (much) larger than BC_MAX_STRING. - if (SIZE_MAX > (BC_MAX_STRING | 0xff)) { - if (i > BC_MAX_STRING) - return bc_error("name too long: must be [1,"BC_MAX_STRING_STR"]"); - } -#endif - bc_vec_string(&p->lex_strnumbuf, i, buf); - - // Increment the index. We minus 1 because it has already been incremented. - p->lex_inbuf += i - 1; - - //return BC_STATUS_SUCCESS; -} - -static void bc_lex_init(void) -{ - bc_char_vec_init(&G.prs.lex_strnumbuf); -} - -static void bc_lex_free(void) -{ - bc_vec_free(&G.prs.lex_strnumbuf); -} - -static void bc_lex_file(void) -{ - G.err_line = G.prs.lex_line = 1; - G.prs.lex_newline = false; -} - static bool bc_lex_more_input(void) { BcParse *p = &G.prs; @@ -2996,6 +2854,147 @@ static bool bc_lex_more_input(void) return G.input_buffer.len > 1; } +// p->lex_inbuf points to the current string to be parsed. +// if p->lex_inbuf points to '\0', it's either EOF or it points after +// last processed line's terminating '\n' (and more reading needs to be done +// to get next character). +// +// If you are in a situation where that is a possibility, call peek_inbuf(). +// If necessary, it performs more reading and changes p->lex_inbuf, +// then it returns *p->lex_inbuf (which will be '\0' only if it's EOF). +// After it, just referencing *p->lex_inbuf is valid, and if it wasn't '\0', +// it's ok to do p->lex_inbuf++ once without end-of-buffer checking. +// +// eat_inbuf() is equvalent to "peek_inbuf(); if (c) p->lex_inbuf++": +// it returns current char and advances the pointer (if not EOF). +// After eat_inbuf(), referencing p->lex_inbuf[-1] and *p->lex_inbuf is valid. +// +// In many cases, you can use fast *p->lex_inbuf instead of peek_inbuf(): +// unless prev char might have been '\n', *p->lex_inbuf is '\0' ONLY +// on real EOF, not end-of-buffer. +static char peek_inbuf(void) +{ + if (G.prs.lex_inbuf == G.prs.lex_end) { + if (G.prs.lex_input_fp) + if (!bc_lex_more_input()) + G.prs.lex_input_fp = NULL; + } + return *G.prs.lex_inbuf; +} +static char eat_inbuf(void) +{ + char c = peek_inbuf(); + if (c) G.prs.lex_inbuf++; + return c; +} + +static void bc_lex_lineComment(void) +{ + BcParse *p = &G.prs; + char c; + + // Try: echo -n '#foo' | bc + p->lex = XC_LEX_WHITESPACE; + + // We depend here on input being done in whole lines: + // '\0' which isn't the EOF can only be seen after '\n'. + while ((c = *p->lex_inbuf) != '\n' && c != '\0') + p->lex_inbuf++; +} + +static void bc_lex_whitespace(void) +{ + BcParse *p = &G.prs; + + p->lex = XC_LEX_WHITESPACE; + for (;;) { + // We depend here on input being done in whole lines: + // '\0' which isn't the EOF can only be seen after '\n'. + char c = *p->lex_inbuf; + if (c == '\n') // this is XC_LEX_NLINE, not XC_LEX_WHITESPACE + break; + if (!isspace(c)) + break; + p->lex_inbuf++; + } +} + +static BC_STATUS zbc_lex_number(char last) +{ + BcParse *p = &G.prs; + bool pt; + + bc_vec_pop_all(&p->lex_strnumbuf); + bc_vec_pushByte(&p->lex_strnumbuf, last); + + pt = (last == '.'); + p->lex = XC_LEX_NUMBER; + for (;;) { + // We depend here on input being done in whole lines: + // '\0' which isn't the EOF can only be seen after '\n'. + char c = *p->lex_inbuf; + check_c: + if (c == '\0') + break; + if (c == '\\' && p->lex_inbuf[1] == '\n') { + p->lex_inbuf += 2; + p->lex_line++; + c = peek_inbuf(); // force next line to be read + goto check_c; + } + if (!isdigit(c) && (c < 'A' || c > 'F')) { + if (c != '.') break; + // if '.' was already seen, stop on second one: + if (pt) break; + pt = true; + } + // c is one of "0-9A-F." + last = c; + bc_vec_push(&p->lex_strnumbuf, p->lex_inbuf); + p->lex_inbuf++; + } + if (last == '.') // remove trailing '.' if any + bc_vec_pop(&p->lex_strnumbuf); + bc_vec_pushZeroByte(&p->lex_strnumbuf); + + G.err_line = G.prs.lex_line; + RETURN_STATUS(BC_STATUS_SUCCESS); +} +#define zbc_lex_number(...) (zbc_lex_number(__VA_ARGS__) COMMA_SUCCESS) + +static void bc_lex_name(void) +{ + BcParse *p = &G.prs; + size_t i; + const char *buf; + + p->lex = XC_LEX_NAME; + + // Since names can't cross lines with \, + // we depend on the fact that whole line is in the buffer + i = 0; + buf = p->lex_inbuf - 1; + for (;;) { + char c = buf[i]; + if ((c < 'a' || c > 'z') && !isdigit(c) && c != '_') break; + i++; + } + +#if 0 // We do not protect against people with gigabyte-long names + // This check makes sense only if size_t is (much) larger than BC_MAX_STRING. + if (SIZE_MAX > (BC_MAX_STRING | 0xff)) { + if (i > BC_MAX_STRING) + return bc_error("name too long: must be [1,"BC_MAX_STRING_STR"]"); + } +#endif + bc_vec_string(&p->lex_strnumbuf, i, buf); + + // Increment the index. We minus 1 because it has already been incremented. + p->lex_inbuf += i - 1; + + //return BC_STATUS_SUCCESS; +} + IF_BC(static BC_STATUS zbc_lex_token(void);) IF_DC(static BC_STATUS zdc_lex_token(void);) #define zbc_lex_token(...) (zbc_lex_token(__VA_ARGS__) COMMA_SUCCESS) @@ -3007,26 +3006,18 @@ static BC_STATUS zbc_lex_next(void) BcStatus s; p->lex_last = p->lex; - if (p->lex_last == XC_LEX_EOF) RETURN_STATUS(bc_error("end of file")); - - p->lex_line += p->lex_newline; - G.err_line = p->lex_line; - p->lex_newline = false; + if (p->lex_last == XC_LEX_EOF) + RETURN_STATUS(bc_error("end of file")); // Loop until failure or we don't have whitespace. This // is so the parser doesn't get inundated with whitespace. // Comments are also XC_LEX_WHITESPACE tokens and eaten here. s = BC_STATUS_SUCCESS; do { - if (p->lex_inbuf == p->lex_end) { + if (*p->lex_inbuf == '\0') { p->lex = XC_LEX_EOF; - if (!G.prs.lex_input_fp) + if (peek_inbuf() == '\0') RETURN_STATUS(BC_STATUS_SUCCESS); - if (!bc_lex_more_input()) { - G.prs.lex_input_fp = NULL; - RETURN_STATUS(BC_STATUS_SUCCESS); - } - // here it's guaranteed that p->lex_ibuf is below p->lex_end } p->lex_next_at = p->lex_inbuf; dbg_lex("next string to parse:'%.*s'", @@ -3126,80 +3117,70 @@ static BC_STATUS zbc_lex_identifier(void) static BC_STATUS zbc_lex_string(void) { BcParse *p = &G.prs; - size_t len, nls, i; p->lex = XC_LEX_STR; - - nls = 0; - i = 0; + bc_vec_pop_all(&p->lex_strnumbuf); for (;;) { - char c = p->lex_inbuf[i]; + char c = peek_inbuf(); // strings can cross lines if (c == '\0') { - p->lex_inbuf += i; - RETURN_STATUS(bc_error("unterminated string")); + RETURN_STATUS(bc_error("unterminated string1")); } if (c == '"') break; - nls += (c == '\n'); - i++; - } - - len = i; - // This check makes sense only if size_t is (much) larger than BC_MAX_STRING. - if (SIZE_MAX > (BC_MAX_STRING | 0xff)) { - if (len > BC_MAX_STRING) - RETURN_STATUS(bc_error("string too long: must be [1,"BC_MAX_STRING_STR"]")); + if (c == '\n') + p->lex_line++; + bc_vec_push(&p->lex_strnumbuf, p->lex_inbuf); + p->lex_inbuf++; } - bc_vec_string(&p->lex_strnumbuf, len, p->lex_inbuf); + bc_vec_pushZeroByte(&p->lex_strnumbuf); + p->lex_inbuf++; - p->lex_inbuf += i + 1; - p->lex_line += nls; G.err_line = p->lex_line; - RETURN_STATUS(BC_STATUS_SUCCESS); } #define zbc_lex_string(...) (zbc_lex_string(__VA_ARGS__) COMMA_SUCCESS) -static void bc_lex_assign(unsigned with_and_without) +static void parse_lex_by_checking_eq_sign(unsigned with_and_without) { BcParse *p = &G.prs; if (*p->lex_inbuf == '=') { + // ^^^ not using peek_inbuf() since '==' etc can't be split across lines p->lex_inbuf++; with_and_without >>= 8; // store "with" value } // else store "without" value p->lex = (with_and_without & 0xff); } -#define bc_lex_assign(with, without) \ - bc_lex_assign(((with)<<8)|(without)) +#define parse_lex_by_checking_eq_sign(with, without) \ + parse_lex_by_checking_eq_sign(((with)<<8)|(without)) static BC_STATUS zbc_lex_comment(void) { BcParse *p = &G.prs; - size_t i, nls = 0; - const char *buf = p->lex_inbuf; p->lex = XC_LEX_WHITESPACE; - i = 0; /* here lex_inbuf[0] is the '*' of opening comment delimiter */ + // here lex_inbuf is at '*' of opening comment delimiter for (;;) { - char c = buf[++i]; + char c; + + p->lex_inbuf++; + c = peek_inbuf(); check_star: if (c == '*') { - c = buf[++i]; + p->lex_inbuf++; + c = peek_inbuf(); if (c == '/') break; goto check_star; } if (c == '\0') { - p->lex_inbuf += i; RETURN_STATUS(bc_error("unterminated comment")); } - nls += (c == '\n'); + if (c == '\n') + p->lex_line++; } + p->lex_inbuf++; // skip trailing '/' - p->lex_inbuf += i + 1; - p->lex_line += nls; G.err_line = p->lex_line; - RETURN_STATUS(BC_STATUS_SUCCESS); } #define zbc_lex_comment(...) (zbc_lex_comment(__VA_ARGS__) COMMA_SUCCESS) @@ -3209,7 +3190,7 @@ static BC_STATUS zbc_lex_token(void) { BcParse *p = &G.prs; BcStatus s = BC_STATUS_SUCCESS; - char c = *p->lex_inbuf++; + char c = eat_inbuf(); char c2; // This is the workhorse of the lexer. @@ -3217,11 +3198,10 @@ static BC_STATUS zbc_lex_token(void) // case '\0': // probably never reached // p->lex_inbuf--; // p->lex = XC_LEX_EOF; -// p->lex_newline = true; // break; case '\n': + p->lex_line++; p->lex = XC_LEX_NLINE; - p->lex_newline = true; break; case '\t': case '\v': @@ -3231,7 +3211,7 @@ static BC_STATUS zbc_lex_token(void) bc_lex_whitespace(); break; case '!': - bc_lex_assign(XC_LEX_OP_REL_NE, BC_LEX_OP_BOOL_NOT); + parse_lex_by_checking_eq_sign(XC_LEX_OP_REL_NE, BC_LEX_OP_BOOL_NOT); if (p->lex == BC_LEX_OP_BOOL_NOT) { s = zbc_POSIX_does_not_allow_bool_ops_this_is_bad("!"); if (s) RETURN_STATUS(s); @@ -3246,7 +3226,7 @@ static BC_STATUS zbc_lex_token(void) bc_lex_lineComment(); break; case '%': - bc_lex_assign(BC_LEX_OP_ASSIGN_MODULUS, XC_LEX_OP_MODULUS); + parse_lex_by_checking_eq_sign(BC_LEX_OP_ASSIGN_MODULUS, XC_LEX_OP_MODULUS); break; case '&': c2 = *p->lex_inbuf; @@ -3265,7 +3245,7 @@ static BC_STATUS zbc_lex_token(void) p->lex = (BcLexType)(c - '(' + BC_LEX_LPAREN); break; case '*': - bc_lex_assign(BC_LEX_OP_ASSIGN_MULTIPLY, XC_LEX_OP_MULTIPLY); + parse_lex_by_checking_eq_sign(BC_LEX_OP_ASSIGN_MULTIPLY, XC_LEX_OP_MULTIPLY); break; case '+': c2 = *p->lex_inbuf; @@ -3273,7 +3253,7 @@ static BC_STATUS zbc_lex_token(void) p->lex_inbuf++; p->lex = BC_LEX_OP_INC; } else - bc_lex_assign(BC_LEX_OP_ASSIGN_PLUS, XC_LEX_OP_PLUS); + parse_lex_by_checking_eq_sign(BC_LEX_OP_ASSIGN_PLUS, XC_LEX_OP_PLUS); break; case ',': p->lex = BC_LEX_COMMA; @@ -3284,7 +3264,7 @@ static BC_STATUS zbc_lex_token(void) p->lex_inbuf++; p->lex = BC_LEX_OP_DEC; } else - bc_lex_assign(BC_LEX_OP_ASSIGN_MINUS, XC_LEX_OP_MINUS); + parse_lex_by_checking_eq_sign(BC_LEX_OP_ASSIGN_MINUS, XC_LEX_OP_MINUS); break; case '.': if (isdigit(*p->lex_inbuf)) @@ -3299,7 +3279,7 @@ static BC_STATUS zbc_lex_token(void) if (c2 == '*') s = zbc_lex_comment(); else - bc_lex_assign(BC_LEX_OP_ASSIGN_DIVIDE, XC_LEX_OP_DIVIDE); + parse_lex_by_checking_eq_sign(BC_LEX_OP_ASSIGN_DIVIDE, XC_LEX_OP_DIVIDE); break; case '0': case '1': @@ -3323,13 +3303,13 @@ static BC_STATUS zbc_lex_token(void) p->lex = BC_LEX_SCOLON; break; case '<': - bc_lex_assign(XC_LEX_OP_REL_LE, XC_LEX_OP_REL_LT); + parse_lex_by_checking_eq_sign(XC_LEX_OP_REL_LE, XC_LEX_OP_REL_LT); break; case '=': - bc_lex_assign(XC_LEX_OP_REL_EQ, BC_LEX_OP_ASSIGN); + parse_lex_by_checking_eq_sign(XC_LEX_OP_REL_EQ, BC_LEX_OP_ASSIGN); break; case '>': - bc_lex_assign(XC_LEX_OP_REL_GE, XC_LEX_OP_REL_GT); + parse_lex_by_checking_eq_sign(XC_LEX_OP_REL_GE, XC_LEX_OP_REL_GT); break; case '[': case ']': @@ -3343,7 +3323,7 @@ static BC_STATUS zbc_lex_token(void) s = bc_error_bad_character(c); break; case '^': - bc_lex_assign(BC_LEX_OP_ASSIGN_POWER, XC_LEX_OP_POWER); + parse_lex_by_checking_eq_sign(BC_LEX_OP_ASSIGN_POWER, XC_LEX_OP_POWER); break; case 'a': case 'b': @@ -3422,43 +3402,30 @@ static BC_STATUS zdc_lex_register(void) static BC_STATUS zdc_lex_string(void) { BcParse *p = &G.prs; - size_t depth, nls, i; + size_t depth; p->lex = XC_LEX_STR; bc_vec_pop_all(&p->lex_strnumbuf); - nls = 0; depth = 1; - i = 0; for (;;) { - char c = p->lex_inbuf[i]; + char c = peek_inbuf(); if (c == '\0') { - p->lex_inbuf += i; - RETURN_STATUS(bc_error("string end could not be found")); - } - nls += (c == '\n'); - if (i == 0 || p->lex_inbuf[i - 1] != '\\') { - if (c == '[') depth++; - if (c == ']') - if (--depth == 0) - break; + RETURN_STATUS(bc_error("unterminated string")); } - bc_vec_push(&p->lex_strnumbuf, &p->lex_inbuf[i]); - i++; + if (c == '[') depth++; + if (c == ']') + if (--depth == 0) + break; + if (c == '\n') + p->lex_line++; + bc_vec_push(&p->lex_strnumbuf, p->lex_inbuf); + p->lex_inbuf++; } - i++; - bc_vec_pushZeroByte(&p->lex_strnumbuf); - // This check makes sense only if size_t is (much) larger than BC_MAX_STRING. - if (SIZE_MAX > (BC_MAX_STRING | 0xff)) { - if (i > BC_MAX_STRING) - RETURN_STATUS(bc_error("string too long: must be [1,"BC_MAX_STRING_STR"]")); - } + p->lex_inbuf++; // skip trailing ']' - p->lex_inbuf += i; - p->lex_line += nls; G.err_line = p->lex_line; - RETURN_STATUS(BC_STATUS_SUCCESS); } #define zdc_lex_string(...) (zdc_lex_string(__VA_ARGS__) COMMA_SUCCESS) @@ -3486,7 +3453,7 @@ static BC_STATUS zdc_lex_token(void) } s = BC_STATUS_SUCCESS; - c = *p->lex_inbuf++; + c = eat_inbuf(); if (c >= '%' && c <= '~' && (p->lex = dc_char_to_LEX[c - '%']) != XC_LEX_INVALID ) { @@ -3507,15 +3474,14 @@ static BC_STATUS zdc_lex_token(void) // commands are not executed on pressing ). // IOW: typing "1p" should print "1" _at once_, // not after some more input. + p->lex_line++; p->lex = XC_LEX_NLINE; - p->lex_newline = true; break; case '\t': case '\v': case '\f': case '\r': case ' ': - p->lex_newline = 0; // was (c == '\n') bc_lex_whitespace(); break; case '!': @@ -3702,7 +3668,7 @@ static void bc_parse_free(void) IF_BC(bc_vec_free(&p->exits);) IF_BC(bc_vec_free(&p->conds);) IF_BC(bc_vec_free(&p->ops);) - bc_lex_free(); + bc_vec_free(&G.prs.lex_strnumbuf); } static void bc_parse_create(size_t fidx) @@ -3710,7 +3676,7 @@ static void bc_parse_create(size_t fidx) BcParse *p = &G.prs; memset(p, 0, sizeof(BcParse)); - bc_lex_init(); + bc_char_vec_init(&G.prs.lex_strnumbuf); IF_BC(bc_vec_init(&p->exits, sizeof(size_t), NULL);) IF_BC(bc_vec_init(&p->conds, sizeof(size_t), NULL);) IF_BC(bc_vec_init(&p->ops, sizeof(BcLexType), NULL);) @@ -4753,11 +4719,13 @@ static BcStatus bc_parse_expr_empty_ok(uint8_t flags) switch (t) { case BC_LEX_OP_INC: case BC_LEX_OP_DEC: + dbg_lex("%s:%d LEX_OP_INC/DEC", __func__, __LINE__); s = zbc_parse_incdec(&prev, &paren_expr, &nexprs, flags); rprn = bin_last = false; //get_token = false; - already is break; case XC_LEX_OP_MINUS: + dbg_lex("%s:%d LEX_OP_MINUS", __func__, __LINE__); s = zbc_parse_minus(&prev, ops_bgn, rprn, &nexprs); rprn = false; //get_token = false; - already is @@ -4770,6 +4738,7 @@ static BcStatus bc_parse_expr_empty_ok(uint8_t flags) case BC_LEX_OP_ASSIGN_PLUS: case BC_LEX_OP_ASSIGN_MINUS: case BC_LEX_OP_ASSIGN: + dbg_lex("%s:%d LEX_ASSIGNxyz", __func__, __LINE__); if (prev != XC_INST_VAR && prev != XC_INST_ARRAY_ELEM && prev != XC_INST_SCALE && prev != XC_INST_IBASE && prev != XC_INST_OBASE && prev != BC_INST_LAST @@ -4794,6 +4763,7 @@ static BcStatus bc_parse_expr_empty_ok(uint8_t flags) case BC_LEX_OP_BOOL_NOT: case BC_LEX_OP_BOOL_OR: case BC_LEX_OP_BOOL_AND: + dbg_lex("%s:%d LEX_OP_xyz", __func__, __LINE__); if (((t == BC_LEX_OP_BOOL_NOT) != bin_last) || (t != BC_LEX_OP_BOOL_NOT && prev == XC_INST_BOOL_NOT) ) { @@ -4808,6 +4778,7 @@ static BcStatus bc_parse_expr_empty_ok(uint8_t flags) bin_last = (t != BC_LEX_OP_BOOL_NOT); break; case BC_LEX_LPAREN: + dbg_lex("%s:%d LEX_LPAREN", __func__, __LINE__); if (BC_PARSE_LEAF(prev, rprn)) return bc_error_bad_expression(); bc_vec_push(&p->ops, &t); @@ -4817,6 +4788,7 @@ static BcStatus bc_parse_expr_empty_ok(uint8_t flags) rprn = bin_last = false; break; case BC_LEX_RPAREN: + dbg_lex("%s:%d LEX_RPAREN", __func__, __LINE__); if (bin_last || prev == XC_INST_BOOL_NOT) return bc_error_bad_expression(); if (nparens == 0) { @@ -4833,6 +4805,7 @@ static BcStatus bc_parse_expr_empty_ok(uint8_t flags) bin_last = false; break; case XC_LEX_NAME: + dbg_lex("%s:%d LEX_NAME", __func__, __LINE__); if (BC_PARSE_LEAF(prev, rprn)) return bc_error_bad_expression(); s = zbc_parse_name(&prev, flags & ~BC_PARSE_NOCALL); @@ -4842,6 +4815,7 @@ static BcStatus bc_parse_expr_empty_ok(uint8_t flags) nexprs++; break; case XC_LEX_NUMBER: + dbg_lex("%s:%d LEX_NUMBER", __func__, __LINE__); if (BC_PARSE_LEAF(prev, rprn)) return bc_error_bad_expression(); bc_parse_pushNUM(); @@ -4854,6 +4828,7 @@ static BcStatus bc_parse_expr_empty_ok(uint8_t flags) case BC_LEX_KEY_IBASE: case BC_LEX_KEY_LAST: case BC_LEX_KEY_OBASE: + dbg_lex("%s:%d LEX_IBASE/LAST/OBASE", __func__, __LINE__); if (BC_PARSE_LEAF(prev, rprn)) return bc_error_bad_expression(); prev = (char) (t - BC_LEX_KEY_IBASE + XC_INST_IBASE); @@ -4865,6 +4840,7 @@ static BcStatus bc_parse_expr_empty_ok(uint8_t flags) break; case BC_LEX_KEY_LENGTH: case BC_LEX_KEY_SQRT: + dbg_lex("%s:%d LEX_LEN/SQRT", __func__, __LINE__); if (BC_PARSE_LEAF(prev, rprn)) return bc_error_bad_expression(); s = zbc_parse_builtin(t, flags, &prev); @@ -4874,6 +4850,7 @@ static BcStatus bc_parse_expr_empty_ok(uint8_t flags) nexprs++; break; case BC_LEX_KEY_READ: + dbg_lex("%s:%d LEX_READ", __func__, __LINE__); if (BC_PARSE_LEAF(prev, rprn)) return bc_error_bad_expression(); s = zbc_parse_read(); @@ -4884,6 +4861,7 @@ static BcStatus bc_parse_expr_empty_ok(uint8_t flags) nexprs++; break; case BC_LEX_KEY_SCALE: + dbg_lex("%s:%d LEX_SCALE", __func__, __LINE__); if (BC_PARSE_LEAF(prev, rprn)) return bc_error_bad_expression(); s = zbc_parse_scale(&prev, flags); @@ -5348,7 +5326,7 @@ static BC_STATUS zbc_program_read(void) sv_parse = G.prs; // struct copy bc_parse_create(BC_PROG_READ); - //bc_lex_file(&G.prs.l); - not needed, error line info is not printed for read() + //G.err_line = G.prs.lex_line = 1; - not needed, error line info is not printed for read() s = zbc_parse_text_init(buf.v); if (s) goto exec_err; @@ -6950,7 +6928,7 @@ static BC_STATUS zbc_vm_execute_FILE(FILE *fp, const char *filename) G.prs.lex_filename = filename; G.prs.lex_input_fp = fp; - bc_lex_file(); + G.err_line = G.prs.lex_line = 1; do { s = zbc_vm_process(""); @@ -7232,7 +7210,6 @@ static BC_STATUS zbc_vm_exec(void) // We know that internal library is not buggy, // thus error checking is normally disabled. # define DEBUG_LIB 0 - bc_lex_file(); s = zbc_vm_process(bc_lib); if (DEBUG_LIB && s) RETURN_STATUS(s); } diff --git a/testsuite/dc_strings_results.txt b/testsuite/dc_strings_results.txt index d606637cc..e49b9b288 100644 --- a/testsuite/dc_strings_results.txt +++ b/testsuite/dc_strings_results.txt @@ -1,9 +1,9 @@ 13 Hello, World! -16 -Hello, \[ World! -16 -Hello, \] World! +Hello, \[ World!]ZpR +[Hello, \[ World!]pR +[Hello, \] World!]ZpR +[Hello, \] World! 1 2 3 -- cgit v1.2.3-55-g6feb From b1b7996a2acd8a95ae13dad1f64f86e221167cb7 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 26 Dec 2018 18:46:03 +0100 Subject: bc: remove all logic for multi-line buffering function old new delta zbc_vm_process 865 874 +9 zbc_parse_text_init 51 38 -13 bc_read_line 394 345 -49 peek_inbuf 292 69 -223 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/3 up/down: 9/-285) Total: -276 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 144 ++++++++------------------------------------------------- 1 file changed, 19 insertions(+), 125 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 5789869a7..632158b7f 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -715,7 +715,6 @@ typedef struct BcParse { smallint lex_last; // was BcLexType size_t lex_line; const char *lex_inbuf; - const char *lex_end; const char *lex_next_at; // last lex_next() was called at this string const char *lex_filename; FILE *lex_input_fp; @@ -2473,21 +2472,6 @@ static FAST_FUNC void bc_result_free(void *result) } } -#if ENABLE_FEATURE_BC_SIGNALS && ENABLE_FEATURE_EDITING -static void bc_vec_concat(BcVec *v, const char *str) -{ - size_t len, slen; - - slen = strlen(str); - len = v->len + slen + 1; - - if (v->cap < len) bc_vec_grow(v, slen); - strcpy(v->v + v->len, str); - - v->len = len; -} -#endif - static int bad_input_byte(char c) { if ((c < ' ' && c != '\t' && c != '\r' && c != '\n') // also allow '\v' '\f'? @@ -2499,10 +2483,10 @@ static int bad_input_byte(char c) return 0; } -// Note: it _appends_ data from fp to vec. static void bc_read_line(BcVec *vec, FILE *fp) { again: + bc_vec_pop_all(vec); fflush_and_check(); #if ENABLE_FEATURE_BC_SIGNALS @@ -2542,7 +2526,7 @@ static void bc_read_line(BcVec *vec, FILE *fp) if (!c) break; if (bad_input_byte(c)) goto again; } - bc_vec_concat(vec, line_buf); + bc_vec_string(vec, n, line_buf); # undef line_buf } else # endif @@ -2550,13 +2534,12 @@ static void bc_read_line(BcVec *vec, FILE *fp) { int c; bool bad_chars = 0; - size_t len = vec->len; do { #if ENABLE_FEATURE_BC_SIGNALS if (G_interrupt) { // ^C was pressed: ignore entire line, get another one - vec->len = len; + bc_vec_pop_all(vec); goto intr; } #endif @@ -2575,7 +2558,6 @@ static void bc_read_line(BcVec *vec, FILE *fp) // Bad chars on this line if (!G.prs.lex_filename) { // stdin // ignore entire line, get another one - vec->len = len; goto again; } bb_perror_msg_and_die("file '%s' is not text", G.prs.lex_filename); @@ -2743,113 +2725,13 @@ static BC_STATUS zbc_num_parse(BcNum *n, const char *val, unsigned base_t) static bool bc_lex_more_input(void) { BcParse *p = &G.prs; - unsigned str; // bool for bc, string nest count for dc - bool comment; bc_vec_pop_all(&G.input_buffer); - // This loop is complex because the vm tries not to send any lines that end - // with a backslash to the parser. The reason for that is because the parser - // treats a backslash+newline combo as whitespace, per the bc spec. In that - // case, and for strings and comments, the parser will expect more stuff. - // - // bc cases to test interactively: - // 1 #comment\ - prints "1" at once (comment is not continued) - // 1 #comment/* - prints "1" at once - // 1 #comment" - prints "1" at once - // 1\#comment - error at once (\ is not a line continuation) - // 1 + /*"*/2 - prints "3" at once - // 1 + /*#*/2 - prints "3" at once - // "str\" - prints "str\" at once - // "str#" - prints "str#" at once - // "str/*" - prints "str/*" at once - // "str#\ - waits for second line - // end" - ...prints "str#\end" -//This is way too complex, we duplicate comment/string logic of lexer -//TODO: switch to char-by-char input like hush does it - str = 0; - comment = false; // stays always false for dc - for (;;) { - size_t prevlen = G.input_buffer.len; - char *string; - - bc_read_line(&G.input_buffer, G.prs.lex_input_fp); - // No more input means EOF - if (G.input_buffer.len <= prevlen + 1) // (we expect +1 for NUL byte) - break; - - string = G.input_buffer.v + prevlen; - while (*string) { - char c = *string++; -#if ENABLE_BC - if (comment) { - // We are in /**/ comment, exit only on "*/" - if (c == '*' && *string == '/') { - comment = false; - string++; - } - continue; - } -#endif - // We are not in /**/ comment - if (str) { - // We are in "string" (bc) or [string] (dc) - if (IS_BC) { - // bc strings have no escapes: \\ is not special, - // \n is not, \" is not, \ is not. - str = (c != '"'); // clear flag when " is seen - } else { - // dc strings have no escapes as well, can nest - if (c == ']') - str--; - if (c == '[') - str++; - } - continue; - } - // We are not in a string or /**/ comment - - // Is it a #comment? Return the string (can't have continuation) - if (c == '#') - goto return_string; -#if ENABLE_BC - if (IS_BC) { - // bc: is it a start of /**/ comment or string? - if (c == '/' && *string == '*') { - comment = true; - string++; - continue; - } - str = (c == '"'); // set flag if " is seen - continue; - } -#endif - // dc: is it a start of string? - str = (c == '['); - } // end of "check all chars in string" loop - - if (str != 0 || comment) { - G.input_buffer.len--; // backstep over the trailing NUL byte - continue; - } - - // Check for backslash+newline. - // We do not check that last char is '\n' - - // if it is not, then it's EOF, and looping back - // to bc_read_line() will detect it: - string -= 2; - if (string >= G.input_buffer.v && *string == '\\') { - G.input_buffer.len--; - continue; - } - - break; - } - return_string: + bc_read_line(&G.input_buffer, G.prs.lex_input_fp); p->lex_inbuf = G.input_buffer.v; // bb_error_msg("G.input_buffer.len:%d '%s'", G.input_buffer.len, G.input_buffer.v); - p->lex_end = p->lex_inbuf + G.input_buffer.len - 1; // do not include NUL return G.input_buffer.len > 1; } @@ -2872,9 +2754,22 @@ static bool bc_lex_more_input(void) // In many cases, you can use fast *p->lex_inbuf instead of peek_inbuf(): // unless prev char might have been '\n', *p->lex_inbuf is '\0' ONLY // on real EOF, not end-of-buffer. +// +// bc cases to test interactively: +// 1 #comment\ - prints "1" at once (comment is not continued) +// 1 #comment/* - prints "1" at once +// 1 #comment" - prints "1" at once +// 1\#comment - error at once (\ is not a line continuation) +// 1 + /*"*/2 - prints "3" at once +// 1 + /*#*/2 - prints "3" at once +// "str\" - prints "str\" at once +// "str#" - prints "str#" at once +// "str/*" - prints "str/*" at once +// "str#\ - waits for second line +// end" - ...prints "str#\end" static char peek_inbuf(void) { - if (G.prs.lex_inbuf == G.prs.lex_end) { + if (*G.prs.lex_inbuf == '\0') { if (G.prs.lex_input_fp) if (!bc_lex_more_input()) G.prs.lex_input_fp = NULL; @@ -3060,7 +2955,6 @@ static BC_STATUS zbc_lex_next_and_skip_NLINE(void) static BC_STATUS zbc_lex_text_init(const char *text) { G.prs.lex_inbuf = text; - G.prs.lex_end = text + strlen(text); G.prs.lex = G.prs.lex_last = XC_LEX_INVALID; RETURN_STATUS(zbc_lex_next()); } @@ -3652,7 +3546,7 @@ static void bc_parse_reset(void) p->func = bc_program_func_BC_PROG_MAIN(); } - p->lex_inbuf = p->lex_end; + p->lex_inbuf += strlen(p->lex_inbuf); p->lex = XC_LEX_EOF; IF_BC(bc_vec_pop_all(&p->exits);) -- cgit v1.2.3-55-g6feb From 2f7352b4f5d9d319de03b7bce2b877e2be90e8c3 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 26 Dec 2018 18:59:42 +0100 Subject: bc: comment out code which appears to be never reached function old new delta zbc_lex_next 1587 1568 -19 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 632158b7f..2237a41b5 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -2901,8 +2901,9 @@ static BC_STATUS zbc_lex_next(void) BcStatus s; p->lex_last = p->lex; - if (p->lex_last == XC_LEX_EOF) - RETURN_STATUS(bc_error("end of file")); +//why? +// if (p->lex_last == XC_LEX_EOF) +// RETURN_STATUS(bc_error("end of file")); // Loop until failure or we don't have whitespace. This // is so the parser doesn't get inundated with whitespace. -- cgit v1.2.3-55-g6feb From 1e87b97da62ea20dbf72f7507f09cf1a8a66a35f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 26 Dec 2018 19:06:05 +0100 Subject: bc: fix "dc only" build Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 2237a41b5..47cde7080 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -3559,7 +3559,7 @@ static void bc_parse_reset(void) static void bc_parse_free(void) { - BcParse *p = &G.prs; + IF_BC(BcParse *p = &G.prs;) IF_BC(bc_vec_free(&p->exits);) IF_BC(bc_vec_free(&p->conds);) IF_BC(bc_vec_free(&p->ops);) -- cgit v1.2.3-55-g6feb From 8a56e3643f83770ba92255ca5c576c20e645617f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 26 Dec 2018 19:09:23 +0100 Subject: bc: fix "bc only" build Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 47cde7080..0e5f26ce4 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -6808,7 +6808,7 @@ static BC_STATUS zbc_vm_process(const char *text) bc_vec_pop_all(&f->code); ip->inst_idx = 0; } - done: + IF_DC(done:) dbg_lex_done("%s:%d done", __func__, __LINE__); RETURN_STATUS(s); } -- cgit v1.2.3-55-g6feb From 1c69ec1597f0f3ddb8123e9122cd7737debd261c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 26 Dec 2018 19:24:15 +0100 Subject: bc: reduce indentation, no code changes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 1647 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 823 insertions(+), 824 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 0e5f26ce4..5b79b2db1 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -3090,184 +3090,184 @@ static BC_STATUS zbc_lex_token(void) // This is the workhorse of the lexer. switch (c) { -// case '\0': // probably never reached -// p->lex_inbuf--; -// p->lex = XC_LEX_EOF; -// break; - case '\n': - p->lex_line++; - p->lex = XC_LEX_NLINE; - break; - case '\t': - case '\v': - case '\f': - case '\r': - case ' ': - bc_lex_whitespace(); - break; - case '!': - parse_lex_by_checking_eq_sign(XC_LEX_OP_REL_NE, BC_LEX_OP_BOOL_NOT); - if (p->lex == BC_LEX_OP_BOOL_NOT) { - s = zbc_POSIX_does_not_allow_bool_ops_this_is_bad("!"); - if (s) RETURN_STATUS(s); - } - break; - case '"': - s = zbc_lex_string(); - break; - case '#': - s = zbc_POSIX_does_not_allow("'#' script comments"); +// case '\0': // probably never reached +// p->lex_inbuf--; +// p->lex = XC_LEX_EOF; +// break; + case '\n': + p->lex_line++; + p->lex = XC_LEX_NLINE; + break; + case '\t': + case '\v': + case '\f': + case '\r': + case ' ': + bc_lex_whitespace(); + break; + case '!': + parse_lex_by_checking_eq_sign(XC_LEX_OP_REL_NE, BC_LEX_OP_BOOL_NOT); + if (p->lex == BC_LEX_OP_BOOL_NOT) { + s = zbc_POSIX_does_not_allow_bool_ops_this_is_bad("!"); if (s) RETURN_STATUS(s); - bc_lex_lineComment(); - break; - case '%': - parse_lex_by_checking_eq_sign(BC_LEX_OP_ASSIGN_MODULUS, XC_LEX_OP_MODULUS); - break; - case '&': - c2 = *p->lex_inbuf; - if (c2 == '&') { - s = zbc_POSIX_does_not_allow_bool_ops_this_is_bad("&&"); - if (s) RETURN_STATUS(s); - p->lex_inbuf++; - p->lex = BC_LEX_OP_BOOL_AND; - } else { - p->lex = XC_LEX_INVALID; - s = bc_error_bad_character('&'); - } - break; - case '(': - case ')': - p->lex = (BcLexType)(c - '(' + BC_LEX_LPAREN); - break; - case '*': - parse_lex_by_checking_eq_sign(BC_LEX_OP_ASSIGN_MULTIPLY, XC_LEX_OP_MULTIPLY); - break; - case '+': - c2 = *p->lex_inbuf; - if (c2 == '+') { - p->lex_inbuf++; - p->lex = BC_LEX_OP_INC; - } else - parse_lex_by_checking_eq_sign(BC_LEX_OP_ASSIGN_PLUS, XC_LEX_OP_PLUS); - break; - case ',': - p->lex = BC_LEX_COMMA; - break; - case '-': - c2 = *p->lex_inbuf; - if (c2 == '-') { - p->lex_inbuf++; - p->lex = BC_LEX_OP_DEC; - } else - parse_lex_by_checking_eq_sign(BC_LEX_OP_ASSIGN_MINUS, XC_LEX_OP_MINUS); - break; - case '.': - if (isdigit(*p->lex_inbuf)) - s = zbc_lex_number(c); - else { - p->lex = BC_LEX_KEY_LAST; - s = zbc_POSIX_does_not_allow("'.' as 'last'"); - } - break; - case '/': - c2 = *p->lex_inbuf; - if (c2 == '*') - s = zbc_lex_comment(); - else - parse_lex_by_checking_eq_sign(BC_LEX_OP_ASSIGN_DIVIDE, XC_LEX_OP_DIVIDE); - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case 'A': - case 'B': - case 'C': - case 'D': - case 'E': - case 'F': + } + break; + case '"': + s = zbc_lex_string(); + break; + case '#': + s = zbc_POSIX_does_not_allow("'#' script comments"); + if (s) RETURN_STATUS(s); + bc_lex_lineComment(); + break; + case '%': + parse_lex_by_checking_eq_sign(BC_LEX_OP_ASSIGN_MODULUS, XC_LEX_OP_MODULUS); + break; + case '&': + c2 = *p->lex_inbuf; + if (c2 == '&') { + s = zbc_POSIX_does_not_allow_bool_ops_this_is_bad("&&"); + if (s) RETURN_STATUS(s); + p->lex_inbuf++; + p->lex = BC_LEX_OP_BOOL_AND; + } else { + p->lex = XC_LEX_INVALID; + s = bc_error_bad_character('&'); + } + break; + case '(': + case ')': + p->lex = (BcLexType)(c - '(' + BC_LEX_LPAREN); + break; + case '*': + parse_lex_by_checking_eq_sign(BC_LEX_OP_ASSIGN_MULTIPLY, XC_LEX_OP_MULTIPLY); + break; + case '+': + c2 = *p->lex_inbuf; + if (c2 == '+') { + p->lex_inbuf++; + p->lex = BC_LEX_OP_INC; + } else + parse_lex_by_checking_eq_sign(BC_LEX_OP_ASSIGN_PLUS, XC_LEX_OP_PLUS); + break; + case ',': + p->lex = BC_LEX_COMMA; + break; + case '-': + c2 = *p->lex_inbuf; + if (c2 == '-') { + p->lex_inbuf++; + p->lex = BC_LEX_OP_DEC; + } else + parse_lex_by_checking_eq_sign(BC_LEX_OP_ASSIGN_MINUS, XC_LEX_OP_MINUS); + break; + case '.': + if (isdigit(*p->lex_inbuf)) s = zbc_lex_number(c); - break; - case ';': - p->lex = BC_LEX_SCOLON; - break; - case '<': - parse_lex_by_checking_eq_sign(XC_LEX_OP_REL_LE, XC_LEX_OP_REL_LT); - break; - case '=': - parse_lex_by_checking_eq_sign(XC_LEX_OP_REL_EQ, BC_LEX_OP_ASSIGN); - break; - case '>': - parse_lex_by_checking_eq_sign(XC_LEX_OP_REL_GE, XC_LEX_OP_REL_GT); - break; - case '[': - case ']': - p->lex = (BcLexType)(c - '[' + BC_LEX_LBRACKET); - break; - case '\\': - if (*p->lex_inbuf == '\n') { - p->lex = XC_LEX_WHITESPACE; - p->lex_inbuf++; - } else - s = bc_error_bad_character(c); - break; - case '^': - parse_lex_by_checking_eq_sign(BC_LEX_OP_ASSIGN_POWER, XC_LEX_OP_POWER); - break; - case 'a': - case 'b': - case 'c': - case 'd': - case 'e': - case 'f': - case 'g': - case 'h': - case 'i': - case 'j': - case 'k': - case 'l': - case 'm': - case 'n': - case 'o': - case 'p': - case 'q': - case 'r': - case 's': - case 't': - case 'u': - case 'v': - case 'w': - case 'x': - case 'y': - case 'z': - s = zbc_lex_identifier(); - break; - case '{': - case '}': - p->lex = (BcLexType)(c - '{' + BC_LEX_LBRACE); - break; - case '|': - c2 = *p->lex_inbuf; - if (c2 == '|') { - s = zbc_POSIX_does_not_allow_bool_ops_this_is_bad("||"); - if (s) RETURN_STATUS(s); - p->lex_inbuf++; - p->lex = BC_LEX_OP_BOOL_OR; - } else { - p->lex = XC_LEX_INVALID; - s = bc_error_bad_character(c); - } - break; - default: + else { + p->lex = BC_LEX_KEY_LAST; + s = zbc_POSIX_does_not_allow("'.' as 'last'"); + } + break; + case '/': + c2 = *p->lex_inbuf; + if (c2 == '*') + s = zbc_lex_comment(); + else + parse_lex_by_checking_eq_sign(BC_LEX_OP_ASSIGN_DIVIDE, XC_LEX_OP_DIVIDE); + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + s = zbc_lex_number(c); + break; + case ';': + p->lex = BC_LEX_SCOLON; + break; + case '<': + parse_lex_by_checking_eq_sign(XC_LEX_OP_REL_LE, XC_LEX_OP_REL_LT); + break; + case '=': + parse_lex_by_checking_eq_sign(XC_LEX_OP_REL_EQ, BC_LEX_OP_ASSIGN); + break; + case '>': + parse_lex_by_checking_eq_sign(XC_LEX_OP_REL_GE, XC_LEX_OP_REL_GT); + break; + case '[': + case ']': + p->lex = (BcLexType)(c - '[' + BC_LEX_LBRACKET); + break; + case '\\': + if (*p->lex_inbuf == '\n') { + p->lex = XC_LEX_WHITESPACE; + p->lex_inbuf++; + } else + s = bc_error_bad_character(c); + break; + case '^': + parse_lex_by_checking_eq_sign(BC_LEX_OP_ASSIGN_POWER, XC_LEX_OP_POWER); + break; + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + case 'h': + case 'i': + case 'j': + case 'k': + case 'l': + case 'm': + case 'n': + case 'o': + case 'p': + case 'q': + case 'r': + case 's': + case 't': + case 'u': + case 'v': + case 'w': + case 'x': + case 'y': + case 'z': + s = zbc_lex_identifier(); + break; + case '{': + case '}': + p->lex = (BcLexType)(c - '{' + BC_LEX_LBRACE); + break; + case '|': + c2 = *p->lex_inbuf; + if (c2 == '|') { + s = zbc_POSIX_does_not_allow_bool_ops_this_is_bad("||"); + if (s) RETURN_STATUS(s); + p->lex_inbuf++; + p->lex = BC_LEX_OP_BOOL_OR; + } else { p->lex = XC_LEX_INVALID; s = bc_error_bad_character(c); - break; + } + break; + default: + p->lex = XC_LEX_INVALID; + s = bc_error_bad_character(c); + break; } RETURN_STATUS(s); @@ -3357,74 +3357,74 @@ static BC_STATUS zdc_lex_token(void) // This is the workhorse of the lexer. switch (c) { -// case '\0': // probably never reached -// p->lex = XC_LEX_EOF; -// break; - case '\n': - // '\n' is XC_LEX_NLINE, not XC_LEX_WHITESPACE - // (and "case '\n':" is not just empty here) - // only to allow interactive dc have a way to exit - // "parse" stage of "parse,execute" loop - // on , not on _next_ token (which would mean - // commands are not executed on pressing ). - // IOW: typing "1p" should print "1" _at once_, - // not after some more input. - p->lex_line++; - p->lex = XC_LEX_NLINE; - break; - case '\t': - case '\v': - case '\f': - case '\r': - case ' ': - bc_lex_whitespace(); - break; - case '!': - c2 = *p->lex_inbuf; - if (c2 == '=') - p->lex = XC_LEX_OP_REL_NE; - else if (c2 == '<') - p->lex = XC_LEX_OP_REL_LE; - else if (c2 == '>') - p->lex = XC_LEX_OP_REL_GE; - else - RETURN_STATUS(bc_error_bad_character(c)); - p->lex_inbuf++; - break; - case '#': - bc_lex_lineComment(); - break; - case '.': - if (isdigit(*p->lex_inbuf)) - s = zbc_lex_number(c); - else - s = bc_error_bad_character(c); - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case 'A': - case 'B': - case 'C': - case 'D': - case 'E': - case 'F': +// case '\0': // probably never reached +// p->lex = XC_LEX_EOF; +// break; + case '\n': + // '\n' is XC_LEX_NLINE, not XC_LEX_WHITESPACE + // (and "case '\n':" is not just empty here) + // only to allow interactive dc have a way to exit + // "parse" stage of "parse,execute" loop + // on , not on _next_ token (which would mean + // commands are not executed on pressing ). + // IOW: typing "1p" should print "1" _at once_, + // not after some more input. + p->lex_line++; + p->lex = XC_LEX_NLINE; + break; + case '\t': + case '\v': + case '\f': + case '\r': + case ' ': + bc_lex_whitespace(); + break; + case '!': + c2 = *p->lex_inbuf; + if (c2 == '=') + p->lex = XC_LEX_OP_REL_NE; + else if (c2 == '<') + p->lex = XC_LEX_OP_REL_LE; + else if (c2 == '>') + p->lex = XC_LEX_OP_REL_GE; + else + RETURN_STATUS(bc_error_bad_character(c)); + p->lex_inbuf++; + break; + case '#': + bc_lex_lineComment(); + break; + case '.': + if (isdigit(*p->lex_inbuf)) s = zbc_lex_number(c); - break; - case '[': - s = zdc_lex_string(); - break; - default: - p->lex = XC_LEX_INVALID; + else s = bc_error_bad_character(c); - break; + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + s = zbc_lex_number(c); + break; + case '[': + s = zdc_lex_string(); + break; + default: + p->lex = XC_LEX_INVALID; + s = bc_error_bad_character(c); + break; } RETURN_STATUS(s); @@ -3559,10 +3559,9 @@ static void bc_parse_reset(void) static void bc_parse_free(void) { - IF_BC(BcParse *p = &G.prs;) - IF_BC(bc_vec_free(&p->exits);) - IF_BC(bc_vec_free(&p->conds);) - IF_BC(bc_vec_free(&p->ops);) + IF_BC(bc_vec_free(&G.prs.exits);) + IF_BC(bc_vec_free(&G.prs.conds);) + IF_BC(bc_vec_free(&G.prs.ops);) bc_vec_free(&G.prs.lex_strnumbuf); } @@ -3571,7 +3570,7 @@ static void bc_parse_create(size_t fidx) BcParse *p = &G.prs; memset(p, 0, sizeof(BcParse)); - bc_char_vec_init(&G.prs.lex_strnumbuf); + bc_char_vec_init(&p->lex_strnumbuf); IF_BC(bc_vec_init(&p->exits, sizeof(size_t), NULL);) IF_BC(bc_vec_init(&p->conds, sizeof(size_t), NULL);) IF_BC(bc_vec_init(&p->ops, sizeof(BcLexType), NULL);) @@ -3938,26 +3937,26 @@ static BC_STATUS zbc_parse_incdec(BcInst *prev, bool *paren_expr, *nexprs = *nexprs + 1; switch (type) { - case XC_LEX_NAME: - s = zbc_parse_name(prev, flags | BC_PARSE_NOCALL); - break; - case BC_LEX_KEY_IBASE: - case BC_LEX_KEY_LAST: - case BC_LEX_KEY_OBASE: - bc_parse_push(type - BC_LEX_KEY_IBASE + XC_INST_IBASE); - s = zbc_lex_next(); - break; - case BC_LEX_KEY_SCALE: - s = zbc_lex_next(); - if (s) RETURN_STATUS(s); - if (p->lex == BC_LEX_LPAREN) - s = bc_error_bad_token(); - else - bc_parse_push(XC_INST_SCALE); - break; - default: + case XC_LEX_NAME: + s = zbc_parse_name(prev, flags | BC_PARSE_NOCALL); + break; + case BC_LEX_KEY_IBASE: + case BC_LEX_KEY_LAST: + case BC_LEX_KEY_OBASE: + bc_parse_push(type - BC_LEX_KEY_IBASE + XC_INST_IBASE); + s = zbc_lex_next(); + break; + case BC_LEX_KEY_SCALE: + s = zbc_lex_next(); + if (s) RETURN_STATUS(s); + if (p->lex == BC_LEX_LPAREN) s = bc_error_bad_token(); - break; + else + bc_parse_push(XC_INST_SCALE); + break; + default: + s = bc_error_bad_token(); + break; } if (!s) bc_parse_push(inst); @@ -4489,74 +4488,74 @@ static BC_STATUS zbc_parse_stmt_possibly_auto(bool auto_allowed) dbg_lex("%s:%d p->lex:%d", __func__, __LINE__, p->lex); switch (p->lex) { - case XC_LEX_OP_MINUS: - case BC_LEX_OP_INC: - case BC_LEX_OP_DEC: - case BC_LEX_OP_BOOL_NOT: - case BC_LEX_LPAREN: - case XC_LEX_NAME: - case XC_LEX_NUMBER: - case BC_LEX_KEY_IBASE: - case BC_LEX_KEY_LAST: - case BC_LEX_KEY_LENGTH: - case BC_LEX_KEY_OBASE: - case BC_LEX_KEY_READ: - case BC_LEX_KEY_SCALE: - case BC_LEX_KEY_SQRT: - s = zbc_parse_expr(BC_PARSE_PRINT); - break; - case XC_LEX_STR: - s = zbc_parse_pushSTR(); - bc_parse_push(XC_INST_PRINT_STR); - break; - case BC_LEX_KEY_BREAK: - case BC_LEX_KEY_CONTINUE: - s = zbc_parse_break_or_continue(p->lex); - break; - case BC_LEX_KEY_FOR: - s = zbc_parse_for(); - break; - case BC_LEX_KEY_HALT: - bc_parse_push(BC_INST_HALT); - s = zbc_lex_next(); - break; - case BC_LEX_KEY_IF: - s = zbc_parse_if(); - break; - case BC_LEX_KEY_LIMITS: - // "limits" is a compile-time command, - // the output is produced at _parse time_. - printf( - "BC_BASE_MAX = "BC_MAX_OBASE_STR "\n" - "BC_DIM_MAX = "BC_MAX_DIM_STR "\n" - "BC_SCALE_MAX = "BC_MAX_SCALE_STR "\n" - "BC_STRING_MAX = "BC_MAX_STRING_STR"\n" - "BC_NAME_MAX = "BC_MAX_NAME_STR "\n" - "BC_NUM_MAX = "BC_MAX_NUM_STR "\n" - "MAX Exponent = "BC_MAX_EXP_STR "\n" - "Number of vars = "BC_MAX_VARS_STR "\n" - ); - s = zbc_lex_next(); - break; - case BC_LEX_KEY_PRINT: - s = zbc_parse_print(); - break; - case BC_LEX_KEY_QUIT: - // "quit" is a compile-time command. For example, - // "if (0 == 1) quit" terminates when parsing the statement, - // not when it is executed - QUIT_OR_RETURN_TO_MAIN; - case BC_LEX_KEY_RETURN: - if (!p->in_funcdef) - RETURN_STATUS(bc_error("'return' not in a function")); - s = zbc_parse_return(); - break; - case BC_LEX_KEY_WHILE: - s = zbc_parse_while(); - break; - default: - s = bc_error_bad_token(); - break; + case XC_LEX_OP_MINUS: + case BC_LEX_OP_INC: + case BC_LEX_OP_DEC: + case BC_LEX_OP_BOOL_NOT: + case BC_LEX_LPAREN: + case XC_LEX_NAME: + case XC_LEX_NUMBER: + case BC_LEX_KEY_IBASE: + case BC_LEX_KEY_LAST: + case BC_LEX_KEY_LENGTH: + case BC_LEX_KEY_OBASE: + case BC_LEX_KEY_READ: + case BC_LEX_KEY_SCALE: + case BC_LEX_KEY_SQRT: + s = zbc_parse_expr(BC_PARSE_PRINT); + break; + case XC_LEX_STR: + s = zbc_parse_pushSTR(); + bc_parse_push(XC_INST_PRINT_STR); + break; + case BC_LEX_KEY_BREAK: + case BC_LEX_KEY_CONTINUE: + s = zbc_parse_break_or_continue(p->lex); + break; + case BC_LEX_KEY_FOR: + s = zbc_parse_for(); + break; + case BC_LEX_KEY_HALT: + bc_parse_push(BC_INST_HALT); + s = zbc_lex_next(); + break; + case BC_LEX_KEY_IF: + s = zbc_parse_if(); + break; + case BC_LEX_KEY_LIMITS: + // "limits" is a compile-time command, + // the output is produced at _parse time_. + printf( + "BC_BASE_MAX = "BC_MAX_OBASE_STR "\n" + "BC_DIM_MAX = "BC_MAX_DIM_STR "\n" + "BC_SCALE_MAX = "BC_MAX_SCALE_STR "\n" + "BC_STRING_MAX = "BC_MAX_STRING_STR"\n" + "BC_NAME_MAX = "BC_MAX_NAME_STR "\n" + "BC_NUM_MAX = "BC_MAX_NUM_STR "\n" + "MAX Exponent = "BC_MAX_EXP_STR "\n" + "Number of vars = "BC_MAX_VARS_STR "\n" + ); + s = zbc_lex_next(); + break; + case BC_LEX_KEY_PRINT: + s = zbc_parse_print(); + break; + case BC_LEX_KEY_QUIT: + // "quit" is a compile-time command. For example, + // "if (0 == 1) quit" terminates when parsing the statement, + // not when it is executed + QUIT_OR_RETURN_TO_MAIN; + case BC_LEX_KEY_RETURN: + if (!p->in_funcdef) + RETURN_STATUS(bc_error("'return' not in a function")); + s = zbc_parse_return(); + break; + case BC_LEX_KEY_WHILE: + s = zbc_parse_while(); + break; + default: + s = bc_error_bad_token(); + break; } dbg_lex_done("%s:%d done", __func__, __LINE__); @@ -4612,162 +4611,162 @@ static BcStatus bc_parse_expr_empty_ok(uint8_t flags) get_token = false; s = BC_STATUS_SUCCESS; switch (t) { - case BC_LEX_OP_INC: - case BC_LEX_OP_DEC: - dbg_lex("%s:%d LEX_OP_INC/DEC", __func__, __LINE__); - s = zbc_parse_incdec(&prev, &paren_expr, &nexprs, flags); - rprn = bin_last = false; - //get_token = false; - already is - break; - case XC_LEX_OP_MINUS: - dbg_lex("%s:%d LEX_OP_MINUS", __func__, __LINE__); - s = zbc_parse_minus(&prev, ops_bgn, rprn, &nexprs); - rprn = false; - //get_token = false; - already is - bin_last = (prev == XC_INST_MINUS); - break; - case BC_LEX_OP_ASSIGN_POWER: - case BC_LEX_OP_ASSIGN_MULTIPLY: - case BC_LEX_OP_ASSIGN_DIVIDE: - case BC_LEX_OP_ASSIGN_MODULUS: - case BC_LEX_OP_ASSIGN_PLUS: - case BC_LEX_OP_ASSIGN_MINUS: - case BC_LEX_OP_ASSIGN: - dbg_lex("%s:%d LEX_ASSIGNxyz", __func__, __LINE__); - if (prev != XC_INST_VAR && prev != XC_INST_ARRAY_ELEM - && prev != XC_INST_SCALE && prev != XC_INST_IBASE - && prev != XC_INST_OBASE && prev != BC_INST_LAST - ) { - return bc_error("bad assignment:" - " left side must be variable" - " or array element" - ); // note: shared string - } - // Fallthrough. - case XC_LEX_OP_POWER: - case XC_LEX_OP_MULTIPLY: - case XC_LEX_OP_DIVIDE: - case XC_LEX_OP_MODULUS: - case XC_LEX_OP_PLUS: - case XC_LEX_OP_REL_EQ: - case XC_LEX_OP_REL_LE: - case XC_LEX_OP_REL_GE: - case XC_LEX_OP_REL_NE: - case XC_LEX_OP_REL_LT: - case XC_LEX_OP_REL_GT: - case BC_LEX_OP_BOOL_NOT: - case BC_LEX_OP_BOOL_OR: - case BC_LEX_OP_BOOL_AND: - dbg_lex("%s:%d LEX_OP_xyz", __func__, __LINE__); - if (((t == BC_LEX_OP_BOOL_NOT) != bin_last) - || (t != BC_LEX_OP_BOOL_NOT && prev == XC_INST_BOOL_NOT) - ) { - return bc_error_bad_expression(); - } - nrelops += (t >= XC_LEX_OP_REL_EQ && t <= XC_LEX_OP_REL_GT); - prev = BC_TOKEN_2_INST(t); - bc_parse_operator(t, ops_bgn, &nexprs); - s = zbc_lex_next(); - rprn = false; - //get_token = false; - already is - bin_last = (t != BC_LEX_OP_BOOL_NOT); - break; - case BC_LEX_LPAREN: - dbg_lex("%s:%d LEX_LPAREN", __func__, __LINE__); - if (BC_PARSE_LEAF(prev, rprn)) - return bc_error_bad_expression(); - bc_vec_push(&p->ops, &t); - nparens++; - get_token = true; - paren_expr = false; - rprn = bin_last = false; - break; - case BC_LEX_RPAREN: - dbg_lex("%s:%d LEX_RPAREN", __func__, __LINE__); - if (bin_last || prev == XC_INST_BOOL_NOT) - return bc_error_bad_expression(); - if (nparens == 0) { - goto exit_loop; - } - if (!paren_expr) { - dbg_lex_done("%s:%d done (returning EMPTY_EXP)", __func__, __LINE__); - return BC_STATUS_PARSE_EMPTY_EXP; - } - s = zbc_parse_rightParen(ops_bgn, &nexprs); - nparens--; - get_token = true; - paren_expr = rprn = true; - bin_last = false; - break; - case XC_LEX_NAME: - dbg_lex("%s:%d LEX_NAME", __func__, __LINE__); - if (BC_PARSE_LEAF(prev, rprn)) - return bc_error_bad_expression(); - s = zbc_parse_name(&prev, flags & ~BC_PARSE_NOCALL); - paren_expr = true; - rprn = bin_last = false; - //get_token = false; - already is - nexprs++; - break; - case XC_LEX_NUMBER: - dbg_lex("%s:%d LEX_NUMBER", __func__, __LINE__); - if (BC_PARSE_LEAF(prev, rprn)) - return bc_error_bad_expression(); - bc_parse_pushNUM(); - prev = XC_INST_NUM; - get_token = true; - paren_expr = true; - rprn = bin_last = false; - nexprs++; - break; - case BC_LEX_KEY_IBASE: - case BC_LEX_KEY_LAST: - case BC_LEX_KEY_OBASE: - dbg_lex("%s:%d LEX_IBASE/LAST/OBASE", __func__, __LINE__); - if (BC_PARSE_LEAF(prev, rprn)) - return bc_error_bad_expression(); - prev = (char) (t - BC_LEX_KEY_IBASE + XC_INST_IBASE); - bc_parse_push((char) prev); - get_token = true; - paren_expr = true; - rprn = bin_last = false; - nexprs++; - break; - case BC_LEX_KEY_LENGTH: - case BC_LEX_KEY_SQRT: - dbg_lex("%s:%d LEX_LEN/SQRT", __func__, __LINE__); - if (BC_PARSE_LEAF(prev, rprn)) - return bc_error_bad_expression(); - s = zbc_parse_builtin(t, flags, &prev); - get_token = true; - paren_expr = true; - rprn = bin_last = false; - nexprs++; - break; - case BC_LEX_KEY_READ: - dbg_lex("%s:%d LEX_READ", __func__, __LINE__); - if (BC_PARSE_LEAF(prev, rprn)) - return bc_error_bad_expression(); - s = zbc_parse_read(); - prev = XC_INST_READ; - get_token = true; - paren_expr = true; - rprn = bin_last = false; - nexprs++; - break; - case BC_LEX_KEY_SCALE: - dbg_lex("%s:%d LEX_SCALE", __func__, __LINE__); - if (BC_PARSE_LEAF(prev, rprn)) - return bc_error_bad_expression(); - s = zbc_parse_scale(&prev, flags); - prev = XC_INST_SCALE; - //get_token = false; - already is - paren_expr = true; - rprn = bin_last = false; - nexprs++; - break; - default: - return bc_error_bad_token(); + case BC_LEX_OP_INC: + case BC_LEX_OP_DEC: + dbg_lex("%s:%d LEX_OP_INC/DEC", __func__, __LINE__); + s = zbc_parse_incdec(&prev, &paren_expr, &nexprs, flags); + rprn = bin_last = false; + //get_token = false; - already is + break; + case XC_LEX_OP_MINUS: + dbg_lex("%s:%d LEX_OP_MINUS", __func__, __LINE__); + s = zbc_parse_minus(&prev, ops_bgn, rprn, &nexprs); + rprn = false; + //get_token = false; - already is + bin_last = (prev == XC_INST_MINUS); + break; + case BC_LEX_OP_ASSIGN_POWER: + case BC_LEX_OP_ASSIGN_MULTIPLY: + case BC_LEX_OP_ASSIGN_DIVIDE: + case BC_LEX_OP_ASSIGN_MODULUS: + case BC_LEX_OP_ASSIGN_PLUS: + case BC_LEX_OP_ASSIGN_MINUS: + case BC_LEX_OP_ASSIGN: + dbg_lex("%s:%d LEX_ASSIGNxyz", __func__, __LINE__); + if (prev != XC_INST_VAR && prev != XC_INST_ARRAY_ELEM + && prev != XC_INST_SCALE && prev != XC_INST_IBASE + && prev != XC_INST_OBASE && prev != BC_INST_LAST + ) { + return bc_error("bad assignment:" + " left side must be variable" + " or array element" + ); // note: shared string + } + // Fallthrough. + case XC_LEX_OP_POWER: + case XC_LEX_OP_MULTIPLY: + case XC_LEX_OP_DIVIDE: + case XC_LEX_OP_MODULUS: + case XC_LEX_OP_PLUS: + case XC_LEX_OP_REL_EQ: + case XC_LEX_OP_REL_LE: + case XC_LEX_OP_REL_GE: + case XC_LEX_OP_REL_NE: + case XC_LEX_OP_REL_LT: + case XC_LEX_OP_REL_GT: + case BC_LEX_OP_BOOL_NOT: + case BC_LEX_OP_BOOL_OR: + case BC_LEX_OP_BOOL_AND: + dbg_lex("%s:%d LEX_OP_xyz", __func__, __LINE__); + if (((t == BC_LEX_OP_BOOL_NOT) != bin_last) + || (t != BC_LEX_OP_BOOL_NOT && prev == XC_INST_BOOL_NOT) + ) { + return bc_error_bad_expression(); + } + nrelops += (t >= XC_LEX_OP_REL_EQ && t <= XC_LEX_OP_REL_GT); + prev = BC_TOKEN_2_INST(t); + bc_parse_operator(t, ops_bgn, &nexprs); + s = zbc_lex_next(); + rprn = false; + //get_token = false; - already is + bin_last = (t != BC_LEX_OP_BOOL_NOT); + break; + case BC_LEX_LPAREN: + dbg_lex("%s:%d LEX_LPAREN", __func__, __LINE__); + if (BC_PARSE_LEAF(prev, rprn)) + return bc_error_bad_expression(); + bc_vec_push(&p->ops, &t); + nparens++; + get_token = true; + paren_expr = false; + rprn = bin_last = false; + break; + case BC_LEX_RPAREN: + dbg_lex("%s:%d LEX_RPAREN", __func__, __LINE__); + if (bin_last || prev == XC_INST_BOOL_NOT) + return bc_error_bad_expression(); + if (nparens == 0) { + goto exit_loop; + } + if (!paren_expr) { + dbg_lex_done("%s:%d done (returning EMPTY_EXP)", __func__, __LINE__); + return BC_STATUS_PARSE_EMPTY_EXP; + } + s = zbc_parse_rightParen(ops_bgn, &nexprs); + nparens--; + get_token = true; + paren_expr = rprn = true; + bin_last = false; + break; + case XC_LEX_NAME: + dbg_lex("%s:%d LEX_NAME", __func__, __LINE__); + if (BC_PARSE_LEAF(prev, rprn)) + return bc_error_bad_expression(); + s = zbc_parse_name(&prev, flags & ~BC_PARSE_NOCALL); + paren_expr = true; + rprn = bin_last = false; + //get_token = false; - already is + nexprs++; + break; + case XC_LEX_NUMBER: + dbg_lex("%s:%d LEX_NUMBER", __func__, __LINE__); + if (BC_PARSE_LEAF(prev, rprn)) + return bc_error_bad_expression(); + bc_parse_pushNUM(); + prev = XC_INST_NUM; + get_token = true; + paren_expr = true; + rprn = bin_last = false; + nexprs++; + break; + case BC_LEX_KEY_IBASE: + case BC_LEX_KEY_LAST: + case BC_LEX_KEY_OBASE: + dbg_lex("%s:%d LEX_IBASE/LAST/OBASE", __func__, __LINE__); + if (BC_PARSE_LEAF(prev, rprn)) + return bc_error_bad_expression(); + prev = (char) (t - BC_LEX_KEY_IBASE + XC_INST_IBASE); + bc_parse_push((char) prev); + get_token = true; + paren_expr = true; + rprn = bin_last = false; + nexprs++; + break; + case BC_LEX_KEY_LENGTH: + case BC_LEX_KEY_SQRT: + dbg_lex("%s:%d LEX_LEN/SQRT", __func__, __LINE__); + if (BC_PARSE_LEAF(prev, rprn)) + return bc_error_bad_expression(); + s = zbc_parse_builtin(t, flags, &prev); + get_token = true; + paren_expr = true; + rprn = bin_last = false; + nexprs++; + break; + case BC_LEX_KEY_READ: + dbg_lex("%s:%d LEX_READ", __func__, __LINE__); + if (BC_PARSE_LEAF(prev, rprn)) + return bc_error_bad_expression(); + s = zbc_parse_read(); + prev = XC_INST_READ; + get_token = true; + paren_expr = true; + rprn = bin_last = false; + nexprs++; + break; + case BC_LEX_KEY_SCALE: + dbg_lex("%s:%d LEX_SCALE", __func__, __LINE__); + if (BC_PARSE_LEAF(prev, rprn)) + return bc_error_bad_expression(); + s = zbc_parse_scale(&prev, flags); + prev = XC_INST_SCALE; + //get_token = false; - already is + paren_expr = true; + rprn = bin_last = false; + nexprs++; + break; + default: + return bc_error_bad_token(); } if (s || G_interrupt) // error, or ^C: stop parsing @@ -4913,65 +4912,65 @@ static BC_STATUS zdc_parse_token(BcLexType t) s = BC_STATUS_SUCCESS; get_token = true; switch (t) { - case XC_LEX_OP_REL_EQ: - case XC_LEX_OP_REL_LE: - case XC_LEX_OP_REL_GE: - case XC_LEX_OP_REL_NE: - case XC_LEX_OP_REL_LT: - case XC_LEX_OP_REL_GT: - dbg_lex("%s:%d LEX_OP_REL_xyz", __func__, __LINE__); - s = zdc_parse_cond(t - XC_LEX_OP_REL_EQ + XC_INST_REL_EQ); - get_token = false; - break; - case DC_LEX_SCOLON: - case DC_LEX_COLON: - dbg_lex("%s:%d LEX_[S]COLON", __func__, __LINE__); - s = zdc_parse_mem(XC_INST_ARRAY_ELEM, true, t == DC_LEX_COLON); - break; - case XC_LEX_STR: - dbg_lex("%s:%d LEX_STR", __func__, __LINE__); - dc_parse_string(); - break; - case XC_LEX_NEG: - dbg_lex("%s:%d LEX_NEG", __func__, __LINE__); - s = zbc_lex_next(); - if (s) RETURN_STATUS(s); - if (G.prs.lex != XC_LEX_NUMBER) - RETURN_STATUS(bc_error_bad_token()); - bc_parse_pushNUM(); - bc_parse_push(XC_INST_NEG); - break; - case XC_LEX_NUMBER: - dbg_lex("%s:%d LEX_NUMBER", __func__, __LINE__); - bc_parse_pushNUM(); - break; - case DC_LEX_READ: - dbg_lex("%s:%d LEX_KEY_READ", __func__, __LINE__); - bc_parse_push(XC_INST_READ); - break; - case DC_LEX_OP_ASSIGN: - case DC_LEX_STORE_PUSH: - dbg_lex("%s:%d LEX_OP_ASSIGN/STORE_PUSH", __func__, __LINE__); - assign = (t == DC_LEX_OP_ASSIGN); - inst = assign ? XC_INST_VAR : DC_INST_PUSH_TO_VAR; - s = zdc_parse_mem(inst, true, assign); - break; - case DC_LEX_LOAD: - case DC_LEX_LOAD_POP: - dbg_lex("%s:%d LEX_OP_LOAD[_POP]", __func__, __LINE__); - inst = t == DC_LEX_LOAD_POP ? DC_INST_PUSH_VAR : DC_INST_LOAD; - s = zdc_parse_mem(inst, true, false); - break; - case DC_LEX_STORE_IBASE: - case DC_LEX_STORE_SCALE: - case DC_LEX_STORE_OBASE: - dbg_lex("%s:%d LEX_OP_STORE_I/OBASE/SCALE", __func__, __LINE__); - inst = t - DC_LEX_STORE_IBASE + XC_INST_IBASE; - s = zdc_parse_mem(inst, false, true); - break; - default: - dbg_lex_done("%s:%d done (bad token)", __func__, __LINE__); + case XC_LEX_OP_REL_EQ: + case XC_LEX_OP_REL_LE: + case XC_LEX_OP_REL_GE: + case XC_LEX_OP_REL_NE: + case XC_LEX_OP_REL_LT: + case XC_LEX_OP_REL_GT: + dbg_lex("%s:%d LEX_OP_REL_xyz", __func__, __LINE__); + s = zdc_parse_cond(t - XC_LEX_OP_REL_EQ + XC_INST_REL_EQ); + get_token = false; + break; + case DC_LEX_SCOLON: + case DC_LEX_COLON: + dbg_lex("%s:%d LEX_[S]COLON", __func__, __LINE__); + s = zdc_parse_mem(XC_INST_ARRAY_ELEM, true, t == DC_LEX_COLON); + break; + case XC_LEX_STR: + dbg_lex("%s:%d LEX_STR", __func__, __LINE__); + dc_parse_string(); + break; + case XC_LEX_NEG: + dbg_lex("%s:%d LEX_NEG", __func__, __LINE__); + s = zbc_lex_next(); + if (s) RETURN_STATUS(s); + if (G.prs.lex != XC_LEX_NUMBER) RETURN_STATUS(bc_error_bad_token()); + bc_parse_pushNUM(); + bc_parse_push(XC_INST_NEG); + break; + case XC_LEX_NUMBER: + dbg_lex("%s:%d LEX_NUMBER", __func__, __LINE__); + bc_parse_pushNUM(); + break; + case DC_LEX_READ: + dbg_lex("%s:%d LEX_KEY_READ", __func__, __LINE__); + bc_parse_push(XC_INST_READ); + break; + case DC_LEX_OP_ASSIGN: + case DC_LEX_STORE_PUSH: + dbg_lex("%s:%d LEX_OP_ASSIGN/STORE_PUSH", __func__, __LINE__); + assign = (t == DC_LEX_OP_ASSIGN); + inst = assign ? XC_INST_VAR : DC_INST_PUSH_TO_VAR; + s = zdc_parse_mem(inst, true, assign); + break; + case DC_LEX_LOAD: + case DC_LEX_LOAD_POP: + dbg_lex("%s:%d LEX_OP_LOAD[_POP]", __func__, __LINE__); + inst = t == DC_LEX_LOAD_POP ? DC_INST_PUSH_VAR : DC_INST_LOAD; + s = zdc_parse_mem(inst, true, false); + break; + case DC_LEX_STORE_IBASE: + case DC_LEX_STORE_SCALE: + case DC_LEX_STORE_OBASE: + dbg_lex("%s:%d LEX_OP_STORE_I/OBASE/SCALE", __func__, __LINE__); + inst = t - DC_LEX_STORE_IBASE + XC_INST_IBASE; + s = zdc_parse_mem(inst, false, true); + break; + default: + dbg_lex_done("%s:%d done (bad token)", __func__, __LINE__); + RETURN_STATUS(bc_error_bad_token()); } if (!s && get_token) s = zbc_lex_next(); @@ -5050,62 +5049,62 @@ static BcVec* bc_program_search(char *id, bool var) static BC_STATUS zbc_program_num(BcResult *r, BcNum **num, bool hex) { switch (r->t) { - case XC_RESULT_STR: - case XC_RESULT_TEMP: - case XC_RESULT_IBASE: - case XC_RESULT_SCALE: - case XC_RESULT_OBASE: - *num = &r->d.n; - break; - case XC_RESULT_CONSTANT: { - BcStatus s; - char *str; - unsigned base_t; - size_t len; - - str = *bc_program_const(r->d.id.idx); - len = strlen(str); - - bc_num_init(&r->d.n, len); - - hex = hex && len == 1; - base_t = hex ? 16 : G.prog.ib_t; - s = zbc_num_parse(&r->d.n, str, base_t); - if (s) { - bc_num_free(&r->d.n); - RETURN_STATUS(s); - } - *num = &r->d.n; - r->t = XC_RESULT_TEMP; - break; - } - case XC_RESULT_VAR: - case XC_RESULT_ARRAY: - case XC_RESULT_ARRAY_ELEM: { - BcVec *v; + case XC_RESULT_STR: + case XC_RESULT_TEMP: + case XC_RESULT_IBASE: + case XC_RESULT_SCALE: + case XC_RESULT_OBASE: + *num = &r->d.n; + break; + case XC_RESULT_CONSTANT: { + BcStatus s; + char *str; + unsigned base_t; + size_t len; - v = bc_program_search(r->d.id.name, r->t == XC_RESULT_VAR); + str = *bc_program_const(r->d.id.idx); + len = strlen(str); - if (r->t == XC_RESULT_ARRAY_ELEM) { - v = bc_vec_top(v); - if (v->len <= r->d.id.idx) bc_array_expand(v, r->d.id.idx + 1); - *num = bc_vec_item(v, r->d.id.idx); - } else - *num = bc_vec_top(v); - break; + bc_num_init(&r->d.n, len); + + hex = hex && len == 1; + base_t = hex ? 16 : G.prog.ib_t; + s = zbc_num_parse(&r->d.n, str, base_t); + if (s) { + bc_num_free(&r->d.n); + RETURN_STATUS(s); } + *num = &r->d.n; + r->t = XC_RESULT_TEMP; + break; + } + case XC_RESULT_VAR: + case XC_RESULT_ARRAY: + case XC_RESULT_ARRAY_ELEM: { + BcVec *v; + + v = bc_program_search(r->d.id.name, r->t == XC_RESULT_VAR); + + if (r->t == XC_RESULT_ARRAY_ELEM) { + v = bc_vec_top(v); + if (v->len <= r->d.id.idx) bc_array_expand(v, r->d.id.idx + 1); + *num = bc_vec_item(v, r->d.id.idx); + } else + *num = bc_vec_top(v); + break; + } #if ENABLE_BC - case BC_RESULT_LAST: - *num = &G.prog.last; - break; - case BC_RESULT_ONE: - *num = &G.prog.one; - break; + case BC_RESULT_LAST: + *num = &G.prog.last; + break; + case BC_RESULT_ONE: + *num = &G.prog.one; + break; #endif #if SANITY_CHECKS - default: - // Testing the theory that dc does not reach LAST/ONE - bb_error_msg_and_die("BUG:%d", r->t); + default: + // Testing the theory that dc does not reach LAST/ONE + bb_error_msg_and_die("BUG:%d", r->t); #endif } @@ -6422,245 +6421,245 @@ static BC_STATUS zbc_program_exec(void) dbg_exec("inst at %zd:%d results.len:%d", ip->inst_idx - 1, inst, G.prog.results.len); switch (inst) { #if ENABLE_BC - case BC_INST_JUMP_ZERO: { - BcNum *num; - bool zero; - dbg_exec("BC_INST_JUMP_ZERO:"); - s = zbc_program_prep(&ptr, &num); - if (s) RETURN_STATUS(s); - zero = (bc_num_cmp(num, &G.prog.zero) == 0); - bc_vec_pop(&G.prog.results); - if (!zero) { - bc_program_index(code, &ip->inst_idx); - break; - } - // else: fall through - } - case BC_INST_JUMP: { - size_t idx = bc_program_index(code, &ip->inst_idx); - size_t *addr = bc_vec_item(&func->labels, idx); - dbg_exec("BC_INST_JUMP: to %ld", (long)*addr); - ip->inst_idx = *addr; + case BC_INST_JUMP_ZERO: { + BcNum *num; + bool zero; + dbg_exec("BC_INST_JUMP_ZERO:"); + s = zbc_program_prep(&ptr, &num); + if (s) RETURN_STATUS(s); + zero = (bc_num_cmp(num, &G.prog.zero) == 0); + bc_vec_pop(&G.prog.results); + if (!zero) { + bc_program_index(code, &ip->inst_idx); break; } - case BC_INST_CALL: - dbg_exec("BC_INST_CALL:"); - s = zbc_program_call(code, &ip->inst_idx); - goto read_updated_ip; - case BC_INST_INC_PRE: - case BC_INST_DEC_PRE: - case BC_INST_INC_POST: - case BC_INST_DEC_POST: - dbg_exec("BC_INST_INCDEC:"); - s = zbc_program_incdec(inst); - break; - case BC_INST_HALT: - dbg_exec("BC_INST_HALT:"); - QUIT_OR_RETURN_TO_MAIN; - break; - case XC_INST_RET: - case BC_INST_RET0: - dbg_exec("BC_INST_RET[0]:"); - s = zbc_program_return(inst); - goto read_updated_ip; - case XC_INST_BOOL_OR: - case XC_INST_BOOL_AND: + // else: fall through + } + case BC_INST_JUMP: { + size_t idx = bc_program_index(code, &ip->inst_idx); + size_t *addr = bc_vec_item(&func->labels, idx); + dbg_exec("BC_INST_JUMP: to %ld", (long)*addr); + ip->inst_idx = *addr; + break; + } + case BC_INST_CALL: + dbg_exec("BC_INST_CALL:"); + s = zbc_program_call(code, &ip->inst_idx); + goto read_updated_ip; + case BC_INST_INC_PRE: + case BC_INST_DEC_PRE: + case BC_INST_INC_POST: + case BC_INST_DEC_POST: + dbg_exec("BC_INST_INCDEC:"); + s = zbc_program_incdec(inst); + break; + case BC_INST_HALT: + dbg_exec("BC_INST_HALT:"); + QUIT_OR_RETURN_TO_MAIN; + break; + case XC_INST_RET: + case BC_INST_RET0: + dbg_exec("BC_INST_RET[0]:"); + s = zbc_program_return(inst); + goto read_updated_ip; + case XC_INST_BOOL_OR: + case XC_INST_BOOL_AND: #endif // ENABLE_BC - case XC_INST_REL_EQ: - case XC_INST_REL_LE: - case XC_INST_REL_GE: - case XC_INST_REL_NE: - case XC_INST_REL_LT: - case XC_INST_REL_GT: - dbg_exec("BC_INST_BOOL:"); - s = zbc_program_logical(inst); - break; - case XC_INST_READ: - dbg_exec("XC_INST_READ:"); - s = zbc_program_read(); - goto read_updated_ip; - case XC_INST_VAR: - dbg_exec("XC_INST_VAR:"); - s = zbc_program_pushVar(code, &ip->inst_idx, false, false); - break; - case XC_INST_ARRAY_ELEM: - case XC_INST_ARRAY: - dbg_exec("XC_INST_ARRAY[_ELEM]:"); - s = zbc_program_pushArray(code, &ip->inst_idx, inst); - break; + case XC_INST_REL_EQ: + case XC_INST_REL_LE: + case XC_INST_REL_GE: + case XC_INST_REL_NE: + case XC_INST_REL_LT: + case XC_INST_REL_GT: + dbg_exec("BC_INST_BOOL:"); + s = zbc_program_logical(inst); + break; + case XC_INST_READ: + dbg_exec("XC_INST_READ:"); + s = zbc_program_read(); + goto read_updated_ip; + case XC_INST_VAR: + dbg_exec("XC_INST_VAR:"); + s = zbc_program_pushVar(code, &ip->inst_idx, false, false); + break; + case XC_INST_ARRAY_ELEM: + case XC_INST_ARRAY: + dbg_exec("XC_INST_ARRAY[_ELEM]:"); + s = zbc_program_pushArray(code, &ip->inst_idx, inst); + break; #if ENABLE_BC - case BC_INST_LAST: - dbg_exec("BC_INST_LAST:"); - r.t = BC_RESULT_LAST; - bc_vec_push(&G.prog.results, &r); - break; + case BC_INST_LAST: + dbg_exec("BC_INST_LAST:"); + r.t = BC_RESULT_LAST; + bc_vec_push(&G.prog.results, &r); + break; #endif - case XC_INST_IBASE: - case XC_INST_OBASE: - case XC_INST_SCALE: - dbg_exec("XC_INST_internalvar(%d):", inst - XC_INST_IBASE); - bc_program_pushGlobal(inst); - break; - case XC_INST_SCALE_FUNC: - case XC_INST_LENGTH: - case XC_INST_SQRT: - dbg_exec("BC_INST_builtin:"); - s = zbc_program_builtin(inst); - break; - case XC_INST_NUM: - dbg_exec("XC_INST_NUM:"); - r.t = XC_RESULT_CONSTANT; - r.d.id.idx = bc_program_index(code, &ip->inst_idx); - bc_vec_push(&G.prog.results, &r); - break; - case XC_INST_POP: - dbg_exec("XC_INST_POP:"); - if (!STACK_HAS_MORE_THAN(&G.prog.results, 0)) - s = bc_error_stack_has_too_few_elements(); - else - bc_vec_pop(&G.prog.results); - break; - case XC_INST_PRINT: - case XC_INST_PRINT_POP: - case XC_INST_PRINT_STR: - dbg_exec("XC_INST_PRINTxyz:"); - s = zbc_program_print(inst, 0); - break; - case XC_INST_STR: - dbg_exec("XC_INST_STR:"); - r.t = XC_RESULT_STR; - r.d.id.idx = bc_program_index(code, &ip->inst_idx); - bc_vec_push(&G.prog.results, &r); - break; - case XC_INST_POWER: - case XC_INST_MULTIPLY: - case XC_INST_DIVIDE: - case XC_INST_MODULUS: - case XC_INST_PLUS: - case XC_INST_MINUS: - dbg_exec("BC_INST_binaryop:"); - s = zbc_program_op(inst); - break; - case XC_INST_BOOL_NOT: { - BcNum *num; - dbg_exec("XC_INST_BOOL_NOT:"); - s = zbc_program_prep(&ptr, &num); - if (s) RETURN_STATUS(s); - bc_num_init_DEF_SIZE(&r.d.n); - if (bc_num_cmp(num, &G.prog.zero) == 0) - bc_num_one(&r.d.n); - //else bc_num_zero(&r.d.n); - already is - bc_program_retire(&r, XC_RESULT_TEMP); - break; - } - case XC_INST_NEG: - dbg_exec("XC_INST_NEG:"); - s = zbc_program_negate(); - break; + case XC_INST_IBASE: + case XC_INST_OBASE: + case XC_INST_SCALE: + dbg_exec("XC_INST_internalvar(%d):", inst - XC_INST_IBASE); + bc_program_pushGlobal(inst); + break; + case XC_INST_SCALE_FUNC: + case XC_INST_LENGTH: + case XC_INST_SQRT: + dbg_exec("BC_INST_builtin:"); + s = zbc_program_builtin(inst); + break; + case XC_INST_NUM: + dbg_exec("XC_INST_NUM:"); + r.t = XC_RESULT_CONSTANT; + r.d.id.idx = bc_program_index(code, &ip->inst_idx); + bc_vec_push(&G.prog.results, &r); + break; + case XC_INST_POP: + dbg_exec("XC_INST_POP:"); + if (!STACK_HAS_MORE_THAN(&G.prog.results, 0)) + s = bc_error_stack_has_too_few_elements(); + else + bc_vec_pop(&G.prog.results); + break; + case XC_INST_PRINT: + case XC_INST_PRINT_POP: + case XC_INST_PRINT_STR: + dbg_exec("XC_INST_PRINTxyz:"); + s = zbc_program_print(inst, 0); + break; + case XC_INST_STR: + dbg_exec("XC_INST_STR:"); + r.t = XC_RESULT_STR; + r.d.id.idx = bc_program_index(code, &ip->inst_idx); + bc_vec_push(&G.prog.results, &r); + break; + case XC_INST_POWER: + case XC_INST_MULTIPLY: + case XC_INST_DIVIDE: + case XC_INST_MODULUS: + case XC_INST_PLUS: + case XC_INST_MINUS: + dbg_exec("BC_INST_binaryop:"); + s = zbc_program_op(inst); + break; + case XC_INST_BOOL_NOT: { + BcNum *num; + dbg_exec("XC_INST_BOOL_NOT:"); + s = zbc_program_prep(&ptr, &num); + if (s) RETURN_STATUS(s); + bc_num_init_DEF_SIZE(&r.d.n); + if (bc_num_cmp(num, &G.prog.zero) == 0) + bc_num_one(&r.d.n); + //else bc_num_zero(&r.d.n); - already is + bc_program_retire(&r, XC_RESULT_TEMP); + break; + } + case XC_INST_NEG: + dbg_exec("XC_INST_NEG:"); + s = zbc_program_negate(); + break; #if ENABLE_BC - case BC_INST_ASSIGN_POWER: - case BC_INST_ASSIGN_MULTIPLY: - case BC_INST_ASSIGN_DIVIDE: - case BC_INST_ASSIGN_MODULUS: - case BC_INST_ASSIGN_PLUS: - case BC_INST_ASSIGN_MINUS: + case BC_INST_ASSIGN_POWER: + case BC_INST_ASSIGN_MULTIPLY: + case BC_INST_ASSIGN_DIVIDE: + case BC_INST_ASSIGN_MODULUS: + case BC_INST_ASSIGN_PLUS: + case BC_INST_ASSIGN_MINUS: #endif - case XC_INST_ASSIGN: - dbg_exec("BC_INST_ASSIGNxyz:"); - s = zbc_program_assign(inst); - break; + case XC_INST_ASSIGN: + dbg_exec("BC_INST_ASSIGNxyz:"); + s = zbc_program_assign(inst); + break; #if ENABLE_DC - case DC_INST_POP_EXEC: - dbg_exec("DC_INST_POP_EXEC:"); - bc_vec_pop(&G.prog.exestack); - goto read_updated_ip; - case DC_INST_MODEXP: - dbg_exec("DC_INST_MODEXP:"); - s = zdc_program_modexp(); - break; - case DC_INST_DIVMOD: - dbg_exec("DC_INST_DIVMOD:"); - s = zdc_program_divmod(); - break; - case DC_INST_EXECUTE: - case DC_INST_EXEC_COND: - dbg_exec("DC_INST_EXEC[_COND]:"); - s = zdc_program_execStr(code, &ip->inst_idx, inst == DC_INST_EXEC_COND); - goto read_updated_ip; - case DC_INST_PRINT_STACK: { - size_t idx; - dbg_exec("DC_INST_PRINT_STACK:"); - for (idx = 0; idx < G.prog.results.len; ++idx) { - s = zbc_program_print(XC_INST_PRINT, idx); - if (s) break; - } - break; - } - case DC_INST_CLEAR_STACK: - dbg_exec("DC_INST_CLEAR_STACK:"); - bc_vec_pop_all(&G.prog.results); - break; - case DC_INST_STACK_LEN: - dbg_exec("DC_INST_STACK_LEN:"); - dc_program_stackLen(); - break; - case DC_INST_DUPLICATE: - dbg_exec("DC_INST_DUPLICATE:"); - if (!STACK_HAS_MORE_THAN(&G.prog.results, 0)) - RETURN_STATUS(bc_error_stack_has_too_few_elements()); - ptr = bc_vec_top(&G.prog.results); - dc_result_copy(&r, ptr); - bc_vec_push(&G.prog.results, &r); - break; - case DC_INST_SWAP: { - BcResult *ptr2; - dbg_exec("DC_INST_SWAP:"); - if (!STACK_HAS_MORE_THAN(&G.prog.results, 1)) - RETURN_STATUS(bc_error_stack_has_too_few_elements()); - ptr = bc_vec_item_rev(&G.prog.results, 0); - ptr2 = bc_vec_item_rev(&G.prog.results, 1); - memcpy(&r, ptr, sizeof(BcResult)); - memcpy(ptr, ptr2, sizeof(BcResult)); - memcpy(ptr2, &r, sizeof(BcResult)); - break; - } - case DC_INST_ASCIIFY: - dbg_exec("DC_INST_ASCIIFY:"); - s = zdc_program_asciify(); - break; - case DC_INST_PRINT_STREAM: - dbg_exec("DC_INST_PRINT_STREAM:"); - s = zdc_program_printStream(); - break; - case DC_INST_LOAD: - case DC_INST_PUSH_VAR: { - bool copy = inst == DC_INST_LOAD; - s = zbc_program_pushVar(code, &ip->inst_idx, true, copy); - break; - } - case DC_INST_PUSH_TO_VAR: { - char *name = bc_program_name(code, &ip->inst_idx); - s = zbc_program_copyToVar(name, true); - free(name); - break; + case DC_INST_POP_EXEC: + dbg_exec("DC_INST_POP_EXEC:"); + bc_vec_pop(&G.prog.exestack); + goto read_updated_ip; + case DC_INST_MODEXP: + dbg_exec("DC_INST_MODEXP:"); + s = zdc_program_modexp(); + break; + case DC_INST_DIVMOD: + dbg_exec("DC_INST_DIVMOD:"); + s = zdc_program_divmod(); + break; + case DC_INST_EXECUTE: + case DC_INST_EXEC_COND: + dbg_exec("DC_INST_EXEC[_COND]:"); + s = zdc_program_execStr(code, &ip->inst_idx, inst == DC_INST_EXEC_COND); + goto read_updated_ip; + case DC_INST_PRINT_STACK: { + size_t idx; + dbg_exec("DC_INST_PRINT_STACK:"); + for (idx = 0; idx < G.prog.results.len; ++idx) { + s = zbc_program_print(XC_INST_PRINT, idx); + if (s) break; } - case DC_INST_QUIT: - dbg_exec("DC_INST_QUIT:"); - if (G.prog.exestack.len <= 2) - QUIT_OR_RETURN_TO_MAIN; - bc_vec_npop(&G.prog.exestack, 2); - goto read_updated_ip; - case DC_INST_NQUIT: - dbg_exec("DC_INST_NQUIT:"); - s = zdc_program_nquit(); - //goto read_updated_ip; - just fall through to it + break; + } + case DC_INST_CLEAR_STACK: + dbg_exec("DC_INST_CLEAR_STACK:"); + bc_vec_pop_all(&G.prog.results); + break; + case DC_INST_STACK_LEN: + dbg_exec("DC_INST_STACK_LEN:"); + dc_program_stackLen(); + break; + case DC_INST_DUPLICATE: + dbg_exec("DC_INST_DUPLICATE:"); + if (!STACK_HAS_MORE_THAN(&G.prog.results, 0)) + RETURN_STATUS(bc_error_stack_has_too_few_elements()); + ptr = bc_vec_top(&G.prog.results); + dc_result_copy(&r, ptr); + bc_vec_push(&G.prog.results, &r); + break; + case DC_INST_SWAP: { + BcResult *ptr2; + dbg_exec("DC_INST_SWAP:"); + if (!STACK_HAS_MORE_THAN(&G.prog.results, 1)) + RETURN_STATUS(bc_error_stack_has_too_few_elements()); + ptr = bc_vec_item_rev(&G.prog.results, 0); + ptr2 = bc_vec_item_rev(&G.prog.results, 1); + memcpy(&r, ptr, sizeof(BcResult)); + memcpy(ptr, ptr2, sizeof(BcResult)); + memcpy(ptr2, &r, sizeof(BcResult)); + break; + } + case DC_INST_ASCIIFY: + dbg_exec("DC_INST_ASCIIFY:"); + s = zdc_program_asciify(); + break; + case DC_INST_PRINT_STREAM: + dbg_exec("DC_INST_PRINT_STREAM:"); + s = zdc_program_printStream(); + break; + case DC_INST_LOAD: + case DC_INST_PUSH_VAR: { + bool copy = inst == DC_INST_LOAD; + s = zbc_program_pushVar(code, &ip->inst_idx, true, copy); + break; + } + case DC_INST_PUSH_TO_VAR: { + char *name = bc_program_name(code, &ip->inst_idx); + s = zbc_program_copyToVar(name, true); + free(name); + break; + } + case DC_INST_QUIT: + dbg_exec("DC_INST_QUIT:"); + if (G.prog.exestack.len <= 2) + QUIT_OR_RETURN_TO_MAIN; + bc_vec_npop(&G.prog.exestack, 2); + goto read_updated_ip; + case DC_INST_NQUIT: + dbg_exec("DC_INST_NQUIT:"); + s = zdc_program_nquit(); + //goto read_updated_ip; - just fall through to it #endif // ENABLE_DC read_updated_ip: - // Instruction stack has changed, read new pointers - ip = bc_vec_top(&G.prog.exestack); - func = bc_program_func(ip->func); - code = func->code.v; - dbg_exec("func:%zd bytes:%zd ip:%zd", ip->func, func->code.len, ip->inst_idx); + // Instruction stack has changed, read new pointers + ip = bc_vec_top(&G.prog.exestack); + func = bc_program_func(ip->func); + code = func->code.v; + dbg_exec("func:%zd bytes:%zd ip:%zd", ip->func, func->code.len, ip->inst_idx); } if (s || G_interrupt) { -- cgit v1.2.3-55-g6feb From f706a18f33a5e6360cd7567c6c5fc9714be3ed39 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 26 Dec 2018 20:02:09 +0100 Subject: bc: use '\0' insteads of 0xff (BC_PARSE_STREND) as name terminator function old new delta zdc_program_printStream - 146 +146 zbc_program_exec 4003 4016 +13 zdc_parse_expr 473 470 -3 bc_parse_pushName 31 20 -11 bc_program_name 63 34 -29 zbc_program_pushArray 147 - -147 ------------------------------------------------------------------------------ (add/remove: 1/1 grow/shrink: 1/3 up/down: 159/-190) Total: -31 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 34 ++++++++++------------------------ 1 file changed, 10 insertions(+), 24 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 5b79b2db1..2569967d6 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -803,8 +803,6 @@ struct globals { #define IS_BC (ENABLE_BC && (!ENABLE_DC || applet_name[0] == 'b')) #define IS_DC (ENABLE_DC && (!ENABLE_BC || applet_name[0] != 'b')) -#define BC_PARSE_STREND (0xff) - #if ENABLE_BC # define BC_PARSE_REL (1 << 0) # define BC_PARSE_PRINT (1 << 1) @@ -3434,16 +3432,16 @@ static BC_STATUS zdc_lex_token(void) static void bc_parse_push(char i) { - BcParse *p = &G.prs; - dbg_compile("%s:%d pushing bytecode %zd:%d", __func__, __LINE__, p->func->code.len, i); - bc_vec_pushByte(&p->func->code, i); + BcVec *code = &G.prs.func->code; + dbg_compile("%s:%d pushing bytecode %zd:%d", __func__, __LINE__, code->len, i); + bc_vec_pushByte(code, i); } static void bc_parse_pushName(char *name) { - while (*name) - bc_parse_push(*name++); - bc_parse_push(BC_PARSE_STREND); + do { + bc_parse_push(*name); + } while (*name++); } static void bc_parse_pushIndex(size_t idx) @@ -4895,7 +4893,7 @@ static BC_STATUS zdc_parse_cond(uint8_t inst) if (s) RETURN_STATUS(s); s = zbc_lex_next(); } else { - bc_parse_push(BC_PARSE_STREND); + bc_parse_push('\0'); } RETURN_STATUS(s); @@ -5271,22 +5269,10 @@ static size_t bc_program_index(char *code, size_t *bgn) static char *bc_program_name(char *code, size_t *bgn) { - size_t i; - char *s; - code += *bgn; - s = xmalloc(strchr(code, BC_PARSE_STREND) - code + 1); - i = 0; - for (;;) { - char c = *code++; - if (c == BC_PARSE_STREND) - break; - s[i++] = c; - } - s[i] = '\0'; - *bgn += i + 1; + *bgn += strlen(code) + 1; - return s; + return xstrdup(code); } static void bc_program_printString(const char *str) @@ -6305,7 +6291,7 @@ static BC_STATUS zdc_program_execStr(char *code, size_t *bgn, bool cond) char *then_name = bc_program_name(code, bgn); char *else_name = NULL; - if (code[*bgn] == BC_PARSE_STREND) + if (code[*bgn] == '\0') (*bgn) += 1; else else_name = bc_program_name(code, bgn); -- cgit v1.2.3-55-g6feb From ab9a98602f9a0c37f9382a57e421fe4e058d4a67 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 26 Dec 2018 20:30:47 +0100 Subject: bc: simple speedups function old new delta bc_parse_pushName 20 56 +36 bc_program_index 47 71 +24 bc_parse_pushIndex 52 58 +6 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 3/0 up/down: 66/0) Total: 66 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 2569967d6..cf04e9ff1 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -3439,17 +3439,38 @@ static void bc_parse_push(char i) static void bc_parse_pushName(char *name) { +#if 1 + BcVec *code = &G.prs.func->code; + size_t pos = code->len; + size_t len = strlen(name) + 1; + + bc_vec_expand(code, pos + len); + strcpy(code->v + pos, name); + code->len = pos + len; +#else + // Smaller code, but way slow: do { bc_parse_push(*name); } while (*name++); +#endif } +// Indexes < 0xfc are encoded verbatim, else first byte is +// 0xfc, 0xfd, 0xfe or 0xff, encoding "1..4 bytes", +// followed by that many bytes, lsb first. +// (The above describes 32-bit case). +#define SMALL_INDEX_LIMIT (0x100 - sizeof(size_t)) + static void bc_parse_pushIndex(size_t idx) { size_t mask; unsigned amt; dbg_lex("%s:%d pushing index %zd", __func__, __LINE__, idx); + if (idx < SMALL_INDEX_LIMIT) { + goto push_idx; + } + mask = ((size_t)0xff) << (sizeof(idx) * 8 - 8); amt = sizeof(idx); do { @@ -3458,9 +3479,10 @@ static void bc_parse_pushIndex(size_t idx) amt--; } while (amt != 0); - bc_parse_push(amt); + bc_parse_push(SMALL_INDEX_LIMIT + amt); while (idx != 0) { + push_idx: bc_parse_push((unsigned char)idx); idx >>= 8; } @@ -5257,6 +5279,11 @@ static size_t bc_program_index(char *code, size_t *bgn) size_t res; amt = *bytes++; + if (amt < SMALL_INDEX_LIMIT) { + *bgn += 1; + return amt; + } + amt -= SMALL_INDEX_LIMIT; *bgn += amt + 1; amt *= 8; -- cgit v1.2.3-55-g6feb From 8af11087b20e2e9d19836a070ea460b7bec82a8f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 26 Dec 2018 21:01:41 +0100 Subject: bc: undo debugging change, add a small optimization Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index cf04e9ff1..af94981ec 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -3016,7 +3016,7 @@ static BC_STATUS zbc_lex_string(void) for (;;) { char c = peek_inbuf(); // strings can cross lines if (c == '\0') { - RETURN_STATUS(bc_error("unterminated string1")); + RETURN_STATUS(bc_error("unterminated string")); } if (c == '"') break; @@ -3060,7 +3060,7 @@ static BC_STATUS zbc_lex_comment(void) check_star: if (c == '*') { p->lex_inbuf++; - c = peek_inbuf(); + c = *p->lex_inbuf; // no need to peek_inbuf() if (c == '/') break; goto check_star; -- cgit v1.2.3-55-g6feb From 2beb1f6fafc341f571501829fc17773f2e0ddbbf Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 26 Dec 2018 21:17:12 +0100 Subject: bc: use ALIGN1 where appropriate text data bss dec hex filename 980138 485 7296 987919 f130f busybox_old 980128 485 7296 987909 f1305 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index af94981ec..9a0db2172 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -610,7 +610,7 @@ static ALWAYS_INLINE long lex_allowed_in_bc_expr(unsigned i) // This is an array of data for operators that correspond to // [XC_LEX_1st_op...] token types. -static const uint8_t bc_parse_ops[] = { +static const uint8_t bc_parse_ops[] ALIGN1 = { #define OP(p,l) ((int)(l) * 0x10 + (p)) OP(1, false), // neg OP(6, true ), OP( 6, true ), OP( 6, true ), OP( 6, true ), OP( 6, true ), OP( 6, true ), // == <= >= != < > @@ -631,7 +631,7 @@ static const uint8_t bc_parse_ops[] = { #if ENABLE_DC static const //BcLexType - should be this type uint8_t -dc_char_to_LEX[] = { +dc_char_to_LEX[] ALIGN1 = { /* %&'( */ XC_LEX_OP_MODULUS, XC_LEX_INVALID, XC_LEX_INVALID, DC_LEX_LPAREN, /* )*+, */ @@ -674,7 +674,7 @@ dc_char_to_LEX[] = { }; static const //BcInst - should be this type. Using signed narrow type since DC_INST_INVALID is -1 int8_t -dc_LEX_to_INST[] = { // starts at XC_LEX_OP_POWER // corresponding XC/DC_LEX_xyz: +dc_LEX_to_INST[] ALIGN1 = { // starts at XC_LEX_OP_POWER // corresponding XC/DC_LEX_xyz: XC_INST_POWER, XC_INST_MULTIPLY, // OP_POWER OP_MULTIPLY XC_INST_DIVIDE, XC_INST_MODULUS, // OP_DIVIDE OP_MODULUS XC_INST_PLUS, XC_INST_MINUS, // OP_PLUS OP_MINUS @@ -3329,7 +3329,7 @@ static BC_STATUS zdc_lex_token(void) BcParse *p = &G.prs; static const //BcLexType - should be this type, but narrower type saves size: uint8_t - dc_lex_regs[] = { + dc_lex_regs[] ALIGN1 = { XC_LEX_OP_REL_EQ, XC_LEX_OP_REL_LE, XC_LEX_OP_REL_GE, XC_LEX_OP_REL_NE, XC_LEX_OP_REL_LT, XC_LEX_OP_REL_GT, DC_LEX_SCOLON, DC_LEX_COLON, DC_LEX_ELSE, DC_LEX_LOAD, DC_LEX_LOAD_POP, DC_LEX_OP_ASSIGN, -- cgit v1.2.3-55-g6feb From 3d27d435dbe7d39894257894b9dd32bfa607604c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 27 Dec 2018 18:03:20 +0100 Subject: randomconfig fixes Signed-off-by: Denys Vlasenko --- archival/libarchive/lzo1x_9x.c | 2 +- libbb/lineedit.c | 18 ++++++++++-------- miscutils/devfsd.c | 2 +- networking/nbd-client.c | 6 ++++++ networking/udhcp/dhcpd.c | 2 +- shell/hush.c | 2 +- 6 files changed, 20 insertions(+), 12 deletions(-) diff --git a/archival/libarchive/lzo1x_9x.c b/archival/libarchive/lzo1x_9x.c index 09ee4ba5c..df26b375f 100644 --- a/archival/libarchive/lzo1x_9x.c +++ b/archival/libarchive/lzo1x_9x.c @@ -487,7 +487,7 @@ static int find_match(lzo1x_999_t *c, lzo_swd_p s, } /* this is a public functions, but there is no prototype in a header file */ -static int lzo1x_999_compress_internal(const uint8_t *in , unsigned in_len, +static int lzo1x_999_compress_internal(const uint8_t *in, unsigned in_len, uint8_t *out, unsigned *out_len, void *wrkmem, unsigned good_length, diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 3ed38e54d..0a888fa70 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -1373,6 +1373,16 @@ void FAST_FUNC show_history(const line_input_t *st) printf("%4d %s\n", i, st->history[i]); } +void FAST_FUNC free_line_input_t(line_input_t *n) +{ +# if ENABLE_FEATURE_EDITING_SAVEHISTORY + int i = n->cnt_history; + while (i > 0) + free(n->history[--i]); +#endif + free(n); +} + # if ENABLE_FEATURE_EDITING_SAVEHISTORY /* We try to ensure that concurrent additions to the history * do not overwrite each other. @@ -1382,14 +1392,6 @@ void FAST_FUNC show_history(const line_input_t *st) * than configured MAX_HISTORY lines. */ -void FAST_FUNC free_line_input_t(line_input_t *n) -{ - int i = n->cnt_history; - while (i > 0) - free(n->history[--i]); - free(n); -} - /* state->flags is already checked to be nonzero */ static void load_history(line_input_t *st_parm) { diff --git a/miscutils/devfsd.c b/miscutils/devfsd.c index 814714f53..3bf06b965 100644 --- a/miscutils/devfsd.c +++ b/miscutils/devfsd.c @@ -694,7 +694,7 @@ static void process_config_line(const char *line, unsigned long *event_mask) return; process_config_line_err: - msg_logger_and_die(LOG_ERR, bb_msg_bad_config, msg , line); + msg_logger_and_die(LOG_ERR, bb_msg_bad_config, msg, line); } /* End Function process_config_line */ static int do_servicing(int fd, unsigned long event_mask) diff --git a/networking/nbd-client.c b/networking/nbd-client.c index 103756b59..1ce974db1 100644 --- a/networking/nbd-client.c +++ b/networking/nbd-client.c @@ -163,7 +163,9 @@ int nbdclient_main(int argc, char **argv) int sock, nbd; int ro; int proto_new; // 0 for old, 1 for new +#if BB_MMU char *data; +#endif // Make sure BLOCKDEV exists nbd = xopen(device, O_RDWR); @@ -200,7 +202,9 @@ int nbdclient_main(int argc, char **argv) ioctl(nbd, NBD_SET_SIZE_BLOCKS, size_blocks); ioctl(nbd, NBD_CLEAR_SOCK); ro = !!(old_nbd_header.flags & htons(2)); +#if BB_MMU data = old_nbd_header.data; +#endif } else { unsigned namelen; uint16_t handshake_flags; @@ -230,7 +234,9 @@ int nbdclient_main(int argc, char **argv) ioctl(nbd, NBD_SET_FLAGS, ntohs(new_nbd_header.transmission_flags)); ro = !!(new_nbd_header.transmission_flags & htons(2)); +#if BB_MMU data = new_nbd_header.data; +#endif } if (ioctl(nbd, BLKROSET, &ro) < 0) { diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c index 477856d11..0c55fa5e4 100644 --- a/networking/udhcp/dhcpd.c +++ b/networking/udhcp/dhcpd.c @@ -378,7 +378,7 @@ struct config_keyword { #define OFS(field) offsetof(struct server_config_t, field) static const struct config_keyword keywords[] = { - /* keyword handler variable address default */ + /* keyword handler variable address default */ {"start" , udhcp_str2nip , OFS(start_ip ), "192.168.0.20"}, {"end" , udhcp_str2nip , OFS(end_ip ), "192.168.0.254"}, {"interface" , read_str , OFS(interface ), "eth0"}, diff --git a/shell/hush.c b/shell/hush.c index 2e4a4bcc6..d80c717e7 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -5998,7 +5998,7 @@ static const char *first_special_char_in_vararg(const char *cp) #endif static char *encode_then_expand_vararg(const char *str, int handle_squotes, int do_unbackslash) { -#if !BASH_PATTERN_SUBST +#if !BASH_PATTERN_SUBST && ENABLE_HUSH_CASE const int do_unbackslash = 0; #endif char *exp_str; -- cgit v1.2.3-55-g6feb From db8d607514c684fe208e8d8cf02864731a123bf6 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 27 Dec 2018 18:08:30 +0100 Subject: bc: G.prog.zero does not need initializing num[] vector function old new delta bc_vm_init 676 665 -11 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 9a0db2172..09cc45254 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -7156,7 +7156,7 @@ static void bc_program_free(void) bc_vec_free(&G.prog.results); bc_vec_free(&G.prog.exestack); IF_BC(bc_num_free(&G.prog.last);) - IF_BC(bc_num_free(&G.prog.zero);) + //IF_BC(bc_num_free(&G.prog.zero);) IF_BC(bc_num_free(&G.prog.one);) bc_vec_free(&G.input_buffer); } @@ -7184,7 +7184,7 @@ static void bc_program_init(void) IF_BC(bc_num_init_DEF_SIZE(&G.prog.last);) //IF_BC(bc_num_zero(&G.prog.last);) - already is - bc_num_init_DEF_SIZE(&G.prog.zero); + //bc_num_init_DEF_SIZE(&G.prog.zero); - not needed //bc_num_zero(&G.prog.zero); - already is IF_BC(bc_num_init_DEF_SIZE(&G.prog.one);) -- cgit v1.2.3-55-g6feb From 10bde14292b3f0abbbf56aaaec16f391f12c0e64 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 27 Dec 2018 18:23:58 +0100 Subject: bc: rename functions common to bc and dc as xc_FOO() Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 805 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 397 insertions(+), 408 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 09cc45254..537612d5e 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -436,7 +436,7 @@ typedef enum BcLexType { BC_LEX_LPAREN, // () are 0x28 and 0x29 BC_LEX_RPAREN, // must be LPAREN+1: code uses (c - '(' + BC_LEX_LPAREN) - BC_LEX_LBRACKET, // [] are 0x5B and 5D + BC_LEX_LBRACKET, // [] are 0x5B and 0x5D BC_LEX_COMMA, BC_LEX_RBRACKET, // must be LBRACKET+2: code uses (c - '[' + BC_LEX_LBRACKET) @@ -632,52 +632,52 @@ static const uint8_t bc_parse_ops[] ALIGN1 = { static const //BcLexType - should be this type uint8_t dc_char_to_LEX[] ALIGN1 = { - /* %&'( */ + // %&'( XC_LEX_OP_MODULUS, XC_LEX_INVALID, XC_LEX_INVALID, DC_LEX_LPAREN, - /* )*+, */ + // )*+, XC_LEX_INVALID, XC_LEX_OP_MULTIPLY, XC_LEX_OP_PLUS, XC_LEX_INVALID, - /* -./ */ + // -./ XC_LEX_OP_MINUS, XC_LEX_INVALID, XC_LEX_OP_DIVIDE, - /* 0123456789 */ + // 0123456789 XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, - /* :;<=>?@ */ + // :;<=>?@ DC_LEX_COLON, DC_LEX_SCOLON, XC_LEX_OP_REL_GT, XC_LEX_OP_REL_EQ, XC_LEX_OP_REL_LT, DC_LEX_READ, XC_LEX_INVALID, - /* ABCDEFGH */ + // ABCDEFGH XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, DC_LEX_EQ_NO_REG, XC_LEX_INVALID, - /* IJKLMNOP */ + // IJKLMNOP DC_LEX_IBASE, XC_LEX_INVALID, DC_LEX_SCALE, DC_LEX_LOAD_POP, XC_LEX_INVALID, DC_LEX_OP_BOOL_NOT, DC_LEX_OBASE, DC_LEX_PRINT_STREAM, - /* QRSTUVWXY */ + // QRSTUVWXY DC_LEX_NQUIT, DC_LEX_POP, DC_LEX_STORE_PUSH, XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, DC_LEX_SCALE_FACTOR, XC_LEX_INVALID, - /* Z[\] */ + // Z[\] DC_LEX_LENGTH, XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, - /* ^_` */ + // ^_` XC_LEX_OP_POWER, XC_LEX_NEG, XC_LEX_INVALID, - /* abcdefgh */ + // abcdefgh DC_LEX_ASCIIFY, XC_LEX_INVALID, DC_LEX_CLEAR_STACK, DC_LEX_DUPLICATE, DC_LEX_ELSE, DC_LEX_PRINT_STACK, XC_LEX_INVALID, XC_LEX_INVALID, - /* ijklmnop */ + // ijklmnop DC_LEX_STORE_IBASE, XC_LEX_INVALID, DC_LEX_STORE_SCALE, DC_LEX_LOAD, XC_LEX_INVALID, DC_LEX_PRINT_POP, DC_LEX_STORE_OBASE, DC_LEX_PRINT, - /* qrstuvwx */ + // qrstuvwx DC_LEX_QUIT, DC_LEX_SWAP, DC_LEX_OP_ASSIGN, XC_LEX_INVALID, XC_LEX_INVALID, DC_LEX_SQRT, XC_LEX_INVALID, DC_LEX_EXECUTE, - /* yz */ + // yz XC_LEX_INVALID, DC_LEX_STACK_LEVEL, - /* {|}~ */ + // {|}~ DC_LEX_LBRACE, DC_LEX_OP_MODEXP, XC_LEX_INVALID, DC_LEX_OP_DIVMOD, }; static const //BcInst - should be this type. Using signed narrow type since DC_INST_INVALID is -1 int8_t -dc_LEX_to_INST[] ALIGN1 = { // starts at XC_LEX_OP_POWER // corresponding XC/DC_LEX_xyz: - XC_INST_POWER, XC_INST_MULTIPLY, // OP_POWER OP_MULTIPLY - XC_INST_DIVIDE, XC_INST_MODULUS, // OP_DIVIDE OP_MODULUS - XC_INST_PLUS, XC_INST_MINUS, // OP_PLUS OP_MINUS +dc_LEX_to_INST[] ALIGN1 = { //starts at XC_LEX_OP_POWER // corresponding XC/DC_LEX_xyz: + XC_INST_POWER, XC_INST_MULTIPLY, // XC_LEX_OP_POWER XC_LEX_OP_MULTIPLY + XC_INST_DIVIDE, XC_INST_MODULUS, // XC_LEX_OP_DIVIDE XC_LEX_OP_MODULUS + XC_INST_PLUS, XC_INST_MINUS, // XC_LEX_OP_PLUS XC_LEX_OP_MINUS XC_INST_BOOL_NOT, // DC_LEX_OP_BOOL_NOT DC_INST_INVALID, // DC_LEX_OP_ASSIGN XC_INST_REL_GT, // DC_LEX_LPAREN @@ -692,18 +692,18 @@ dc_LEX_to_INST[] ALIGN1 = { // starts at XC_LEX_OP_POWER // corresponding XC_INST_SQRT, // DC_LEX_SQRT XC_INST_REL_GE, // DC_LEX_LBRACE XC_INST_REL_EQ, // DC_LEX_EQ_NO_REG - DC_INST_MODEXP, DC_INST_DIVMOD, // OP_MODEXP OP_DIVMOD - DC_INST_INVALID, DC_INST_INVALID, // COLON ELSE - DC_INST_EXECUTE, // EXECUTE - DC_INST_PRINT_STACK, DC_INST_CLEAR_STACK, // PRINT_STACK CLEAR_STACK - DC_INST_STACK_LEN, DC_INST_DUPLICATE, // STACK_LEVEL DUPLICATE - DC_INST_SWAP, XC_INST_POP, // SWAP POP - DC_INST_ASCIIFY, DC_INST_PRINT_STREAM, // ASCIIFY PRINT_STREAM - DC_INST_INVALID, DC_INST_INVALID, // STORE_IBASE STORE_OBASE - DC_INST_INVALID, DC_INST_INVALID, // STORE_SCALE LOAD - DC_INST_INVALID, DC_INST_INVALID, // LOAD_POP STORE_PUSH - XC_INST_PRINT, DC_INST_NQUIT, // PRINT_POP NQUIT - XC_INST_SCALE_FUNC, // SCALE_FACTOR + DC_INST_MODEXP, DC_INST_DIVMOD, // DC_LEX_OP_MODEXP DC_LEX_OP_DIVMOD + DC_INST_INVALID, DC_INST_INVALID, // DC_LEX_COLON DC_LEX_ELSE + DC_INST_EXECUTE, // DC_LEX_EXECUTE + DC_INST_PRINT_STACK, DC_INST_CLEAR_STACK, // DC_LEX_PRINT_STACK DC_LEX_CLEAR_STACK + DC_INST_STACK_LEN, DC_INST_DUPLICATE, // DC_LEX_STACK_LEVEL DC_LEX_DUPLICATE + DC_INST_SWAP, XC_INST_POP, // DC_LEX_SWAP DC_LEX_POP + DC_INST_ASCIIFY, DC_INST_PRINT_STREAM, // DC_LEX_ASCIIFY DC_LEX_PRINT_STREAM + DC_INST_INVALID, DC_INST_INVALID, // DC_LEX_STORE_IBASE DC_LEX_STORE_OBASE + DC_INST_INVALID, DC_INST_INVALID, // DC_LEX_STORE_SCALE DC_LEX_LOAD + DC_INST_INVALID, DC_INST_INVALID, // DC_LEX_LOAD_POP DC_LEX_STORE_PUSH + XC_INST_PRINT, DC_INST_NQUIT, // DC_LEX_PRINT_POP DC_LEX_NQUIT + XC_INST_SCALE_FUNC, // DC_LEX_SCALE_FACTOR // DC_INST_INVALID in this table either means that corresponding LEX // is not possible for dc, or that it does not compile one-to-one // to a single INST. @@ -825,8 +825,8 @@ struct globals { #define BC_FLAG_S (1 << 2) #define BC_FLAG_Q (1 << 3) #define BC_FLAG_L (1 << 4) -#define BC_FLAG_I (1 << 5) -#define DC_FLAG_X (1 << 6) +#define BC_FLAG_I ((1 << 5) * ENABLE_DC) +#define DC_FLAG_X ((1 << 6) * ENABLE_DC) #define BC_MAX(a, b) ((a) > (b) ? (a) : (b)) #define BC_MIN(a, b) ((a) < (b) ? (a) : (b)) @@ -911,9 +911,6 @@ do { \ return BC_STATUS_FAILURE; \ } while (0) #else -#define QUIT_OR_RETURN_TO_MAIN quit() -#endif - static void quit(void) NORETURN; static void quit(void) { @@ -923,6 +920,8 @@ static void quit(void) dbg_exec("quit(): exiting with exitcode SUCCESS"); exit(0); } +#define QUIT_OR_RETURN_TO_MAIN quit() +#endif static void bc_verror_msg(const char *fmt, va_list p) { @@ -1165,23 +1164,23 @@ static FAST_FUNC void bc_vec_free(void *vec) free(v->v); } -static BcFunc* bc_program_func(size_t idx) +static BcFunc* xc_program_func(size_t idx) { return bc_vec_item(&G.prog.fns, idx); } // BC_PROG_MAIN is zeroth element, so: -#define bc_program_func_BC_PROG_MAIN() ((BcFunc*)(G.prog.fns.v)) +#define xc_program_func_BC_PROG_MAIN() ((BcFunc*)(G.prog.fns.v)) #if ENABLE_BC static BcFunc* bc_program_current_func(void) { BcInstPtr *ip = bc_vec_top(&G.prog.exestack); - BcFunc *func = bc_program_func(ip->func); + BcFunc *func = xc_program_func(ip->func); return func; } #endif -static char** bc_program_str(size_t idx) +static char** xc_program_str(size_t idx) { #if ENABLE_BC if (IS_BC) { @@ -1192,7 +1191,7 @@ static char** bc_program_str(size_t idx) IF_DC(return bc_vec_item(&G.prog.strs, idx);) } -static char** bc_program_const(size_t idx) +static char** xc_program_const(size_t idx) { #if ENABLE_BC if (IS_BC) { @@ -1637,7 +1636,7 @@ static FAST_FUNC BC_STATUS zbc_num_pow(BcNum *a, BcNum *b, BcNum *c, size_t scal RETURN_STATUS(zbc_num_binary(a, b, c, scale, zbc_num_p, a->len * b->len + 1)); } -static const BcNumBinaryOp zbc_program_ops[] = { +static const BcNumBinaryOp zxc_program_ops[] = { zbc_num_pow, zbc_num_mul, zbc_num_div, zbc_num_mod, zbc_num_add, zbc_num_sub, }; #define zbc_num_add(...) (zbc_num_add(__VA_ARGS__) COMMA_SUCCESS) @@ -2481,7 +2480,7 @@ static int bad_input_byte(char c) return 0; } -static void bc_read_line(BcVec *vec, FILE *fp) +static void xc_read_line(BcVec *vec, FILE *fp) { again: bc_vec_pop_all(vec); @@ -2568,7 +2567,7 @@ static void bc_read_line(BcVec *vec, FILE *fp) // Parsing routines // -static bool bc_num_strValid(const char *val, size_t base) +static bool xc_num_strValid(const char *val, size_t base) { BcDig b; bool radix; @@ -2703,9 +2702,9 @@ static void bc_num_parseBase(BcNum *n, const char *val, unsigned base_t) bc_num_free(&temp); } -static BC_STATUS zbc_num_parse(BcNum *n, const char *val, unsigned base_t) +static BC_STATUS zxc_num_parse(BcNum *n, const char *val, unsigned base_t) { - if (!bc_num_strValid(val, base_t)) + if (!xc_num_strValid(val, base_t)) RETURN_STATUS(bc_error("bad number string")); bc_num_zero(n); @@ -2718,15 +2717,15 @@ static BC_STATUS zbc_num_parse(BcNum *n, const char *val, unsigned base_t) RETURN_STATUS(BC_STATUS_SUCCESS); } -#define zbc_num_parse(...) (zbc_num_parse(__VA_ARGS__) COMMA_SUCCESS) +#define zxc_num_parse(...) (zxc_num_parse(__VA_ARGS__) COMMA_SUCCESS) -static bool bc_lex_more_input(void) +static bool xc_lex_more_input(void) { BcParse *p = &G.prs; bc_vec_pop_all(&G.input_buffer); - bc_read_line(&G.input_buffer, G.prs.lex_input_fp); + xc_read_line(&G.input_buffer, G.prs.lex_input_fp); p->lex_inbuf = G.input_buffer.v; // bb_error_msg("G.input_buffer.len:%d '%s'", G.input_buffer.len, G.input_buffer.v); @@ -2769,7 +2768,7 @@ static char peek_inbuf(void) { if (*G.prs.lex_inbuf == '\0') { if (G.prs.lex_input_fp) - if (!bc_lex_more_input()) + if (!xc_lex_more_input()) G.prs.lex_input_fp = NULL; } return *G.prs.lex_inbuf; @@ -2781,7 +2780,7 @@ static char eat_inbuf(void) return c; } -static void bc_lex_lineComment(void) +static void xc_lex_lineComment(void) { BcParse *p = &G.prs; char c; @@ -2795,7 +2794,7 @@ static void bc_lex_lineComment(void) p->lex_inbuf++; } -static void bc_lex_whitespace(void) +static void xc_lex_whitespace(void) { BcParse *p = &G.prs; @@ -2812,7 +2811,7 @@ static void bc_lex_whitespace(void) } } -static BC_STATUS zbc_lex_number(char last) +static BC_STATUS zxc_lex_number(char last) { BcParse *p = &G.prs; bool pt; @@ -2853,9 +2852,9 @@ static BC_STATUS zbc_lex_number(char last) G.err_line = G.prs.lex_line; RETURN_STATUS(BC_STATUS_SUCCESS); } -#define zbc_lex_number(...) (zbc_lex_number(__VA_ARGS__) COMMA_SUCCESS) +#define zxc_lex_number(...) (zxc_lex_number(__VA_ARGS__) COMMA_SUCCESS) -static void bc_lex_name(void) +static void xc_lex_name(void) { BcParse *p = &G.prs; size_t i; @@ -2893,7 +2892,7 @@ IF_DC(static BC_STATUS zdc_lex_token(void);) #define zbc_lex_token(...) (zbc_lex_token(__VA_ARGS__) COMMA_SUCCESS) #define zdc_lex_token(...) (zdc_lex_token(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zbc_lex_next(void) +static BC_STATUS zxc_lex_next(void) { BcParse *p = &G.prs; BcStatus s; @@ -2928,13 +2927,13 @@ static BC_STATUS zbc_lex_next(void) RETURN_STATUS(s); } -#define zbc_lex_next(...) (zbc_lex_next(__VA_ARGS__) COMMA_SUCCESS) +#define zxc_lex_next(...) (zxc_lex_next(__VA_ARGS__) COMMA_SUCCESS) #if ENABLE_BC static BC_STATUS zbc_lex_skip_if_at_NLINE(void) { if (G.prs.lex == XC_LEX_NLINE) - RETURN_STATUS(zbc_lex_next()); + RETURN_STATUS(zxc_lex_next()); RETURN_STATUS(BC_STATUS_SUCCESS); } #define zbc_lex_skip_if_at_NLINE(...) (zbc_lex_skip_if_at_NLINE(__VA_ARGS__) COMMA_SUCCESS) @@ -2942,24 +2941,14 @@ static BC_STATUS zbc_lex_skip_if_at_NLINE(void) static BC_STATUS zbc_lex_next_and_skip_NLINE(void) { BcStatus s; - s = zbc_lex_next(); + s = zxc_lex_next(); if (s) RETURN_STATUS(s); // if(cond)stmt is accepted too (but not 2+ newlines) s = zbc_lex_skip_if_at_NLINE(); RETURN_STATUS(s); } #define zbc_lex_next_and_skip_NLINE(...) (zbc_lex_next_and_skip_NLINE(__VA_ARGS__) COMMA_SUCCESS) -#endif - -static BC_STATUS zbc_lex_text_init(const char *text) -{ - G.prs.lex_inbuf = text; - G.prs.lex = G.prs.lex_last = XC_LEX_INVALID; - RETURN_STATUS(zbc_lex_next()); -} -#define zbc_lex_text_init(...) (zbc_lex_text_init(__VA_ARGS__) COMMA_SUCCESS) -#if ENABLE_BC static BC_STATUS zbc_lex_identifier(void) { BcParse *p = &G.prs; @@ -2991,7 +2980,7 @@ static BC_STATUS zbc_lex_identifier(void) RETURN_STATUS(BC_STATUS_SUCCESS); } - bc_lex_name(); + xc_lex_name(); s = BC_STATUS_SUCCESS; if (p->lex_strnumbuf.len > 2) { @@ -3101,7 +3090,7 @@ static BC_STATUS zbc_lex_token(void) case '\f': case '\r': case ' ': - bc_lex_whitespace(); + xc_lex_whitespace(); break; case '!': parse_lex_by_checking_eq_sign(XC_LEX_OP_REL_NE, BC_LEX_OP_BOOL_NOT); @@ -3116,7 +3105,7 @@ static BC_STATUS zbc_lex_token(void) case '#': s = zbc_POSIX_does_not_allow("'#' script comments"); if (s) RETURN_STATUS(s); - bc_lex_lineComment(); + xc_lex_lineComment(); break; case '%': parse_lex_by_checking_eq_sign(BC_LEX_OP_ASSIGN_MODULUS, XC_LEX_OP_MODULUS); @@ -3161,7 +3150,7 @@ static BC_STATUS zbc_lex_token(void) break; case '.': if (isdigit(*p->lex_inbuf)) - s = zbc_lex_number(c); + s = zxc_lex_number(c); else { p->lex = BC_LEX_KEY_LAST; s = zbc_POSIX_does_not_allow("'.' as 'last'"); @@ -3190,7 +3179,7 @@ static BC_STATUS zbc_lex_token(void) case 'D': case 'E': case 'F': - s = zbc_lex_number(c); + s = zxc_lex_number(c); break; case ';': p->lex = BC_LEX_SCOLON; @@ -3278,9 +3267,9 @@ static BC_STATUS zdc_lex_register(void) { BcParse *p = &G.prs; if (G_exreg && isspace(*p->lex_inbuf)) { - bc_lex_whitespace(); // eats whitespace (but not newline) - p->lex_inbuf++; // bc_lex_name() expects this - bc_lex_name(); + xc_lex_whitespace(); // eats whitespace (but not newline) + p->lex_inbuf++; // xc_lex_name() expects this + xc_lex_name(); } else { bc_vec_pop_all(&p->lex_strnumbuf); bc_vec_push(&p->lex_strnumbuf, p->lex_inbuf++); @@ -3326,7 +3315,6 @@ static BC_STATUS zdc_lex_string(void) #undef zdc_lex_token static BC_STATUS zdc_lex_token(void) { - BcParse *p = &G.prs; static const //BcLexType - should be this type, but narrower type saves size: uint8_t dc_lex_regs[] ALIGN1 = { @@ -3336,6 +3324,7 @@ static BC_STATUS zdc_lex_token(void) DC_LEX_STORE_PUSH, }; + BcParse *p = &G.prs; BcStatus s; char c, c2; size_t i; @@ -3375,7 +3364,7 @@ static BC_STATUS zdc_lex_token(void) case '\f': case '\r': case ' ': - bc_lex_whitespace(); + xc_lex_whitespace(); break; case '!': c2 = *p->lex_inbuf; @@ -3390,11 +3379,11 @@ static BC_STATUS zdc_lex_token(void) p->lex_inbuf++; break; case '#': - bc_lex_lineComment(); + xc_lex_lineComment(); break; case '.': if (isdigit(*p->lex_inbuf)) - s = zbc_lex_number(c); + s = zxc_lex_number(c); else s = bc_error_bad_character(c); break; @@ -3414,7 +3403,7 @@ static BC_STATUS zdc_lex_token(void) case 'D': case 'E': case 'F': - s = zbc_lex_number(c); + s = zxc_lex_number(c); break; case '[': s = zdc_lex_string(); @@ -3430,14 +3419,14 @@ static BC_STATUS zdc_lex_token(void) #define zdc_lex_token(...) (zdc_lex_token(__VA_ARGS__) COMMA_SUCCESS) #endif // ENABLE_DC -static void bc_parse_push(char i) +static void xc_parse_push(char i) { BcVec *code = &G.prs.func->code; dbg_compile("%s:%d pushing bytecode %zd:%d", __func__, __LINE__, code->len, i); bc_vec_pushByte(code, i); } -static void bc_parse_pushName(char *name) +static void xc_parse_pushName(char *name) { #if 1 BcVec *code = &G.prs.func->code; @@ -3450,7 +3439,7 @@ static void bc_parse_pushName(char *name) #else // Smaller code, but way slow: do { - bc_parse_push(*name); + xc_parse_push(*name); } while (*name++); #endif } @@ -3461,7 +3450,7 @@ static void bc_parse_pushName(char *name) // (The above describes 32-bit case). #define SMALL_INDEX_LIMIT (0x100 - sizeof(size_t)) -static void bc_parse_pushIndex(size_t idx) +static void xc_parse_pushIndex(size_t idx) { size_t mask; unsigned amt; @@ -3479,11 +3468,11 @@ static void bc_parse_pushIndex(size_t idx) amt--; } while (amt != 0); - bc_parse_push(SMALL_INDEX_LIMIT + amt); + xc_parse_push(SMALL_INDEX_LIMIT + amt); while (idx != 0) { push_idx: - bc_parse_push((unsigned char)idx); + xc_parse_push((unsigned char)idx); idx >>= 8; } } @@ -3491,14 +3480,14 @@ static void bc_parse_pushIndex(size_t idx) #if ENABLE_BC static void bc_parse_pushJUMP(size_t idx) { - bc_parse_push(BC_INST_JUMP); - bc_parse_pushIndex(idx); + xc_parse_push(BC_INST_JUMP); + xc_parse_pushIndex(idx); } static void bc_parse_pushJUMP_ZERO(size_t idx) { - bc_parse_push(BC_INST_JUMP_ZERO); - bc_parse_pushIndex(idx); + xc_parse_push(BC_INST_JUMP_ZERO); + xc_parse_pushIndex(idx); } static BC_STATUS zbc_parse_pushSTR(void) @@ -3506,16 +3495,16 @@ static BC_STATUS zbc_parse_pushSTR(void) BcParse *p = &G.prs; char *str = xstrdup(p->lex_strnumbuf.v); - bc_parse_push(XC_INST_STR); - bc_parse_pushIndex(p->func->strs.len); + xc_parse_push(XC_INST_STR); + xc_parse_pushIndex(p->func->strs.len); bc_vec_push(&p->func->strs, &str); - RETURN_STATUS(zbc_lex_next()); + RETURN_STATUS(zxc_lex_next()); } #define zbc_parse_pushSTR(...) (zbc_parse_pushSTR(__VA_ARGS__) COMMA_SUCCESS) #endif -static void bc_parse_pushNUM(void) +static void xc_parse_pushNUM(void) { BcParse *p = &G.prs; char *num = xstrdup(p->lex_strnumbuf.v); @@ -3526,22 +3515,22 @@ static void bc_parse_pushNUM(void) #else // DC size_t idx = bc_vec_push(&G.prog.consts, &num); #endif - bc_parse_push(XC_INST_NUM); - bc_parse_pushIndex(idx); + xc_parse_push(XC_INST_NUM); + xc_parse_pushIndex(idx); } -static BC_STATUS zbc_parse_text_init(const char *text) +static BC_STATUS zxc_parse_text_init(const char *text) { - BcParse *p = &G.prs; - p->func = bc_program_func(p->fidx); - - RETURN_STATUS(zbc_lex_text_init(text)); + G.prs.func = xc_program_func(G.prs.fidx); + G.prs.lex_inbuf = text; + G.prs.lex = G.prs.lex_last = XC_LEX_INVALID; + RETURN_STATUS(zxc_lex_next()); } -#define zbc_parse_text_init(...) (zbc_parse_text_init(__VA_ARGS__) COMMA_SUCCESS) +#define zxc_parse_text_init(...) (zxc_parse_text_init(__VA_ARGS__) COMMA_SUCCESS) // Called when parsing or execution detects a failure, // resets execution structures. -static void bc_program_reset(void) +static void xc_program_reset(void) { BcFunc *f; BcInstPtr *ip; @@ -3549,14 +3538,14 @@ static void bc_program_reset(void) bc_vec_npop(&G.prog.exestack, G.prog.exestack.len - 1); bc_vec_pop_all(&G.prog.results); - f = bc_program_func_BC_PROG_MAIN(); + f = xc_program_func_BC_PROG_MAIN(); ip = bc_vec_top(&G.prog.exestack); ip->inst_idx = f->code.len; } // Called when parsing code detects a failure, // resets parsing structures. -static void bc_parse_reset(void) +static void xc_parse_reset(void) { BcParse *p = &G.prs; if (p->fidx != BC_PROG_MAIN) { @@ -3564,7 +3553,7 @@ static void bc_parse_reset(void) bc_func_init(p->func); p->fidx = BC_PROG_MAIN; - p->func = bc_program_func_BC_PROG_MAIN(); + p->func = xc_program_func_BC_PROG_MAIN(); } p->lex_inbuf += strlen(p->lex_inbuf); @@ -3574,10 +3563,10 @@ static void bc_parse_reset(void) IF_BC(bc_vec_pop_all(&p->conds);) IF_BC(bc_vec_pop_all(&p->ops);) - bc_program_reset(); + xc_program_reset(); } -static void bc_parse_free(void) +static void xc_parse_free(void) { IF_BC(bc_vec_free(&G.prs.exits);) IF_BC(bc_vec_free(&G.prs.conds);) @@ -3585,7 +3574,7 @@ static void bc_parse_free(void) bc_vec_free(&G.prs.lex_strnumbuf); } -static void bc_parse_create(size_t fidx) +static void xc_parse_create(size_t fidx) { BcParse *p = &G.prs; memset(p, 0, sizeof(BcParse)); @@ -3596,10 +3585,10 @@ static void bc_parse_create(size_t fidx) IF_BC(bc_vec_init(&p->ops, sizeof(BcLexType), NULL);) p->fidx = fidx; - p->func = bc_program_func(fidx); + p->func = xc_program_func(fidx); } -static void bc_program_add_fn(void) +static void xc_program_add_fn(void) { //size_t idx; BcFunc f; @@ -3630,11 +3619,11 @@ static size_t bc_program_addFunc(char *name) if (!inserted) { // There is already a function with this name. // It'll be redefined now, clear old definition. - BcFunc *func = bc_program_func(entry_ptr->idx); + BcFunc *func = xc_program_func(entry_ptr->idx); bc_func_free(func); bc_func_init(func); } else { - bc_program_add_fn(); + xc_program_add_fn(); } return idx; @@ -3695,7 +3684,7 @@ static void bc_parse_operator(BcLexType type, size_t start, size_t *nexprs) l = bc_parse_op_PREC(t - XC_LEX_1st_op); if (l >= r && (l != r || !left)) break; - bc_parse_push(BC_TOKEN_2_INST(t)); + xc_parse_push(BC_TOKEN_2_INST(t)); bc_vec_pop(&p->ops); *nexprs -= (t != BC_LEX_OP_BOOL_NOT && t != XC_LEX_NEG); } @@ -3713,7 +3702,7 @@ static BC_STATUS zbc_parse_rightParen(size_t ops_bgn, size_t *nexs) top = BC_PARSE_TOP_OP(p); while (top != BC_LEX_LPAREN) { - bc_parse_push(BC_TOKEN_2_INST(top)); + xc_parse_push(BC_TOKEN_2_INST(top)); bc_vec_pop(&p->ops); *nexs -= (top != BC_LEX_OP_BOOL_NOT && top != XC_LEX_NEG); @@ -3738,7 +3727,7 @@ static BC_STATUS zbc_parse_params(uint8_t flags) dbg_lex("%s:%d p->lex:%d", __func__, __LINE__, p->lex); flags = (flags & ~(BC_PARSE_PRINT | BC_PARSE_REL)) | BC_PARSE_ARRAY; - s = zbc_lex_next(); + s = zxc_lex_next(); if (s) RETURN_STATUS(s); nparams = 0; @@ -3752,13 +3741,13 @@ static BC_STATUS zbc_parse_params(uint8_t flags) break; RETURN_STATUS(bc_error_bad_token()); } - s = zbc_lex_next(); + s = zxc_lex_next(); if (s) RETURN_STATUS(s); } } - bc_parse_push(BC_INST_CALL); - bc_parse_pushIndex(nparams); + xc_parse_push(BC_INST_CALL); + xc_parse_pushIndex(nparams); RETURN_STATUS(BC_STATUS_SUCCESS); } @@ -3792,9 +3781,9 @@ static BC_STATUS zbc_parse_call(char *name, uint8_t flags) free(name); entry_ptr = bc_vec_item(&G.prog.fn_map, idx); - bc_parse_pushIndex(entry_ptr->idx); + xc_parse_pushIndex(entry_ptr->idx); - RETURN_STATUS(zbc_lex_next()); + RETURN_STATUS(zxc_lex_next()); err: free(name); RETURN_STATUS(s); @@ -3808,11 +3797,11 @@ static BC_STATUS zbc_parse_name(BcInst *type, uint8_t flags) char *name; name = xstrdup(p->lex_strnumbuf.v); - s = zbc_lex_next(); + s = zxc_lex_next(); if (s) goto err; if (p->lex == BC_LEX_LBRACKET) { - s = zbc_lex_next(); + s = zxc_lex_next(); if (s) goto err; if (p->lex == BC_LEX_RBRACKET) { @@ -3827,10 +3816,10 @@ static BC_STATUS zbc_parse_name(BcInst *type, uint8_t flags) s = zbc_parse_expr(flags); if (s) goto err; } - s = zbc_lex_next(); + s = zxc_lex_next(); if (s) goto err; - bc_parse_push(*type); - bc_parse_pushName(name); + xc_parse_push(*type); + xc_parse_pushName(name); free(name); } else if (p->lex == BC_LEX_LPAREN) { if (flags & BC_PARSE_NOCALL) { @@ -3841,8 +3830,8 @@ static BC_STATUS zbc_parse_name(BcInst *type, uint8_t flags) s = zbc_parse_call(name, flags); } else { *type = XC_INST_VAR; - bc_parse_push(XC_INST_VAR); - bc_parse_pushName(name); + xc_parse_push(XC_INST_VAR); + xc_parse_pushName(name); free(name); } @@ -3858,15 +3847,15 @@ static BC_STATUS zbc_parse_read(void) BcParse *p = &G.prs; BcStatus s; - s = zbc_lex_next(); + s = zxc_lex_next(); if (s) RETURN_STATUS(s); if (p->lex != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); - s = zbc_lex_next(); + s = zxc_lex_next(); if (s) RETURN_STATUS(s); if (p->lex != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); - bc_parse_push(XC_INST_READ); + xc_parse_push(XC_INST_READ); RETURN_STATUS(s); } @@ -3877,13 +3866,13 @@ static BC_STATUS zbc_parse_builtin(BcLexType type, uint8_t flags, BcInst *prev) BcParse *p = &G.prs; BcStatus s; - s = zbc_lex_next(); + s = zxc_lex_next(); if (s) RETURN_STATUS(s); if (p->lex != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); flags = (flags & ~(BC_PARSE_PRINT | BC_PARSE_REL)) | BC_PARSE_ARRAY; - s = zbc_lex_next(); + s = zxc_lex_next(); if (s) RETURN_STATUS(s); s = zbc_parse_expr(flags); @@ -3892,7 +3881,7 @@ static BC_STATUS zbc_parse_builtin(BcLexType type, uint8_t flags, BcInst *prev) if (p->lex != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); *prev = (type == BC_LEX_KEY_LENGTH) ? XC_INST_LENGTH : XC_INST_SQRT; - bc_parse_push(*prev); + xc_parse_push(*prev); RETURN_STATUS(s); } @@ -3903,28 +3892,28 @@ static BC_STATUS zbc_parse_scale(BcInst *type, uint8_t flags) BcParse *p = &G.prs; BcStatus s; - s = zbc_lex_next(); + s = zxc_lex_next(); if (s) RETURN_STATUS(s); if (p->lex != BC_LEX_LPAREN) { *type = XC_INST_SCALE; - bc_parse_push(XC_INST_SCALE); + xc_parse_push(XC_INST_SCALE); RETURN_STATUS(BC_STATUS_SUCCESS); } *type = XC_INST_SCALE_FUNC; flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL); - s = zbc_lex_next(); + s = zxc_lex_next(); if (s) RETURN_STATUS(s); s = zbc_parse_expr(flags); if (s) RETURN_STATUS(s); if (p->lex != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); - bc_parse_push(XC_INST_SCALE_FUNC); + xc_parse_push(XC_INST_SCALE_FUNC); - RETURN_STATUS(zbc_lex_next()); + RETURN_STATUS(zxc_lex_next()); } #define zbc_parse_scale(...) (zbc_parse_scale(__VA_ARGS__) COMMA_SUCCESS) @@ -3942,13 +3931,13 @@ static BC_STATUS zbc_parse_incdec(BcInst *prev, bool *paren_expr, || etype == XC_INST_IBASE || etype == XC_INST_OBASE ) { *prev = inst = BC_INST_INC_POST + (p->lex != BC_LEX_OP_INC); - bc_parse_push(inst); - s = zbc_lex_next(); + xc_parse_push(inst); + s = zxc_lex_next(); } else { *prev = inst = BC_INST_INC_PRE + (p->lex != BC_LEX_OP_INC); *paren_expr = true; - s = zbc_lex_next(); + s = zxc_lex_next(); if (s) RETURN_STATUS(s); type = p->lex; @@ -3963,23 +3952,23 @@ static BC_STATUS zbc_parse_incdec(BcInst *prev, bool *paren_expr, case BC_LEX_KEY_IBASE: case BC_LEX_KEY_LAST: case BC_LEX_KEY_OBASE: - bc_parse_push(type - BC_LEX_KEY_IBASE + XC_INST_IBASE); - s = zbc_lex_next(); + xc_parse_push(type - BC_LEX_KEY_IBASE + XC_INST_IBASE); + s = zxc_lex_next(); break; case BC_LEX_KEY_SCALE: - s = zbc_lex_next(); + s = zxc_lex_next(); if (s) RETURN_STATUS(s); if (p->lex == BC_LEX_LPAREN) s = bc_error_bad_token(); else - bc_parse_push(XC_INST_SCALE); + xc_parse_push(XC_INST_SCALE); break; default: s = bc_error_bad_token(); break; } - if (!s) bc_parse_push(inst); + if (!s) xc_parse_push(inst); } RETURN_STATUS(s); @@ -4012,7 +4001,7 @@ static BC_STATUS zbc_parse_minus(BcInst *prev, size_t ops_bgn, BcLexType type; BcInst etype = *prev; - s = zbc_lex_next(); + s = zxc_lex_next(); if (s) RETURN_STATUS(s); type = BC_PARSE_LEAF(etype, rparen) ? XC_LEX_OP_MINUS : XC_LEX_NEG; @@ -4036,7 +4025,7 @@ static BC_STATUS zbc_parse_print(void) BcLexType type; for (;;) { - s = zbc_lex_next(); + s = zxc_lex_next(); if (s) RETURN_STATUS(s); type = p->lex; if (type == XC_LEX_STR) { @@ -4045,7 +4034,7 @@ static BC_STATUS zbc_parse_print(void) s = zbc_parse_expr(0); } if (s) RETURN_STATUS(s); - bc_parse_push(XC_INST_PRINT_POP); + xc_parse_push(XC_INST_PRINT_POP); if (p->lex != BC_LEX_COMMA) break; } @@ -4061,18 +4050,18 @@ static BC_STATUS zbc_parse_return(void) BcLexType t; dbg_lex_enter("%s:%d entered", __func__, __LINE__); - s = zbc_lex_next(); + s = zxc_lex_next(); if (s) RETURN_STATUS(s); t = p->lex; if (t == XC_LEX_NLINE || t == BC_LEX_SCOLON) - bc_parse_push(BC_INST_RET0); + xc_parse_push(BC_INST_RET0); else { bool paren = (t == BC_LEX_LPAREN); s = bc_parse_expr_empty_ok(0); if (s == BC_STATUS_PARSE_EMPTY_EXP) { - bc_parse_push(BC_INST_RET0); - s = zbc_lex_next(); + xc_parse_push(BC_INST_RET0); + s = zxc_lex_next(); } if (s) RETURN_STATUS(s); @@ -4081,7 +4070,7 @@ static BC_STATUS zbc_parse_return(void) if (s) RETURN_STATUS(s); } - bc_parse_push(XC_INST_RET); + xc_parse_push(XC_INST_RET); } dbg_lex_done("%s:%d done", __func__, __LINE__); @@ -4103,11 +4092,11 @@ static BC_STATUS zbc_parse_if(void) size_t ip_idx; dbg_lex_enter("%s:%d entered", __func__, __LINE__); - s = zbc_lex_next(); + s = zxc_lex_next(); if (s) RETURN_STATUS(s); if (p->lex != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); - s = zbc_lex_next(); + s = zxc_lex_next(); if (s) RETURN_STATUS(s); s = zbc_parse_expr(BC_PARSE_REL); if (s) RETURN_STATUS(s); @@ -4155,10 +4144,10 @@ static BC_STATUS zbc_parse_while(void) size_t cond_idx; size_t ip_idx; - s = zbc_lex_next(); + s = zxc_lex_next(); if (s) RETURN_STATUS(s); if (p->lex != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); - s = zbc_lex_next(); + s = zxc_lex_next(); if (s) RETURN_STATUS(s); cond_idx = bc_vec_push(&p->func->labels, &p->func->code.len); @@ -4197,15 +4186,15 @@ static BC_STATUS zbc_parse_for(void) size_t cond_idx, exit_idx, body_idx, update_idx; dbg_lex("%s:%d p->lex:%d", __func__, __LINE__, p->lex); - s = zbc_lex_next(); + s = zxc_lex_next(); if (s) RETURN_STATUS(s); if (p->lex != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); - s = zbc_lex_next(); + s = zxc_lex_next(); if (s) RETURN_STATUS(s); if (p->lex != BC_LEX_SCOLON) { s = zbc_parse_expr(0); - bc_parse_push(XC_INST_POP); + xc_parse_push(XC_INST_POP); if (s) RETURN_STATUS(s); } else { s = zbc_POSIX_does_not_allow_empty_X_expression_in_for("init"); @@ -4213,7 +4202,7 @@ static BC_STATUS zbc_parse_for(void) } if (p->lex != BC_LEX_SCOLON) RETURN_STATUS(bc_error_bad_token()); - s = zbc_lex_next(); + s = zxc_lex_next(); if (s) RETURN_STATUS(s); cond_idx = bc_vec_push(&p->func->labels, &p->func->code.len); @@ -4224,18 +4213,18 @@ static BC_STATUS zbc_parse_for(void) if (p->lex != BC_LEX_SCOLON) s = zbc_parse_expr(BC_PARSE_REL); else { - // Set this for the next call to bc_parse_pushNUM(). + // Set this for the next call to xc_parse_pushNUM(). // This is safe to set because the current token is a semicolon, // which has no string requirement. bc_vec_string(&p->lex_strnumbuf, 1, "1"); - bc_parse_pushNUM(); + xc_parse_pushNUM(); s = zbc_POSIX_does_not_allow_empty_X_expression_in_for("condition"); } if (s) RETURN_STATUS(s); if (p->lex != BC_LEX_SCOLON) RETURN_STATUS(bc_error_bad_token()); - s = zbc_lex_next(); + s = zxc_lex_next(); if (s) RETURN_STATUS(s); bc_parse_pushJUMP_ZERO(exit_idx); @@ -4248,7 +4237,7 @@ static BC_STATUS zbc_parse_for(void) s = zbc_parse_expr(0); if (s) RETURN_STATUS(s); if (p->lex != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); - bc_parse_push(XC_INST_POP); + xc_parse_push(XC_INST_POP); } else { s = zbc_POSIX_does_not_allow_empty_X_expression_in_for("update"); if (s) RETURN_STATUS(s); @@ -4290,7 +4279,7 @@ static BC_STATUS zbc_parse_break_or_continue(BcLexType type) } bc_parse_pushJUMP(i); - RETURN_STATUS(zbc_lex_next()); + RETURN_STATUS(zxc_lex_next()); } #define zbc_parse_break_or_continue(...) (zbc_parse_break_or_continue(__VA_ARGS__) COMMA_SUCCESS) @@ -4323,20 +4312,20 @@ static BC_STATUS zbc_parse_funcdef(void) char *name; dbg_lex_enter("%s:%d entered", __func__, __LINE__); - s = zbc_lex_next(); + s = zxc_lex_next(); if (s) RETURN_STATUS(s); if (p->lex != XC_LEX_NAME) RETURN_STATUS(bc_error("bad function definition")); name = xstrdup(p->lex_strnumbuf.v); p->fidx = bc_program_addFunc(name); - p->func = bc_program_func(p->fidx); + p->func = xc_program_func(p->fidx); - s = zbc_lex_next(); + s = zxc_lex_next(); if (s) RETURN_STATUS(s); if (p->lex != BC_LEX_LPAREN) RETURN_STATUS(bc_error("bad function definition")); - s = zbc_lex_next(); + s = zxc_lex_next(); if (s) RETURN_STATUS(s); while (p->lex != BC_LEX_RPAREN) { @@ -4346,13 +4335,13 @@ static BC_STATUS zbc_parse_funcdef(void) ++p->func->nparams; name = xstrdup(p->lex_strnumbuf.v); - s = zbc_lex_next(); + s = zxc_lex_next(); if (s) goto err; var = p->lex != BC_LEX_LBRACKET; if (!var) { - s = zbc_lex_next(); + s = zxc_lex_next(); if (s) goto err; if (p->lex != BC_LEX_RBRACKET) { @@ -4360,13 +4349,13 @@ static BC_STATUS zbc_parse_funcdef(void) goto err; } - s = zbc_lex_next(); + s = zxc_lex_next(); if (s) goto err; } comma = p->lex == BC_LEX_COMMA; if (comma) { - s = zbc_lex_next(); + s = zxc_lex_next(); if (s) goto err; } @@ -4376,7 +4365,7 @@ static BC_STATUS zbc_parse_funcdef(void) if (comma) RETURN_STATUS(bc_error("bad function definition")); - s = zbc_lex_next(); + s = zxc_lex_next(); if (s) RETURN_STATUS(s); if (p->lex != BC_LEX_LBRACE) { @@ -4396,11 +4385,11 @@ static BC_STATUS zbc_parse_funcdef(void) p->in_funcdef--; if (s) RETURN_STATUS(s); - bc_parse_push(BC_INST_RET0); + xc_parse_push(BC_INST_RET0); // Subsequent code generation is into main program p->fidx = BC_PROG_MAIN; - p->func = bc_program_func_BC_PROG_MAIN(); + p->func = xc_program_func_BC_PROG_MAIN(); dbg_lex_done("%s:%d done", __func__, __LINE__); RETURN_STATUS(s); @@ -4418,7 +4407,7 @@ static BC_STATUS zbc_parse_auto(void) char *name; dbg_lex_enter("%s:%d entered", __func__, __LINE__); - s = zbc_lex_next(); + s = zxc_lex_next(); if (s) RETURN_STATUS(s); for (;;) { @@ -4428,19 +4417,19 @@ static BC_STATUS zbc_parse_auto(void) RETURN_STATUS(bc_error("bad 'auto' syntax")); name = xstrdup(p->lex_strnumbuf.v); - s = zbc_lex_next(); + s = zxc_lex_next(); if (s) goto err; var = (p->lex != BC_LEX_LBRACKET); if (!var) { - s = zbc_lex_next(); + s = zxc_lex_next(); if (s) goto err; if (p->lex != BC_LEX_RBRACKET) { s = bc_error("bad 'auto' syntax"); goto err; } - s = zbc_lex_next(); + s = zxc_lex_next(); if (s) goto err; } @@ -4455,7 +4444,7 @@ static BC_STATUS zbc_parse_auto(void) } if (p->lex != BC_LEX_COMMA) RETURN_STATUS(bc_error("bad 'auto' syntax")); - s = zbc_lex_next(); // skip comma + s = zxc_lex_next(); // skip comma if (s) RETURN_STATUS(s); } @@ -4478,17 +4467,17 @@ static BC_STATUS zbc_parse_stmt_possibly_auto(bool auto_allowed) if (p->lex == XC_LEX_NLINE) { dbg_lex_done("%s:%d done (seen XC_LEX_NLINE)", __func__, __LINE__); - RETURN_STATUS(zbc_lex_next()); + RETURN_STATUS(zxc_lex_next()); } if (p->lex == BC_LEX_SCOLON) { dbg_lex_done("%s:%d done (seen BC_LEX_SCOLON)", __func__, __LINE__); - RETURN_STATUS(zbc_lex_next()); + RETURN_STATUS(zxc_lex_next()); } if (p->lex == BC_LEX_LBRACE) { dbg_lex("%s:%d BC_LEX_LBRACE: (auto_allowed:%d)", __func__, __LINE__, auto_allowed); do { - s = zbc_lex_next(); + s = zxc_lex_next(); if (s) RETURN_STATUS(s); } while (p->lex == XC_LEX_NLINE); if (auto_allowed && p->lex == BC_LEX_KEY_AUTO) { @@ -4501,7 +4490,7 @@ static BC_STATUS zbc_parse_stmt_possibly_auto(bool auto_allowed) s = zbc_parse_stmt(); if (s) RETURN_STATUS(s); } - s = zbc_lex_next(); + s = zxc_lex_next(); dbg_lex_done("%s:%d done (seen BC_LEX_RBRACE)", __func__, __LINE__); RETURN_STATUS(s); } @@ -4526,7 +4515,7 @@ static BC_STATUS zbc_parse_stmt_possibly_auto(bool auto_allowed) break; case XC_LEX_STR: s = zbc_parse_pushSTR(); - bc_parse_push(XC_INST_PRINT_STR); + xc_parse_push(XC_INST_PRINT_STR); break; case BC_LEX_KEY_BREAK: case BC_LEX_KEY_CONTINUE: @@ -4536,8 +4525,8 @@ static BC_STATUS zbc_parse_stmt_possibly_auto(bool auto_allowed) s = zbc_parse_for(); break; case BC_LEX_KEY_HALT: - bc_parse_push(BC_INST_HALT); - s = zbc_lex_next(); + xc_parse_push(BC_INST_HALT); + s = zxc_lex_next(); break; case BC_LEX_KEY_IF: s = zbc_parse_if(); @@ -4555,7 +4544,7 @@ static BC_STATUS zbc_parse_stmt_possibly_auto(bool auto_allowed) "MAX Exponent = "BC_MAX_EXP_STR "\n" "Number of vars = "BC_MAX_VARS_STR "\n" ); - s = zbc_lex_next(); + s = zxc_lex_next(); break; case BC_LEX_KEY_PRINT: s = zbc_parse_print(); @@ -4686,7 +4675,7 @@ static BcStatus bc_parse_expr_empty_ok(uint8_t flags) nrelops += (t >= XC_LEX_OP_REL_EQ && t <= XC_LEX_OP_REL_GT); prev = BC_TOKEN_2_INST(t); bc_parse_operator(t, ops_bgn, &nexprs); - s = zbc_lex_next(); + s = zxc_lex_next(); rprn = false; //get_token = false; - already is bin_last = (t != BC_LEX_OP_BOOL_NOT); @@ -4732,7 +4721,7 @@ static BcStatus bc_parse_expr_empty_ok(uint8_t flags) dbg_lex("%s:%d LEX_NUMBER", __func__, __LINE__); if (BC_PARSE_LEAF(prev, rprn)) return bc_error_bad_expression(); - bc_parse_pushNUM(); + xc_parse_pushNUM(); prev = XC_INST_NUM; get_token = true; paren_expr = true; @@ -4746,7 +4735,7 @@ static BcStatus bc_parse_expr_empty_ok(uint8_t flags) if (BC_PARSE_LEAF(prev, rprn)) return bc_error_bad_expression(); prev = (char) (t - BC_LEX_KEY_IBASE + XC_INST_IBASE); - bc_parse_push((char) prev); + xc_parse_push((char) prev); get_token = true; paren_expr = true; rprn = bin_last = false; @@ -4792,7 +4781,7 @@ static BcStatus bc_parse_expr_empty_ok(uint8_t flags) if (s || G_interrupt) // error, or ^C: stop parsing return BC_STATUS_FAILURE; if (get_token) { - s = zbc_lex_next(); + s = zxc_lex_next(); if (s) return s; } } @@ -4805,7 +4794,7 @@ static BcStatus bc_parse_expr_empty_ok(uint8_t flags) if (top == BC_LEX_LPAREN || top == BC_LEX_RPAREN) return bc_error_bad_expression(); - bc_parse_push(BC_TOKEN_2_INST(top)); + xc_parse_push(BC_TOKEN_2_INST(top)); nexprs -= (top != BC_LEX_OP_BOOL_NOT && top != XC_LEX_NEG); bc_vec_pop(&p->ops); @@ -4826,8 +4815,8 @@ static BcStatus bc_parse_expr_empty_ok(uint8_t flags) if (flags & BC_PARSE_PRINT) { if (paren_first || !assign) - bc_parse_push(XC_INST_PRINT); - bc_parse_push(XC_INST_POP); + xc_parse_push(XC_INST_PRINT); + xc_parse_push(XC_INST_POP); } dbg_lex_done("%s:%d done", __func__, __LINE__); @@ -4843,11 +4832,11 @@ static BC_STATUS zdc_parse_register(void) BcParse *p = &G.prs; BcStatus s; - s = zbc_lex_next(); + s = zxc_lex_next(); if (s) RETURN_STATUS(s); if (p->lex != XC_LEX_NAME) RETURN_STATUS(bc_error_bad_token()); - bc_parse_pushName(p->lex_strnumbuf.v); + xc_parse_pushName(p->lex_strnumbuf.v); RETURN_STATUS(s); } @@ -4862,13 +4851,13 @@ static void dc_parse_string(void) dbg_lex_enter("%s:%d entered", __func__, __LINE__); str = xstrdup(p->lex_strnumbuf.v); - bc_parse_push(XC_INST_STR); - bc_parse_pushIndex(len); + xc_parse_push(XC_INST_STR); + xc_parse_pushIndex(len); bc_vec_push(&G.prog.strs, &str); // Explanation needed here - bc_program_add_fn(); - p->func = bc_program_func(p->fidx); + xc_program_add_fn(); + p->func = xc_program_func(p->fidx); dbg_lex_done("%s:%d done", __func__, __LINE__); } @@ -4877,16 +4866,16 @@ static BC_STATUS zdc_parse_mem(uint8_t inst, bool name, bool store) { BcStatus s; - bc_parse_push(inst); + xc_parse_push(inst); if (name) { s = zdc_parse_register(); if (s) RETURN_STATUS(s); } if (store) { - bc_parse_push(DC_INST_SWAP); - bc_parse_push(XC_INST_ASSIGN); - bc_parse_push(XC_INST_POP); + xc_parse_push(DC_INST_SWAP); + xc_parse_push(XC_INST_ASSIGN); + xc_parse_push(XC_INST_POP); } RETURN_STATUS(BC_STATUS_SUCCESS); @@ -4898,13 +4887,13 @@ static BC_STATUS zdc_parse_cond(uint8_t inst) BcParse *p = &G.prs; BcStatus s; - bc_parse_push(inst); - bc_parse_push(DC_INST_EXEC_COND); + xc_parse_push(inst); + xc_parse_push(DC_INST_EXEC_COND); s = zdc_parse_register(); if (s) RETURN_STATUS(s); - s = zbc_lex_next(); + s = zxc_lex_next(); if (s) RETURN_STATUS(s); // Note that 'else' part can not be on the next line: @@ -4913,9 +4902,9 @@ static BC_STATUS zdc_parse_cond(uint8_t inst) if (p->lex == DC_LEX_ELSE) { s = zdc_parse_register(); if (s) RETURN_STATUS(s); - s = zbc_lex_next(); + s = zxc_lex_next(); } else { - bc_parse_push('\0'); + xc_parse_push('\0'); } RETURN_STATUS(s); @@ -4953,20 +4942,20 @@ static BC_STATUS zdc_parse_token(BcLexType t) break; case XC_LEX_NEG: dbg_lex("%s:%d LEX_NEG", __func__, __LINE__); - s = zbc_lex_next(); + s = zxc_lex_next(); if (s) RETURN_STATUS(s); if (G.prs.lex != XC_LEX_NUMBER) RETURN_STATUS(bc_error_bad_token()); - bc_parse_pushNUM(); - bc_parse_push(XC_INST_NEG); + xc_parse_pushNUM(); + xc_parse_push(XC_INST_NEG); break; case XC_LEX_NUMBER: dbg_lex("%s:%d LEX_NUMBER", __func__, __LINE__); - bc_parse_pushNUM(); + xc_parse_pushNUM(); break; case DC_LEX_READ: dbg_lex("%s:%d LEX_KEY_READ", __func__, __LINE__); - bc_parse_push(XC_INST_READ); + xc_parse_push(XC_INST_READ); break; case DC_LEX_OP_ASSIGN: case DC_LEX_STORE_PUSH: @@ -4993,7 +4982,7 @@ static BC_STATUS zdc_parse_token(BcLexType t) RETURN_STATUS(bc_error_bad_token()); } - if (!s && get_token) s = zbc_lex_next(); + if (!s && get_token) s = zxc_lex_next(); dbg_lex_done("%s:%d done", __func__, __LINE__); RETURN_STATUS(s); @@ -5009,8 +4998,8 @@ static BC_STATUS zdc_parse_expr(void) if (i >= 0) { BcInst inst = dc_LEX_to_INST[i]; if (inst != DC_INST_INVALID) { - bc_parse_push(inst); - RETURN_STATUS(zbc_lex_next()); + xc_parse_push(inst); + RETURN_STATUS(zxc_lex_next()); } } RETURN_STATUS(zdc_parse_token(p->lex)); @@ -5040,7 +5029,7 @@ static BC_STATUS zdc_parse_exprs_until_eof(void) #define STACK_HAS_MORE_THAN(s, n) ((s)->len > ((size_t)(n))) #define STACK_HAS_EQUAL_OR_MORE_THAN(s, n) ((s)->len >= ((size_t)(n))) -static BcVec* bc_program_search(char *id, bool var) +static BcVec* xc_program_search(char *id, bool var) { BcId e, *ptr; BcVec *v, *map; @@ -5066,7 +5055,7 @@ static BcVec* bc_program_search(char *id, bool var) } // 'num' need not be initialized on entry -static BC_STATUS zbc_program_num(BcResult *r, BcNum **num, bool hex) +static BC_STATUS zxc_program_num(BcResult *r, BcNum **num, bool hex) { switch (r->t) { case XC_RESULT_STR: @@ -5082,14 +5071,14 @@ static BC_STATUS zbc_program_num(BcResult *r, BcNum **num, bool hex) unsigned base_t; size_t len; - str = *bc_program_const(r->d.id.idx); + str = *xc_program_const(r->d.id.idx); len = strlen(str); bc_num_init(&r->d.n, len); hex = hex && len == 1; base_t = hex ? 16 : G.prog.ib_t; - s = zbc_num_parse(&r->d.n, str, base_t); + s = zxc_num_parse(&r->d.n, str, base_t); if (s) { bc_num_free(&r->d.n); RETURN_STATUS(s); @@ -5103,7 +5092,7 @@ static BC_STATUS zbc_program_num(BcResult *r, BcNum **num, bool hex) case XC_RESULT_ARRAY_ELEM: { BcVec *v; - v = bc_program_search(r->d.id.name, r->t == XC_RESULT_VAR); + v = xc_program_search(r->d.id.name, r->t == XC_RESULT_VAR); if (r->t == XC_RESULT_ARRAY_ELEM) { v = bc_vec_top(v); @@ -5130,9 +5119,9 @@ static BC_STATUS zbc_program_num(BcResult *r, BcNum **num, bool hex) RETURN_STATUS(BC_STATUS_SUCCESS); } -#define zbc_program_num(...) (zbc_program_num(__VA_ARGS__) COMMA_SUCCESS) +#define zxc_program_num(...) (zxc_program_num(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zbc_program_binOpPrep(BcResult **l, BcNum **ln, +static BC_STATUS zxc_program_binOpPrep(BcResult **l, BcNum **ln, BcResult **r, BcNum **rn, bool assign) { BcStatus s; @@ -5149,15 +5138,15 @@ static BC_STATUS zbc_program_binOpPrep(BcResult **l, BcNum **ln, rt = (*r)->t; hex = assign && (lt == XC_RESULT_IBASE || lt == XC_RESULT_OBASE); - s = zbc_program_num(*l, ln, false); + s = zxc_program_num(*l, ln, false); if (s) RETURN_STATUS(s); - s = zbc_program_num(*r, rn, hex); + s = zxc_program_num(*r, rn, hex); if (s) RETURN_STATUS(s); // We run this again under these conditions in case any vector has been // reallocated out from under the BcNums or arrays we had. if (lt == rt && (lt == XC_RESULT_VAR || lt == XC_RESULT_ARRAY_ELEM)) { - s = zbc_program_num(*l, ln, false); + s = zxc_program_num(*l, ln, false); if (s) RETURN_STATUS(s); } @@ -5168,9 +5157,9 @@ static BC_STATUS zbc_program_binOpPrep(BcResult **l, BcNum **ln, RETURN_STATUS(s); } -#define zbc_program_binOpPrep(...) (zbc_program_binOpPrep(__VA_ARGS__) COMMA_SUCCESS) +#define zxc_program_binOpPrep(...) (zxc_program_binOpPrep(__VA_ARGS__) COMMA_SUCCESS) -static void bc_program_binOpRetire(BcResult *r) +static void xc_program_binOpRetire(BcResult *r) { r->t = XC_RESULT_TEMP; bc_vec_pop(&G.prog.results); @@ -5178,7 +5167,7 @@ static void bc_program_binOpRetire(BcResult *r) } // Note: *r and *n need not be initialized by caller -static BC_STATUS zbc_program_prep(BcResult **r, BcNum **n) +static BC_STATUS zxc_program_prep(BcResult **r, BcNum **n) { BcStatus s; @@ -5186,7 +5175,7 @@ static BC_STATUS zbc_program_prep(BcResult **r, BcNum **n) RETURN_STATUS(bc_error_stack_has_too_few_elements()); *r = bc_vec_top(&G.prog.results); - s = zbc_program_num(*r, n, false); + s = zxc_program_num(*r, n, false); if (s) RETURN_STATUS(s); if (!BC_PROG_NUM((*r), (*n))) @@ -5194,37 +5183,37 @@ static BC_STATUS zbc_program_prep(BcResult **r, BcNum **n) RETURN_STATUS(s); } -#define zbc_program_prep(...) (zbc_program_prep(__VA_ARGS__) COMMA_SUCCESS) +#define zxc_program_prep(...) (zxc_program_prep(__VA_ARGS__) COMMA_SUCCESS) -static void bc_program_retire(BcResult *r, BcResultType t) +static void xc_program_retire(BcResult *r, BcResultType t) { r->t = t; bc_result_pop_and_push(r); } -static BC_STATUS zbc_program_op(char inst) +static BC_STATUS zxc_program_op(char inst) { BcStatus s; BcResult *opd1, *opd2, res; BcNum *n1, *n2; - s = zbc_program_binOpPrep(&opd1, &n1, &opd2, &n2, false); + s = zxc_program_binOpPrep(&opd1, &n1, &opd2, &n2, false); if (s) RETURN_STATUS(s); bc_num_init_DEF_SIZE(&res.d.n); s = BC_STATUS_SUCCESS; - IF_ERROR_RETURN_POSSIBLE(s =) zbc_program_ops[inst - XC_INST_POWER](n1, n2, &res.d.n, G.prog.scale); + IF_ERROR_RETURN_POSSIBLE(s =) zxc_program_ops[inst - XC_INST_POWER](n1, n2, &res.d.n, G.prog.scale); if (s) goto err; - bc_program_binOpRetire(&res); + xc_program_binOpRetire(&res); RETURN_STATUS(s); err: bc_num_free(&res.d.n); RETURN_STATUS(s); } -#define zbc_program_op(...) (zbc_program_op(__VA_ARGS__) COMMA_SUCCESS) +#define zxc_program_op(...) (zxc_program_op(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zbc_program_read(void) +static BC_STATUS zxc_program_read(void) { BcStatus s; BcParse sv_parse; @@ -5233,16 +5222,16 @@ static BC_STATUS zbc_program_read(void) BcFunc *f; bc_char_vec_init(&buf); - bc_read_line(&buf, stdin); + xc_read_line(&buf, stdin); - f = bc_program_func(BC_PROG_READ); + f = xc_program_func(BC_PROG_READ); bc_vec_pop_all(&f->code); sv_parse = G.prs; // struct copy - bc_parse_create(BC_PROG_READ); + xc_parse_create(BC_PROG_READ); //G.err_line = G.prs.lex_line = 1; - not needed, error line info is not printed for read() - s = zbc_parse_text_init(buf.v); + s = zxc_parse_text_init(buf.v); if (s) goto exec_err; if (IS_BC) { IF_BC(s = zbc_parse_expr(0)); @@ -5260,18 +5249,18 @@ static BC_STATUS zbc_program_read(void) ip.inst_idx = 0; IF_BC(ip.results_len_before_call = G.prog.results.len;) - bc_parse_push(XC_INST_RET); + xc_parse_push(XC_INST_RET); bc_vec_push(&G.prog.exestack, &ip); exec_err: - bc_parse_free(); + xc_parse_free(); G.prs = sv_parse; // struct copy bc_vec_free(&buf); RETURN_STATUS(s); } -#define zbc_program_read(...) (zbc_program_read(__VA_ARGS__) COMMA_SUCCESS) +#define zxc_program_read(...) (zxc_program_read(__VA_ARGS__) COMMA_SUCCESS) -static size_t bc_program_index(char *code, size_t *bgn) +static size_t xc_program_index(char *code, size_t *bgn) { unsigned char *bytes = (void*)(code + *bgn); unsigned amt; @@ -5294,7 +5283,7 @@ static size_t bc_program_index(char *code, size_t *bgn) return res; } -static char *bc_program_name(char *code, size_t *bgn) +static char *xc_program_name(char *code, size_t *bgn) { code += *bgn; *bgn += strlen(code) + 1; @@ -5302,7 +5291,7 @@ static char *bc_program_name(char *code, size_t *bgn) return xstrdup(code); } -static void bc_program_printString(const char *str) +static void xc_program_printString(const char *str) { #if ENABLE_DC if (!str[0]) { @@ -5424,7 +5413,7 @@ static void bc_num_printDecimal(BcNum *n) typedef void (*BcNumDigitOp)(size_t, size_t, bool) FAST_FUNC; -static BC_STATUS zbc_num_printNum(BcNum *n, unsigned base_t, size_t width, BcNumDigitOp print) +static BC_STATUS zxc_num_printNum(BcNum *n, unsigned base_t, size_t width, BcNumDigitOp print) { BcStatus s; BcVec stack; @@ -5490,9 +5479,9 @@ static BC_STATUS zbc_num_printNum(BcNum *n, unsigned base_t, size_t width, BcNum bc_vec_free(&stack); RETURN_STATUS(s); } -#define zbc_num_printNum(...) (zbc_num_printNum(__VA_ARGS__) COMMA_SUCCESS) +#define zxc_num_printNum(...) (zxc_num_printNum(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zbc_num_printBase(BcNum *n) +static BC_STATUS zxc_num_printBase(BcNum *n) { BcStatus s; size_t width; @@ -5521,14 +5510,14 @@ static BC_STATUS zbc_num_printBase(BcNum *n) print = bc_num_printDigits; } - s = zbc_num_printNum(n, G.prog.ob_t, width, print); + s = zxc_num_printNum(n, G.prog.ob_t, width, print); n->neg = neg; RETURN_STATUS(s); } -#define zbc_num_printBase(...) (zbc_num_printBase(__VA_ARGS__) COMMA_SUCCESS) +#define zxc_num_printBase(...) (zxc_num_printBase(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zbc_num_print(BcNum *n, bool newline) +static BC_STATUS zxc_num_print(BcNum *n, bool newline) { BcStatus s = BC_STATUS_SUCCESS; @@ -5540,7 +5529,7 @@ static BC_STATUS zbc_num_print(BcNum *n, bool newline) } else if (G.prog.ob_t == 10) bc_num_printDecimal(n); else - s = zbc_num_printBase(n); + s = zxc_num_printBase(n); if (newline) { bb_putchar('\n'); @@ -5549,9 +5538,9 @@ static BC_STATUS zbc_num_print(BcNum *n, bool newline) RETURN_STATUS(s); } -#define zbc_num_print(...) (zbc_num_print(__VA_ARGS__) COMMA_SUCCESS) +#define zxc_num_print(...) (zxc_num_print(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zbc_program_print(char inst, size_t idx) +static BC_STATUS zxc_program_print(char inst, size_t idx) { BcStatus s; BcResult *r; @@ -5562,11 +5551,11 @@ static BC_STATUS zbc_program_print(char inst, size_t idx) RETURN_STATUS(bc_error_stack_has_too_few_elements()); r = bc_vec_item_rev(&G.prog.results, idx); - s = zbc_program_num(r, &num, false); + s = zxc_program_num(r, &num, false); if (s) RETURN_STATUS(s); if (BC_PROG_NUM(r, num)) { - s = zbc_num_print(num, !pop); + s = zxc_num_print(num, !pop); #if ENABLE_BC if (!s && IS_BC) bc_num_copy(&G.prog.last, num); #endif @@ -5574,7 +5563,7 @@ static BC_STATUS zbc_program_print(char inst, size_t idx) char *str; idx = (r->t == XC_RESULT_STR) ? r->d.id.idx : num->rdx; - str = *bc_program_str(idx); + str = *xc_program_str(idx); if (inst == XC_INST_PRINT_STR) { for (;;) { @@ -5585,7 +5574,7 @@ static BC_STATUS zbc_program_print(char inst, size_t idx) if (c == '\n') G.prog.nchars = 0; } } else { - bc_program_printString(str); + xc_program_printString(str); if (inst == XC_INST_PRINT) bb_putchar('\n'); } } @@ -5594,35 +5583,35 @@ static BC_STATUS zbc_program_print(char inst, size_t idx) RETURN_STATUS(s); } -#define zbc_program_print(...) (zbc_program_print(__VA_ARGS__) COMMA_SUCCESS) +#define zxc_program_print(...) (zxc_program_print(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zbc_program_negate(void) +static BC_STATUS zxc_program_negate(void) { BcStatus s; BcResult res, *ptr; BcNum *num; - s = zbc_program_prep(&ptr, &num); + s = zxc_program_prep(&ptr, &num); if (s) RETURN_STATUS(s); bc_num_init(&res.d.n, num->len); bc_num_copy(&res.d.n, num); if (res.d.n.len) res.d.n.neg = !res.d.n.neg; - bc_program_retire(&res, XC_RESULT_TEMP); + xc_program_retire(&res, XC_RESULT_TEMP); RETURN_STATUS(s); } -#define zbc_program_negate(...) (zbc_program_negate(__VA_ARGS__) COMMA_SUCCESS) +#define zxc_program_negate(...) (zxc_program_negate(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zbc_program_logical(char inst) +static BC_STATUS zxc_program_logical(char inst) { BcStatus s; BcResult *opd1, *opd2, res; BcNum *n1, *n2; ssize_t cond; - s = zbc_program_binOpPrep(&opd1, &n1, &opd2, &n2, false); + s = zxc_program_binOpPrep(&opd1, &n1, &opd2, &n2, false); if (s) RETURN_STATUS(s); bc_num_init_DEF_SIZE(&res.d.n); @@ -5658,11 +5647,11 @@ static BC_STATUS zbc_program_logical(char inst) if (cond) bc_num_one(&res.d.n); //else bc_num_zero(&res.d.n); - already is - bc_program_binOpRetire(&res); + xc_program_binOpRetire(&res); RETURN_STATUS(s); } -#define zbc_program_logical(...) (zbc_program_logical(__VA_ARGS__) COMMA_SUCCESS) +#define zxc_program_logical(...) (zxc_program_logical(__VA_ARGS__) COMMA_SUCCESS) #if ENABLE_DC static BC_STATUS zdc_program_assignStr(BcResult *r, BcVec *v, bool push) @@ -5689,7 +5678,7 @@ static BC_STATUS zdc_program_assignStr(BcResult *r, BcVec *v, bool push) #define zdc_program_assignStr(...) (zdc_program_assignStr(__VA_ARGS__) COMMA_SUCCESS) #endif // ENABLE_DC -static BC_STATUS zbc_program_copyToVar(char *name, bool var) +static BC_STATUS zxc_program_copyToVar(char *name, bool var) { BcStatus s; BcResult *ptr, r; @@ -5702,7 +5691,7 @@ static BC_STATUS zbc_program_copyToVar(char *name, bool var) ptr = bc_vec_top(&G.prog.results); if ((ptr->t == XC_RESULT_ARRAY) != !var) RETURN_STATUS(bc_error_variable_is_wrong_type()); - v = bc_program_search(name, var); + v = xc_program_search(name, var); #if ENABLE_DC if (ptr->t == XC_RESULT_STR && !var) @@ -5711,11 +5700,11 @@ static BC_STATUS zbc_program_copyToVar(char *name, bool var) RETURN_STATUS(zdc_program_assignStr(ptr, v, true)); #endif - s = zbc_program_num(ptr, &n, false); + s = zxc_program_num(ptr, &n, false); if (s) RETURN_STATUS(s); // Do this once more to make sure that pointers were not invalidated. - v = bc_program_search(name, var); + v = xc_program_search(name, var); if (var) { bc_num_init_DEF_SIZE(&r.d.n); @@ -5730,9 +5719,9 @@ static BC_STATUS zbc_program_copyToVar(char *name, bool var) RETURN_STATUS(s); } -#define zbc_program_copyToVar(...) (zbc_program_copyToVar(__VA_ARGS__) COMMA_SUCCESS) +#define zxc_program_copyToVar(...) (zxc_program_copyToVar(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zbc_program_assign(char inst) +static BC_STATUS zxc_program_assign(char inst) { BcStatus s; BcResult *left, *right, res; @@ -5740,7 +5729,7 @@ static BC_STATUS zbc_program_assign(char inst) bool assign = (inst == XC_INST_ASSIGN); bool ib, sc; - s = zbc_program_binOpPrep(&left, &l, &right, &r, assign); + s = zxc_program_binOpPrep(&left, &l, &right, &r, assign); if (s) RETURN_STATUS(s); ib = left->t == XC_RESULT_IBASE; @@ -5752,7 +5741,7 @@ static BC_STATUS zbc_program_assign(char inst) if (left->t != XC_RESULT_VAR) RETURN_STATUS(bc_error_variable_is_wrong_type()); - v = bc_program_search(left->d.id.name, true); + v = xc_program_search(left->d.id.name, true); RETURN_STATUS(zdc_program_assignStr(right, v, false)); } @@ -5772,7 +5761,7 @@ static BC_STATUS zbc_program_assign(char inst) bc_num_copy(l, r); else { s = BC_STATUS_SUCCESS; - IF_ERROR_RETURN_POSSIBLE(s =) zbc_program_ops[inst - BC_INST_ASSIGN_POWER](l, r, l, G.prog.scale); + IF_ERROR_RETURN_POSSIBLE(s =) zxc_program_ops[inst - BC_INST_ASSIGN_POWER](l, r, l, G.prog.scale); } if (s) RETURN_STATUS(s); #else @@ -5811,29 +5800,29 @@ static BC_STATUS zbc_program_assign(char inst) bc_num_init(&res.d.n, l->len); bc_num_copy(&res.d.n, l); - bc_program_binOpRetire(&res); + xc_program_binOpRetire(&res); RETURN_STATUS(s); } -#define zbc_program_assign(...) (zbc_program_assign(__VA_ARGS__) COMMA_SUCCESS) +#define zxc_program_assign(...) (zxc_program_assign(__VA_ARGS__) COMMA_SUCCESS) #if !ENABLE_DC -#define bc_program_pushVar(code, bgn, pop, copy) \ - bc_program_pushVar(code, bgn) +#define xc_program_pushVar(code, bgn, pop, copy) \ + xc_program_pushVar(code, bgn) // for bc, 'pop' and 'copy' are always false #endif -static BC_STATUS bc_program_pushVar(char *code, size_t *bgn, +static BC_STATUS xc_program_pushVar(char *code, size_t *bgn, bool pop, bool copy) { BcResult r; - char *name = bc_program_name(code, bgn); + char *name = xc_program_name(code, bgn); r.t = XC_RESULT_VAR; r.d.id.name = name; #if ENABLE_DC if (pop || copy) { - BcVec *v = bc_program_search(name, true); + BcVec *v = xc_program_search(name, true); BcNum *num = bc_vec_top(v); free(name); @@ -5858,7 +5847,7 @@ static BC_STATUS bc_program_pushVar(char *code, size_t *bgn, RETURN_STATUS(BC_STATUS_SUCCESS); } -#define zbc_program_pushVar(...) (bc_program_pushVar(__VA_ARGS__) COMMA_SUCCESS) +#define zxc_program_pushVar(...) (xc_program_pushVar(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_program_pushArray(char *code, size_t *bgn, char inst) { @@ -5866,7 +5855,7 @@ static BC_STATUS zbc_program_pushArray(char *code, size_t *bgn, char inst) BcResult r; BcNum *num; - r.d.id.name = bc_program_name(code, bgn); + r.d.id.name = xc_program_name(code, bgn); if (inst == XC_INST_ARRAY) { r.t = XC_RESULT_ARRAY; @@ -5875,7 +5864,7 @@ static BC_STATUS zbc_program_pushArray(char *code, size_t *bgn, char inst) BcResult *operand; unsigned long temp; - s = zbc_program_prep(&operand, &num); + s = zxc_program_prep(&operand, &num); if (s) goto err; s = zbc_num_ulong(num, &temp); if (s) goto err; @@ -5886,7 +5875,7 @@ static BC_STATUS zbc_program_pushArray(char *code, size_t *bgn, char inst) } r.d.id.idx = (size_t) temp; - bc_program_retire(&r, XC_RESULT_ARRAY_ELEM); + xc_program_retire(&r, XC_RESULT_ARRAY_ELEM); } err: if (s) free(r.d.id.name); @@ -5902,7 +5891,7 @@ static BC_STATUS zbc_program_incdec(char inst) BcNum *num; char inst2 = inst; - s = zbc_program_prep(&ptr, &num); + s = zxc_program_prep(&ptr, &num); if (s) RETURN_STATUS(s); if (inst == BC_INST_INC_POST || inst == BC_INST_DEC_POST) { @@ -5917,7 +5906,7 @@ static BC_STATUS zbc_program_incdec(char inst) : BC_INST_ASSIGN_MINUS; bc_vec_push(&G.prog.results, &res); - s = zbc_program_assign(inst); + s = zxc_program_assign(inst); if (s) RETURN_STATUS(s); if (inst2 == BC_INST_INC_POST || inst2 == BC_INST_DEC_POST) { @@ -5936,10 +5925,10 @@ static BC_STATUS zbc_program_call(char *code, size_t *idx) BcId *a; BcResult *arg; - nparams = bc_program_index(code, idx); + nparams = xc_program_index(code, idx); ip.inst_idx = 0; - ip.func = bc_program_index(code, idx); - func = bc_program_func(ip.func); + ip.func = xc_program_index(code, idx); + func = xc_program_func(ip.func); if (func->code.len == 0) { RETURN_STATUS(bc_error("undefined function")); @@ -5958,7 +5947,7 @@ static BC_STATUS zbc_program_call(char *code, size_t *idx) if ((!a->idx) != (arg->t == XC_RESULT_ARRAY) || arg->t == XC_RESULT_STR) RETURN_STATUS(bc_error_variable_is_wrong_type()); - s = zbc_program_copyToVar(a->name, a->idx); + s = zxc_program_copyToVar(a->name, a->idx); if (s) RETURN_STATUS(s); } @@ -5966,7 +5955,7 @@ static BC_STATUS zbc_program_call(char *code, size_t *idx) for (; i < func->autos.len; i++, a++) { BcVec *v; - v = bc_program_search(a->name, a->idx); + v = xc_program_search(a->name, a->idx); if (a->idx) { BcNum n2; bc_num_init_DEF_SIZE(&n2); @@ -5995,7 +5984,7 @@ static BC_STATUS zbc_program_return(char inst) if (!STACK_HAS_EQUAL_OR_MORE_THAN(&G.prog.results, ip->results_len_before_call + (inst == XC_INST_RET))) RETURN_STATUS(bc_error_stack_has_too_few_elements()); - f = bc_program_func(ip->func); + f = xc_program_func(ip->func); res.t = XC_RESULT_TEMP; if (inst == XC_INST_RET) { @@ -6003,7 +5992,7 @@ static BC_STATUS zbc_program_return(char inst) BcNum *num; BcResult *operand = bc_vec_top(&G.prog.results); - s = zbc_program_num(operand, &num, false); + s = zxc_program_num(operand, &num, false); if (s) RETURN_STATUS(s); bc_num_init(&res.d.n, num->len); bc_num_copy(&res.d.n, num); @@ -6016,7 +6005,7 @@ static BC_STATUS zbc_program_return(char inst) a = (void*)f->autos.v; for (i = 0; i < f->autos.len; i++, a++) { BcVec *v; - v = bc_program_search(a->name, a->idx); + v = xc_program_search(a->name, a->idx); bc_vec_pop(v); } @@ -6029,12 +6018,12 @@ static BC_STATUS zbc_program_return(char inst) #define zbc_program_return(...) (zbc_program_return(__VA_ARGS__) COMMA_SUCCESS) #endif // ENABLE_BC -static unsigned long bc_program_scale(BcNum *n) +static unsigned long xc_program_scale(BcNum *n) { return (unsigned long) n->rdx; } -static unsigned long bc_program_len(BcNum *n) +static unsigned long xc_program_len(BcNum *n) { size_t len = n->len; @@ -6047,7 +6036,7 @@ static unsigned long bc_program_len(BcNum *n) return len; } -static BC_STATUS zbc_program_builtin(char inst) +static BC_STATUS zxc_program_builtin(char inst) { BcStatus s; BcResult *opnd; @@ -6059,7 +6048,7 @@ static BC_STATUS zbc_program_builtin(char inst) RETURN_STATUS(bc_error_stack_has_too_few_elements()); opnd = bc_vec_top(&G.prog.results); - s = zbc_program_num(opnd, &num, false); + s = zxc_program_num(opnd, &num, false); if (s) RETURN_STATUS(s); #if ENABLE_DC @@ -6081,19 +6070,19 @@ static BC_STATUS zbc_program_builtin(char inst) char **str; size_t idx = opnd->t == XC_RESULT_STR ? opnd->d.id.idx : num->rdx; - str = bc_program_str(idx); + str = xc_program_str(idx); bc_num_ulong2num(&res.d.n, strlen(*str)); } #endif else { - bc_num_ulong2num(&res.d.n, len ? bc_program_len(num) : bc_program_scale(num)); + bc_num_ulong2num(&res.d.n, len ? xc_program_len(num) : xc_program_scale(num)); } - bc_program_retire(&res, XC_RESULT_TEMP); + xc_program_retire(&res, XC_RESULT_TEMP); RETURN_STATUS(s); } -#define zbc_program_builtin(...) (zbc_program_builtin(__VA_ARGS__) COMMA_SUCCESS) +#define zxc_program_builtin(...) (zxc_program_builtin(__VA_ARGS__) COMMA_SUCCESS) #if ENABLE_DC static BC_STATUS zdc_program_divmod(void) @@ -6102,7 +6091,7 @@ static BC_STATUS zdc_program_divmod(void) BcResult *opd1, *opd2, res, res2; BcNum *n1, *n2; - s = zbc_program_binOpPrep(&opd1, &n1, &opd2, &n2, false); + s = zxc_program_binOpPrep(&opd1, &n1, &opd2, &n2, false); if (s) RETURN_STATUS(s); bc_num_init_DEF_SIZE(&res.d.n); @@ -6111,7 +6100,7 @@ static BC_STATUS zdc_program_divmod(void) s = zbc_num_divmod(n1, n2, &res2.d.n, &res.d.n, G.prog.scale); if (s) goto err; - bc_program_binOpRetire(&res2); + xc_program_binOpRetire(&res2); res.t = XC_RESULT_TEMP; bc_vec_push(&G.prog.results, &res); @@ -6131,11 +6120,11 @@ static BC_STATUS zdc_program_modexp(void) if (!STACK_HAS_MORE_THAN(&G.prog.results, 2)) RETURN_STATUS(bc_error_stack_has_too_few_elements()); - s = zbc_program_binOpPrep(&r2, &n2, &r3, &n3, false); + s = zxc_program_binOpPrep(&r2, &n2, &r3, &n3, false); if (s) RETURN_STATUS(s); r1 = bc_vec_item_rev(&G.prog.results, 2); - s = zbc_program_num(r1, &n1, false); + s = zxc_program_num(r1, &n1, false); if (s) RETURN_STATUS(s); if (!BC_PROG_NUM(r1, n1)) RETURN_STATUS(bc_error_variable_is_wrong_type()); @@ -6143,11 +6132,11 @@ static BC_STATUS zdc_program_modexp(void) // Make sure that the values have their pointers updated, if necessary. if (r1->t == XC_RESULT_VAR || r1->t == XC_RESULT_ARRAY_ELEM) { if (r1->t == r2->t) { - s = zbc_program_num(r2, &n2, false); + s = zxc_program_num(r2, &n2, false); if (s) RETURN_STATUS(s); } if (r1->t == r3->t) { - s = zbc_program_num(r3, &n3, false); + s = zxc_program_num(r3, &n3, false); if (s) RETURN_STATUS(s); } } @@ -6157,7 +6146,7 @@ static BC_STATUS zdc_program_modexp(void) if (s) goto err; bc_vec_pop(&G.prog.results); - bc_program_binOpRetire(&res); + xc_program_binOpRetire(&res); RETURN_STATUS(s); err: @@ -6192,7 +6181,7 @@ static BC_STATUS zdc_program_asciify(void) RETURN_STATUS(bc_error_stack_has_too_few_elements()); r = bc_vec_top(&G.prog.results); - s = zbc_program_num(r, &num, false); + s = zxc_program_num(r, &num, false); if (s) RETURN_STATUS(s); if (BC_PROG_NUM(r, num)) { @@ -6219,7 +6208,7 @@ static BC_STATUS zdc_program_asciify(void) } else { char *sp; idx = (r->t == XC_RESULT_STR) ? r->d.id.idx : num->rdx; - sp = *bc_program_str(idx); + sp = *xc_program_str(idx); c = sp[0]; } @@ -6256,15 +6245,15 @@ static BC_STATUS zdc_program_printStream(void) RETURN_STATUS(bc_error_stack_has_too_few_elements()); r = bc_vec_top(&G.prog.results); - s = zbc_program_num(r, &n, false); + s = zxc_program_num(r, &n, false); if (s) RETURN_STATUS(s); if (BC_PROG_NUM(r, n)) { - s = zbc_num_printNum(n, 0x100, 1, dc_num_printChar); + s = zxc_num_printNum(n, 0x100, 1, dc_num_printChar); } else { char *str; idx = (r->t == XC_RESULT_STR) ? r->d.id.idx : n->rdx; - str = *bc_program_str(idx); + str = *xc_program_str(idx); fputs(str, stdout); } @@ -6279,7 +6268,7 @@ static BC_STATUS zdc_program_nquit(void) BcNum *num; unsigned long val; - s = zbc_program_prep(&opnd, &num); + s = zxc_program_prep(&opnd, &num); if (s) RETURN_STATUS(s); s = zbc_num_ulong(num, &val); if (s) RETURN_STATUS(s); @@ -6315,13 +6304,13 @@ static BC_STATUS zdc_program_execStr(char *code, size_t *bgn, bool cond) BcNum *n = n; // for compiler bool exec; char *name; - char *then_name = bc_program_name(code, bgn); + char *then_name = xc_program_name(code, bgn); char *else_name = NULL; if (code[*bgn] == '\0') (*bgn) += 1; else - else_name = bc_program_name(code, bgn); + else_name = xc_program_name(code, bgn); exec = r->d.n.len != 0; name = then_name; @@ -6332,7 +6321,7 @@ static BC_STATUS zdc_program_execStr(char *code, size_t *bgn, bool cond) if (exec) { BcVec *v; - v = bc_program_search(name, true); + v = xc_program_search(name, true); n = bc_vec_top(v); } @@ -6351,7 +6340,7 @@ static BC_STATUS zdc_program_execStr(char *code, size_t *bgn, bool cond) sidx = r->d.id.idx; } else if (r->t == XC_RESULT_VAR) { BcNum *n; - s = zbc_program_num(r, &n, false); + s = zxc_program_num(r, &n, false); if (s || !BC_PROG_STR(n)) goto exit; sidx = n->rdx; } else @@ -6360,24 +6349,24 @@ static BC_STATUS zdc_program_execStr(char *code, size_t *bgn, bool cond) fidx = sidx + BC_PROG_REQ_FUNCS; - f = bc_program_func(fidx); + f = xc_program_func(fidx); if (f->code.len == 0) { BcParse sv_parse; char *str; sv_parse = G.prs; // struct copy - bc_parse_create(fidx); - str = *bc_program_str(sidx); - s = zbc_parse_text_init(str); + xc_parse_create(fidx); + str = *xc_program_str(sidx); + s = zxc_parse_text_init(str); if (s) goto err; s = zdc_parse_exprs_until_eof(); if (s) goto err; - bc_parse_push(DC_INST_POP_EXEC); + xc_parse_push(DC_INST_POP_EXEC); if (G.prs.lex != XC_LEX_EOF) s = bc_error_bad_expression(); - bc_parse_free(); + xc_parse_free(); G.prs = sv_parse; // struct copy if (s) { err: @@ -6400,7 +6389,7 @@ static BC_STATUS zdc_program_execStr(char *code, size_t *bgn, bool cond) #define zdc_program_execStr(...) (zdc_program_execStr(__VA_ARGS__) COMMA_SUCCESS) #endif // ENABLE_DC -static void bc_program_pushGlobal(char inst) +static void xc_program_pushGlobal(char inst) { BcResult res; unsigned long val; @@ -6418,11 +6407,11 @@ static void bc_program_pushGlobal(char inst) bc_vec_push(&G.prog.results, &res); } -static BC_STATUS zbc_program_exec(void) +static BC_STATUS zxc_program_exec(void) { BcResult r, *ptr; BcInstPtr *ip = bc_vec_top(&G.prog.exestack); - BcFunc *func = bc_program_func(ip->func); + BcFunc *func = xc_program_func(ip->func); char *code = func->code.v; dbg_exec("func:%zd bytes:%zd ip:%zd results.len:%d", @@ -6438,18 +6427,18 @@ static BC_STATUS zbc_program_exec(void) BcNum *num; bool zero; dbg_exec("BC_INST_JUMP_ZERO:"); - s = zbc_program_prep(&ptr, &num); + s = zxc_program_prep(&ptr, &num); if (s) RETURN_STATUS(s); zero = (bc_num_cmp(num, &G.prog.zero) == 0); bc_vec_pop(&G.prog.results); if (!zero) { - bc_program_index(code, &ip->inst_idx); + xc_program_index(code, &ip->inst_idx); break; } // else: fall through } case BC_INST_JUMP: { - size_t idx = bc_program_index(code, &ip->inst_idx); + size_t idx = xc_program_index(code, &ip->inst_idx); size_t *addr = bc_vec_item(&func->labels, idx); dbg_exec("BC_INST_JUMP: to %ld", (long)*addr); ip->inst_idx = *addr; @@ -6485,15 +6474,15 @@ static BC_STATUS zbc_program_exec(void) case XC_INST_REL_LT: case XC_INST_REL_GT: dbg_exec("BC_INST_BOOL:"); - s = zbc_program_logical(inst); + s = zxc_program_logical(inst); break; case XC_INST_READ: dbg_exec("XC_INST_READ:"); - s = zbc_program_read(); + s = zxc_program_read(); goto read_updated_ip; case XC_INST_VAR: dbg_exec("XC_INST_VAR:"); - s = zbc_program_pushVar(code, &ip->inst_idx, false, false); + s = zxc_program_pushVar(code, &ip->inst_idx, false, false); break; case XC_INST_ARRAY_ELEM: case XC_INST_ARRAY: @@ -6511,18 +6500,18 @@ static BC_STATUS zbc_program_exec(void) case XC_INST_OBASE: case XC_INST_SCALE: dbg_exec("XC_INST_internalvar(%d):", inst - XC_INST_IBASE); - bc_program_pushGlobal(inst); + xc_program_pushGlobal(inst); break; case XC_INST_SCALE_FUNC: case XC_INST_LENGTH: case XC_INST_SQRT: dbg_exec("BC_INST_builtin:"); - s = zbc_program_builtin(inst); + s = zxc_program_builtin(inst); break; case XC_INST_NUM: dbg_exec("XC_INST_NUM:"); r.t = XC_RESULT_CONSTANT; - r.d.id.idx = bc_program_index(code, &ip->inst_idx); + r.d.id.idx = xc_program_index(code, &ip->inst_idx); bc_vec_push(&G.prog.results, &r); break; case XC_INST_POP: @@ -6536,12 +6525,12 @@ static BC_STATUS zbc_program_exec(void) case XC_INST_PRINT_POP: case XC_INST_PRINT_STR: dbg_exec("XC_INST_PRINTxyz:"); - s = zbc_program_print(inst, 0); + s = zxc_program_print(inst, 0); break; case XC_INST_STR: dbg_exec("XC_INST_STR:"); r.t = XC_RESULT_STR; - r.d.id.idx = bc_program_index(code, &ip->inst_idx); + r.d.id.idx = xc_program_index(code, &ip->inst_idx); bc_vec_push(&G.prog.results, &r); break; case XC_INST_POWER: @@ -6551,23 +6540,23 @@ static BC_STATUS zbc_program_exec(void) case XC_INST_PLUS: case XC_INST_MINUS: dbg_exec("BC_INST_binaryop:"); - s = zbc_program_op(inst); + s = zxc_program_op(inst); break; case XC_INST_BOOL_NOT: { BcNum *num; dbg_exec("XC_INST_BOOL_NOT:"); - s = zbc_program_prep(&ptr, &num); + s = zxc_program_prep(&ptr, &num); if (s) RETURN_STATUS(s); bc_num_init_DEF_SIZE(&r.d.n); if (bc_num_cmp(num, &G.prog.zero) == 0) bc_num_one(&r.d.n); //else bc_num_zero(&r.d.n); - already is - bc_program_retire(&r, XC_RESULT_TEMP); + xc_program_retire(&r, XC_RESULT_TEMP); break; } case XC_INST_NEG: dbg_exec("XC_INST_NEG:"); - s = zbc_program_negate(); + s = zxc_program_negate(); break; #if ENABLE_BC case BC_INST_ASSIGN_POWER: @@ -6579,7 +6568,7 @@ static BC_STATUS zbc_program_exec(void) #endif case XC_INST_ASSIGN: dbg_exec("BC_INST_ASSIGNxyz:"); - s = zbc_program_assign(inst); + s = zxc_program_assign(inst); break; #if ENABLE_DC case DC_INST_POP_EXEC: @@ -6603,7 +6592,7 @@ static BC_STATUS zbc_program_exec(void) size_t idx; dbg_exec("DC_INST_PRINT_STACK:"); for (idx = 0; idx < G.prog.results.len; ++idx) { - s = zbc_program_print(XC_INST_PRINT, idx); + s = zxc_program_print(XC_INST_PRINT, idx); if (s) break; } break; @@ -6647,12 +6636,12 @@ static BC_STATUS zbc_program_exec(void) case DC_INST_LOAD: case DC_INST_PUSH_VAR: { bool copy = inst == DC_INST_LOAD; - s = zbc_program_pushVar(code, &ip->inst_idx, true, copy); + s = zxc_program_pushVar(code, &ip->inst_idx, true, copy); break; } case DC_INST_PUSH_TO_VAR: { - char *name = bc_program_name(code, &ip->inst_idx); - s = zbc_program_copyToVar(name, true); + char *name = xc_program_name(code, &ip->inst_idx); + s = zxc_program_copyToVar(name, true); free(name); break; } @@ -6670,13 +6659,13 @@ static BC_STATUS zbc_program_exec(void) read_updated_ip: // Instruction stack has changed, read new pointers ip = bc_vec_top(&G.prog.exestack); - func = bc_program_func(ip->func); + func = xc_program_func(ip->func); code = func->code.v; dbg_exec("func:%zd bytes:%zd ip:%zd", ip->func, func->code.len, ip->inst_idx); } if (s || G_interrupt) { - bc_program_reset(); + xc_program_reset(); RETURN_STATUS(s); } @@ -6685,9 +6674,9 @@ static BC_STATUS zbc_program_exec(void) RETURN_STATUS(BC_STATUS_SUCCESS); } -#define zbc_program_exec(...) (zbc_program_exec(__VA_ARGS__) COMMA_SUCCESS) +#define zxc_program_exec(...) (zxc_program_exec(__VA_ARGS__) COMMA_SUCCESS) -static unsigned bc_vm_envLen(const char *var) +static unsigned xc_vm_envLen(const char *var) { char *lenv; unsigned len; @@ -6703,12 +6692,12 @@ static unsigned bc_vm_envLen(const char *var) return len; } -static BC_STATUS zbc_vm_process(const char *text) +static BC_STATUS zxc_vm_process(const char *text) { BcStatus s; dbg_lex_enter("%s:%d entered", __func__, __LINE__); - s = zbc_parse_text_init(text); // does the first zbc_lex_next() + s = zxc_parse_text_init(text); // does the first zxc_lex_next() if (s) RETURN_STATUS(s); IF_BC(check_eof:) @@ -6722,7 +6711,7 @@ static BC_STATUS zbc_vm_process(const char *text) if (G.prs.lex == BC_LEX_SCOLON || G.prs.lex == XC_LEX_NLINE ) { - s = zbc_lex_next(); + s = zxc_lex_next(); if (s) goto err; goto check_eof; } @@ -6746,14 +6735,14 @@ static BC_STATUS zbc_vm_process(const char *text) goto err; } // The above logic is fragile. Check these examples: - // - interative read() still works + // - interactive read() still works #endif } else { #if ENABLE_DC // Most of dc parsing assumes all whitespace, // including '\n', is eaten. while (G.prs.lex == XC_LEX_NLINE) { - s = zbc_lex_next(); + s = zxc_lex_next(); if (s) goto err; if (G.prs.lex == XC_LEX_EOF) goto done; @@ -6763,14 +6752,14 @@ static BC_STATUS zbc_vm_process(const char *text) } if (s || G_interrupt) { err: - bc_parse_reset(); // includes bc_program_reset() + xc_parse_reset(); // includes xc_program_reset() RETURN_STATUS(BC_STATUS_FAILURE); } dbg_lex("%s:%d executing...", __func__, __LINE__); - s = zbc_program_exec(); + s = zxc_program_exec(); if (s) { - bc_program_reset(); + xc_program_reset(); break; } @@ -6781,7 +6770,7 @@ static BC_STATUS zbc_vm_process(const char *text) if (ip->func != BC_PROG_MAIN) bb_error_msg_and_die("BUG:not MAIN"); #endif - f = bc_program_func_BC_PROG_MAIN(); + f = xc_program_func_BC_PROG_MAIN(); // bc discards strings, constants and code after each // top-level statement in the "main program". // This prevents "yes 1 | bc" from growing its memory @@ -6824,9 +6813,9 @@ static BC_STATUS zbc_vm_process(const char *text) dbg_lex_done("%s:%d done", __func__, __LINE__); RETURN_STATUS(s); } -#define zbc_vm_process(...) (zbc_vm_process(__VA_ARGS__) COMMA_SUCCESS) +#define zxc_vm_process(...) (zxc_vm_process(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zbc_vm_execute_FILE(FILE *fp, const char *filename) +static BC_STATUS zxc_vm_execute_FILE(FILE *fp, const char *filename) { // So far bc/dc have no way to include a file from another file, // therefore we know G.prs.lex_filename == NULL on entry @@ -6838,7 +6827,7 @@ static BC_STATUS zbc_vm_execute_FILE(FILE *fp, const char *filename) G.err_line = G.prs.lex_line = 1; do { - s = zbc_vm_process(""); + s = zxc_vm_process(""); // We do not stop looping on errors here if reading stdin. // Example: start interactive bc and enter "return". // It should say "'return' not in a function" @@ -6847,20 +6836,20 @@ static BC_STATUS zbc_vm_execute_FILE(FILE *fp, const char *filename) G.prs.lex_filename = NULL; RETURN_STATUS(s); } -#define zbc_vm_execute_FILE(...) (zbc_vm_execute_FILE(__VA_ARGS__) COMMA_SUCCESS) +#define zxc_vm_execute_FILE(...) (zxc_vm_execute_FILE(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zbc_vm_file(const char *file) +static BC_STATUS zxc_vm_file(const char *file) { BcStatus s; FILE *fp; fp = xfopen_for_read(file); - s = zbc_vm_execute_FILE(fp, file); + s = zxc_vm_execute_FILE(fp, file); fclose(fp); RETURN_STATUS(s); } -#define zbc_vm_file(...) (zbc_vm_file(__VA_ARGS__) COMMA_SUCCESS) +#define zxc_vm_file(...) (zxc_vm_file(__VA_ARGS__) COMMA_SUCCESS) #if ENABLE_BC static void bc_vm_info(void) @@ -7106,7 +7095,7 @@ static const char bc_lib[] ALIGN1 = { }; #endif // ENABLE_BC -static BC_STATUS zbc_vm_exec(void) +static BC_STATUS zxc_vm_exec(void) { char **fname; BcStatus s; @@ -7117,7 +7106,7 @@ static BC_STATUS zbc_vm_exec(void) // We know that internal library is not buggy, // thus error checking is normally disabled. # define DEBUG_LIB 0 - s = zbc_vm_process(bc_lib); + s = zxc_vm_process(bc_lib); if (DEBUG_LIB && s) RETURN_STATUS(s); } #endif @@ -7125,7 +7114,7 @@ static BC_STATUS zbc_vm_exec(void) s = BC_STATUS_SUCCESS; fname = (void*)G.files.v; for (i = 0; i < G.files.len; i++) { - s = zbc_vm_file(*fname++); + s = zxc_vm_file(*fname++); if (ENABLE_FEATURE_CLEAN_UP && !G_ttyin && s) { // Debug config, non-interactive mode: // return all the way back to main. @@ -7136,14 +7125,14 @@ static BC_STATUS zbc_vm_exec(void) } if (IS_BC || (option_mask32 & BC_FLAG_I)) - s = zbc_vm_execute_FILE(stdin, /*filename:*/ NULL); + s = zxc_vm_execute_FILE(stdin, /*filename:*/ NULL); RETURN_STATUS(s); } -#define zbc_vm_exec(...) (zbc_vm_exec(__VA_ARGS__) COMMA_SUCCESS) +#define zxc_vm_exec(...) (zxc_vm_exec(__VA_ARGS__) COMMA_SUCCESS) #if ENABLE_FEATURE_CLEAN_UP -static void bc_program_free(void) +static void xc_program_free(void) { bc_vec_free(&G.prog.fns); IF_BC(bc_vec_free(&G.prog.fn_map);) @@ -7161,16 +7150,16 @@ static void bc_program_free(void) bc_vec_free(&G.input_buffer); } -static void bc_vm_free(void) +static void xc_vm_free(void) { bc_vec_free(&G.files); - bc_program_free(); - bc_parse_free(); + xc_program_free(); + xc_parse_free(); free(G.env_args); } #endif -static void bc_program_init(void) +static void xc_program_init(void) { BcInstPtr ip; @@ -7200,8 +7189,8 @@ static void bc_program_init(void) IF_BC(bc_program_addFunc(xstrdup("1"))); // func #1: for read() } else { // in dc, functions have no names - bc_program_add_fn(); - bc_program_add_fn(); + xc_program_add_fn(); + xc_program_add_fn(); } bc_vec_init(&G.prog.vars, sizeof(BcVec), bc_vec_free); @@ -7219,17 +7208,17 @@ static void bc_program_init(void) bc_char_vec_init(&G.input_buffer); } -static int bc_vm_init(const char *env_len) +static int xc_vm_init(const char *env_len) { #if ENABLE_FEATURE_EDITING G.line_input_state = new_line_input_t(DO_HISTORY); #endif - G.prog.len = bc_vm_envLen(env_len); + G.prog.len = xc_vm_envLen(env_len); bc_vec_init(&G.files, sizeof(char *), NULL); + xc_program_init(); IF_BC(if (IS_BC) bc_vm_envArgs();) - bc_program_init(); - bc_parse_create(BC_PROG_MAIN); + xc_parse_create(BC_PROG_MAIN); //TODO: in GNU bc, the check is (isatty(0) && isatty(1)), //-i option unconditionally enables this regardless of isatty(): @@ -7261,13 +7250,13 @@ static int bc_vm_init(const char *env_len) return 0; // "not a tty" } -static BcStatus bc_vm_run(void) +static BcStatus xc_vm_run(void) { - BcStatus st = zbc_vm_exec(); + BcStatus st = zxc_vm_exec(); #if ENABLE_FEATURE_CLEAN_UP if (G_exiting) // it was actually "halt" or "quit" st = EXIT_SUCCESS; - bc_vm_free(); + xc_vm_free(); # if ENABLE_FEATURE_EDITING free_line_input_t(G.line_input_state); # endif @@ -7285,14 +7274,14 @@ int bc_main(int argc UNUSED_PARAM, char **argv) INIT_G(); - is_tty = bc_vm_init("BC_LINE_LENGTH"); + is_tty = xc_vm_init("BC_LINE_LENGTH"); bc_args(argv); if (is_tty && !(option_mask32 & BC_FLAG_Q)) bc_vm_info(); - return bc_vm_run(); + return xc_vm_run(); } #endif @@ -7314,7 +7303,7 @@ int dc_main(int argc UNUSED_PARAM, char **argv) // |123\ | // |456 | // Do the same, or it's a bug? - bc_vm_init("DC_LINE_LENGTH"); + xc_vm_init("DC_LINE_LENGTH"); // Run -e'SCRIPT' and -fFILE in order of appearance, then handle FILEs noscript = BC_FLAG_I; @@ -7325,12 +7314,12 @@ int dc_main(int argc UNUSED_PARAM, char **argv) switch (n) { case 'e': noscript = 0; - n = zbc_vm_process(optarg); + n = zxc_vm_process(optarg); if (n) return n; break; case 'f': noscript = 0; - n = zbc_vm_file(optarg); + n = zxc_vm_file(optarg); if (n) return n; break; case 'x': @@ -7349,7 +7338,7 @@ int dc_main(int argc UNUSED_PARAM, char **argv) option_mask32 |= noscript; // set BC_FLAG_I if we need to interpret stdin - return bc_vm_run(); + return xc_vm_run(); } #endif -- cgit v1.2.3-55-g6feb From b097a84d62dcfcf201a695b54bcfafae70cac8a6 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 28 Dec 2018 03:20:17 +0100 Subject: config: update size information Signed-off-by: Denys Vlasenko --- archival/bbunzip.c | 12 ++++++------ archival/bzip2.c | 2 +- archival/cpio.c | 2 +- archival/dpkg.c | 2 +- archival/gzip.c | 2 +- archival/lzop.c | 2 +- archival/rpm.c | 4 ++-- archival/tar.c | 2 +- archival/unzip.c | 2 +- console-tools/dumpkmap.c | 2 +- console-tools/fgconsole.c | 2 +- console-tools/kbd_mode.c | 2 +- console-tools/loadfont.c | 4 ++-- console-tools/loadkmap.c | 2 +- console-tools/openvt.c | 2 +- console-tools/reset.c | 2 +- console-tools/resize.c | 2 +- console-tools/setconsole.c | 2 +- console-tools/setkeycodes.c | 2 +- coreutils/basename.c | 2 +- coreutils/chgrp.c | 2 +- coreutils/chmod.c | 2 +- coreutils/chown.c | 2 +- coreutils/cksum.c | 2 +- coreutils/comm.c | 2 +- coreutils/cp.c | 2 +- coreutils/cut.c | 2 +- coreutils/date.c | 2 +- coreutils/dd.c | 2 +- coreutils/df.c | 2 +- coreutils/dirname.c | 2 +- coreutils/dos2unix.c | 4 ++-- coreutils/env.c | 2 +- coreutils/expand.c | 4 ++-- coreutils/expr.c | 2 +- coreutils/factor.c | 2 +- coreutils/fsync.c | 2 +- coreutils/head.c | 2 +- coreutils/hostid.c | 2 +- coreutils/id.c | 4 ++-- coreutils/link.c | 2 +- coreutils/ln.c | 2 +- coreutils/logname.c | 2 +- coreutils/md5_sha1_sum.c | 10 +++++----- coreutils/mkdir.c | 2 +- coreutils/mkfifo.c | 2 +- coreutils/mknod.c | 2 +- coreutils/mktemp.c | 2 +- coreutils/mv.c | 2 +- coreutils/nice.c | 2 +- coreutils/nl.c | 2 +- coreutils/nproc.c | 2 +- coreutils/paste.c | 2 +- coreutils/printenv.c | 2 +- coreutils/printf.c | 2 +- coreutils/pwd.c | 2 +- coreutils/readlink.c | 2 +- coreutils/realpath.c | 2 +- coreutils/rm.c | 2 +- coreutils/rmdir.c | 2 +- coreutils/seq.c | 2 +- coreutils/shred.c | 2 +- coreutils/sleep.c | 2 +- coreutils/sort.c | 2 +- coreutils/split.c | 2 +- coreutils/stat.c | 2 +- coreutils/stty.c | 2 +- coreutils/sum.c | 2 +- coreutils/sync.c | 2 +- coreutils/tac.c | 2 +- coreutils/tail.c | 2 +- coreutils/tee.c | 2 +- coreutils/test.c | 2 +- coreutils/timeout.c | 2 +- coreutils/touch.c | 2 +- coreutils/tr.c | 2 +- coreutils/truncate.c | 2 +- coreutils/tty.c | 2 +- coreutils/uname.c | 4 ++-- coreutils/uniq.c | 2 +- coreutils/unlink.c | 2 +- coreutils/usleep.c | 2 +- coreutils/uudecode.c | 4 ++-- coreutils/uuencode.c | 2 +- coreutils/wc.c | 2 +- coreutils/who.c | 6 +++--- coreutils/whoami.c | 2 +- coreutils/yes.c | 2 +- debianutils/pipe_progress.c | 2 +- debianutils/run_parts.c | 2 +- debianutils/which.c | 2 +- e2fsprogs/chattr.c | 2 +- e2fsprogs/fsck.c | 2 +- e2fsprogs/lsattr.c | 2 +- editors/awk.c | 2 +- editors/cmp.c | 2 +- editors/ed.c | 2 +- editors/patch.c | 2 +- editors/patch_toybox.c | 2 +- editors/vi.c | 2 +- findutils/grep.c | 6 +++--- findutils/xargs.c | 2 +- init/halt.c | 6 +++--- init/init.c | 2 +- klibc-utils/nuke.c | 2 +- klibc-utils/resume.c | 2 +- klibc-utils/run-init.c | 2 +- loginutils/add-remove-shell.c | 4 ++-- loginutils/addgroup.c | 2 +- loginutils/deluser.c | 4 ++-- mailutils/makemime.c | 2 +- miscutils/adjtimex.c | 2 +- miscutils/bc.c | 4 ++-- miscutils/beep.c | 2 +- miscutils/chat.c | 2 +- miscutils/crond.c | 2 +- miscutils/crontab.c | 2 +- miscutils/fbsplash.c | 2 +- miscutils/flash_eraseall.c | 2 +- miscutils/flashcp.c | 2 +- miscutils/hdparm.c | 2 +- miscutils/hexedit.c | 2 +- miscutils/i2c_tools.c | 8 ++++---- miscutils/inotifyd.c | 2 +- miscutils/less.c | 2 +- miscutils/lsscsi.c | 2 +- miscutils/makedevs.c | 2 +- miscutils/man.c | 2 +- miscutils/microcom.c | 2 +- miscutils/mt.c | 2 +- miscutils/nandwrite.c | 4 ++-- miscutils/partprobe.c | 2 +- miscutils/raidautorun.c | 2 +- miscutils/readahead.c | 2 +- miscutils/rfkill.c | 2 +- miscutils/runlevel.c | 2 +- miscutils/setfattr.c | 2 +- miscutils/setserial.c | 2 +- miscutils/strings.c | 2 +- miscutils/time.c | 2 +- miscutils/ttysize.c | 2 +- miscutils/ubi_tools.c | 12 ++++++------ miscutils/ubirename.c | 2 +- miscutils/volname.c | 2 +- miscutils/watchdog.c | 2 +- modutils/depmod.c | 2 +- modutils/lsmod.c | 2 +- modutils/modinfo.c | 2 +- modutils/modprobe.c | 2 +- modutils/rmmod.c | 2 +- networking/arp.c | 2 +- networking/arping.c | 2 +- networking/ether-wake.c | 2 +- networking/ftpgetput.c | 4 ++-- networking/hostname.c | 2 +- networking/ifplugd.c | 2 +- networking/ifupdown.c | 4 ++-- networking/ip.c | 4 ++-- networking/ipcalc.c | 2 +- networking/isrv_identd.c | 2 +- networking/nbd-client.c | 2 +- networking/nslookup.c | 2 +- networking/ntpd.c | 2 +- networking/ping.c | 4 ++-- networking/pscan.c | 2 +- networking/route.c | 2 +- networking/slattach.c | 2 +- networking/ssl_client.c | 2 +- networking/tc.c | 2 +- networking/tcpudp.c | 2 +- networking/telnet.c | 2 +- networking/tftp.c | 2 +- networking/traceroute.c | 2 +- networking/tunctl.c | 2 +- networking/udhcp/d6_dhcpc.c | 2 +- networking/vconfig.c | 2 +- networking/wget.c | 2 +- networking/whois.c | 2 +- networking/zcip.c | 2 +- printutils/lpd.c | 2 +- printutils/lpr.c | 4 ++-- procps/free.c | 2 +- procps/iostat.c | 2 +- procps/kill.c | 2 +- procps/lsof.c | 2 +- procps/mpstat.c | 2 +- procps/nmeter.c | 2 +- procps/pgrep.c | 4 ++-- procps/pidof.c | 2 +- procps/powertop.c | 2 +- procps/pstree.c | 2 +- procps/pwdx.c | 2 +- procps/sysctl.c | 2 +- procps/top.c | 2 +- procps/uptime.c | 2 +- procps/watch.c | 2 +- runit/chpst.c | 8 ++++---- runit/runsv.c | 2 +- runit/runsvdir.c | 2 +- runit/sv.c | 6 +++--- runit/svlogd.c | 2 +- shell/ash.c | 2 +- shell/cttyhack.c | 2 +- shell/hush.c | 2 +- size_single_applets.sh | 8 ++++++++ sysklogd/klogd.c | 2 +- sysklogd/logger.c | 2 +- sysklogd/logread.c | 2 +- sysklogd/syslogd.c | 2 +- util-linux/acpid.c | 2 +- util-linux/blkdiscard.c | 2 +- util-linux/blkid.c | 2 +- util-linux/blockdev.c | 2 +- util-linux/cal.c | 2 +- util-linux/chrt.c | 2 +- util-linux/dmesg.c | 2 +- util-linux/eject.c | 2 +- util-linux/fallocate.c | 2 +- util-linux/fbset.c | 2 +- util-linux/fdformat.c | 2 +- util-linux/fdisk.c | 2 +- util-linux/findfs.c | 2 +- util-linux/flock.c | 2 +- util-linux/freeramdisk.c | 4 ++-- util-linux/fsfreeze.c | 2 +- util-linux/fstrim.c | 2 +- util-linux/getopt.c | 2 +- util-linux/hexdump.c | 4 ++-- util-linux/ionice.c | 2 +- util-linux/ipcrm.c | 2 +- util-linux/last.c | 2 +- util-linux/losetup.c | 2 +- util-linux/lspci.c | 2 +- util-linux/lsusb.c | 2 +- util-linux/mdev.c | 2 +- util-linux/mesg.c | 2 +- util-linux/mkfs_ext2.c | 4 ++-- util-linux/mkfs_vfat.c | 4 ++-- util-linux/mkswap.c | 2 +- util-linux/more.c | 2 +- util-linux/mount.c | 2 +- util-linux/mountpoint.c | 2 +- util-linux/nsenter.c | 2 +- util-linux/pivot_root.c | 2 +- util-linux/rdate.c | 2 +- util-linux/rdev.c | 2 +- util-linux/readprofile.c | 2 +- util-linux/renice.c | 2 +- util-linux/rev.c | 2 +- util-linux/rtcwake.c | 2 +- util-linux/script.c | 2 +- util-linux/scriptreplay.c | 2 +- util-linux/setarch.c | 6 +++--- util-linux/setpriv.c | 2 +- util-linux/setsid.c | 2 +- util-linux/swaponoff.c | 4 ++-- util-linux/switch_root.c | 2 +- util-linux/taskset.c | 2 +- util-linux/uevent.c | 2 +- util-linux/umount.c | 2 +- util-linux/unshare.c | 2 +- util-linux/wall.c | 2 +- 262 files changed, 321 insertions(+), 313 deletions(-) diff --git a/archival/bbunzip.c b/archival/bbunzip.c index a2ce0a13c..93f30d324 100644 --- a/archival/bbunzip.c +++ b/archival/bbunzip.c @@ -299,7 +299,7 @@ int uncompress_main(int argc UNUSED_PARAM, char **argv) //usage: "Decompress to stdout" //config:config GUNZIP -//config: bool "gunzip (12 kb)" +//config: bool "gunzip (11 kb)" //config: default y //config: select FEATURE_GZIP_DECOMPRESS //config: help @@ -308,7 +308,7 @@ int uncompress_main(int argc UNUSED_PARAM, char **argv) //config: an archive, without decompressing it. //config: //config:config ZCAT -//config: bool "zcat (25 kb)" +//config: bool "zcat (24 kb)" //config: default y //config: select FEATURE_GZIP_DECOMPRESS //config: help @@ -413,7 +413,7 @@ int gunzip_main(int argc UNUSED_PARAM, char **argv) //usage: "Decompress to stdout" //config:config BUNZIP2 -//config: bool "bunzip2 (8.8 kb)" +//config: bool "bunzip2 (8.7 kb)" //config: default y //config: select FEATURE_BZIP2_DECOMPRESS //config: help @@ -427,7 +427,7 @@ int gunzip_main(int argc UNUSED_PARAM, char **argv) //config: should probably say N here. //config: //config:config BZCAT -//config: bool "bzcat (8.8 kb)" +//config: bool "bzcat (8.7 kb)" //config: default y //config: select FEATURE_BZIP2_DECOMPRESS //config: help @@ -481,7 +481,7 @@ int bunzip2_main(int argc UNUSED_PARAM, char **argv) //usage: "Decompress to stdout" //config:config UNLZMA -//config: bool "unlzma (8.6 kb)" +//config: bool "unlzma (7.5 kb)" //config: default y //config: help //config: unlzma is a compression utility using the Lempel-Ziv-Markov chain @@ -490,7 +490,7 @@ int bunzip2_main(int argc UNUSED_PARAM, char **argv) //config: compressors. //config: //config:config LZCAT -//config: bool "lzcat (8.5 kb)" +//config: bool "lzcat (7.5 kb)" //config: default y //config: help //config: Alias to "unlzma -c". diff --git a/archival/bzip2.c b/archival/bzip2.c index 357891ca3..38cc0219a 100644 --- a/archival/bzip2.c +++ b/archival/bzip2.c @@ -7,7 +7,7 @@ * about bzip2 library code. */ //config:config BZIP2 -//config: bool "bzip2 (18 kb)" +//config: bool "bzip2 (16 kb)" //config: default y //config: help //config: bzip2 is a compression utility using the Burrows-Wheeler block diff --git a/archival/cpio.c b/archival/cpio.c index 9cacf9de6..0f37ffbb9 100644 --- a/archival/cpio.c +++ b/archival/cpio.c @@ -11,7 +11,7 @@ * Only supports new ASCII and CRC formats */ //config:config CPIO -//config: bool "cpio (14 kb)" +//config: bool "cpio (15 kb)" //config: default y //config: help //config: cpio is an archival utility program used to create, modify, and diff --git a/archival/dpkg.c b/archival/dpkg.c index 58bc4dba3..ddb5daf09 100644 --- a/archival/dpkg.c +++ b/archival/dpkg.c @@ -26,7 +26,7 @@ * - (unknown, please let me know when you find any) */ //config:config DPKG -//config: bool "dpkg (44 kb)" +//config: bool "dpkg (43 kb)" //config: default y //config: select FEATURE_SEAMLESS_GZ //config: help diff --git a/archival/gzip.c b/archival/gzip.c index 74d5d685f..12c1df242 100644 --- a/archival/gzip.c +++ b/archival/gzip.c @@ -22,7 +22,7 @@ gzip: bogus: No such file or directory aa: 85.1% -- replaced with aa.gz */ //config:config GZIP -//config: bool "gzip (19 kb)" +//config: bool "gzip (17 kb)" //config: default y //config: help //config: gzip is used to compress files. diff --git a/archival/lzop.c b/archival/lzop.c index 8f604254c..585632c4e 100644 --- a/archival/lzop.c +++ b/archival/lzop.c @@ -25,7 +25,7 @@ "Minimalized" for busybox by Alain Knaff */ //config:config LZOP -//config: bool "lzop (13 kb)" +//config: bool "lzop (12 kb)" //config: default y //config: help //config: Lzop compression/decompresion. diff --git a/archival/rpm.c b/archival/rpm.c index 790eeb59d..95b2531e8 100644 --- a/archival/rpm.c +++ b/archival/rpm.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config RPM -//config: bool "rpm (33 kb)" +//config: bool "rpm (32 kb)" //config: default y //config: help //config: Mini RPM applet - queries and extracts RPM packages. @@ -499,7 +499,7 @@ int rpm_main(int argc, char **argv) * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config RPM2CPIO -//config: bool "rpm2cpio (20 kb)" +//config: bool "rpm2cpio (21 kb)" //config: default y //config: help //config: Converts a RPM file into a CPIO archive. diff --git a/archival/tar.c b/archival/tar.c index 6950c271d..3ef89fb0a 100644 --- a/archival/tar.c +++ b/archival/tar.c @@ -23,7 +23,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config TAR -//config: bool "tar (40 kb)" +//config: bool "tar (39 kb)" //config: default y //config: help //config: tar is an archiving program. It's commonly used with gzip to diff --git a/archival/unzip.c b/archival/unzip.c index c406d53c4..466794031 100644 --- a/archival/unzip.c +++ b/archival/unzip.c @@ -17,7 +17,7 @@ * Zip64 + other methods */ //config:config UNZIP -//config: bool "unzip (24 kb)" +//config: bool "unzip (26 kb)" //config: default y //config: help //config: unzip will list or extract files from a ZIP archive, diff --git a/console-tools/dumpkmap.c b/console-tools/dumpkmap.c index f1c9287b5..fd4fd5623 100644 --- a/console-tools/dumpkmap.c +++ b/console-tools/dumpkmap.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config DUMPKMAP -//config: bool "dumpkmap (1.3 kb)" +//config: bool "dumpkmap (1.6 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/console-tools/fgconsole.c b/console-tools/fgconsole.c index a353becd5..554a32403 100644 --- a/console-tools/fgconsole.c +++ b/console-tools/fgconsole.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config FGCONSOLE -//config: bool "fgconsole (1.6 kb)" +//config: bool "fgconsole (1.5 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/console-tools/kbd_mode.c b/console-tools/kbd_mode.c index f16449dcd..cee37ab50 100644 --- a/console-tools/kbd_mode.c +++ b/console-tools/kbd_mode.c @@ -9,7 +9,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config KBD_MODE -//config: bool "kbd_mode (4 kb)" +//config: bool "kbd_mode (4.1 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/console-tools/loadfont.c b/console-tools/loadfont.c index 81d0c3db4..b5d4e8f43 100644 --- a/console-tools/loadfont.c +++ b/console-tools/loadfont.c @@ -10,14 +10,14 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config LOADFONT -//config: bool "loadfont (5.4 kb)" +//config: bool "loadfont (5.2 kb)" //config: default y //config: select PLATFORM_LINUX //config: help //config: This program loads a console font from standard input. //config: //config:config SETFONT -//config: bool "setfont (26 kb)" +//config: bool "setfont (24 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/console-tools/loadkmap.c b/console-tools/loadkmap.c index 404aba1fb..d4981ad21 100644 --- a/console-tools/loadkmap.c +++ b/console-tools/loadkmap.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config LOADKMAP -//config: bool "loadkmap (1.5 kb)" +//config: bool "loadkmap (1.8 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/console-tools/openvt.c b/console-tools/openvt.c index 423122fe9..b01229a56 100644 --- a/console-tools/openvt.c +++ b/console-tools/openvt.c @@ -8,7 +8,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config OPENVT -//config: bool "openvt (7 kb)" +//config: bool "openvt (7.2 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/console-tools/reset.c b/console-tools/reset.c index 614806ba7..113bb5c76 100644 --- a/console-tools/reset.c +++ b/console-tools/reset.c @@ -8,7 +8,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config RESET -//config: bool "reset (275 bytes)" +//config: bool "reset (345 bytes)" //config: default y //config: help //config: This program is used to reset the terminal screen, if it diff --git a/console-tools/resize.c b/console-tools/resize.c index 8aa487c41..59d468d48 100644 --- a/console-tools/resize.c +++ b/console-tools/resize.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config RESIZE -//config: bool "resize (756 bytes)" +//config: bool "resize (903 bytes)" //config: default y //config: help //config: This program is used to (re)set the width and height of your current diff --git a/console-tools/setconsole.c b/console-tools/setconsole.c index 7f0f9c711..0bc587241 100644 --- a/console-tools/setconsole.c +++ b/console-tools/setconsole.c @@ -8,7 +8,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config SETCONSOLE -//config: bool "setconsole (3.7 kb)" +//config: bool "setconsole (3.6 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/console-tools/setkeycodes.c b/console-tools/setkeycodes.c index 1363ac9d1..259946dbb 100644 --- a/console-tools/setkeycodes.c +++ b/console-tools/setkeycodes.c @@ -9,7 +9,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config SETKEYCODES -//config: bool "setkeycodes (1.7 kb)" +//config: bool "setkeycodes (2.1 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/coreutils/basename.c b/coreutils/basename.c index 812a5e63e..0dd2c43c7 100644 --- a/coreutils/basename.c +++ b/coreutils/basename.c @@ -14,7 +14,7 @@ * 3) Save some space by using strcmp(). Calling strncmp() here was silly. */ //config:config BASENAME -//config: bool "basename (371 bytes)" +//config: bool "basename (438 bytes)" //config: default y //config: help //config: basename is used to strip the directory and suffix from filenames, diff --git a/coreutils/chgrp.c b/coreutils/chgrp.c index 27a0edf0d..ae216aa3f 100644 --- a/coreutils/chgrp.c +++ b/coreutils/chgrp.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config CHGRP -//config: bool "chgrp (7.2 kb)" +//config: bool "chgrp (7.6 kb)" //config: default y //config: help //config: chgrp is used to change the group ownership of files. diff --git a/coreutils/chmod.c b/coreutils/chmod.c index 88989bf67..27e9b6b86 100644 --- a/coreutils/chmod.c +++ b/coreutils/chmod.c @@ -10,7 +10,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config CHMOD -//config: bool "chmod (5.1 kb)" +//config: bool "chmod (5.5 kb)" //config: default y //config: help //config: chmod is used to change the access permission of files. diff --git a/coreutils/chown.c b/coreutils/chown.c index 6429fd030..a1c5c0224 100644 --- a/coreutils/chown.c +++ b/coreutils/chown.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config CHOWN -//config: bool "chown (7.2 kb)" +//config: bool "chown (7.6 kb)" //config: default y //config: help //config: chown is used to change the user and/or group ownership diff --git a/coreutils/cksum.c b/coreutils/cksum.c index e46e249f2..633322bc7 100644 --- a/coreutils/cksum.c +++ b/coreutils/cksum.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config CKSUM -//config: bool "cksum (4.2 kb)" +//config: bool "cksum (4.1 kb)" //config: default y //config: help //config: cksum is used to calculate the CRC32 checksum of a file. diff --git a/coreutils/comm.c b/coreutils/comm.c index 4bee77677..c59fccdd1 100644 --- a/coreutils/comm.c +++ b/coreutils/comm.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config COMM -//config: bool "comm (3.9 kb)" +//config: bool "comm (4.2 kb)" //config: default y //config: help //config: comm is used to compare two files line by line and return diff --git a/coreutils/cp.c b/coreutils/cp.c index b26c0e954..59e3d2f80 100644 --- a/coreutils/cp.c +++ b/coreutils/cp.c @@ -12,7 +12,7 @@ * Size reduction. */ //config:config CP -//config: bool "cp (9.7 kb)" +//config: bool "cp (10 kb)" //config: default y //config: help //config: cp is used to copy files and directories. diff --git a/coreutils/cut.c b/coreutils/cut.c index cdd90ab44..e952dc17b 100644 --- a/coreutils/cut.c +++ b/coreutils/cut.c @@ -9,7 +9,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config CUT -//config: bool "cut (5.3 kb)" +//config: bool "cut (5.8 kb)" //config: default y //config: help //config: cut is used to print selected parts of lines from diff --git a/coreutils/date.c b/coreutils/date.c index 87dc3bbd0..9cbc7302f 100644 --- a/coreutils/date.c +++ b/coreutils/date.c @@ -19,7 +19,7 @@ much as possible, missed out a lot of bounds checking */ //config:config DATE -//config: bool "date (7.1 kb)" +//config: bool "date (7 kb)" //config: default y //config: help //config: date is used to set the system date or display the diff --git a/coreutils/dd.c b/coreutils/dd.c index 39ce5019f..4b31e9a7b 100644 --- a/coreutils/dd.c +++ b/coreutils/dd.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config DD -//config: bool "dd (7.1 kb)" +//config: bool "dd (7.5 kb)" //config: default y //config: help //config: dd copies a file (from standard input to standard output, diff --git a/coreutils/df.c b/coreutils/df.c index 50dccac52..f6d66e4b6 100644 --- a/coreutils/df.c +++ b/coreutils/df.c @@ -18,7 +18,7 @@ * Implement -P and -B; better coreutils compat; cleanup */ //config:config DF -//config: bool "df (7.5 kb)" +//config: bool "df (6.8 kb)" //config: default y //config: help //config: df reports the amount of disk space used and available diff --git a/coreutils/dirname.c b/coreutils/dirname.c index 511267b78..5aad121b5 100644 --- a/coreutils/dirname.c +++ b/coreutils/dirname.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config DIRNAME -//config: bool "dirname (289 bytes)" +//config: bool "dirname (329 bytes)" //config: default y //config: help //config: dirname is used to strip a non-directory suffix from diff --git a/coreutils/dos2unix.c b/coreutils/dos2unix.c index 9f098e41e..4039ed38c 100644 --- a/coreutils/dos2unix.c +++ b/coreutils/dos2unix.c @@ -12,14 +12,14 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config DOS2UNIX -//config: bool "dos2unix (5.1 kb)" +//config: bool "dos2unix (5.2 kb)" //config: default y //config: help //config: dos2unix is used to convert a text file from DOS format to //config: UNIX format, and vice versa. //config: //config:config UNIX2DOS -//config: bool "unix2dos (5.1 kb)" +//config: bool "unix2dos (5.2 kb)" //config: default y //config: help //config: unix2dos is used to convert a text file from UNIX format to diff --git a/coreutils/env.c b/coreutils/env.c index 0aebead1b..878068f09 100644 --- a/coreutils/env.c +++ b/coreutils/env.c @@ -24,7 +24,7 @@ * - use xfunc_error_retval */ //config:config ENV -//config: bool "env (3.8 kb)" +//config: bool "env (4 kb)" //config: default y //config: help //config: env is used to set an environment variable and run diff --git a/coreutils/expand.c b/coreutils/expand.c index 91084b80b..f7e4619f9 100644 --- a/coreutils/expand.c +++ b/coreutils/expand.c @@ -21,13 +21,13 @@ * Caveat: this versions of expand and unexpand don't accept tab lists. */ //config:config EXPAND -//config: bool "expand (5.8 kb)" +//config: bool "expand (5.1 kb)" //config: default y //config: help //config: By default, convert all tabs to spaces. //config: //config:config UNEXPAND -//config: bool "unexpand (6 kb)" +//config: bool "unexpand (5.3 kb)" //config: default y //config: help //config: By default, convert only leading sequences of blanks to tabs. diff --git a/coreutils/expr.c b/coreutils/expr.c index e54afbb62..1bdfba004 100644 --- a/coreutils/expr.c +++ b/coreutils/expr.c @@ -23,7 +23,7 @@ * provided they all associate ((x op x) op x). */ //config:config EXPR -//config: bool "expr (6.1 kb)" +//config: bool "expr (6.6 kb)" //config: default y //config: help //config: expr is used to calculate numbers and print the result diff --git a/coreutils/factor.c b/coreutils/factor.c index 467e23a4d..1f24784fd 100644 --- a/coreutils/factor.c +++ b/coreutils/factor.c @@ -4,7 +4,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config FACTOR -//config: bool "factor (2.6 kb)" +//config: bool "factor (2.7 kb)" //config: default y //config: help //config: factor factorizes integers diff --git a/coreutils/fsync.c b/coreutils/fsync.c index 5e77e2c16..c7cba9f61 100644 --- a/coreutils/fsync.c +++ b/coreutils/fsync.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config FSYNC -//config: bool "fsync (3.7 kb)" +//config: bool "fsync (3.6 kb)" //config: default y //config: help //config: fsync is used to flush file-related cached blocks to disk. diff --git a/coreutils/head.c b/coreutils/head.c index fc3a48d5b..1219dfe8b 100644 --- a/coreutils/head.c +++ b/coreutils/head.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config HEAD -//config: bool "head (3.7 kb)" +//config: bool "head (3.8 kb)" //config: default y //config: help //config: head is used to print the first specified number of lines diff --git a/coreutils/hostid.c b/coreutils/hostid.c index d21e6d6ac..038809452 100644 --- a/coreutils/hostid.c +++ b/coreutils/hostid.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config HOSTID -//config: bool "hostid (247 bytes)" +//config: bool "hostid (286 bytes)" //config: default y //config: help //config: hostid prints the numeric identifier (in hexadecimal) for diff --git a/coreutils/id.c b/coreutils/id.c index 5a7fb9aaf..00c0cd8ab 100644 --- a/coreutils/id.c +++ b/coreutils/id.c @@ -13,13 +13,13 @@ * Added -G option Tito Ragusa (C) 2008 for SUSv3. */ //config:config ID -//config: bool "id (6.7 kb)" +//config: bool "id (7 kb)" //config: default y //config: help //config: id displays the current user and group ID names. //config: //config:config GROUPS -//config: bool "groups (6.5 kb)" +//config: bool "groups (6.7 kb)" //config: default y //config: help //config: Print the group names associated with current user id. diff --git a/coreutils/link.c b/coreutils/link.c index d8d583b7b..23e0cfdd0 100644 --- a/coreutils/link.c +++ b/coreutils/link.c @@ -6,7 +6,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config LINK -//config: bool "link (3.1 kb)" +//config: bool "link (3.2 kb)" //config: default y //config: help //config: link creates hard links between files. diff --git a/coreutils/ln.c b/coreutils/ln.c index 2dda5dae9..3fe2f3f64 100644 --- a/coreutils/ln.c +++ b/coreutils/ln.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config LN -//config: bool "ln (4.5 kb)" +//config: bool "ln (4.9 kb)" //config: default y //config: help //config: ln is used to create hard or soft links between files. diff --git a/coreutils/logname.c b/coreutils/logname.c index e614ca7cf..31ce61f0c 100644 --- a/coreutils/logname.c +++ b/coreutils/logname.c @@ -16,7 +16,7 @@ * a diagnostic message and an error return. */ //config:config LOGNAME -//config: bool "logname (894 bytes)" +//config: bool "logname (1.1 kb)" //config: default y //config: help //config: logname is used to print the current user's login name. diff --git a/coreutils/md5_sha1_sum.c b/coreutils/md5_sha1_sum.c index 871145143..538df251b 100644 --- a/coreutils/md5_sha1_sum.c +++ b/coreutils/md5_sha1_sum.c @@ -6,31 +6,31 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config MD5SUM -//config: bool "md5sum (6.8 kb)" +//config: bool "md5sum (6.5 kb)" //config: default y //config: help //config: Compute and check MD5 message digest //config: //config:config SHA1SUM -//config: bool "sha1sum (6 kb)" +//config: bool "sha1sum (5.9 kb)" //config: default y //config: help //config: Compute and check SHA1 message digest //config: //config:config SHA256SUM -//config: bool "sha256sum (7.1 kb)" +//config: bool "sha256sum (7 kb)" //config: default y //config: help //config: Compute and check SHA256 message digest //config: //config:config SHA512SUM -//config: bool "sha512sum (7.6 kb)" +//config: bool "sha512sum (7.4 kb)" //config: default y //config: help //config: Compute and check SHA512 message digest //config: //config:config SHA3SUM -//config: bool "sha3sum (6.3 kb)" +//config: bool "sha3sum (6.1 kb)" //config: default y //config: help //config: Compute and check SHA3 message digest diff --git a/coreutils/mkdir.c b/coreutils/mkdir.c index 986353dc6..0ee1d1f72 100644 --- a/coreutils/mkdir.c +++ b/coreutils/mkdir.c @@ -14,7 +14,7 @@ /* Nov 28, 2006 Yoshinori Sato : Add SELinux Support. */ //config:config MKDIR -//config: bool "mkdir (4.4 kb)" +//config: bool "mkdir (4.5 kb)" //config: default y //config: help //config: mkdir is used to create directories with the specified names. diff --git a/coreutils/mkfifo.c b/coreutils/mkfifo.c index 0f614017e..e9d420ed8 100644 --- a/coreutils/mkfifo.c +++ b/coreutils/mkfifo.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config MKFIFO -//config: bool "mkfifo (3.7 kb)" +//config: bool "mkfifo (3.8 kb)" //config: default y //config: help //config: mkfifo is used to create FIFOs (named pipes). diff --git a/coreutils/mknod.c b/coreutils/mknod.c index d57167f7d..eee0ac71d 100644 --- a/coreutils/mknod.c +++ b/coreutils/mknod.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config MKNOD -//config: bool "mknod (4 kb)" +//config: bool "mknod (4.5 kb)" //config: default y //config: help //config: mknod is used to create FIFOs or block/character special diff --git a/coreutils/mktemp.c b/coreutils/mktemp.c index c041fedf7..5393320a5 100644 --- a/coreutils/mktemp.c +++ b/coreutils/mktemp.c @@ -29,7 +29,7 @@ * -p; else /tmp [deprecated] */ //config:config MKTEMP -//config: bool "mktemp (4 kb)" +//config: bool "mktemp (4.2 kb)" //config: default y //config: help //config: mktemp is used to create unique temporary files diff --git a/coreutils/mv.c b/coreutils/mv.c index 6e11197a1..b9f8f6982 100644 --- a/coreutils/mv.c +++ b/coreutils/mv.c @@ -12,7 +12,7 @@ * Size reduction and improved error checking. */ //config:config MV -//config: bool "mv (9.8 kb)" +//config: bool "mv (10 kb)" //config: default y //config: help //config: mv is used to move or rename files or directories. diff --git a/coreutils/nice.c b/coreutils/nice.c index da1696c42..28591ac61 100644 --- a/coreutils/nice.c +++ b/coreutils/nice.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config NICE -//config: bool "nice (1.8 kb)" +//config: bool "nice (2.1 kb)" //config: default y //config: help //config: nice runs a program with modified scheduling priority. diff --git a/coreutils/nl.c b/coreutils/nl.c index 2fdc9d85e..aea019c56 100644 --- a/coreutils/nl.c +++ b/coreutils/nl.c @@ -5,7 +5,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config NL -//config: bool "nl (4.3 kb)" +//config: bool "nl (4.6 kb)" //config: default y //config: help //config: nl is used to number lines of files. diff --git a/coreutils/nproc.c b/coreutils/nproc.c index 0ea8d1001..31e452bc4 100644 --- a/coreutils/nproc.c +++ b/coreutils/nproc.c @@ -4,7 +4,7 @@ * Licensed under GPLv2, see LICENSE in this source tree */ //config:config NPROC -//config: bool "nproc (248 bytes)" +//config: bool "nproc (3.7 kb)" //config: default y //config: help //config: Print number of CPUs diff --git a/coreutils/paste.c b/coreutils/paste.c index 52f67f951..3d81a5f1a 100644 --- a/coreutils/paste.c +++ b/coreutils/paste.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config PASTE -//config: bool "paste (4.5 kb)" +//config: bool "paste (4.9 kb)" //config: default y //config: help //config: paste is used to paste lines of different files together diff --git a/coreutils/printenv.c b/coreutils/printenv.c index b0468b3f7..5e195deaa 100644 --- a/coreutils/printenv.c +++ b/coreutils/printenv.c @@ -8,7 +8,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config PRINTENV -//config: bool "printenv (1 kb)" +//config: bool "printenv (1.3 kb)" //config: default y //config: help //config: printenv is used to print all or part of environment. diff --git a/coreutils/printf.c b/coreutils/printf.c index 67d3b2eda..5cf518699 100644 --- a/coreutils/printf.c +++ b/coreutils/printf.c @@ -38,7 +38,7 @@ /* 19990508 Busy Boxed! Dave Cinege */ //config:config PRINTF -//config: bool "printf (3.3 kb)" +//config: bool "printf (3.8 kb)" //config: default y //config: help //config: printf is used to format and print specified strings. diff --git a/coreutils/pwd.c b/coreutils/pwd.c index 345d85100..4c42284f4 100644 --- a/coreutils/pwd.c +++ b/coreutils/pwd.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config PWD -//config: bool "pwd (3.4 kb)" +//config: bool "pwd (3.7 kb)" //config: default y //config: help //config: pwd is used to print the current directory. diff --git a/coreutils/readlink.c b/coreutils/readlink.c index 49361cea0..09d69df2b 100644 --- a/coreutils/readlink.c +++ b/coreutils/readlink.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config READLINK -//config: bool "readlink (3.6 kb)" +//config: bool "readlink (4 kb)" //config: default y //config: help //config: This program reads a symbolic link and returns the name diff --git a/coreutils/realpath.c b/coreutils/realpath.c index 43923681c..f5f868744 100644 --- a/coreutils/realpath.c +++ b/coreutils/realpath.c @@ -8,7 +8,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config REALPATH -//config: bool "realpath (1.1 kb)" +//config: bool "realpath (1.6 kb)" //config: default y //config: help //config: Return the canonicalized absolute pathname. diff --git a/coreutils/rm.c b/coreutils/rm.c index b68a82dc4..fd94bb5c4 100644 --- a/coreutils/rm.c +++ b/coreutils/rm.c @@ -11,7 +11,7 @@ * Size reduction. */ //config:config RM -//config: bool "rm (4.9 kb)" +//config: bool "rm (5.4 kb)" //config: default y //config: help //config: rm is used to remove files or directories. diff --git a/coreutils/rmdir.c b/coreutils/rmdir.c index 955740494..5092a5dfc 100644 --- a/coreutils/rmdir.c +++ b/coreutils/rmdir.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config RMDIR -//config: bool "rmdir (3.4 kb)" +//config: bool "rmdir (3.5 kb)" //config: default y //config: help //config: rmdir is used to remove empty directories. diff --git a/coreutils/seq.c b/coreutils/seq.c index c26ff06b9..beb339d1e 100644 --- a/coreutils/seq.c +++ b/coreutils/seq.c @@ -7,7 +7,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config SEQ -//config: bool "seq (3.6 kb)" +//config: bool "seq (3.8 kb)" //config: default y //config: help //config: print a sequence of numbers diff --git a/coreutils/shred.c b/coreutils/shred.c index 3ceb58d19..8f3d9c5c9 100644 --- a/coreutils/shred.c +++ b/coreutils/shred.c @@ -5,7 +5,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config SHRED -//config: bool "shred (5 kb)" +//config: bool "shred (4.9 kb)" //config: default y //config: help //config: Overwrite a file to hide its contents, and optionally delete it diff --git a/coreutils/sleep.c b/coreutils/sleep.c index 126665839..5c9cda9f0 100644 --- a/coreutils/sleep.c +++ b/coreutils/sleep.c @@ -13,7 +13,7 @@ * time suffixes for seconds, minutes, hours, and days. */ //config:config SLEEP -//config: bool "sleep (1.7 kb)" +//config: bool "sleep (2 kb)" //config: default y //config: help //config: sleep is used to pause for a specified number of seconds. diff --git a/coreutils/sort.c b/coreutils/sort.c index 05e5c9071..f04c6067b 100644 --- a/coreutils/sort.c +++ b/coreutils/sort.c @@ -12,7 +12,7 @@ * http://www.opengroup.org/onlinepubs/007904975/utilities/sort.html */ //config:config SORT -//config: bool "sort (7.4 kb)" +//config: bool "sort (7.7 kb)" //config: default y //config: help //config: sort is used to sort lines of text in specified files. diff --git a/coreutils/split.c b/coreutils/split.c index 4e1db190c..c1e4ceab2 100644 --- a/coreutils/split.c +++ b/coreutils/split.c @@ -6,7 +6,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config SPLIT -//config: bool "split (5.4 kb)" +//config: bool "split (5 kb)" //config: default y //config: help //config: Split a file into pieces. diff --git a/coreutils/stat.c b/coreutils/stat.c index 3d527ae63..122029bda 100644 --- a/coreutils/stat.c +++ b/coreutils/stat.c @@ -13,7 +13,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config STAT -//config: bool "stat (10 kb)" +//config: bool "stat (11 kb)" //config: default y //config: help //config: display file or filesystem status. diff --git a/coreutils/stty.c b/coreutils/stty.c index 424d909cf..6251f2aef 100644 --- a/coreutils/stty.c +++ b/coreutils/stty.c @@ -21,7 +21,7 @@ * Special for busybox ported by Vladimir Oleynik 2001 */ //config:config STTY -//config: bool "stty (8.6 kb)" +//config: bool "stty (8.9 kb)" //config: default y //config: help //config: stty is used to change and print terminal line settings. diff --git a/coreutils/sum.c b/coreutils/sum.c index 487e93f4a..16ec44540 100644 --- a/coreutils/sum.c +++ b/coreutils/sum.c @@ -13,7 +13,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config SUM -//config: bool "sum (4.3 kb)" +//config: bool "sum (4 kb)" //config: default y //config: help //config: checksum and count the blocks in a file diff --git a/coreutils/sync.c b/coreutils/sync.c index 9be47ab64..b93476aee 100644 --- a/coreutils/sync.c +++ b/coreutils/sync.c @@ -8,7 +8,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config SYNC -//config: bool "sync (769 bytes)" +//config: bool "sync (3.8 kb)" //config: default y //config: help //config: sync is used to flush filesystem buffers. diff --git a/coreutils/tac.c b/coreutils/tac.c index 6d3ea9c19..25e85f6f3 100644 --- a/coreutils/tac.c +++ b/coreutils/tac.c @@ -13,7 +13,7 @@ * http://www.uclibc.org/lists/busybox/2003-July/008813.html */ //config:config TAC -//config: bool "tac (4.1 kb)" +//config: bool "tac (3.9 kb)" //config: default y //config: help //config: tac is used to concatenate and print files in reverse. diff --git a/coreutils/tail.c b/coreutils/tail.c index 7335ba11e..14ed85d16 100644 --- a/coreutils/tail.c +++ b/coreutils/tail.c @@ -19,7 +19,7 @@ * 7) lseek attempted when count==0 even if arg was +0 (from top) */ //config:config TAIL -//config: bool "tail (7.1 kb)" +//config: bool "tail (6.8 kb)" //config: default y //config: help //config: tail is used to print the last specified number of lines diff --git a/coreutils/tee.c b/coreutils/tee.c index f0ec791bb..fe5694331 100644 --- a/coreutils/tee.c +++ b/coreutils/tee.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config TEE -//config: bool "tee (4.3 kb)" +//config: bool "tee (4.2 kb)" //config: default y //config: help //config: tee is used to read from standard input and write diff --git a/coreutils/test.c b/coreutils/test.c index ddb66ddce..8d7dac025 100644 --- a/coreutils/test.c +++ b/coreutils/test.c @@ -20,7 +20,7 @@ * "This program is in the Public Domain." */ //config:config TEST -//config: bool "test (3.6 kb)" +//config: bool "test (4.1 kb)" //config: default y //config: help //config: test is used to check file types and compare values, diff --git a/coreutils/timeout.c b/coreutils/timeout.c index e42aba85c..8b7bc2eaa 100644 --- a/coreutils/timeout.c +++ b/coreutils/timeout.c @@ -28,7 +28,7 @@ * rewrite 14-11-2008 vda */ //config:config TIMEOUT -//config: bool "timeout (5.5 kb)" +//config: bool "timeout (6 kb)" //config: default y //config: help //config: Runs a program and watches it. If it does not terminate in diff --git a/coreutils/touch.c b/coreutils/touch.c index 857761578..b30811157 100644 --- a/coreutils/touch.c +++ b/coreutils/touch.c @@ -13,7 +13,7 @@ * Also, exiting on a failure was a bug. All args should be processed. */ //config:config TOUCH -//config: bool "touch (5.8 kb)" +//config: bool "touch (5.9 kb)" //config: default y //config: help //config: touch is used to create or change the access and/or diff --git a/coreutils/tr.c b/coreutils/tr.c index 10284e1c9..ae35a9ee3 100644 --- a/coreutils/tr.c +++ b/coreutils/tr.c @@ -19,7 +19,7 @@ * TODO: graph, print */ //config:config TR -//config: bool "tr (5.5 kb)" +//config: bool "tr (5.1 kb)" //config: default y //config: help //config: tr is used to squeeze, and/or delete characters from standard diff --git a/coreutils/truncate.c b/coreutils/truncate.c index f693570aa..233d0f2d1 100644 --- a/coreutils/truncate.c +++ b/coreutils/truncate.c @@ -6,7 +6,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config TRUNCATE -//config: bool "truncate (4.7 kb)" +//config: bool "truncate (4.2 kb)" //config: default y //config: help //config: truncate truncates files to a given size. If a file does diff --git a/coreutils/tty.c b/coreutils/tty.c index 18ad7c566..ff6f2bb3b 100644 --- a/coreutils/tty.c +++ b/coreutils/tty.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config TTY -//config: bool "tty (3.3 kb)" +//config: bool "tty (3.6 kb)" //config: default y //config: help //config: tty is used to print the name of the current terminal to diff --git a/coreutils/uname.c b/coreutils/uname.c index 765809658..2a1602b4c 100644 --- a/coreutils/uname.c +++ b/coreutils/uname.c @@ -44,7 +44,7 @@ * Fix handling of -a to not print "unknown", add -o and -i support. */ //config:config UNAME -//config: bool "uname (3.7 kb)" +//config: bool "uname (3.9 kb)" //config: default y //config: help //config: uname is used to print system information. @@ -59,7 +59,7 @@ //config: //can't use "ARCH" for this applet, all hell breaks loose in build system :) //config:config BB_ARCH -//config: bool "arch (1.6 kb)" +//config: bool "arch (1.1 kb)" //config: default y //config: help //config: Same as uname -m. diff --git a/coreutils/uniq.c b/coreutils/uniq.c index f71557b67..317f45531 100644 --- a/coreutils/uniq.c +++ b/coreutils/uniq.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config UNIQ -//config: bool "uniq (4.8 kb)" +//config: bool "uniq (4.9 kb)" //config: default y //config: help //config: uniq is used to remove duplicate lines from a sorted file. diff --git a/coreutils/unlink.c b/coreutils/unlink.c index 61b108a84..24be81da6 100644 --- a/coreutils/unlink.c +++ b/coreutils/unlink.c @@ -7,7 +7,7 @@ * Licensed under GPLv2, see LICENSE in this source tree */ //config:config UNLINK -//config: bool "unlink (3.5 kb)" +//config: bool "unlink (3.2 kb)" //config: default y //config: help //config: unlink deletes a file by calling unlink() diff --git a/coreutils/usleep.c b/coreutils/usleep.c index 684ab781b..51a015c44 100644 --- a/coreutils/usleep.c +++ b/coreutils/usleep.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config USLEEP -//config: bool "usleep (1.1 kb)" +//config: bool "usleep (1.3 kb)" //config: default y //config: help //config: usleep is used to pause for a specified number of microseconds. diff --git a/coreutils/uudecode.c b/coreutils/uudecode.c index 5ef05ee4d..5f69e62b3 100644 --- a/coreutils/uudecode.c +++ b/coreutils/uudecode.c @@ -11,7 +11,7 @@ * "end" line */ //config:config UUDECODE -//config: bool "uudecode (5.9 kb)" +//config: bool "uudecode (5.8 kb)" //config: default y //config: help //config: uudecode is used to decode a uuencoded file. @@ -175,7 +175,7 @@ int uudecode_main(int argc UNUSED_PARAM, char **argv) //kbuild:lib-$(CONFIG_BASE64) += uudecode.o //config:config BASE64 -//config: bool "base64 (5 kb)" +//config: bool "base64 (4.9 kb)" //config: default y //config: help //config: Base64 encode and decode diff --git a/coreutils/uuencode.c b/coreutils/uuencode.c index aa53b14a6..2807ef82a 100644 --- a/coreutils/uuencode.c +++ b/coreutils/uuencode.c @@ -8,7 +8,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config UUENCODE -//config: bool "uuencode (4.6 kb)" +//config: bool "uuencode (4.4 kb)" //config: default y //config: help //config: uuencode is used to uuencode a file. diff --git a/coreutils/wc.c b/coreutils/wc.c index c74b7a65f..99eb9dc87 100644 --- a/coreutils/wc.c +++ b/coreutils/wc.c @@ -33,7 +33,7 @@ * for which 'wc -c' should output '0'. */ //config:config WC -//config: bool "wc (4.4 kb)" +//config: bool "wc (4.5 kb)" //config: default y //config: help //config: wc is used to print the number of bytes, words, and lines, diff --git a/coreutils/who.c b/coreutils/who.c index 80226c3d6..be9c3ccca 100644 --- a/coreutils/who.c +++ b/coreutils/who.c @@ -15,7 +15,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config WHO -//config: bool "who (3.7 kb)" +//config: bool "who (3.9 kb)" //config: default y //config: depends on FEATURE_UTMP //config: help @@ -23,14 +23,14 @@ //config: // procps-ng has this variation of "who": //config:config W -//config: bool "w (3.7 kb)" +//config: bool "w (3.8 kb)" //config: default y //config: depends on FEATURE_UTMP //config: help //config: Print users currently logged on. //config: //config:config USERS -//config: bool "users (3.2 kb)" +//config: bool "users (3.4 kb)" //config: default y //config: depends on FEATURE_UTMP //config: help diff --git a/coreutils/whoami.c b/coreutils/whoami.c index 9dab15817..49b5dd368 100644 --- a/coreutils/whoami.c +++ b/coreutils/whoami.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config WHOAMI -//config: bool "whoami (2.9 kb)" +//config: bool "whoami (3.2 kb)" //config: default y //config: help //config: whoami is used to print the username of the current diff --git a/coreutils/yes.c b/coreutils/yes.c index c244bfe10..9a435a761 100644 --- a/coreutils/yes.c +++ b/coreutils/yes.c @@ -11,7 +11,7 @@ * Size reductions and removed redundant applet name prefix from error messages. */ //config:config YES -//config: bool "yes (956 bytes)" +//config: bool "yes (1.2 kb)" //config: default y //config: help //config: yes is used to repeatedly output a specific string, or diff --git a/debianutils/pipe_progress.c b/debianutils/pipe_progress.c index e6b7601fa..ab7e2528f 100644 --- a/debianutils/pipe_progress.c +++ b/debianutils/pipe_progress.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config PIPE_PROGRESS -//config: bool "pipe_progress (225 bytes)" +//config: bool "pipe_progress (275 bytes)" //config: default y //config: help //config: Display a dot to indicate pipe activity. diff --git a/debianutils/run_parts.c b/debianutils/run_parts.c index e4d61df35..c80cc863f 100644 --- a/debianutils/run_parts.c +++ b/debianutils/run_parts.c @@ -23,7 +23,7 @@ * broken compatibility because the BusyBox policy doesn't allow them. */ //config:config RUN_PARTS -//config: bool "run-parts (5.6 kb)" +//config: bool "run-parts (6.1 kb)" //config: default y //config: help //config: run-parts is a utility designed to run all the scripts in a directory. diff --git a/debianutils/which.c b/debianutils/which.c index 02f77a216..98876521f 100644 --- a/debianutils/which.c +++ b/debianutils/which.c @@ -6,7 +6,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config WHICH -//config: bool "which (3.7 kb)" +//config: bool "which (3.8 kb)" //config: default y //config: help //config: which is used to find programs in your PATH and diff --git a/e2fsprogs/chattr.c b/e2fsprogs/chattr.c index 76a5253b6..c93e209b5 100644 --- a/e2fsprogs/chattr.c +++ b/e2fsprogs/chattr.c @@ -10,7 +10,7 @@ * Public License */ //config:config CHATTR -//config: bool "chattr (3.2 kb)" +//config: bool "chattr (3.8 kb)" //config: default y //config: help //config: chattr changes the file attributes on a second extended file system. diff --git a/e2fsprogs/fsck.c b/e2fsprogs/fsck.c index f5aa3dbe4..8a14b3bdc 100644 --- a/e2fsprogs/fsck.c +++ b/e2fsprogs/fsck.c @@ -34,7 +34,7 @@ * It doesn't guess filesystem types from on-disk format. */ //config:config FSCK -//config: bool "fsck (6.7 kb)" +//config: bool "fsck (7.4 kb)" //config: default y //config: help //config: fsck is used to check and optionally repair one or more filesystems. diff --git a/e2fsprogs/lsattr.c b/e2fsprogs/lsattr.c index 56c1187c1..be1488b79 100644 --- a/e2fsprogs/lsattr.c +++ b/e2fsprogs/lsattr.c @@ -10,7 +10,7 @@ * Public License */ //config:config LSATTR -//config: bool "lsattr (5 kb)" +//config: bool "lsattr (5.5 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/editors/awk.c b/editors/awk.c index af103e3cc..b6d8cf203 100644 --- a/editors/awk.c +++ b/editors/awk.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config AWK -//config: bool "awk (22 kb)" +//config: bool "awk (23 kb)" //config: default y //config: help //config: Awk is used as a pattern scanning and processing language. diff --git a/editors/cmp.c b/editors/cmp.c index 2a410fdec..6e27a841a 100644 --- a/editors/cmp.c +++ b/editors/cmp.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config CMP -//config: bool "cmp (5.4 kb)" +//config: bool "cmp (4.9 kb)" //config: default y //config: help //config: cmp is used to compare two files and returns the result diff --git a/editors/ed.c b/editors/ed.c index 05797692c..1a36add39 100644 --- a/editors/ed.c +++ b/editors/ed.c @@ -7,7 +7,7 @@ * The "ed" built-in command (much simplified) */ //config:config ED -//config: bool "ed (25 kb)" +//config: bool "ed (21 kb)" //config: default y //config: help //config: The original 1970's Unix text editor, from the days of teletypes. diff --git a/editors/patch.c b/editors/patch.c index eca6bc5f6..0ce0210fd 100644 --- a/editors/patch.c +++ b/editors/patch.c @@ -21,7 +21,7 @@ * [file] which file to patch */ //config:config PATCH -//config: bool "patch (9.1 kb)" +//config: bool "patch (9.4 kb)" //config: default y //config: help //config: Apply a unified diff formatted patch. diff --git a/editors/patch_toybox.c b/editors/patch_toybox.c index 2c958d287..3ffbf9084 100644 --- a/editors/patch_toybox.c +++ b/editors/patch_toybox.c @@ -26,7 +26,7 @@ USE_PATCH(NEWTOY(patch, USE_TOYBOX_DEBUG("x")"up#i:R", TOYFLAG_USR|TOYFLAG_BIN)) config PATCH - bool "patch (9.1 kb)" + bool "patch (9.4 kb)" default y help usage: patch [-i file] [-p depth] [-Ru] diff --git a/editors/vi.c b/editors/vi.c index 271529404..32144abaa 100644 --- a/editors/vi.c +++ b/editors/vi.c @@ -19,7 +19,7 @@ * An "ex" line oriented mode- maybe using "cmdedit" */ //config:config VI -//config: bool "vi (22 kb)" +//config: bool "vi (23 kb)" //config: default y //config: help //config: 'vi' is a text editor. More specifically, it is the One True diff --git a/findutils/grep.c b/findutils/grep.c index 3e8ea9239..a4033a40b 100644 --- a/findutils/grep.c +++ b/findutils/grep.c @@ -18,19 +18,19 @@ * (C) 2006 Jac Goudsmit added -o option */ //config:config GREP -//config: bool "grep (8.5 kb)" +//config: bool "grep (8.6 kb)" //config: default y //config: help //config: grep is used to search files for a specified pattern. //config: //config:config EGREP -//config: bool "egrep (7.6 kb)" +//config: bool "egrep (7.8 kb)" //config: default y //config: help //config: Alias to "grep -E". //config: //config:config FGREP -//config: bool "fgrep (7.6 kb)" +//config: bool "fgrep (7.8 kb)" //config: default y //config: help //config: Alias to "grep -F". diff --git a/findutils/xargs.c b/findutils/xargs.c index 0dedb6356..35a06f723 100644 --- a/findutils/xargs.c +++ b/findutils/xargs.c @@ -15,7 +15,7 @@ * http://www.opengroup.org/onlinepubs/007904975/utilities/xargs.html */ //config:config XARGS -//config: bool "xargs (6.7 kb)" +//config: bool "xargs (7.2 kb)" //config: default y //config: help //config: xargs is used to execute a specified command for diff --git a/init/halt.c b/init/halt.c index e6dcb1c67..785c38130 100644 --- a/init/halt.c +++ b/init/halt.c @@ -7,19 +7,19 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config HALT -//config: bool "halt (3.7 kb)" +//config: bool "halt (4 kb)" //config: default y //config: help //config: Stop all processes and halt the system. //config: //config:config POWEROFF -//config: bool "poweroff (3.7 kb)" +//config: bool "poweroff (4 kb)" //config: default y //config: help //config: Stop all processes and power off the system. //config: //config:config REBOOT -//config: bool "reboot (3.7 kb)" +//config: bool "reboot (4 kb)" //config: default y //config: help //config: Stop all processes and reboot the system. diff --git a/init/init.c b/init/init.c index fde35f6b6..87086b48b 100644 --- a/init/init.c +++ b/init/init.c @@ -9,7 +9,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config INIT -//config: bool "init (9.3 kb)" +//config: bool "init (10 kb)" //config: default y //config: select FEATURE_SYSLOG //config: help diff --git a/klibc-utils/nuke.c b/klibc-utils/nuke.c index 60a5f7145..d7c16f5cf 100644 --- a/klibc-utils/nuke.c +++ b/klibc-utils/nuke.c @@ -4,7 +4,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config NUKE -//config: bool "nuke (2.4 kb)" +//config: bool "nuke (2.9 kb)" //config: default y //config: help //config: Alias to "rm -rf". diff --git a/klibc-utils/resume.c b/klibc-utils/resume.c index 3424f076b..2bf50f9b8 100644 --- a/klibc-utils/resume.c +++ b/klibc-utils/resume.c @@ -4,7 +4,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config RESUME -//config: bool "resume (3.3 kb)" +//config: bool "resume (3.2 kb)" //config: default y //config: help //config: Resume from saved "suspend-to-disk" image diff --git a/klibc-utils/run-init.c b/klibc-utils/run-init.c index 61c16fd0b..77fc0e60c 100644 --- a/klibc-utils/run-init.c +++ b/klibc-utils/run-init.c @@ -6,7 +6,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config RUN_INIT -//config: bool "run-init (7.5 kb)" +//config: bool "run-init (7.7 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/loginutils/add-remove-shell.c b/loginutils/add-remove-shell.c index 6d03de254..b09555aae 100644 --- a/loginutils/add-remove-shell.c +++ b/loginutils/add-remove-shell.c @@ -8,13 +8,13 @@ * for details. */ //config:config ADD_SHELL -//config: bool "add-shell (2.8 kb)" +//config: bool "add-shell (3.1 kb)" //config: default y if DESKTOP //config: help //config: Add shells to /etc/shells. //config: //config:config REMOVE_SHELL -//config: bool "remove-shell (2.7 kb)" +//config: bool "remove-shell (3 kb)" //config: default y if DESKTOP //config: help //config: Remove shells from /etc/shells. diff --git a/loginutils/addgroup.c b/loginutils/addgroup.c index 6839eafbd..baa961ff3 100644 --- a/loginutils/addgroup.c +++ b/loginutils/addgroup.c @@ -9,7 +9,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config ADDGROUP -//config: bool "addgroup (8.2 kb)" +//config: bool "addgroup (8.6 kb)" //config: default y //config: select LONG_OPTS //config: help diff --git a/loginutils/deluser.c b/loginutils/deluser.c index 5ee22d4f1..d7e9327ba 100644 --- a/loginutils/deluser.c +++ b/loginutils/deluser.c @@ -9,13 +9,13 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config DELUSER -//config: bool "deluser (8.4 kb)" +//config: bool "deluser (9.1 kb)" //config: default y //config: help //config: Utility for deleting a user account. //config: //config:config DELGROUP -//config: bool "delgroup (5.6 kb)" +//config: bool "delgroup (6.4 kb)" //config: default y //config: help //config: Utility for deleting a group account. diff --git a/mailutils/makemime.c b/mailutils/makemime.c index 7539d5134..53a1820f1 100644 --- a/mailutils/makemime.c +++ b/mailutils/makemime.c @@ -7,7 +7,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config MAKEMIME -//config: bool "makemime (5.9 kb)" +//config: bool "makemime (5.4 kb)" //config: default y //config: help //config: Create MIME-formatted messages. diff --git a/miscutils/adjtimex.c b/miscutils/adjtimex.c index c1718e909..8ca90d58a 100644 --- a/miscutils/adjtimex.c +++ b/miscutils/adjtimex.c @@ -11,7 +11,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config ADJTIMEX -//config: bool "adjtimex (4.5 kb)" +//config: bool "adjtimex (4.7 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/miscutils/bc.c b/miscutils/bc.c index 537612d5e..7179811fe 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -5,7 +5,7 @@ * Original code copyright (c) 2018 Gavin D. Howard and contributors. */ //config:config BC -//config: bool "bc (45 kb; 49 kb when combined with dc)" +//config: bool "bc (45 kb)" //config: default y //config: help //config: bc is a command-line, arbitrary-precision calculator with a @@ -41,7 +41,7 @@ //config: j(n, x) Bessel function of integer order n of x //config: //config:config DC -//config: bool "dc (38 kb; 49 kb when combined with bc)" +//config: bool "dc (36 kb)" //config: default y //config: help //config: dc is a reverse-polish notation command-line calculator which diff --git a/miscutils/beep.c b/miscutils/beep.c index 0c8a8225e..92faa1cd5 100644 --- a/miscutils/beep.c +++ b/miscutils/beep.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config BEEP -//config: bool "beep (3 kb)" +//config: bool "beep (2.4 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/miscutils/chat.c b/miscutils/chat.c index 2dfe52c4f..5183d1369 100644 --- a/miscutils/chat.c +++ b/miscutils/chat.c @@ -8,7 +8,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config CHAT -//config: bool "chat (6.6 kb)" +//config: bool "chat (6.3 kb)" //config: default y //config: help //config: Simple chat utility. diff --git a/miscutils/crond.c b/miscutils/crond.c index f6580a9d4..2e36c406b 100644 --- a/miscutils/crond.c +++ b/miscutils/crond.c @@ -9,7 +9,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config CROND -//config: bool "crond (13 kb)" +//config: bool "crond (14 kb)" //config: default y //config: select FEATURE_SYSLOG //config: help diff --git a/miscutils/crontab.c b/miscutils/crontab.c index 4787fa08f..96dc4741a 100644 --- a/miscutils/crontab.c +++ b/miscutils/crontab.c @@ -10,7 +10,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config CRONTAB -//config: bool "crontab (9.7 kb)" +//config: bool "crontab (10 kb)" //config: default y //config: help //config: Crontab manipulates the crontab for a particular user. Only diff --git a/miscutils/fbsplash.c b/miscutils/fbsplash.c index bc3c61055..bba22d6d1 100644 --- a/miscutils/fbsplash.c +++ b/miscutils/fbsplash.c @@ -21,7 +21,7 @@ * "exit" (or just close fifo) - well you guessed it. */ //config:config FBSPLASH -//config: bool "fbsplash (27 kb)" +//config: bool "fbsplash (26 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/miscutils/flash_eraseall.c b/miscutils/flash_eraseall.c index 8e93060ca..a3dabdadb 100644 --- a/miscutils/flash_eraseall.c +++ b/miscutils/flash_eraseall.c @@ -11,7 +11,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config FLASH_ERASEALL -//config: bool "flash_eraseall (5.5 kb)" +//config: bool "flash_eraseall (5.9 kb)" //config: default n # doesn't build on Ubuntu 8.04 //config: help //config: The flash_eraseall binary from mtd-utils as of git head c4c6a59eb. diff --git a/miscutils/flashcp.c b/miscutils/flashcp.c index 858cee194..1ca9d158d 100644 --- a/miscutils/flashcp.c +++ b/miscutils/flashcp.c @@ -7,7 +7,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config FLASHCP -//config: bool "flashcp (5.4 kb)" +//config: bool "flashcp (5.3 kb)" //config: default n # doesn't build on Ubuntu 8.04 //config: help //config: The flashcp binary, inspired by mtd-utils as of git head 5eceb74f7. diff --git a/miscutils/hdparm.c b/miscutils/hdparm.c index 0bbe6ca10..342e240fa 100644 --- a/miscutils/hdparm.c +++ b/miscutils/hdparm.c @@ -12,7 +12,7 @@ * - by Mark Lord (C) 1994-2002 -- freely distributable */ //config:config HDPARM -//config: bool "hdparm (23 kb)" +//config: bool "hdparm (25 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/miscutils/hexedit.c b/miscutils/hexedit.c index 298eb8149..5c2f4a555 100644 --- a/miscutils/hexedit.c +++ b/miscutils/hexedit.c @@ -4,7 +4,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config HEXEDIT -//config: bool "hexedit (20 kb)" +//config: bool "hexedit (21 kb)" //config: default y //config: help //config: Edit file in hexadecimal. diff --git a/miscutils/i2c_tools.c b/miscutils/i2c_tools.c index 6a2134063..610fed5d6 100644 --- a/miscutils/i2c_tools.c +++ b/miscutils/i2c_tools.c @@ -9,28 +9,28 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config I2CGET -//config: bool "i2cget (5.6 kb)" +//config: bool "i2cget (5.5 kb)" //config: default y //config: select PLATFORM_LINUX //config: help //config: Read from I2C/SMBus chip registers. //config: //config:config I2CSET -//config: bool "i2cset (6.9 kb)" +//config: bool "i2cset (6.7 kb)" //config: default y //config: select PLATFORM_LINUX //config: help //config: Set I2C registers. //config: //config:config I2CDUMP -//config: bool "i2cdump (7.2 kb)" +//config: bool "i2cdump (7.1 kb)" //config: default y //config: select PLATFORM_LINUX //config: help //config: Examine I2C registers. //config: //config:config I2CDETECT -//config: bool "i2cdetect (7.2 kb)" +//config: bool "i2cdetect (7.1 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/miscutils/inotifyd.c b/miscutils/inotifyd.c index 0060797ed..ec0321941 100644 --- a/miscutils/inotifyd.c +++ b/miscutils/inotifyd.c @@ -27,7 +27,7 @@ * See below for mask names explanation. */ //config:config INOTIFYD -//config: bool "inotifyd (3.5 kb)" +//config: bool "inotifyd (3.6 kb)" //config: default n # doesn't build on Knoppix 5 //config: help //config: Simple inotify daemon. Reports filesystem changes. Requires diff --git a/miscutils/less.c b/miscutils/less.c index 938d9842f..223c2558d 100644 --- a/miscutils/less.c +++ b/miscutils/less.c @@ -20,7 +20,7 @@ * redirected input has been read from stdin */ //config:config LESS -//config: bool "less (15 kb)" +//config: bool "less (16 kb)" //config: default y //config: help //config: 'less' is a pager, meaning that it displays text files. It possesses diff --git a/miscutils/lsscsi.c b/miscutils/lsscsi.c index 0aaa01ded..f737d33d9 100644 --- a/miscutils/lsscsi.c +++ b/miscutils/lsscsi.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config LSSCSI -//config: bool "lsscsi (2.4 kb)" +//config: bool "lsscsi (2.5 kb)" //config: default y //config: #select PLATFORM_LINUX //config: help diff --git a/miscutils/makedevs.c b/miscutils/makedevs.c index 80975c652..93c550042 100644 --- a/miscutils/makedevs.c +++ b/miscutils/makedevs.c @@ -7,7 +7,7 @@ * known bugs: can't deal with alpha ranges */ //config:config MAKEDEVS -//config: bool "makedevs (9.3 kb)" +//config: bool "makedevs (9.2 kb)" //config: default y //config: help //config: 'makedevs' is a utility used to create a batch of devices with diff --git a/miscutils/man.c b/miscutils/man.c index ba6bb4c01..01155c8f0 100644 --- a/miscutils/man.c +++ b/miscutils/man.c @@ -3,7 +3,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config MAN -//config: bool "man (27 kb)" +//config: bool "man (26 kb)" //config: default y //config: help //config: Format and display manual pages. diff --git a/miscutils/microcom.c b/miscutils/microcom.c index fa090057e..399d4cf7f 100644 --- a/miscutils/microcom.c +++ b/miscutils/microcom.c @@ -8,7 +8,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config MICROCOM -//config: bool "microcom (5.6 kb)" +//config: bool "microcom (5.7 kb)" //config: default y //config: help //config: The poor man's minicom utility for chatting with serial port devices. diff --git a/miscutils/mt.c b/miscutils/mt.c index fad656e95..9f1aecfca 100644 --- a/miscutils/mt.c +++ b/miscutils/mt.c @@ -3,7 +3,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config MT -//config: bool "mt (2.6 kb)" +//config: bool "mt (2.5 kb)" //config: default y //config: help //config: mt is used to control tape devices. You can use the mt utility diff --git a/miscutils/nandwrite.c b/miscutils/nandwrite.c index 29c800612..09bcaaf63 100644 --- a/miscutils/nandwrite.c +++ b/miscutils/nandwrite.c @@ -8,14 +8,14 @@ * TODO: add support for large (>4GB) MTD devices */ //config:config NANDWRITE -//config: bool "nandwrite (5.9 kb)" +//config: bool "nandwrite (4.8 kb)" //config: default y //config: select PLATFORM_LINUX //config: help //config: Write to the specified MTD device, with bad blocks awareness //config: //config:config NANDDUMP -//config: bool "nanddump (6.3 kb)" +//config: bool "nanddump (5.2 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/miscutils/partprobe.c b/miscutils/partprobe.c index d1ae27348..0abed6ff1 100644 --- a/miscutils/partprobe.c +++ b/miscutils/partprobe.c @@ -5,7 +5,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config PARTPROBE -//config: bool "partprobe (3.6 kb)" +//config: bool "partprobe (3.5 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/miscutils/raidautorun.c b/miscutils/raidautorun.c index d315c2734..39816ab1f 100644 --- a/miscutils/raidautorun.c +++ b/miscutils/raidautorun.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config RAIDAUTORUN -//config: bool "raidautorun (1.4 kb)" +//config: bool "raidautorun (1.3 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/miscutils/readahead.c b/miscutils/readahead.c index 972302a18..cc0ba5ba3 100644 --- a/miscutils/readahead.c +++ b/miscutils/readahead.c @@ -10,7 +10,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config READAHEAD -//config: bool "readahead (2 kb)" +//config: bool "readahead (1.5 kb)" //config: default y //config: depends on LFS //config: select PLATFORM_LINUX diff --git a/miscutils/rfkill.c b/miscutils/rfkill.c index ae38c182d..766bad8c7 100644 --- a/miscutils/rfkill.c +++ b/miscutils/rfkill.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config RFKILL -//config: bool "rfkill (5.3 kb)" +//config: bool "rfkill (4.4 kb)" //config: default n # doesn't build on Ubuntu 9.04 //config: select PLATFORM_LINUX //config: help diff --git a/miscutils/runlevel.c b/miscutils/runlevel.c index 0b2098564..885b403db 100644 --- a/miscutils/runlevel.c +++ b/miscutils/runlevel.c @@ -12,7 +12,7 @@ * initially busyboxified by Bernhard Reutner-Fischer */ //config:config RUNLEVEL -//config: bool "runlevel (518 bytes)" +//config: bool "runlevel (559 bytes)" //config: default y //config: depends on FEATURE_UTMP //config: help diff --git a/miscutils/setfattr.c b/miscutils/setfattr.c index 12eebc56e..9792c2660 100644 --- a/miscutils/setfattr.c +++ b/miscutils/setfattr.c @@ -6,7 +6,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config SETFATTR -//config: bool "setfattr (3.6 kb)" +//config: bool "setfattr (3.7 kb)" //config: default y //config: help //config: Set/delete extended attributes on files diff --git a/miscutils/setserial.c b/miscutils/setserial.c index fd88ed106..71b274568 100644 --- a/miscutils/setserial.c +++ b/miscutils/setserial.c @@ -8,7 +8,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config SETSERIAL -//config: bool "setserial (6.6 kb)" +//config: bool "setserial (6.9 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/miscutils/strings.c b/miscutils/strings.c index ccb05f6d4..51412f401 100644 --- a/miscutils/strings.c +++ b/miscutils/strings.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config STRINGS -//config: bool "strings (4.3 kb)" +//config: bool "strings (4.6 kb)" //config: default y //config: help //config: strings prints the printable character sequences for each file diff --git a/miscutils/time.c b/miscutils/time.c index 7d6a7a29f..064888ab8 100644 --- a/miscutils/time.c +++ b/miscutils/time.c @@ -10,7 +10,7 @@ * Heavily modified for busybox by Erik Andersen */ //config:config TIME -//config: bool "time (7 kb)" +//config: bool "time (6.8 kb)" //config: default y //config: help //config: The time command runs the specified program with the given arguments. diff --git a/miscutils/ttysize.c b/miscutils/ttysize.c index 2c2d4ec33..d635b29ce 100644 --- a/miscutils/ttysize.c +++ b/miscutils/ttysize.c @@ -10,7 +10,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config TTYSIZE -//config: bool "ttysize (372 bytes)" +//config: bool "ttysize (432 bytes)" //config: default y //config: help //config: A replacement for "stty size". Unlike stty, can report only width, diff --git a/miscutils/ubi_tools.c b/miscutils/ubi_tools.c index a947abab5..dc7af25a4 100644 --- a/miscutils/ubi_tools.c +++ b/miscutils/ubi_tools.c @@ -4,42 +4,42 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config UBIATTACH -//config: bool "ubiattach (4.7 kb)" +//config: bool "ubiattach (4.2 kb)" //config: default y //config: select PLATFORM_LINUX //config: help //config: Attach MTD device to an UBI device. //config: //config:config UBIDETACH -//config: bool "ubidetach (4.6 kb)" +//config: bool "ubidetach (4.1 kb)" //config: default y //config: select PLATFORM_LINUX //config: help //config: Detach MTD device from an UBI device. //config: //config:config UBIMKVOL -//config: bool "ubimkvol (5.8 kb)" +//config: bool "ubimkvol (5.3 kb)" //config: default y //config: select PLATFORM_LINUX //config: help //config: Create a UBI volume. //config: //config:config UBIRMVOL -//config: bool "ubirmvol (5.2 kb)" +//config: bool "ubirmvol (4.9 kb)" //config: default y //config: select PLATFORM_LINUX //config: help //config: Delete a UBI volume. //config: //config:config UBIRSVOL -//config: bool "ubirsvol (4.6 kb)" +//config: bool "ubirsvol (4.2 kb)" //config: default y //config: select PLATFORM_LINUX //config: help //config: Resize a UBI volume. //config: //config:config UBIUPDATEVOL -//config: bool "ubiupdatevol (5.6 kb)" +//config: bool "ubiupdatevol (5.2 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/miscutils/ubirename.c b/miscutils/ubirename.c index ecc8fe137..21bd10111 100644 --- a/miscutils/ubirename.c +++ b/miscutils/ubirename.c @@ -7,7 +7,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config UBIRENAME -//config: bool "ubirename (2.2 kb)" +//config: bool "ubirename (2.4 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/miscutils/volname.c b/miscutils/volname.c index 6e6bbaa44..027d01272 100644 --- a/miscutils/volname.c +++ b/miscutils/volname.c @@ -28,7 +28,7 @@ * Matthew Stoltenberg */ //config:config VOLNAME -//config: bool "volname (1.7 kb)" +//config: bool "volname (1.6 kb)" //config: default y //config: help //config: Prints a CD-ROM volume name. diff --git a/miscutils/watchdog.c b/miscutils/watchdog.c index 392d05646..1e9ecc5e8 100644 --- a/miscutils/watchdog.c +++ b/miscutils/watchdog.c @@ -9,7 +9,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config WATCHDOG -//config: bool "watchdog (5.1 kb)" +//config: bool "watchdog (5.3 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/modutils/depmod.c b/modutils/depmod.c index 004c67a11..b5244fc60 100644 --- a/modutils/depmod.c +++ b/modutils/depmod.c @@ -8,7 +8,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config DEPMOD -//config: bool "depmod (26 kb)" +//config: bool "depmod (27 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/modutils/lsmod.c b/modutils/lsmod.c index 84860cd79..694205fda 100644 --- a/modutils/lsmod.c +++ b/modutils/lsmod.c @@ -8,7 +8,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config LSMOD -//config: bool "lsmod (4.3 kb)" +//config: bool "lsmod (1.9 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/modutils/modinfo.c b/modutils/modinfo.c index 3f91622a9..1e63f745f 100644 --- a/modutils/modinfo.c +++ b/modutils/modinfo.c @@ -6,7 +6,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config MODINFO -//config: bool "modinfo (25 kb)" +//config: bool "modinfo (24 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/modutils/modprobe.c b/modutils/modprobe.c index 291e4cb90..0a372a049 100644 --- a/modutils/modprobe.c +++ b/modutils/modprobe.c @@ -8,7 +8,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config MODPROBE -//config: bool "modprobe (29 kb)" +//config: bool "modprobe (28 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/modutils/rmmod.c b/modutils/rmmod.c index df50e58af..a3548879c 100644 --- a/modutils/rmmod.c +++ b/modutils/rmmod.c @@ -8,7 +8,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config RMMOD -//config: bool "rmmod (3.6 kb)" +//config: bool "rmmod (3.3 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/networking/arp.c b/networking/arp.c index 177ab1571..71bfe3cbf 100644 --- a/networking/arp.c +++ b/networking/arp.c @@ -13,7 +13,7 @@ * modified for getopt32 by Arne Bernin */ //config:config ARP -//config: bool "arp (11 kb)" +//config: bool "arp (10 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/networking/arping.c b/networking/arping.c index 788fded3c..901578b68 100644 --- a/networking/arping.c +++ b/networking/arping.c @@ -6,7 +6,7 @@ * Busybox port: Nick Fedchik */ //config:config ARPING -//config: bool "arping (9.3 kb)" +//config: bool "arping (9 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/networking/ether-wake.c b/networking/ether-wake.c index 6677f07d5..acaac16f8 100644 --- a/networking/ether-wake.c +++ b/networking/ether-wake.c @@ -64,7 +64,7 @@ * filter. That configuration consumes more power. */ //config:config ETHER_WAKE -//config: bool "ether-wake (6.6 kb)" +//config: bool "ether-wake (4.9 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/networking/ftpgetput.c b/networking/ftpgetput.c index 2f2921366..cb6910fb0 100644 --- a/networking/ftpgetput.c +++ b/networking/ftpgetput.c @@ -13,13 +13,13 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config FTPGET -//config: bool "ftpget (8 kb)" +//config: bool "ftpget (7.8 kb)" //config: default y //config: help //config: Retrieve a remote file via FTP. //config: //config:config FTPPUT -//config: bool "ftpput (7.7 kb)" +//config: bool "ftpput (7.5 kb)" //config: default y //config: help //config: Store a remote file via FTP. diff --git a/networking/hostname.c b/networking/hostname.c index 8e3238d99..248d8b65a 100644 --- a/networking/hostname.c +++ b/networking/hostname.c @@ -10,7 +10,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config HOSTNAME -//config: bool "hostname (5.6 kb)" +//config: bool "hostname (5.5 kb)" //config: default y //config: help //config: Show or set the system's host name. diff --git a/networking/ifplugd.c b/networking/ifplugd.c index 9a67d24d8..026ff1cc8 100644 --- a/networking/ifplugd.c +++ b/networking/ifplugd.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config IFPLUGD -//config: bool "ifplugd (9.9 kb)" +//config: bool "ifplugd (10 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/networking/ifupdown.c b/networking/ifupdown.c index 80fce87a6..8a6efc976 100644 --- a/networking/ifupdown.c +++ b/networking/ifupdown.c @@ -17,7 +17,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config IFUP -//config: bool "ifup (17 kb)" +//config: bool "ifup (14 kb)" //config: default y //config: help //config: Activate the specified interfaces. This applet makes use @@ -33,7 +33,7 @@ //config: via busybox or via standalone utilities. //config: //config:config IFDOWN -//config: bool "ifdown (15 kb)" +//config: bool "ifdown (13 kb)" //config: default y //config: help //config: Deactivate the specified interfaces. diff --git a/networking/ip.c b/networking/ip.c index 97d618cd9..034ee4fc8 100644 --- a/networking/ip.c +++ b/networking/ip.c @@ -9,7 +9,7 @@ * Bernhard Reutner-Fischer rewrote to use index_in_substr_array */ //config:config IP -//config: bool "ip (34 kb)" +//config: bool "ip (35 kb)" //config: default y //config: select PLATFORM_LINUX //config: help @@ -28,7 +28,7 @@ //config: Short form of "ip addr" //config: //config:config IPLINK -//config: bool "iplink (16 kb)" +//config: bool "iplink (17 kb)" //config: default y //config: select FEATURE_IP_LINK //config: select PLATFORM_LINUX diff --git a/networking/ipcalc.c b/networking/ipcalc.c index cdae8eea8..67f768836 100644 --- a/networking/ipcalc.c +++ b/networking/ipcalc.c @@ -12,7 +12,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config IPCALC -//config: bool "ipcalc (4.3 kb)" +//config: bool "ipcalc (4.4 kb)" //config: default y //config: help //config: ipcalc takes an IP address and netmask and calculates the diff --git a/networking/isrv_identd.c b/networking/isrv_identd.c index 0c33dde4f..f564d604a 100644 --- a/networking/isrv_identd.c +++ b/networking/isrv_identd.c @@ -7,7 +7,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config FAKEIDENTD -//config: bool "fakeidentd (8.9 kb)" +//config: bool "fakeidentd (8.7 kb)" //config: default y //config: select FEATURE_SYSLOG //config: help diff --git a/networking/nbd-client.c b/networking/nbd-client.c index 1ce974db1..0dc8d0c43 100644 --- a/networking/nbd-client.c +++ b/networking/nbd-client.c @@ -4,7 +4,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config NBDCLIENT -//config: bool "nbd-client (4.6 kb)" +//config: bool "nbd-client (6 kb)" //config: default y //config: help //config: Network block device client diff --git a/networking/nslookup.c b/networking/nslookup.c index e153eb585..cd3c00003 100644 --- a/networking/nslookup.c +++ b/networking/nslookup.c @@ -1,7 +1,7 @@ /* vi: set sw=4 ts=4: */ //config:config NSLOOKUP -//config: bool "nslookup (4.5 kb)" +//config: bool "nslookup (9.7 kb)" //config: default y //config: help //config: nslookup is a tool to query Internet name servers. diff --git a/networking/ntpd.c b/networking/ntpd.c index 041cac762..855815ece 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c @@ -41,7 +41,7 @@ *********************************************************************** */ //config:config NTPD -//config: bool "ntpd (17 kb)" +//config: bool "ntpd (22 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/networking/ping.c b/networking/ping.c index 570184fee..b534c74c7 100644 --- a/networking/ping.c +++ b/networking/ping.c @@ -25,7 +25,7 @@ * The code was modified by Bart Visscher */ //config:config PING -//config: bool "ping (9.5 kb)" +//config: bool "ping (10 kb)" //config: default y //config: select PLATFORM_LINUX //config: help @@ -33,7 +33,7 @@ //config: elicit an ICMP ECHO_RESPONSE from a host or gateway. //config: //config:config PING6 -//config: bool "ping6 (10 kb)" +//config: bool "ping6 (11 kb)" //config: default y //config: depends on FEATURE_IPV6 //config: help diff --git a/networking/pscan.c b/networking/pscan.c index 95b0a937d..2715ef2df 100644 --- a/networking/pscan.c +++ b/networking/pscan.c @@ -6,7 +6,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config PSCAN -//config: bool "pscan (6.6 kb)" +//config: bool "pscan (6 kb)" //config: default y //config: help //config: Simple network port scanner. diff --git a/networking/route.c b/networking/route.c index 8387ce1bb..ac1d94c28 100644 --- a/networking/route.c +++ b/networking/route.c @@ -25,7 +25,7 @@ * remove ridiculous amounts of bloat. */ //config:config ROUTE -//config: bool "route (8.9 kb)" +//config: bool "route (8.7 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/networking/slattach.c b/networking/slattach.c index e0a388926..c6feca248 100644 --- a/networking/slattach.c +++ b/networking/slattach.c @@ -13,7 +13,7 @@ * - The -F options allows disabling of RTS/CTS flow control. */ //config:config SLATTACH -//config: bool "slattach (6.1 kb)" +//config: bool "slattach (6.2 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/networking/ssl_client.c b/networking/ssl_client.c index 875352d18..397aad297 100644 --- a/networking/ssl_client.c +++ b/networking/ssl_client.c @@ -4,7 +4,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config SSL_CLIENT -//config: bool "ssl_client (23 kb)" +//config: bool "ssl_client (25 kb)" //config: default y //config: select TLS //config: help diff --git a/networking/tc.c b/networking/tc.c index 4fa3e47bf..3e9808328 100644 --- a/networking/tc.c +++ b/networking/tc.c @@ -7,7 +7,7 @@ * Bernhard Reutner-Fischer adjusted for busybox */ //config:config TC -//config: bool "tc (3.1 kb)" +//config: bool "tc (8.3 kb)" //config: default y //config: help //config: Show / manipulate traffic control settings diff --git a/networking/tcpudp.c b/networking/tcpudp.c index c914221ae..a0af64981 100644 --- a/networking/tcpudp.c +++ b/networking/tcpudp.c @@ -29,7 +29,7 @@ * - don't know how to retrieve ORIGDST for udp. */ //config:config TCPSVD -//config: bool "tcpsvd (13 kb)" +//config: bool "tcpsvd (14 kb)" //config: default y //config: help //config: tcpsvd listens on a TCP port and runs a program for each new diff --git a/networking/telnet.c b/networking/telnet.c index 1e6be85bd..7f65ff3e6 100644 --- a/networking/telnet.c +++ b/networking/telnet.c @@ -20,7 +20,7 @@ * by Fernando Silveira */ //config:config TELNET -//config: bool "telnet (8.7 kb)" +//config: bool "telnet (8.8 kb)" //config: default y //config: help //config: Telnet is an interface to the TELNET protocol, but is also commonly diff --git a/networking/tftp.c b/networking/tftp.c index 4cd39186a..1828688d4 100644 --- a/networking/tftp.c +++ b/networking/tftp.c @@ -19,7 +19,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config TFTP -//config: bool "tftp (12 kb)" +//config: bool "tftp (11 kb)" //config: default y //config: help //config: Trivial File Transfer Protocol client. TFTP is usually used diff --git a/networking/traceroute.c b/networking/traceroute.c index a027b928a..bdf451186 100644 --- a/networking/traceroute.c +++ b/networking/traceroute.c @@ -217,7 +217,7 @@ //config: Utility to trace the route of IP packets. //config: //config:config TRACEROUTE6 -//config: bool "traceroute6 (12 kb)" +//config: bool "traceroute6 (13 kb)" //config: default y //config: depends on FEATURE_IPV6 //config: help diff --git a/networking/tunctl.c b/networking/tunctl.c index f2dc645a1..a0e3926e9 100644 --- a/networking/tunctl.c +++ b/networking/tunctl.c @@ -10,7 +10,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config TUNCTL -//config: bool "tunctl (6.4 kb)" +//config: bool "tunctl (6.2 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index 3c6129249..38c91cbb4 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c @@ -9,7 +9,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config UDHCPC6 -//config: bool "udhcpc6" +//config: bool "udhcpc6 (21 kb)" //config: default n # not yet ready //config: depends on FEATURE_IPV6 //config: help diff --git a/networking/vconfig.c b/networking/vconfig.c index 8548c8c3b..3cc5f2460 100644 --- a/networking/vconfig.c +++ b/networking/vconfig.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config VCONFIG -//config: bool "vconfig (2.5 kb)" +//config: bool "vconfig (2.3 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/networking/wget.c b/networking/wget.c index 58a51d9ff..30683dfc0 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -9,7 +9,7 @@ * Kuhn's copyrights are licensed GPLv2-or-later. File as a whole remains GPLv2. */ //config:config WGET -//config: bool "wget (35 kb)" +//config: bool "wget (38 kb)" //config: default y //config: help //config: wget is a utility for non-interactive download of files from HTTP diff --git a/networking/whois.c b/networking/whois.c index f3da32b4e..55e1de964 100644 --- a/networking/whois.c +++ b/networking/whois.c @@ -10,7 +10,7 @@ * Add proxy support */ //config:config WHOIS -//config: bool "whois (6.6 kb)" +//config: bool "whois (6.3 kb)" //config: default y //config: help //config: whois is a client for the whois directory service diff --git a/networking/zcip.c b/networking/zcip.c index 94e49adcb..434762f12 100644 --- a/networking/zcip.c +++ b/networking/zcip.c @@ -14,7 +14,7 @@ * certainly be used. Its naming is built over multicast DNS. */ //config:config ZCIP -//config: bool "zcip (7.8 kb)" +//config: bool "zcip (8.4 kb)" //config: default y //config: select PLATFORM_LINUX //config: select FEATURE_SYSLOG diff --git a/printutils/lpd.c b/printutils/lpd.c index 662d3a224..ce5944026 100644 --- a/printutils/lpd.c +++ b/printutils/lpd.c @@ -70,7 +70,7 @@ * mv -f ./"$DATAFILE" save/ */ //config:config LPD -//config: bool "lpd (5.3 kb)" +//config: bool "lpd (5.5 kb)" //config: default y //config: help //config: lpd is a print spooling daemon. diff --git a/printutils/lpr.c b/printutils/lpr.c index 808ecb5dc..7acb6c357 100644 --- a/printutils/lpr.c +++ b/printutils/lpr.c @@ -12,13 +12,13 @@ * See RFC 1179 for protocol description. */ //config:config LPR -//config: bool "lpr (10 kb)" +//config: bool "lpr (9.9 kb)" //config: default y //config: help //config: lpr sends files (or standard input) to a print spooling daemon. //config: //config:config LPQ -//config: bool "lpq (10 kb)" +//config: bool "lpq (9.9 kb)" //config: default y //config: help //config: lpq is a print spool queue examination and manipulation program. diff --git a/procps/free.c b/procps/free.c index ee0cd981a..3acfc4072 100644 --- a/procps/free.c +++ b/procps/free.c @@ -7,7 +7,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config FREE -//config: bool "free (2.4 kb)" +//config: bool "free (3.1 kb)" //config: default y //config: select PLATFORM_LINUX #sysinfo() //config: help diff --git a/procps/iostat.c b/procps/iostat.c index 8fb4594da..1c6fb87ba 100644 --- a/procps/iostat.c +++ b/procps/iostat.c @@ -7,7 +7,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config IOSTAT -//config: bool "iostat (7.4 kb)" +//config: bool "iostat (7.6 kb)" //config: default y //config: help //config: Report CPU and I/O statistics diff --git a/procps/kill.c b/procps/kill.c index c95afb8b3..a30a79dd8 100644 --- a/procps/kill.c +++ b/procps/kill.c @@ -8,7 +8,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config KILL -//config: bool "kill (2.6 kb)" +//config: bool "kill (3.1 kb)" //config: default y //config: help //config: The command kill sends the specified signal to the specified diff --git a/procps/lsof.c b/procps/lsof.c index 4917cf899..21ac85ed3 100644 --- a/procps/lsof.c +++ b/procps/lsof.c @@ -7,7 +7,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config LSOF -//config: bool "lsof (3.6 kb)" +//config: bool "lsof (3.4 kb)" //config: default y //config: help //config: Show open files in the format of: diff --git a/procps/mpstat.c b/procps/mpstat.c index ed678f456..4ea1b5d97 100644 --- a/procps/mpstat.c +++ b/procps/mpstat.c @@ -7,7 +7,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config MPSTAT -//config: bool "mpstat (10 kb)" +//config: bool "mpstat (9.8 kb)" //config: default y //config: help //config: Per-processor statistics diff --git a/procps/nmeter.c b/procps/nmeter.c index 166c8ab18..a01d19a6a 100644 --- a/procps/nmeter.c +++ b/procps/nmeter.c @@ -6,7 +6,7 @@ * Contact me: vda.linux@googlemail.com */ //config:config NMETER -//config: bool "nmeter (10 kb)" +//config: bool "nmeter (11 kb)" //config: default y //config: help //config: Prints selected system stats continuously, one line per update. diff --git a/procps/pgrep.c b/procps/pgrep.c index a16a6e959..495e0ef9d 100644 --- a/procps/pgrep.c +++ b/procps/pgrep.c @@ -7,13 +7,13 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config PGREP -//config: bool "pgrep (6.8 kb)" +//config: bool "pgrep (6.5 kb)" //config: default y //config: help //config: Look for processes by name. //config: //config:config PKILL -//config: bool "pkill (7.6 kb)" +//config: bool "pkill (7.5 kb)" //config: default y //config: help //config: Send signals to processes by name. diff --git a/procps/pidof.c b/procps/pidof.c index 98d7949f8..5595e3421 100644 --- a/procps/pidof.c +++ b/procps/pidof.c @@ -7,7 +7,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config PIDOF -//config: bool "pidof (6.6 kb)" +//config: bool "pidof (6.3 kb)" //config: default y //config: help //config: Pidof finds the process id's (pids) of the named programs. It prints diff --git a/procps/powertop.c b/procps/powertop.c index 004b4ce19..e70f5433b 100644 --- a/procps/powertop.c +++ b/procps/powertop.c @@ -9,7 +9,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config POWERTOP -//config: bool "powertop (9.1 kb)" +//config: bool "powertop (9.6 kb)" //config: default y //config: help //config: Analyze power consumption on Intel-based laptops diff --git a/procps/pstree.c b/procps/pstree.c index 4fda1c21c..1d124d2d2 100644 --- a/procps/pstree.c +++ b/procps/pstree.c @@ -10,7 +10,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config PSTREE -//config: bool "pstree (9.4 kb)" +//config: bool "pstree (9.3 kb)" //config: default y //config: help //config: Display a tree of processes. diff --git a/procps/pwdx.c b/procps/pwdx.c index 6009e2aa3..24ba25d90 100644 --- a/procps/pwdx.c +++ b/procps/pwdx.c @@ -8,7 +8,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config PWDX -//config: bool "pwdx (3.5 kb)" +//config: bool "pwdx (3.7 kb)" //config: default y //config: help //config: Report current working directory of a process diff --git a/procps/sysctl.c b/procps/sysctl.c index 827e09cce..5fa7646d1 100644 --- a/procps/sysctl.c +++ b/procps/sysctl.c @@ -11,7 +11,7 @@ * v1.01.1 - busybox applet aware by */ //config:config BB_SYSCTL -//config: bool "sysctl (6.9 kb)" +//config: bool "sysctl (7.4 kb)" //config: default y //config: help //config: Configure kernel parameters at runtime. diff --git a/procps/top.c b/procps/top.c index f016f5501..3db077060 100644 --- a/procps/top.c +++ b/procps/top.c @@ -50,7 +50,7 @@ * chroot . ./top -bn1 >top1.out */ //config:config TOP -//config: bool "top (17 kb)" +//config: bool "top (18 kb)" //config: default y //config: help //config: The top program provides a dynamic real-time view of a running diff --git a/procps/uptime.c b/procps/uptime.c index 3262f41b4..31581271f 100644 --- a/procps/uptime.c +++ b/procps/uptime.c @@ -12,7 +12,7 @@ * Added FEATURE_UPTIME_UTMP_SUPPORT flag. */ //config:config UPTIME -//config: bool "uptime (632 bytes)" +//config: bool "uptime (3.7 kb)" //config: default y //config: select PLATFORM_LINUX #sysinfo() //config: help diff --git a/procps/watch.c b/procps/watch.c index 420e6d3d1..dbe427aad 100644 --- a/procps/watch.c +++ b/procps/watch.c @@ -8,7 +8,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config WATCH -//config: bool "watch (4.1 kb)" +//config: bool "watch (4.4 kb)" //config: default y //config: help //config: watch is used to execute a program periodically, showing diff --git a/runit/chpst.c b/runit/chpst.c index c2641ce8a..5e77245f6 100644 --- a/runit/chpst.c +++ b/runit/chpst.c @@ -28,20 +28,20 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /* Busyboxed by Denys Vlasenko */ //config:config CHPST -//config: bool "chpst (8.7 kb)" +//config: bool "chpst (9 kb)" //config: default y //config: help //config: chpst changes the process state according to the given options, and //config: execs specified program. //config: //config:config SETUIDGID -//config: bool "setuidgid (4.2 kb)" +//config: bool "setuidgid (4 kb)" //config: default y //config: help //config: Sets soft resource limits as specified by options //config: //config:config ENVUIDGID -//config: bool "envuidgid (3.6 kb)" +//config: bool "envuidgid (3.9 kb)" //config: default y //config: help //config: Sets $UID to account's uid and $GID to account's gid @@ -54,7 +54,7 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. //config: in the given directory //config: //config:config SOFTLIMIT -//config: bool "softlimit (4.3 kb)" +//config: bool "softlimit (4.5 kb)" //config: default y //config: help //config: Sets soft resource limits as specified by options diff --git a/runit/runsv.c b/runit/runsv.c index a67280b4b..ccc762d78 100644 --- a/runit/runsv.c +++ b/runit/runsv.c @@ -28,7 +28,7 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /* Busyboxed by Denys Vlasenko */ //config:config RUNSV -//config: bool "runsv (7.2 kb)" +//config: bool "runsv (7.8 kb)" //config: default y //config: help //config: runsv starts and monitors a service and optionally an appendant log diff --git a/runit/runsvdir.c b/runit/runsvdir.c index 11ab40abf..55dd47e0d 100644 --- a/runit/runsvdir.c +++ b/runit/runsvdir.c @@ -28,7 +28,7 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /* Busyboxed by Denys Vlasenko */ //config:config RUNSVDIR -//config: bool "runsvdir (6 kb)" +//config: bool "runsvdir (6.3 kb)" //config: default y //config: help //config: runsvdir starts a runsv process for each subdirectory, or symlink to diff --git a/runit/sv.c b/runit/sv.c index 8054daedf..5c249ff95 100644 --- a/runit/sv.c +++ b/runit/sv.c @@ -154,7 +154,7 @@ Exit Codes /* Busyboxed by Denys Vlasenko */ //config:config SV -//config: bool "sv (7.8 kb)" +//config: bool "sv (8.5 kb)" //config: default y //config: help //config: sv reports the current status and controls the state of services @@ -169,14 +169,14 @@ Exit Codes //config: Defaults to "/var/service" //config: //config:config SVC -//config: bool "svc (7.8 kb)" +//config: bool "svc (8.4 kb)" //config: default y //config: help //config: svc controls the state of services monitored by the runsv supervisor. //config: It is compatible with daemontools command with the same name. //config: //config:config SVOK -//config: bool "svok" +//config: bool "svok (1.5 kb)" //config: default y //config: help //config: svok checks whether runsv supervisor is running. diff --git a/runit/svlogd.c b/runit/svlogd.c index b0690d794..c9e5346d1 100644 --- a/runit/svlogd.c +++ b/runit/svlogd.c @@ -124,7 +124,7 @@ log message, you can use a pattern like this instead -*: *: pid * */ //config:config SVLOGD -//config: bool "svlogd (15 kb)" +//config: bool "svlogd (16 kb)" //config: default y //config: help //config: svlogd continuously reads log data from its standard input, optionally diff --git a/shell/ash.c b/shell/ash.c index a01c8fa8b..a284b084d 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -16,7 +16,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config ASH -//config: bool "ash (77 kb)" +//config: bool "ash (78 kb)" //config: default y //config: depends on !NOMMU //config: help diff --git a/shell/cttyhack.c b/shell/cttyhack.c index ec1b6c429..b9ee59bd0 100644 --- a/shell/cttyhack.c +++ b/shell/cttyhack.c @@ -5,7 +5,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config CTTYHACK -//config: bool "cttyhack (2.5 kb)" +//config: bool "cttyhack (2.4 kb)" //config: default y //config: help //config: One common problem reported on the mailing list is the "can't diff --git a/shell/hush.c b/shell/hush.c index d80c717e7..920a85299 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -93,7 +93,7 @@ * add =~ regex match operator: STR =~ REGEX */ //config:config HUSH -//config: bool "hush (64 kb)" +//config: bool "hush (68 kb)" //config: default y //config: help //config: hush is a small shell. It handles the normal flow control diff --git a/size_single_applets.sh b/size_single_applets.sh index ee16d4de7..f7f327b43 100755 --- a/size_single_applets.sh +++ b/size_single_applets.sh @@ -1,4 +1,12 @@ #!/bin/bash +# Which config to use when updating the sizes in "official" +# source tree? I am using x86 glibc toolchain of some typical distro, +# not-static build, 32-bit defconfig build: +# # CONFIG_STATIC is not set +# CONFIG_CROSS_COMPILER_PREFIX="" +# CONFIG_EXTRA_CFLAGS="-m32" +# CONFIG_EXTRA_LDFLAGS="-m32" + # The list of all applet config symbols test -f include/applets.h || { echo "No include/applets.h file"; exit 1; } apps="` diff --git a/sysklogd/klogd.c b/sysklogd/klogd.c index 25ddf3172..76eccf1da 100644 --- a/sysklogd/klogd.c +++ b/sysklogd/klogd.c @@ -17,7 +17,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config KLOGD -//config: bool "klogd (5.5 kb)" +//config: bool "klogd (5.7 kb)" //config: default y //config: help //config: klogd is a utility which intercepts and logs all diff --git a/sysklogd/logger.c b/sysklogd/logger.c index 1e0384c09..4d692d6fc 100644 --- a/sysklogd/logger.c +++ b/sysklogd/logger.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config LOGGER -//config: bool "logger (6.4 kb)" +//config: bool "logger (6.3 kb)" //config: default y //config: select FEATURE_SYSLOG //config: help diff --git a/sysklogd/logread.c b/sysklogd/logread.c index da552e087..ea41fc0c8 100644 --- a/sysklogd/logread.c +++ b/sysklogd/logread.c @@ -9,7 +9,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config LOGREAD -//config: bool "logread (6 kb)" +//config: bool "logread (4.8 kb)" //config: default y //WRONG: it should be compilable without SYSLOG=y: //WRONG: depends on FEATURE_IPC_SYSLOG diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c index 5630d97fc..f12359476 100644 --- a/sysklogd/syslogd.c +++ b/sysklogd/syslogd.c @@ -13,7 +13,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config SYSLOGD -//config: bool "syslogd (12 kb)" +//config: bool "syslogd (13 kb)" //config: default y //config: help //config: The syslogd utility is used to record logs of all the diff --git a/util-linux/acpid.c b/util-linux/acpid.c index 4f491fa14..7274b6866 100644 --- a/util-linux/acpid.c +++ b/util-linux/acpid.c @@ -7,7 +7,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config ACPID -//config: bool "acpid (8.7 kb)" +//config: bool "acpid (9 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/util-linux/blkdiscard.c b/util-linux/blkdiscard.c index e4902e5b5..a77c7d057 100644 --- a/util-linux/blkdiscard.c +++ b/util-linux/blkdiscard.c @@ -6,7 +6,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config BLKDISCARD -//config: bool "blkdiscard (5.3 kb)" +//config: bool "blkdiscard (4.3 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/util-linux/blkid.c b/util-linux/blkid.c index a56b69661..008ae5d9e 100644 --- a/util-linux/blkid.c +++ b/util-linux/blkid.c @@ -7,7 +7,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config BLKID -//config: bool "blkid (11 kb)" +//config: bool "blkid (12 kb)" //config: default y //config: select PLATFORM_LINUX //config: select VOLUMEID diff --git a/util-linux/blockdev.c b/util-linux/blockdev.c index e53ade995..5d8e465b4 100644 --- a/util-linux/blockdev.c +++ b/util-linux/blockdev.c @@ -6,7 +6,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config BLOCKDEV -//config: bool "blockdev (2.4 kb)" +//config: bool "blockdev (2.3 kb)" //config: default y //config: help //config: Performs some ioctls with block devices. diff --git a/util-linux/cal.c b/util-linux/cal.c index a4a20d5f0..006bc817b 100644 --- a/util-linux/cal.c +++ b/util-linux/cal.c @@ -11,7 +11,7 @@ * Major size reduction... over 50% (>1.5k) on i386. */ //config:config CAL -//config: bool "cal (6.5 kb)" +//config: bool "cal (5.8 kb)" //config: default y //config: help //config: cal is used to display a monthly calendar. diff --git a/util-linux/chrt.c b/util-linux/chrt.c index 45459d940..28e65457c 100644 --- a/util-linux/chrt.c +++ b/util-linux/chrt.c @@ -6,7 +6,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config CHRT -//config: bool "chrt (4.4 kb)" +//config: bool "chrt (4.7 kb)" //config: default y //config: help //config: Manipulate real-time attributes of a process. diff --git a/util-linux/dmesg.c b/util-linux/dmesg.c index 6da9d9f4e..b797c7b2a 100644 --- a/util-linux/dmesg.c +++ b/util-linux/dmesg.c @@ -9,7 +9,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config DMESG -//config: bool "dmesg (3.5 kb)" +//config: bool "dmesg (3.7 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/util-linux/eject.c b/util-linux/eject.c index 6c30facd2..749e2c986 100644 --- a/util-linux/eject.c +++ b/util-linux/eject.c @@ -13,7 +13,7 @@ * Most of the dirty work blatantly ripped off from cat.c =) */ //config:config EJECT -//config: bool "eject (4.1 kb)" +//config: bool "eject (4 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/util-linux/fallocate.c b/util-linux/fallocate.c index 8542586dc..3935e7c9b 100644 --- a/util-linux/fallocate.c +++ b/util-linux/fallocate.c @@ -5,7 +5,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config FALLOCATE -//config: bool "fallocate (5 kb)" +//config: bool "fallocate (4.1 kb)" //config: default y //config: help //config: Preallocate space for files. diff --git a/util-linux/fbset.c b/util-linux/fbset.c index 11cb20cb2..699a19372 100644 --- a/util-linux/fbset.c +++ b/util-linux/fbset.c @@ -12,7 +12,7 @@ * Geert Uytterhoeven (Geert.Uytterhoeven@cs.kuleuven.ac.be) */ //config:config FBSET -//config: bool "fbset (5.8 kb)" +//config: bool "fbset (5.9 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/util-linux/fdformat.c b/util-linux/fdformat.c index c72da8b89..ff3bc4870 100644 --- a/util-linux/fdformat.c +++ b/util-linux/fdformat.c @@ -6,7 +6,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config FDFORMAT -//config: bool "fdformat (4.5 kb)" +//config: bool "fdformat (4.4 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/util-linux/fdisk.c b/util-linux/fdisk.c index 288b9235f..58e93bb92 100644 --- a/util-linux/fdisk.c +++ b/util-linux/fdisk.c @@ -8,7 +8,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config FDISK -//config: bool "fdisk (41 kb)" +//config: bool "fdisk (37 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/util-linux/findfs.c b/util-linux/findfs.c index 1102eeff5..7ca9dc96b 100644 --- a/util-linux/findfs.c +++ b/util-linux/findfs.c @@ -8,7 +8,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config FINDFS -//config: bool "findfs (11 kb)" +//config: bool "findfs (12 kb)" //config: default y //config: select PLATFORM_LINUX //config: select VOLUMEID diff --git a/util-linux/flock.c b/util-linux/flock.c index dd0bfd430..130627e93 100644 --- a/util-linux/flock.c +++ b/util-linux/flock.c @@ -4,7 +4,7 @@ * This is free software, licensed under the GNU General Public License v2. */ //config:config FLOCK -//config: bool "flock (6.1 kb)" +//config: bool "flock (6.3 kb)" //config: default y //config: help //config: Manage locks from shell scripts diff --git a/util-linux/freeramdisk.c b/util-linux/freeramdisk.c index 6752e49d8..d27113d97 100644 --- a/util-linux/freeramdisk.c +++ b/util-linux/freeramdisk.c @@ -9,7 +9,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config FDFLUSH -//config: bool "fdflush (1.4 kb)" +//config: bool "fdflush (1.3 kb)" //config: default y //config: select PLATFORM_LINUX //config: help @@ -22,7 +22,7 @@ //config: leave this disabled. //config: //config:config FREERAMDISK -//config: bool "freeramdisk (1.4 kb)" +//config: bool "freeramdisk (1.3 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/util-linux/fsfreeze.c b/util-linux/fsfreeze.c index c485810aa..fb0b3c4bd 100644 --- a/util-linux/fsfreeze.c +++ b/util-linux/fsfreeze.c @@ -5,7 +5,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config FSFREEZE -//config: bool "fsfreeze (3.6 kb)" +//config: bool "fsfreeze (3.5 kb)" //config: default y //config: select PLATFORM_LINUX //config: select LONG_OPTS diff --git a/util-linux/fstrim.c b/util-linux/fstrim.c index 558a94a9e..48948e839 100644 --- a/util-linux/fstrim.c +++ b/util-linux/fstrim.c @@ -8,7 +8,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config FSTRIM -//config: bool "fstrim (5.5 kb)" +//config: bool "fstrim (4.4 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/util-linux/getopt.c b/util-linux/getopt.c index 4431a7e74..1666d3d30 100644 --- a/util-linux/getopt.c +++ b/util-linux/getopt.c @@ -29,7 +29,7 @@ * Replaced our_malloc with xmalloc and our_realloc with xrealloc */ //config:config GETOPT -//config: bool "getopt (5.6 kb)" +//config: bool "getopt (5.8 kb)" //config: default y //config: help //config: The getopt utility is used to break up (parse) options in command diff --git a/util-linux/hexdump.c b/util-linux/hexdump.c index 719feaf4e..065b83980 100644 --- a/util-linux/hexdump.c +++ b/util-linux/hexdump.c @@ -9,7 +9,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config HEXDUMP -//config: bool "hexdump (8.8 kb)" +//config: bool "hexdump (8.6 kb)" //config: default y //config: help //config: The hexdump utility is used to display binary data in a readable @@ -26,7 +26,7 @@ //config: aimed to be portable. //config: //config:config HD -//config: bool "hd (8 kb)" +//config: bool "hd (7.8 kb)" //config: default y //config: help //config: hd is an alias to hexdump -C. diff --git a/util-linux/ionice.c b/util-linux/ionice.c index 5b9664d25..daf64d537 100644 --- a/util-linux/ionice.c +++ b/util-linux/ionice.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config IONICE -//config: bool "ionice (3.6 kb)" +//config: bool "ionice (3.8 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/util-linux/ipcrm.c b/util-linux/ipcrm.c index a93ceee11..3d3ad0b56 100644 --- a/util-linux/ipcrm.c +++ b/util-linux/ipcrm.c @@ -8,7 +8,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config IPCRM -//config: bool "ipcrm (2.9 kb)" +//config: bool "ipcrm (3.2 kb)" //config: default y //config: help //config: The ipcrm utility allows the removal of System V interprocess diff --git a/util-linux/last.c b/util-linux/last.c index f5ee8e5f4..689aa7a34 100644 --- a/util-linux/last.c +++ b/util-linux/last.c @@ -7,7 +7,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config LAST -//config: bool "last (6.2 kb)" +//config: bool "last (6.1 kb)" //config: default y //config: depends on FEATURE_WTMP //config: help diff --git a/util-linux/losetup.c b/util-linux/losetup.c index 6b171d710..bf480e9bf 100644 --- a/util-linux/losetup.c +++ b/util-linux/losetup.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config LOSETUP -//config: bool "losetup (5.4 kb)" +//config: bool "losetup (5.5 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/util-linux/lspci.c b/util-linux/lspci.c index 0000fbfda..a6b4e850f 100644 --- a/util-linux/lspci.c +++ b/util-linux/lspci.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config LSPCI -//config: bool "lspci (5.7 kb)" +//config: bool "lspci (6.3 kb)" //config: default y //config: #select PLATFORM_LINUX //config: help diff --git a/util-linux/lsusb.c b/util-linux/lsusb.c index 33639413a..e27aa7f31 100644 --- a/util-linux/lsusb.c +++ b/util-linux/lsusb.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config LSUSB -//config: bool "lsusb (3.5 kb)" +//config: bool "lsusb (4.2 kb)" //config: default y //config: #select PLATFORM_LINUX //config: help diff --git a/util-linux/mdev.c b/util-linux/mdev.c index 5ad09e09a..63b55536a 100644 --- a/util-linux/mdev.c +++ b/util-linux/mdev.c @@ -8,7 +8,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config MDEV -//config: bool "mdev (16 kb)" +//config: bool "mdev (17 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/util-linux/mesg.c b/util-linux/mesg.c index 35c4ec13d..c7b696853 100644 --- a/util-linux/mesg.c +++ b/util-linux/mesg.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config MESG -//config: bool "mesg (1.2 kb)" +//config: bool "mesg (1.4 kb)" //config: default y //config: help //config: Mesg controls access to your terminal by others. It is typically diff --git a/util-linux/mkfs_ext2.c b/util-linux/mkfs_ext2.c index bda168f1e..845ba0a24 100644 --- a/util-linux/mkfs_ext2.c +++ b/util-linux/mkfs_ext2.c @@ -8,14 +8,14 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config MKE2FS -//config: bool "mke2fs (9.7 kb)" +//config: bool "mke2fs (10 kb)" //config: default y //config: select PLATFORM_LINUX //config: help //config: Utility to create EXT2 filesystems. //config: //config:config MKFS_EXT2 -//config: bool "mkfs.ext2 (9.8 kb)" +//config: bool "mkfs.ext2 (10 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/util-linux/mkfs_vfat.c b/util-linux/mkfs_vfat.c index 6a6dc652f..b760fb2aa 100644 --- a/util-linux/mkfs_vfat.c +++ b/util-linux/mkfs_vfat.c @@ -8,14 +8,14 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config MKDOSFS -//config: bool "mkdosfs (6.8 kb)" +//config: bool "mkdosfs (7.2 kb)" //config: default y //config: select PLATFORM_LINUX //config: help //config: Utility to create FAT32 filesystems. //config: //config:config MKFS_VFAT -//config: bool "mkfs.vfat (6.8 kb)" +//config: bool "mkfs.vfat (7.2 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/util-linux/mkswap.c b/util-linux/mkswap.c index 2eb16bd84..38413606d 100644 --- a/util-linux/mkswap.c +++ b/util-linux/mkswap.c @@ -7,7 +7,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config MKSWAP -//config: bool "mkswap (5.8 kb)" +//config: bool "mkswap (6.3 kb)" //config: default y //config: help //config: The mkswap utility is used to configure a file or disk partition as diff --git a/util-linux/more.c b/util-linux/more.c index 926cf5f26..eea69da06 100644 --- a/util-linux/more.c +++ b/util-linux/more.c @@ -14,7 +14,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config MORE -//config: bool "more (6.7 kb)" +//config: bool "more (7 kb)" //config: default y //config: help //config: more is a simple utility which allows you to read text one screen diff --git a/util-linux/mount.c b/util-linux/mount.c index fa2e7b114..526b4130c 100644 --- a/util-linux/mount.c +++ b/util-linux/mount.c @@ -18,7 +18,7 @@ // //config:config MOUNT -//config: bool "mount (30 kb)" +//config: bool "mount (23 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/util-linux/mountpoint.c b/util-linux/mountpoint.c index 6b21a5fb3..a44cf6013 100644 --- a/util-linux/mountpoint.c +++ b/util-linux/mountpoint.c @@ -9,7 +9,7 @@ * Based on sysvinit's mountpoint */ //config:config MOUNTPOINT -//config: bool "mountpoint (4.5 kb)" +//config: bool "mountpoint (4.9 kb)" //config: default y //config: help //config: mountpoint checks if the directory is a mountpoint. diff --git a/util-linux/nsenter.c b/util-linux/nsenter.c index ae8103a52..4eeaa9f3e 100644 --- a/util-linux/nsenter.c +++ b/util-linux/nsenter.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config NSENTER -//config: bool "nsenter (8.6 kb)" +//config: bool "nsenter (6.5 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/util-linux/pivot_root.c b/util-linux/pivot_root.c index d6a26b912..41f29da32 100644 --- a/util-linux/pivot_root.c +++ b/util-linux/pivot_root.c @@ -9,7 +9,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config PIVOT_ROOT -//config: bool "pivot_root (898 bytes)" +//config: bool "pivot_root (1.1 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/util-linux/rdate.c b/util-linux/rdate.c index 5ec795208..70f829e7f 100644 --- a/util-linux/rdate.c +++ b/util-linux/rdate.c @@ -8,7 +8,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config RDATE -//config: bool "rdate (6 kb)" +//config: bool "rdate (5.6 kb)" //config: default y //config: help //config: The rdate utility allows you to synchronize the date and time of your diff --git a/util-linux/rdev.c b/util-linux/rdev.c index 97279ce61..d6b515ebc 100644 --- a/util-linux/rdev.c +++ b/util-linux/rdev.c @@ -8,7 +8,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config RDEV -//config: bool "rdev (1.4 kb)" +//config: bool "rdev (1.8 kb)" //config: default y //config: help //config: Print the device node associated with the filesystem mounted at '/'. diff --git a/util-linux/readprofile.c b/util-linux/readprofile.c index 219c0c18c..cab2c4319 100644 --- a/util-linux/readprofile.c +++ b/util-linux/readprofile.c @@ -32,7 +32,7 @@ * Paul Mundt . */ //config:config READPROFILE -//config: bool "readprofile (7.2 kb)" +//config: bool "readprofile (7.1 kb)" //config: default y //config: #select PLATFORM_LINUX //config: help diff --git a/util-linux/renice.c b/util-linux/renice.c index ee0fb3c8e..a318ffce0 100644 --- a/util-linux/renice.c +++ b/util-linux/renice.c @@ -18,7 +18,7 @@ * following IDs (if any). Multiple switches are allowed. */ //config:config RENICE -//config: bool "renice (3.8 kb)" +//config: bool "renice (4.2 kb)" //config: default y //config: help //config: Renice alters the scheduling priority of one or more running diff --git a/util-linux/rev.c b/util-linux/rev.c index 2bef9b9be..ede4fbc9c 100644 --- a/util-linux/rev.c +++ b/util-linux/rev.c @@ -6,7 +6,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config REV -//config: bool "rev (4.5 kb)" +//config: bool "rev (4.4 kb)" //config: default y //config: help //config: Reverse lines of a file or files. diff --git a/util-linux/rtcwake.c b/util-linux/rtcwake.c index 8ffa4f3a6..29c440b82 100644 --- a/util-linux/rtcwake.c +++ b/util-linux/rtcwake.c @@ -23,7 +23,7 @@ * That flag should not be needed on systems with adjtime support. */ //config:config RTCWAKE -//config: bool "rtcwake (6.4 kb)" +//config: bool "rtcwake (6.8 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/util-linux/script.c b/util-linux/script.c index aac77c3ba..4eac5e94f 100644 --- a/util-linux/script.c +++ b/util-linux/script.c @@ -11,7 +11,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config SCRIPT -//config: bool "script (8 kb)" +//config: bool "script (8.6 kb)" //config: default y //config: help //config: The script makes typescript of terminal session. diff --git a/util-linux/scriptreplay.c b/util-linux/scriptreplay.c index e3083ab93..3c032eec5 100644 --- a/util-linux/scriptreplay.c +++ b/util-linux/scriptreplay.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config SCRIPTREPLAY -//config: bool "scriptreplay (2.6 kb)" +//config: bool "scriptreplay (2.4 kb)" //config: default y //config: help //config: This program replays a typescript, using timing information diff --git a/util-linux/setarch.c b/util-linux/setarch.c index 520865318..57051a683 100644 --- a/util-linux/setarch.c +++ b/util-linux/setarch.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config SETARCH -//config: bool "setarch (3.4 kb)" +//config: bool "setarch (3.6 kb)" //config: default y //config: select PLATFORM_LINUX //config: help @@ -17,14 +17,14 @@ //config: (like amd64/x86, ppc64/ppc, sparc64/sparc, etc...). //config: //config:config LINUX32 -//config: bool "linux32 (3.2 kb)" +//config: bool "linux32 (3.3 kb)" //config: default y //config: select PLATFORM_LINUX //config: help //config: Alias to "setarch linux32". //config: //config:config LINUX64 -//config: bool "linux64 (3.2 kb)" +//config: bool "linux64 (3.3 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/util-linux/setpriv.c b/util-linux/setpriv.c index af079fae8..b69b8cbb6 100644 --- a/util-linux/setpriv.c +++ b/util-linux/setpriv.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config SETPRIV -//config: bool "setpriv (3.4 kb)" +//config: bool "setpriv (6.6 kb)" //config: default y //config: select PLATFORM_LINUX //config: select LONG_OPTS diff --git a/util-linux/setsid.c b/util-linux/setsid.c index 8385a9115..cdad8c1d3 100644 --- a/util-linux/setsid.c +++ b/util-linux/setsid.c @@ -14,7 +14,7 @@ * - busyboxed */ //config:config SETSID -//config: bool "setsid (3.9 kb)" +//config: bool "setsid (3.6 kb)" //config: default y //config: help //config: setsid runs a program in a new session diff --git a/util-linux/swaponoff.c b/util-linux/swaponoff.c index f432ce180..567869cc7 100644 --- a/util-linux/swaponoff.c +++ b/util-linux/swaponoff.c @@ -7,7 +7,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config SWAPON -//config: bool "swapon (4.9 kb)" +//config: bool "swapon (15 kb)" //config: default y //config: select PLATFORM_LINUX //config: help @@ -34,7 +34,7 @@ //config: Enable support for setting swap device priority in swapon. //config: //config:config SWAPOFF -//config: bool "swapoff (4.3 kb)" +//config: bool "swapoff (14 kb)" //config: default y //config: select PLATFORM_LINUX //config: diff --git a/util-linux/switch_root.c b/util-linux/switch_root.c index 947dd0cdc..ae9d412d1 100644 --- a/util-linux/switch_root.c +++ b/util-linux/switch_root.c @@ -7,7 +7,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config SWITCH_ROOT -//config: bool "switch_root (5.2 kb)" +//config: bool "switch_root (5.5 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/util-linux/taskset.c b/util-linux/taskset.c index 67df1cb73..ed8878ad4 100644 --- a/util-linux/taskset.c +++ b/util-linux/taskset.c @@ -6,7 +6,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config TASKSET -//config: bool "taskset (4.1 kb)" +//config: bool "taskset (4.2 kb)" //config: default y //config: help //config: Retrieve or set a processes's CPU affinity. diff --git a/util-linux/uevent.c b/util-linux/uevent.c index 7ff866cec..761743f45 100644 --- a/util-linux/uevent.c +++ b/util-linux/uevent.c @@ -4,7 +4,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config UEVENT -//config: bool "uevent (3.2 kb)" +//config: bool "uevent (3.1 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/util-linux/umount.c b/util-linux/umount.c index e2329f8b3..077b635c8 100644 --- a/util-linux/umount.c +++ b/util-linux/umount.c @@ -8,7 +8,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config UMOUNT -//config: bool "umount (4.5 kb)" +//config: bool "umount (5.1 kb)" //config: default y //config: select PLATFORM_LINUX //config: help diff --git a/util-linux/unshare.c b/util-linux/unshare.c index fffee28a0..61fc71197 100644 --- a/util-linux/unshare.c +++ b/util-linux/unshare.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config UNSHARE -//config: bool "unshare (9.2 kb)" +//config: bool "unshare (7.2 kb)" //config: default y //config: depends on !NOMMU //config: select PLATFORM_LINUX diff --git a/util-linux/wall.c b/util-linux/wall.c index 939736592..23fb87517 100644 --- a/util-linux/wall.c +++ b/util-linux/wall.c @@ -6,7 +6,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config WALL -//config: bool "wall (2.5 kb)" +//config: bool "wall (2.6 kb)" //config: default y //config: depends on FEATURE_UTMP //config: help -- cgit v1.2.3-55-g6feb From 83e7e13628686c3b11ef14dec94fae169ee08c43 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 28 Dec 2018 13:03:48 +0100 Subject: config: add size information for udhcpc Signed-off-by: Denys Vlasenko --- networking/udhcp/Config.src | 6 +++--- size_single_applets.sh | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/networking/udhcp/Config.src b/networking/udhcp/Config.src index e5958804b..e13a3ec82 100644 --- a/networking/udhcp/Config.src +++ b/networking/udhcp/Config.src @@ -4,7 +4,7 @@ # config UDHCPD - bool "udhcpd" + bool "udhcpd (21 kb)" default y select PLATFORM_LINUX help @@ -44,7 +44,7 @@ config DHCPD_LEASES_FILE of the file. Normally it is safe to leave it untouched. config DUMPLEASES - bool "dumpleases (6.4 kb)" + bool "dumpleases (5.1 kb)" default y help dumpleases displays the leases written out by the udhcpd. @@ -52,7 +52,7 @@ config DUMPLEASES by the absolute time that it expires in seconds from epoch. config DHCPRELAY - bool "dhcprelay (5.8 kb)" + bool "dhcprelay (5.2 kb)" default y help dhcprelay listens for DHCP requests on one or more interfaces diff --git a/size_single_applets.sh b/size_single_applets.sh index f7f327b43..6df5d7bee 100755 --- a/size_single_applets.sh +++ b/size_single_applets.sh @@ -57,8 +57,8 @@ grep ^IF_ include/applets.h \ test -f "$b" || continue file=`grep -lF "bool \"$name" $(find -name '*.c') | xargs` - # so far all such items are in .c files; if need to check Config.* files: - #test "$file" || file=`grep -lF "bool \"$name" $(find -name 'Config.*') | xargs` + # A few applets have their CONFIG items in Config.* files, not .c files: + test "$file" || file=`grep -lF "bool \"$name" $(find -name 'Config.*') | xargs` test "$file" || continue #echo "FILE:'$file'" -- cgit v1.2.3-55-g6feb From 1476760600eff7c51c78b0ba02f1b08558178289 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 27 Dec 2018 22:52:13 +0100 Subject: bc: rename config options Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 63 +++++++++++++++++++++------------------------------ testsuite/dc.tests | 3 +++ testsuite/head.tests | 2 ++ testsuite/unzip.tests | 4 ++-- 4 files changed, 33 insertions(+), 39 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 7179811fe..6463817bb 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -27,19 +27,6 @@ //config: easier. //config: 5) "read()" accepts expressions, not only numeric literals. //config: -//config: Options: -//config: -i --interactive force interactive mode -//config: -q --quiet don't print version and copyright -//config: -s --standard error if any non-POSIX extensions are used -//config: -w --warn warn if any non-POSIX extensions are used -//config: -l --mathlib use predefined math routines: -//config: s(expr) sine in radians -//config: c(expr) cosine in radians -//config: a(expr) arctangent, returning radians -//config: l(expr) natural log -//config: e(expr) raises e to the power of expr -//config: j(n, x) Bessel function of integer order n of x -//config: //config:config DC //config: bool "dc (36 kb)" //config: default y @@ -60,31 +47,32 @@ //config: whitespace where a register should be, it skips the whitespace. //config: If the character following is not a lowercase letter, an error //config: is issued. Otherwise, the register name is parsed by the -//config: following regex: -//config: [a-z][a-z0-9_]* +//config: following regex: [a-z][a-z0-9_]* //config: This generally means that register names will be surrounded by //config: whitespace. Examples: //config: l idx s temp L index S temp2 < do_thing //config: Also note that, like the FreeBSD dc, extended registers are not //config: allowed unless the "-x" option is given. //config: -//config:config FEATURE_DC_SMALL -//config: bool "Minimal dc implementation (4.2 kb), not using bc code base" +//config:if BC || DC # for menuconfig indenting +//config: +//config:config FEATURE_DC_BIG +//config: bool "Use bc code base for dc (larger, more features)" //config: depends on DC && !BC -//config: default n +//config: default y //config: //config:config FEATURE_DC_LIBM //config: bool "Enable power and exp functions (requires libm)" //config: default y -//config: depends on FEATURE_DC_SMALL +//config: depends on DC && !BC && !FEATURE_DC_BIG //config: help //config: Enable power and exp functions. //config: NOTE: This will require libm to be present for linking. //config: -//config:config FEATURE_BC_SIGNALS +//config:config FEATURE_BC_INTERACTIVE //config: bool "Interactive mode (+4kb)" //config: default y -//config: depends on (BC || DC) && !FEATURE_DC_SMALL +//config: depends on BC || (DC && FEATURE_DC_BIG) //config: help //config: Enable interactive mode: when started on a tty, //config: ^C interrupts execution and returns to command line, @@ -99,9 +87,9 @@ //config:config FEATURE_BC_LONG_OPTIONS //config: bool "Enable bc/dc long options" //config: default y -//config: depends on (BC || DC) && !FEATURE_DC_SMALL -//config: help -//config: Enable long options for bc and dc. +//config: depends on BC || (DC && FEATURE_DC_BIG) +//config: +//config:endif //applet:IF_BC(APPLET(bc, BB_DIR_USR_BIN, BB_SUID_DROP)) //applet:IF_DC(APPLET(dc, BB_DIR_USR_BIN, BB_SUID_DROP)) @@ -137,11 +125,11 @@ //usage: "obase = A\n" //usage: //usage:#define dc_trivial_usage -//usage: IF_NOT_FEATURE_DC_SMALL("[-x] ")"[-eSCRIPT]... [-fFILE]... [FILE]..." +//usage: IF_FEATURE_DC_BIG("[-x] ")"[-eSCRIPT]... [-fFILE]... [FILE]..." //usage: //usage:#define dc_full_usage "\n" //usage: "\nTiny RPN calculator. Operations:" -//usage: "\n+, -, *, /, %, ~, ^," IF_NOT_FEATURE_DC_SMALL(" |,") +//usage: "\n+, -, *, /, %, ~, ^," IF_FEATURE_DC_BIG(" |,") //usage: "\np - print top of the stack without popping" //usage: "\nf - print entire stack" //usage: "\nk - pop the value and set the precision" @@ -164,7 +152,7 @@ #include "libbb.h" #include "common_bufsiz.h" -#if ENABLE_FEATURE_DC_SMALL +#if !ENABLE_BC && !ENABLE_FEATURE_DC_BIG # include "dc.c" #else @@ -765,7 +753,7 @@ struct globals { BcVec input_buffer; - IF_FEATURE_BC_SIGNALS(smallint ttyin;) + IF_FEATURE_BC_INTERACTIVE(smallint ttyin;) IF_FEATURE_CLEAN_UP(smallint exiting;) BcProgram prog; @@ -788,7 +776,7 @@ struct globals { #define G_posix (ENABLE_BC && (option_mask32 & BC_FLAG_S)) #define G_warn (ENABLE_BC && (option_mask32 & BC_FLAG_W)) #define G_exreg (ENABLE_DC && (option_mask32 & DC_FLAG_X)) -#if ENABLE_FEATURE_BC_SIGNALS +#if ENABLE_FEATURE_BC_INTERACTIVE # define G_interrupt bb_got_signal # define G_ttyin G.ttyin #else @@ -876,7 +864,7 @@ struct globals { // To make code more readable, each such function has a "z" // ("always returning zero") prefix, i.e. zbc_foo or zdc_foo. // -#if ENABLE_FEATURE_BC_SIGNALS || ENABLE_FEATURE_CLEAN_UP +#if ENABLE_FEATURE_BC_INTERACTIVE || ENABLE_FEATURE_CLEAN_UP # define ERRORS_ARE_FATAL 0 # define ERRORFUNC /*nothing*/ # define IF_ERROR_RETURN_POSSIBLE(a) a @@ -906,7 +894,7 @@ static void fflush_and_check(void) #if ENABLE_FEATURE_CLEAN_UP #define QUIT_OR_RETURN_TO_MAIN \ do { \ - IF_FEATURE_BC_SIGNALS(G_ttyin = 0;) /* do not loop in main loop anymore */ \ + IF_FEATURE_BC_INTERACTIVE(G_ttyin = 0;) /* do not loop in main loop anymore */ \ G_exiting = 1; \ return BC_STATUS_FAILURE; \ } while (0) @@ -1834,7 +1822,7 @@ static FAST_FUNC BC_STATUS zbc_num_k(BcNum *restrict a, BcNum *restrict b, c->num[i + j] += (BcDig) carry; len = BC_MAX(len, i + j + !!carry); -#if ENABLE_FEATURE_BC_SIGNALS +#if ENABLE_FEATURE_BC_INTERACTIVE // a=2^1000000 // a*a <- without check below, this will not be interruptible if (G_interrupt) return BC_STATUS_FAILURE; @@ -2001,7 +1989,7 @@ static FAST_FUNC BC_STATUS zbc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size for (q = 0; n[len] != 0 || bc_num_compare(n, b->num, len) >= 0; ++q) bc_num_subArrays(n, b->num, len); c->num[i] = q; -#if ENABLE_FEATURE_BC_SIGNALS +#if ENABLE_FEATURE_BC_INTERACTIVE // a=2^100000 // scale=40000 // 1/a <- without check below, this will not be interruptible @@ -2486,7 +2474,7 @@ static void xc_read_line(BcVec *vec, FILE *fp) bc_vec_pop_all(vec); fflush_and_check(); -#if ENABLE_FEATURE_BC_SIGNALS +#if ENABLE_FEATURE_BC_INTERACTIVE if (G_interrupt) { // ^C was pressed intr: if (fp != stdin) { @@ -2533,7 +2521,7 @@ static void xc_read_line(BcVec *vec, FILE *fp) bool bad_chars = 0; do { -#if ENABLE_FEATURE_BC_SIGNALS +#if ENABLE_FEATURE_BC_INTERACTIVE if (G_interrupt) { // ^C was pressed: ignore entire line, get another one bc_vec_pop_all(vec); @@ -7223,7 +7211,7 @@ static int xc_vm_init(const char *env_len) //TODO: in GNU bc, the check is (isatty(0) && isatty(1)), //-i option unconditionally enables this regardless of isatty(): if (isatty(0)) { -#if ENABLE_FEATURE_BC_SIGNALS +#if ENABLE_FEATURE_BC_INTERACTIVE G_ttyin = 1; // With SA_RESTART, most system calls will restart // (IOW: they won't fail with EINTR). @@ -7342,4 +7330,5 @@ int dc_main(int argc UNUSED_PARAM, char **argv) } #endif -#endif // not DC_SMALL +#endif // DC_BIG + diff --git a/testsuite/dc.tests b/testsuite/dc.tests index 2756608f7..29b413cad 100755 --- a/testsuite/dc.tests +++ b/testsuite/dc.tests @@ -41,6 +41,9 @@ testing "dc complex without spaces (multiple args)" \ "16\n" \ "" "" +optional FEATURE_DC_BIG +# All tests below depend on FEATURE_DC_BIG + testing "dc '>a' (conditional execute string) 1" \ "dc" \ "1\n9\n" \ diff --git a/testsuite/head.tests b/testsuite/head.tests index 50660d267..97bf889d8 100755 --- a/testsuite/head.tests +++ b/testsuite/head.tests @@ -31,10 +31,12 @@ testing "head -n " \ "line 1\nline 2\n" \ "" "" +optional FEATURE_FANCY_HEAD testing "head -n " \ "head -n -9 head.input" \ "line 1\nline 2\nline 3\n" \ "" "" +SKIP= rm head.input diff --git a/testsuite/unzip.tests b/testsuite/unzip.tests index af53de9df..e198dfc4b 100755 --- a/testsuite/unzip.tests +++ b/testsuite/unzip.tests @@ -31,10 +31,10 @@ rmdir foo rm foo.zip # File containing some damaged encrypted stream -optional FEATURE_UNZIP_CDF +optional FEATURE_UNZIP_CDF CONFIG_UNICODE_SUPPORT testing "unzip (bad archive)" "uudecode; unzip bad.zip 2>&1; echo \$?" \ "Archive: bad.zip - inflating: ]3j½r«IK-%Ix + inflating: ]3j½r«I??K-%Ix unzip: corrupted data unzip: inflate error 1 -- cgit v1.2.3-55-g6feb From df1ff103c9e0496e7de9528500cddff36701609e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 28 Dec 2018 13:37:44 +0100 Subject: config: add size information for three more applets Signed-off-by: Denys Vlasenko --- networking/udhcp/Config.src | 2 +- size_single_applets.sh | 4 ++-- util-linux/fsck_minix.c | 2 +- util-linux/mkfs_minix.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/networking/udhcp/Config.src b/networking/udhcp/Config.src index e13a3ec82..f16fc0a4f 100644 --- a/networking/udhcp/Config.src +++ b/networking/udhcp/Config.src @@ -60,7 +60,7 @@ config DHCPRELAY server. config UDHCPC - bool "udhcpc" + bool "udhcpc (24 kb)" default y select PLATFORM_LINUX help diff --git a/size_single_applets.sh b/size_single_applets.sh index 6df5d7bee..4b70e761f 100755 --- a/size_single_applets.sh +++ b/size_single_applets.sh @@ -56,9 +56,9 @@ grep ^IF_ include/applets.h \ b="busybox_${app}" test -f "$b" || continue - file=`grep -lF "bool \"$name" $(find -name '*.c') | xargs` + file=`grep -l "bool \"$name[\" ]" $(find -name '*.c') | xargs` # A few applets have their CONFIG items in Config.* files, not .c files: - test "$file" || file=`grep -lF "bool \"$name" $(find -name 'Config.*') | xargs` + test "$file" || file=`grep -l "bool \"$name[\" ]" $(find -name 'Config.*') | xargs` test "$file" || continue #echo "FILE:'$file'" diff --git a/util-linux/fsck_minix.c b/util-linux/fsck_minix.c index c4612f251..f523da945 100644 --- a/util-linux/fsck_minix.c +++ b/util-linux/fsck_minix.c @@ -86,7 +86,7 @@ * enforced (but it's not much fun on a character device :-). */ //config:config FSCK_MINIX -//config: bool "fsck_minix" +//config: bool "fsck.minix (13 kb)" //config: default y //config: help //config: The minix filesystem is a nice, small, compact, read-write filesystem diff --git a/util-linux/mkfs_minix.c b/util-linux/mkfs_minix.c index 69dfcd123..e191acbd0 100644 --- a/util-linux/mkfs_minix.c +++ b/util-linux/mkfs_minix.c @@ -63,7 +63,7 @@ * removed getopt based parser and added a hand rolled one. */ //config:config MKFS_MINIX -//config: bool "mkfs_minix" +//config: bool "mkfs.minix (10 kb)" //config: default y //config: select PLATFORM_LINUX //config: help -- cgit v1.2.3-55-g6feb From cdadad58a1555b50fe8478291a0cd9ff23e2aadb Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 28 Dec 2018 15:13:23 +0100 Subject: bc: bc enables FEATURE_DC_BIG, for correct dc testsuite operation Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 6463817bb..c10cd73fa 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -7,6 +7,7 @@ //config:config BC //config: bool "bc (45 kb)" //config: default y +//config: select FEATURE_DC_BIG //config: help //config: bc is a command-line, arbitrary-precision calculator with a //config: Turing-complete language. See the GNU bc manual @@ -58,7 +59,6 @@ //config: //config:config FEATURE_DC_BIG //config: bool "Use bc code base for dc (larger, more features)" -//config: depends on DC && !BC //config: default y //config: //config:config FEATURE_DC_LIBM -- cgit v1.2.3-55-g6feb From b86b39bfda8fa050f406ae00119bf0557bb909c2 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 28 Dec 2018 17:45:35 +0100 Subject: config: more tweaks Signed-off-by: Denys Vlasenko --- archival/dpkg_deb.c | 2 +- coreutils/du.c | 6 ++---- coreutils/echo.c | 4 ++-- init/bootchartd.c | 2 +- miscutils/runlevel.c | 2 +- networking/tftp.c | 3 --- 6 files changed, 7 insertions(+), 12 deletions(-) diff --git a/archival/dpkg_deb.c b/archival/dpkg_deb.c index dc4738d28..892cb3b8f 100644 --- a/archival/dpkg_deb.c +++ b/archival/dpkg_deb.c @@ -5,7 +5,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config DPKG_DEB -//config: bool "dpkg_deb" +//config: bool "dpkg_deb (30 kb)" //config: default y //config: select FEATURE_SEAMLESS_GZ //config: help diff --git a/coreutils/du.c b/coreutils/du.c index d5ce46cf2..6d737fbfb 100644 --- a/coreutils/du.c +++ b/coreutils/du.c @@ -19,18 +19,16 @@ * 4) Fixed busybox bug #1284 involving long overflow with human_readable. */ //config:config DU -//config: bool "du (default blocksize of 512 bytes)" +//config: bool "du (6.3 kb)" //config: default y //config: help //config: du is used to report the amount of disk space used //config: for specified files. //config: //config:config FEATURE_DU_DEFAULT_BLOCKSIZE_1K -//config: bool "Use a default blocksize of 1024 bytes (1K)" +//config: bool "Use default blocksize of 1024 bytes (else it's 512 bytes)" //config: default y //config: depends on DU -//config: help -//config: Use a blocksize of (1K) instead of the default 512b. //applet:IF_DU(APPLET(du, BB_DIR_USR_BIN, BB_SUID_DROP)) diff --git a/coreutils/echo.c b/coreutils/echo.c index e45b90940..5dc5be072 100644 --- a/coreutils/echo.c +++ b/coreutils/echo.c @@ -19,10 +19,10 @@ * The previous version did not allow 4-digit octals. */ //config:config ECHO -//config: bool "echo (basic SuSv3 version taking no options)" +//config: bool "echo (1.8 kb)" //config: default y //config: help -//config: echo is used to print a specified string to stdout. +//config: echo prints a specified string to stdout. //config: //config:# this entry also appears in shell/Config.in, next to the echo builtin //config:config FEATURE_FANCY_ECHO diff --git a/init/bootchartd.c b/init/bootchartd.c index 373cde2d8..4377d90e3 100644 --- a/init/bootchartd.c +++ b/init/bootchartd.c @@ -23,7 +23,7 @@ //config: help //config: Create extended header file compatible with "big" bootchartd. //config: "Big" bootchartd is a shell script and it dumps some -//config: "convenient" info int the header, such as: +//config: "convenient" info into the header, such as: //config: title = Boot chart for `hostname` (`date`) //config: system.uname = `uname -srvm` //config: system.release = `cat /etc/DISTRO-release` diff --git a/miscutils/runlevel.c b/miscutils/runlevel.c index 885b403db..2f1581ead 100644 --- a/miscutils/runlevel.c +++ b/miscutils/runlevel.c @@ -16,7 +16,7 @@ //config: default y //config: depends on FEATURE_UTMP //config: help -//config: find the current and previous system runlevel. +//config: Find the current and previous system runlevel. //config: //config: This applet uses utmp but does not rely on busybox supporing //config: utmp on purpose. It is used by e.g. emdebian via /etc/init.d/rc. diff --git a/networking/tftp.c b/networking/tftp.c index 1828688d4..d20d4ca4b 100644 --- a/networking/tftp.c +++ b/networking/tftp.c @@ -41,9 +41,6 @@ //config: In other words: it should be run from inetd in nowait mode, //config: or from udpsvd. Example: "udpsvd -E 0 69 tftpd DIR" //config: -//config:comment "Common options for tftp/tftpd" -//config: depends on TFTP || TFTPD -//config: //config:config FEATURE_TFTP_GET //config: bool "Enable 'tftp get' and/or tftpd upload code" //config: default y -- cgit v1.2.3-55-g6feb From f9b4cc114cb4eb2a997f08daa43af30ad598322c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 28 Dec 2018 18:24:45 +0100 Subject: config: dpkg_deb should be dpkg-deb Signed-off-by: Denys Vlasenko --- archival/dpkg_deb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/archival/dpkg_deb.c b/archival/dpkg_deb.c index 892cb3b8f..c2c4cbbcc 100644 --- a/archival/dpkg_deb.c +++ b/archival/dpkg_deb.c @@ -5,7 +5,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config DPKG_DEB -//config: bool "dpkg_deb (30 kb)" +//config: bool "dpkg-deb (30 kb)" //config: default y //config: select FEATURE_SEAMLESS_GZ //config: help -- cgit v1.2.3-55-g6feb From e16a5223d20e5715b98e1fd21fa8d59e75e4e793 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 29 Dec 2018 02:24:19 +0100 Subject: bc: fix handling of "digits" above 9 function old new delta zxc_lex_next 1573 1608 +35 xc_parse_pushIndex 58 56 -2 xc_program_index 71 63 -8 zxc_program_num 1022 990 -32 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/3 up/down: 35/-42) Total: -7 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 82 ++++++++++++++++++++++++++++++--------- testsuite/bc_numbers1.bc | 23 +++++++++++ testsuite/bc_numbers1_results.txt | 17 ++++++++ 3 files changed, 103 insertions(+), 19 deletions(-) create mode 100644 testsuite/bc_numbers1.bc create mode 100644 testsuite/bc_numbers1_results.txt diff --git a/miscutils/bc.c b/miscutils/bc.c index c10cd73fa..07327af6f 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -2555,13 +2555,16 @@ static void xc_read_line(BcVec *vec, FILE *fp) // Parsing routines // -static bool xc_num_strValid(const char *val, size_t base) -{ - BcDig b; - bool radix; - - b = (BcDig)(base <= 10 ? base + '0' : base - 10 + 'A'); - radix = false; +// "Input numbers may contain the characters 0-9 and A-Z. +// (Note: They must be capitals. Lower case letters are variable names.) +// Single digit numbers always have the value of the digit regardless of +// the value of ibase. (i.e. A = 10.) For multi-digit numbers, bc changes +// all input digits greater or equal to ibase to the value of ibase-1. +// This makes the number ZZZ always be the largest 3 digit number of the +// input base." +static bool xc_num_strValid(const char *val) +{ + bool radix = false; for (;;) { BcDig c = *val++; if (c == '\0') @@ -2571,7 +2574,7 @@ static bool xc_num_strValid(const char *val, size_t base) radix = true; continue; } - if (c < '0' || c >= b || (c > '9' && c < 'A')) + if ((c < '0' || c > '9') && (c < 'A' || c > 'Z')) return false; } return true; @@ -2599,10 +2602,21 @@ static void bc_num_parseDecimal(BcNum *n, const char *val) for (i = 0; val[i]; ++i) { if (val[i] != '0' && val[i] != '.') { // Not entirely zero value - convert it, and exit + if (len == 1) { + char c = val[0] - '0'; + if (c > 9) // A-Z => 10-36 + c -= ('A' - '9' - 1); + n->num[0] = c; + n->len = 1; + break; + } i = len - 1; for (;;) { - n->num[n->len] = val[i] - '0'; - ++n->len; + char c = val[i] - '0'; + if (c > 9) // A-Z => 9 + c = 9; + n->num[n->len] = c; + n->len++; skip_dot: if (i == 0) break; if (val[--i] == '.') goto skip_dot; @@ -2692,7 +2706,7 @@ static void bc_num_parseBase(BcNum *n, const char *val, unsigned base_t) static BC_STATUS zxc_num_parse(BcNum *n, const char *val, unsigned base_t) { - if (!xc_num_strValid(val, base_t)) + if (!xc_num_strValid(val)) RETURN_STATUS(bc_error("bad number string")); bc_num_zero(n); @@ -2807,6 +2821,13 @@ static BC_STATUS zxc_lex_number(char last) bc_vec_pop_all(&p->lex_strnumbuf); bc_vec_pushByte(&p->lex_strnumbuf, last); +// "Input numbers may contain the characters 0-9 and A-Z. +// (Note: They must be capitals. Lower case letters are variable names.) +// Single digit numbers always have the value of the digit regardless of +// the value of ibase. (i.e. A = 10.) For multi-digit numbers, bc changes +// all input digits greater or equal to ibase to the value of ibase-1. +// This makes the number ZZZ always be the largest 3 digit number of the +// input base." pt = (last == '.'); p->lex = XC_LEX_NUMBER; for (;;) { @@ -2822,13 +2843,13 @@ static BC_STATUS zxc_lex_number(char last) c = peek_inbuf(); // force next line to be read goto check_c; } - if (!isdigit(c) && (c < 'A' || c > 'F')) { + if (!isdigit(c) && (c < 'A' || c > 'Z')) { if (c != '.') break; // if '.' was already seen, stop on second one: if (pt) break; pt = true; } - // c is one of "0-9A-F." + // c is one of "0-9A-Z." last = c; bc_vec_push(&p->lex_strnumbuf, p->lex_inbuf); p->lex_inbuf++; @@ -3167,6 +3188,26 @@ static BC_STATUS zbc_lex_token(void) case 'D': case 'E': case 'F': + case 'G': + case 'H': + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'S': + case 'T': + case 'U': + case 'V': + case 'W': + case 'X': + case 'Y': + case 'Z': s = zxc_lex_number(c); break; case ';': @@ -3450,13 +3491,14 @@ static void xc_parse_pushIndex(size_t idx) mask = ((size_t)0xff) << (sizeof(idx) * 8 - 8); amt = sizeof(idx); - do { + for (;;) { if (idx & mask) break; mask >>= 8; amt--; - } while (amt != 0); + } + // amt is at least 1 here - "one byte of length data follows" - xc_parse_push(SMALL_INDEX_LIMIT + amt); + xc_parse_push((SMALL_INDEX_LIMIT - 1) + amt); while (idx != 0) { push_idx: @@ -5260,13 +5302,15 @@ static size_t xc_program_index(char *code, size_t *bgn) *bgn += 1; return amt; } - amt -= SMALL_INDEX_LIMIT; + amt -= (SMALL_INDEX_LIMIT - 1); // amt is 1 or more here *bgn += amt + 1; - amt *= 8; res = 0; - for (i = 0; i < amt; i += 8) + i = 0; + do { res |= (size_t)(*bytes++) << i; + i += 8; + } while (--amt != 0); return res; } diff --git a/testsuite/bc_numbers1.bc b/testsuite/bc_numbers1.bc new file mode 100644 index 000000000..fd4e225ee --- /dev/null +++ b/testsuite/bc_numbers1.bc @@ -0,0 +1,23 @@ +ibase=G +define f() { +a00=00;a01=01;a02=02;a03=03;a04=04;a05=05;a06=06;a07=07;a08=08;a09=09;a0a=0A;a0b=0B;a0c=0C;a0d=0D;a0e=0E;a0f=0F +a10=10;a11=11;a12=12;a13=13;a14=14;a15=15;a16=16;a17=17;a18=18;a19=19;a1a=1A;a1b=1B;a1c=1C;a1d=1D;a1e=1E;a1f=1F +a20=20;a21=21;a22=22;a23=23;a24=24;a25=25;a26=26;a27=27;a28=28;a29=29;a2a=2A;a2b=2B;a2c=2C;a2d=2D;a2e=2E;a2f=2F +a30=30;a31=31;a32=32;a33=33;a34=34;a35=35;a36=36;a37=37;a38=38;a39=39;a3a=3A;a3b=3B;a3c=3C;a3d=3D;a3e=3E;a3f=3F +a40=40;a41=41;a42=42;a43=43;a44=44;a45=45;a46=46;a47=47;a48=48;a49=49;a4a=4A;a4b=4B;a4c=4C;a4d=4D;a4e=4E;a4f=4F +a50=50;a51=51;a52=52;a53=53;a54=54;a55=55;a56=56;a57=57;a58=58;a59=59;a5a=5A;a5b=5B;a5c=5C;a5d=5D;a5e=5E;a5f=5F +a60=60;a61=61;a62=62;a63=63;a64=64;a65=65;a66=66;a67=67;a68=68;a69=69;a6a=6A;a6b=6B;a6c=6C;a6d=6D;a6e=6E;a6f=6F +a70=70;a71=71;a72=72;a73=73;a74=74;a75=75;a76=76;a77=77;a78=78;a79=79;a7a=7A;a7b=7B;a7c=7C;a7d=7D;a7e=7E;a7f=7F +a80=80;a81=81;a82=82;a83=83;a84=84;a85=85;a86=86;a87=87;a88=88;a89=89;a8a=8A;a8b=8B;a8c=8C;a8d=8D;a8e=8E;a8f=8F +a90=90;a91=91;a92=92;a93=93;a94=94;a95=95;a96=96;a97=97;a98=98;a99=99;a9a=9A;a9b=9B;a9c=9C;a9d=9D;a9e=9E;a9f=9F +aa0=A0;aa1=A1;aa2=A2;aa3=A3;aa4=A4;aa5=A5;aa6=A6;aa7=A7;aa8=A8;aa9=A9;aaa=AA;aab=AB;aac=AC;aad=AD;aae=AE;aaf=AF +ab0=B0;ab1=B1;ab2=B2;ab3=B3;ab4=B4;ab5=B5;ab6=B6;ab7=B7;ab8=B8;ab9=B9;aba=BA;abb=BB;abc=BC;abd=BD;abe=BE;abf=BF +ac0=C0;ac1=C1;ac2=C2;ac3=C3;ac4=C4;ac5=C5;ac6=C6;ac7=C7;ac8=C8;ac9=C9;aca=CA;acb=CB;acc=CC;acd=CD;ace=CE;acf=CF +ad0=D0;ad1=D1;ad2=D2;ad3=D3;ad4=D4;ad5=D5;ad6=D6;ad7=D7;ad8=D8;ad9=D9;ada=DA;adb=DB;adc=DC;add=DD;ade=DE;adf=DF +ae0=E0;ae1=E1;ae2=E2;ae3=E3;ae4=E4;ae5=E5;ae6=E6;ae7=E7;ae8=E8;ae9=E9;aea=EA;aeb=EB;aec=EC;aed=ED;aee=EE;aef=EF +af0=F0;af1=F1;af2=F2;af3=F3;af4=F4;af5=F5;af6=F6;af7=F7;af8=F8;af9=F9;afa=FA;afb=FB;afc=FC;afd=FD;afe=FE;aff=FF +# this tests "index encoding" in bc.c: are numbers after 0xfc encoded correctly? +af0;af1;af2;af3;af4;af5;af6;af7;af8;af9;afa;afb;afc;afd;afe;aff +} +f() +halt diff --git a/testsuite/bc_numbers1_results.txt b/testsuite/bc_numbers1_results.txt new file mode 100644 index 000000000..e0ace1049 --- /dev/null +++ b/testsuite/bc_numbers1_results.txt @@ -0,0 +1,17 @@ +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +0 -- cgit v1.2.3-55-g6feb From d5b0fa6abf725cc9281f3b11fc2a4c0f12df0793 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 29 Dec 2018 02:40:03 +0100 Subject: bc: more fixes for unusual input bases function old new delta zxc_program_num 990 1020 +30 zxc_lex_number 172 202 +30 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 60/0) Total: 60 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 19 ++++++++++----- testsuite/bc_numbers2.bc | 18 ++++++++++++++ testsuite/bc_numbers2_results.txt | 50 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 6 deletions(-) create mode 100644 testsuite/bc_numbers2.bc create mode 100644 testsuite/bc_numbers2_results.txt diff --git a/miscutils/bc.c b/miscutils/bc.c index 07327af6f..cc15a8dd2 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -2591,7 +2591,7 @@ static void bc_num_parseDecimal(BcNum *n, const char *val) if (len == 0) return; - bc_num_expand(n, len); + bc_num_expand(n, len + 1); // +1 for e.g. "A" converting into 10 ptr = strchr(val, '.'); @@ -2603,11 +2603,15 @@ static void bc_num_parseDecimal(BcNum *n, const char *val) if (val[i] != '0' && val[i] != '.') { // Not entirely zero value - convert it, and exit if (len == 1) { - char c = val[0] - '0'; - if (c > 9) // A-Z => 10-36 + unsigned c = val[0] - '0'; + n->len = 1; + if (c > 9) { // A-Z => 10-36 + n->len = 2; c -= ('A' - '9' - 1); + n->num[1] = c/10; + c = c%10; + } n->num[0] = c; - n->len = 1; break; } i = len - 1; @@ -2817,17 +2821,20 @@ static BC_STATUS zxc_lex_number(char last) { BcParse *p = &G.prs; bool pt; + char last_valid_ch; bc_vec_pop_all(&p->lex_strnumbuf); bc_vec_pushByte(&p->lex_strnumbuf, last); -// "Input numbers may contain the characters 0-9 and A-Z. +// bc: "Input numbers may contain the characters 0-9 and A-Z. // (Note: They must be capitals. Lower case letters are variable names.) // Single digit numbers always have the value of the digit regardless of // the value of ibase. (i.e. A = 10.) For multi-digit numbers, bc changes // all input digits greater or equal to ibase to the value of ibase-1. // This makes the number ZZZ always be the largest 3 digit number of the // input base." +// dc only allows A-F, the rules about single-char and multi-char are the same. + last_valid_ch = (IS_BC ? 'Z' : 'F'); pt = (last == '.'); p->lex = XC_LEX_NUMBER; for (;;) { @@ -2843,7 +2850,7 @@ static BC_STATUS zxc_lex_number(char last) c = peek_inbuf(); // force next line to be read goto check_c; } - if (!isdigit(c) && (c < 'A' || c > 'Z')) { + if (!isdigit(c) && (c < 'A' || c > last_valid_ch)) { if (c != '.') break; // if '.' was already seen, stop on second one: if (pt) break; diff --git a/testsuite/bc_numbers2.bc b/testsuite/bc_numbers2.bc new file mode 100644 index 000000000..208fe0d4d --- /dev/null +++ b/testsuite/bc_numbers2.bc @@ -0,0 +1,18 @@ +define f() { + "ibase:";ibase + a=A;a + a=F;a + a=G;a + a=Z;a + a=0A;a + a=0F;a + a=0G;a + a=0Z;a +} +f() +ibase=9;f() +ibase=A;f() +ibase=F;f() +ibase=G;f() +#ibase=Z;f() +halt diff --git a/testsuite/bc_numbers2_results.txt b/testsuite/bc_numbers2_results.txt new file mode 100644 index 000000000..e3400bd92 --- /dev/null +++ b/testsuite/bc_numbers2_results.txt @@ -0,0 +1,50 @@ +ibase:10 +10 +15 +16 +35 +10 +15 +16 +35 +0 +ibase:9 +10 +15 +16 +35 +10 +15 +16 +35 +0 +ibase:10 +10 +15 +16 +35 +10 +15 +16 +35 +0 +ibase:15 +10 +15 +16 +35 +10 +15 +16 +35 +0 +ibase:16 +10 +15 +16 +35 +10 +15 +16 +35 +0 -- cgit v1.2.3-55-g6feb From 374d2c47ec956b43ced2879cd8305db616625103 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 29 Dec 2018 14:52:30 +0100 Subject: bc: remove special-cased assignment to ibase, it works correctly with general rules function old new delta zxc_program_print 683 681 -2 zxc_program_prep 91 89 -2 zxc_program_copyToVar 300 298 -2 zdc_program_printStream 146 144 -2 zdc_program_execStr 520 518 -2 zdc_program_asciify 370 368 -2 zxc_program_exec 4016 4012 -4 zdc_program_modexp 694 688 -6 zxc_program_num 1020 995 -25 zxc_program_binOpPrep 306 243 -63 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/10 up/down: 0/-110) Total: -110 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 43 +++++++++++++++++++------------------------ 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index cc15a8dd2..500d97123 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -5092,7 +5092,7 @@ static BcVec* xc_program_search(char *id, bool var) } // 'num' need not be initialized on entry -static BC_STATUS zxc_program_num(BcResult *r, BcNum **num, bool hex) +static BC_STATUS zxc_program_num(BcResult *r, BcNum **num) { switch (r->t) { case XC_RESULT_STR: @@ -5105,7 +5105,6 @@ static BC_STATUS zxc_program_num(BcResult *r, BcNum **num, bool hex) case XC_RESULT_CONSTANT: { BcStatus s; char *str; - unsigned base_t; size_t len; str = *xc_program_const(r->d.id.idx); @@ -5113,9 +5112,7 @@ static BC_STATUS zxc_program_num(BcResult *r, BcNum **num, bool hex) bc_num_init(&r->d.n, len); - hex = hex && len == 1; - base_t = hex ? 16 : G.prog.ib_t; - s = zxc_num_parse(&r->d.n, str, base_t); + s = zxc_num_parse(&r->d.n, str, G.prog.ib_t); if (s) { bc_num_free(&r->d.n); RETURN_STATUS(s); @@ -5162,7 +5159,6 @@ static BC_STATUS zxc_program_binOpPrep(BcResult **l, BcNum **ln, BcResult **r, BcNum **rn, bool assign) { BcStatus s; - bool hex; BcResultType lt, rt; if (!STACK_HAS_MORE_THAN(&G.prog.results, 1)) @@ -5171,19 +5167,18 @@ static BC_STATUS zxc_program_binOpPrep(BcResult **l, BcNum **ln, *r = bc_vec_item_rev(&G.prog.results, 0); *l = bc_vec_item_rev(&G.prog.results, 1); - lt = (*l)->t; - rt = (*r)->t; - hex = assign && (lt == XC_RESULT_IBASE || lt == XC_RESULT_OBASE); - - s = zxc_program_num(*l, ln, false); + s = zxc_program_num(*l, ln); if (s) RETURN_STATUS(s); - s = zxc_program_num(*r, rn, hex); + s = zxc_program_num(*r, rn); if (s) RETURN_STATUS(s); + lt = (*l)->t; + rt = (*r)->t; + // We run this again under these conditions in case any vector has been // reallocated out from under the BcNums or arrays we had. if (lt == rt && (lt == XC_RESULT_VAR || lt == XC_RESULT_ARRAY_ELEM)) { - s = zxc_program_num(*l, ln, false); + s = zxc_program_num(*l, ln); if (s) RETURN_STATUS(s); } @@ -5212,7 +5207,7 @@ static BC_STATUS zxc_program_prep(BcResult **r, BcNum **n) RETURN_STATUS(bc_error_stack_has_too_few_elements()); *r = bc_vec_top(&G.prog.results); - s = zxc_program_num(*r, n, false); + s = zxc_program_num(*r, n); if (s) RETURN_STATUS(s); if (!BC_PROG_NUM((*r), (*n))) @@ -5590,7 +5585,7 @@ static BC_STATUS zxc_program_print(char inst, size_t idx) RETURN_STATUS(bc_error_stack_has_too_few_elements()); r = bc_vec_item_rev(&G.prog.results, idx); - s = zxc_program_num(r, &num, false); + s = zxc_program_num(r, &num); if (s) RETURN_STATUS(s); if (BC_PROG_NUM(r, num)) { @@ -5739,7 +5734,7 @@ static BC_STATUS zxc_program_copyToVar(char *name, bool var) RETURN_STATUS(zdc_program_assignStr(ptr, v, true)); #endif - s = zxc_program_num(ptr, &n, false); + s = zxc_program_num(ptr, &n); if (s) RETURN_STATUS(s); // Do this once more to make sure that pointers were not invalidated. @@ -6031,7 +6026,7 @@ static BC_STATUS zbc_program_return(char inst) BcNum *num; BcResult *operand = bc_vec_top(&G.prog.results); - s = zxc_program_num(operand, &num, false); + s = zxc_program_num(operand, &num); if (s) RETURN_STATUS(s); bc_num_init(&res.d.n, num->len); bc_num_copy(&res.d.n, num); @@ -6087,7 +6082,7 @@ static BC_STATUS zxc_program_builtin(char inst) RETURN_STATUS(bc_error_stack_has_too_few_elements()); opnd = bc_vec_top(&G.prog.results); - s = zxc_program_num(opnd, &num, false); + s = zxc_program_num(opnd, &num); if (s) RETURN_STATUS(s); #if ENABLE_DC @@ -6163,7 +6158,7 @@ static BC_STATUS zdc_program_modexp(void) if (s) RETURN_STATUS(s); r1 = bc_vec_item_rev(&G.prog.results, 2); - s = zxc_program_num(r1, &n1, false); + s = zxc_program_num(r1, &n1); if (s) RETURN_STATUS(s); if (!BC_PROG_NUM(r1, n1)) RETURN_STATUS(bc_error_variable_is_wrong_type()); @@ -6171,11 +6166,11 @@ static BC_STATUS zdc_program_modexp(void) // Make sure that the values have their pointers updated, if necessary. if (r1->t == XC_RESULT_VAR || r1->t == XC_RESULT_ARRAY_ELEM) { if (r1->t == r2->t) { - s = zxc_program_num(r2, &n2, false); + s = zxc_program_num(r2, &n2); if (s) RETURN_STATUS(s); } if (r1->t == r3->t) { - s = zxc_program_num(r3, &n3, false); + s = zxc_program_num(r3, &n3); if (s) RETURN_STATUS(s); } } @@ -6220,7 +6215,7 @@ static BC_STATUS zdc_program_asciify(void) RETURN_STATUS(bc_error_stack_has_too_few_elements()); r = bc_vec_top(&G.prog.results); - s = zxc_program_num(r, &num, false); + s = zxc_program_num(r, &num); if (s) RETURN_STATUS(s); if (BC_PROG_NUM(r, num)) { @@ -6284,7 +6279,7 @@ static BC_STATUS zdc_program_printStream(void) RETURN_STATUS(bc_error_stack_has_too_few_elements()); r = bc_vec_top(&G.prog.results); - s = zxc_program_num(r, &n, false); + s = zxc_program_num(r, &n); if (s) RETURN_STATUS(s); if (BC_PROG_NUM(r, n)) { @@ -6379,7 +6374,7 @@ static BC_STATUS zdc_program_execStr(char *code, size_t *bgn, bool cond) sidx = r->d.id.idx; } else if (r->t == XC_RESULT_VAR) { BcNum *n; - s = zxc_program_num(r, &n, false); + s = zxc_program_num(r, &n); if (s || !BC_PROG_STR(n)) goto exit; sidx = n->rdx; } else -- cgit v1.2.3-55-g6feb From 8ab209f00ebfc9afeeed70bc950817a2567e7389 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 29 Dec 2018 16:23:34 +0100 Subject: bc: simplify representation of 0.5 in sqrt() function old new delta zxc_program_exec 4012 4149 +137 zdc_program_printStream 144 - -144 ------------------------------------------------------------------------------ (add/remove: 0/1 grow/shrink: 1/0 up/down: 137/-144) Total: -7 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 500d97123..081e48ba8 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -2157,6 +2157,7 @@ static BC_STATUS zbc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale) { BcStatus s; BcNum num1, num2, half, f, fprime, *x0, *x1, *temp; + BcDig half_digs[1]; size_t pow, len, digs, digs1, resrdx, req, times = 0; ssize_t cmp = 1, cmp1 = SSIZE_MAX, cmp2 = SSIZE_MAX; @@ -2181,10 +2182,11 @@ static BC_STATUS zbc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale) bc_num_init(&num1, len); bc_num_init(&num2, len); - bc_num_init_DEF_SIZE(&half); + half.cap = ARRAY_SIZE(half_digs); + half.num = half_digs; bc_num_one(&half); - half.num[0] = 5; + half_digs[0] = 5; half.rdx = 1; bc_num_init(&f, len); @@ -2247,7 +2249,6 @@ static BC_STATUS zbc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale) err: bc_num_free(&fprime); bc_num_free(&f); - bc_num_free(&half); bc_num_free(&num2); bc_num_free(&num1); RETURN_STATUS(s); @@ -2285,7 +2286,7 @@ static BC_STATUS zdc_num_modexp(BcNum *a, BcNum *b, BcNum *c, BcNum *restrict d) { BcStatus s; BcNum base, exp, two, temp; - BcDig two_digs[2]; + BcDig two_digs[1]; if (c->len == 0) RETURN_STATUS(bc_error("divide by zero")); @@ -5125,15 +5126,19 @@ static BC_STATUS zxc_program_num(BcResult *r, BcNum **num) case XC_RESULT_ARRAY: case XC_RESULT_ARRAY_ELEM: { BcVec *v; - + void *p; v = xc_program_search(r->d.id.name, r->t == XC_RESULT_VAR); - +// dc variables are all stacks, so here we have this: + p = bc_vec_top(v); +// TODO: eliminate these stacks for bc-only config? if (r->t == XC_RESULT_ARRAY_ELEM) { - v = bc_vec_top(v); - if (v->len <= r->d.id.idx) bc_array_expand(v, r->d.id.idx + 1); + v = p; + if (v->len <= r->d.id.idx) + bc_array_expand(v, r->d.id.idx + 1); *num = bc_vec_item(v, r->d.id.idx); - } else - *num = bc_vec_top(v); + } else { + *num = p; + } break; } #if ENABLE_BC -- cgit v1.2.3-55-g6feb From 2cd8c04632a0e966e7ada16f5e44d1086c65a3a1 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 30 Dec 2018 15:56:36 +0100 Subject: bc: tidying up, no logic changes function old new delta bc_ops_prec_and_assoc - 25 +25 xc_vm_init 665 663 -2 bc_parse_ops 25 - -25 ------------------------------------------------------------------------------ (add/remove: 1/1 grow/shrink: 0/1 up/down: 25/-27) Total: -2 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 87 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 44 insertions(+), 43 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 081e48ba8..de6f9aab8 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -4,6 +4,17 @@ * Adapted from https://github.com/gavinhoward/bc * Original code copyright (c) 2018 Gavin D. Howard and contributors. */ +//TODO: GNU extensions: +// support ibase up to 36 +// support "define void f()..." +// support "define f(*param[])" - "pass array by reference" syntax + +#define DEBUG_LEXER 0 +#define DEBUG_COMPILE 0 +#define DEBUG_EXEC 0 +// This can be left enabled for production as well: +#define SANITY_CHECKS 1 + //config:config BC //config: bool "bc (45 kb)" //config: default y @@ -156,12 +167,6 @@ # include "dc.c" #else -#define DEBUG_LEXER 0 -#define DEBUG_COMPILE 0 -#define DEBUG_EXEC 0 -// This can be left enabled for production as well: -#define SANITY_CHECKS 1 - #if DEBUG_LEXER static uint8_t lex_indent; #define dbg_lex(...) \ @@ -203,8 +208,8 @@ typedef enum BcStatus { BC_STATUS_PARSE_EMPTY_EXP = 2, // bc_parse_expr_empty_ok() uses this } BcStatus; -#define BC_VEC_INVALID_IDX ((size_t) -1) -#define BC_VEC_START_CAP (1 << 5) +#define BC_VEC_INVALID_IDX ((size_t) -1) +#define BC_VEC_START_CAP (1 << 5) typedef void (*BcVecFree)(void *) FAST_FUNC; @@ -228,10 +233,10 @@ typedef struct BcNum { #define BC_NUM_MAX_IBASE ((unsigned long) 16) // larger value might speed up BIGNUM calculations a bit: -#define BC_NUM_DEF_SIZE (16) -#define BC_NUM_PRINT_WIDTH (69) +#define BC_NUM_DEF_SIZE 16 +#define BC_NUM_PRINT_WIDTH 69 -#define BC_NUM_KARATSUBA_LEN (32) +#define BC_NUM_KARATSUBA_LEN 32 typedef enum BcInst { #if ENABLE_BC @@ -441,10 +446,10 @@ typedef enum BcLexType { BC_LEX_KEY_FOR, BC_LEX_KEY_HALT, // code uses "type - BC_LEX_KEY_IBASE + XC_INST_IBASE" construct, - BC_LEX_KEY_IBASE, // relative order should match for: XC_INST_IBASE - BC_LEX_KEY_OBASE, // relative order should match for: XC_INST_OBASE + BC_LEX_KEY_IBASE, // relative order should match for: XC_INST_IBASE + BC_LEX_KEY_OBASE, // relative order should match for: XC_INST_OBASE BC_LEX_KEY_IF, - IF_BC(BC_LEX_KEY_LAST,) // relative order should match for: BC_INST_LAST + BC_LEX_KEY_LAST, // relative order should match for: BC_INST_LAST BC_LEX_KEY_LENGTH, BC_LEX_KEY_LIMITS, BC_LEX_KEY_PRINT, @@ -598,7 +603,7 @@ static ALWAYS_INLINE long lex_allowed_in_bc_expr(unsigned i) // This is an array of data for operators that correspond to // [XC_LEX_1st_op...] token types. -static const uint8_t bc_parse_ops[] ALIGN1 = { +static const uint8_t bc_ops_prec_and_assoc[] ALIGN1 = { #define OP(p,l) ((int)(l) * 0x10 + (p)) OP(1, false), // neg OP(6, true ), OP( 6, true ), OP( 6, true ), OP( 6, true ), OP( 6, true ), OP( 6, true ), // == <= >= != < > @@ -612,8 +617,8 @@ static const uint8_t bc_parse_ops[] ALIGN1 = { OP(0, false), OP( 0, false ), // inc dec #undef OP }; -#define bc_parse_op_PREC(i) (bc_parse_ops[i] & 0x0f) -#define bc_parse_op_LEFT(i) (bc_parse_ops[i] & 0x10) +#define bc_operation_PREC(i) (bc_ops_prec_and_assoc[i] & 0x0f) +#define bc_operation_LEFT(i) (bc_ops_prec_and_assoc[i] & 0x10) #endif // ENABLE_BC #if ENABLE_DC @@ -798,16 +803,12 @@ struct globals { # define BC_PARSE_NOCALL (1 << 3) #endif -#define BC_PROG_MAIN (0) -#define BC_PROG_READ (1) +#define BC_PROG_MAIN 0 +#define BC_PROG_READ 1 #if ENABLE_DC -#define BC_PROG_REQ_FUNCS (2) +#define BC_PROG_REQ_FUNCS 2 #endif -#define BC_PROG_STR(n) (!(n)->num && !(n)->cap) -#define BC_PROG_NUM(r, n) \ - ((r)->t != XC_RESULT_ARRAY && (r)->t != XC_RESULT_STR && !BC_PROG_STR(n)) - #define BC_FLAG_W (1 << 0) #define BC_FLAG_V (1 << 1) #define BC_FLAG_S (1 << 2) @@ -816,9 +817,6 @@ struct globals { #define BC_FLAG_I ((1 << 5) * ENABLE_DC) #define DC_FLAG_X ((1 << 6) * ENABLE_DC) -#define BC_MAX(a, b) ((a) > (b) ? (a) : (b)) -#define BC_MIN(a, b) ((a) < (b) ? (a) : (b)) - #define BC_MAX_OBASE ((unsigned) 999) #define BC_MAX_DIM ((unsigned) INT_MAX) #define BC_MAX_SCALE ((unsigned) UINT_MAX) @@ -884,6 +882,9 @@ struct globals { // Utility routines // +#define BC_MAX(a, b) ((a) > (b) ? (a) : (b)) +#define BC_MIN(a, b) ((a) < (b) ? (a) : (b)) + static void fflush_and_check(void) { fflush_all(); @@ -3712,14 +3713,14 @@ static BC_STATUS zbc_parse_stmt_allow_NLINE_before(const char *after_X) static void bc_parse_operator(BcLexType type, size_t start, size_t *nexprs) { BcParse *p = &G.prs; - char l, r = bc_parse_op_PREC(type - XC_LEX_1st_op); - bool left = bc_parse_op_LEFT(type - XC_LEX_1st_op); + char l, r = bc_operation_PREC(type - XC_LEX_1st_op); + bool left = bc_operation_LEFT(type - XC_LEX_1st_op); while (p->ops.len > start) { BcLexType t = BC_PARSE_TOP_OP(p); if (t == BC_LEX_LPAREN) break; - l = bc_parse_op_PREC(t - XC_LEX_1st_op); + l = bc_operation_PREC(t - XC_LEX_1st_op); if (l >= r && (l != r || !left)) break; xc_parse_push(BC_TOKEN_2_INST(t)); @@ -5064,6 +5065,10 @@ static BC_STATUS zdc_parse_exprs_until_eof(void) // Execution engine // +#define BC_PROG_STR(n) (!(n)->num && !(n)->cap) +#define BC_PROG_NUM(r, n) \ + ((r)->t != XC_RESULT_ARRAY && (r)->t != XC_RESULT_STR && !BC_PROG_STR(n)) + #define STACK_HAS_MORE_THAN(s, n) ((s)->len > ((size_t)(n))) #define STACK_HAS_EQUAL_OR_MORE_THAN(s, n) ((s)->len >= ((size_t)(n))) @@ -6218,8 +6223,8 @@ static BC_STATUS zdc_program_asciify(void) if (!STACK_HAS_MORE_THAN(&G.prog.results, 0)) RETURN_STATUS(bc_error_stack_has_too_few_elements()); - r = bc_vec_top(&G.prog.results); + r = bc_vec_top(&G.prog.results); s = zxc_program_num(r, &num); if (s) RETURN_STATUS(s); @@ -6235,8 +6240,8 @@ static BC_STATUS zdc_program_asciify(void) strmb.cap = ARRAY_SIZE(strmb_digs); strmb.num = strmb_digs; bc_num_ulong2num(&strmb, 0x100); - s = zbc_num_mod(&n, &strmb, &n, 0); + s = zbc_num_mod(&n, &strmb, &n, 0); if (s) goto num_err; s = zbc_num_ulong(&n, &val); if (s) goto num_err; @@ -7188,14 +7193,6 @@ static void xc_program_free(void) IF_BC(bc_num_free(&G.prog.one);) bc_vec_free(&G.input_buffer); } - -static void xc_vm_free(void) -{ - bc_vec_free(&G.files); - xc_program_free(); - xc_parse_free(); - free(G.env_args); -} #endif static void xc_program_init(void) @@ -7249,12 +7246,12 @@ static void xc_program_init(void) static int xc_vm_init(const char *env_len) { + G.prog.len = xc_vm_envLen(env_len); #if ENABLE_FEATURE_EDITING G.line_input_state = new_line_input_t(DO_HISTORY); #endif - G.prog.len = xc_vm_envLen(env_len); - bc_vec_init(&G.files, sizeof(char *), NULL); + xc_program_init(); IF_BC(if (IS_BC) bc_vm_envArgs();) xc_parse_create(BC_PROG_MAIN); @@ -7295,7 +7292,11 @@ static BcStatus xc_vm_run(void) #if ENABLE_FEATURE_CLEAN_UP if (G_exiting) // it was actually "halt" or "quit" st = EXIT_SUCCESS; - xc_vm_free(); + + bc_vec_free(&G.files); + xc_program_free(); + xc_parse_free(); + free(G.env_args); # if ENABLE_FEATURE_EDITING free_line_input_t(G.line_input_state); # endif -- cgit v1.2.3-55-g6feb From ef800e5441185585986f9b7aaf39010a926fbd5f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 30 Dec 2018 16:15:57 +0100 Subject: Bump version to 1.30.0 Signed-off-by: Denys Vlasenko --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f0b4da234..b411524c1 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 1 PATCHLEVEL = 30 SUBLEVEL = 0 -EXTRAVERSION = .git +EXTRAVERSION = NAME = Unnamed # *DOCUMENTATION* -- cgit v1.2.3-55-g6feb From 29bc59312f92623dad8b2273f0814f9cb09515a5 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 30 Dec 2018 16:32:00 +0100 Subject: Start 1.31.0 development cycle Signed-off-by: Denys Vlasenko --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index b411524c1..6fedcffba 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 1 -PATCHLEVEL = 30 +PATCHLEVEL = 31 SUBLEVEL = 0 -EXTRAVERSION = +EXTRAVERSION = .git NAME = Unnamed # *DOCUMENTATION* -- cgit v1.2.3-55-g6feb From 8b710ef000c383f3476245b27bacf034532d9786 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 30 Dec 2018 20:07:54 +0100 Subject: make_single_applets.sh: fix for BSS trick Signed-off-by: Denys Vlasenko --- make_single_applets.sh | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/make_single_applets.sh b/make_single_applets.sh index 2075cb9a7..a37168cdf 100755 --- a/make_single_applets.sh +++ b/make_single_applets.sh @@ -72,6 +72,16 @@ for app; do echo "NUM_APPLETS != 1 for ${app}: `cat include/NUM_APPLETS.h`" mv .config busybox_config_${app} else + if grep -q 'use larger COMMON_BUFSIZE' busybox_make_${app}.log; then + # FEATURE_USE_BSS_TAIL=y is selected, and build system + # recommends rebuilding. Do so, and print some + # debug info to see whether it works right: + tail -n1 busybox_make_${app}.log + nm busybox_unstripped | grep ' _end' + make >/dev/null 2>&1 + nm busybox_unstripped | grep ' _end' + grep ^bb_common_bufsiz1 busybox_unstripped.map + fi grep -i -e error: -e warning: busybox_make_${app}.log \ || rm busybox_make_${app}.log mv busybox busybox_${app} -- cgit v1.2.3-55-g6feb From aad76968cd5934ee17f36cd8e817e86ae952b533 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 30 Dec 2018 20:24:59 +0100 Subject: pmap: make 32-bit version work better on 64-bit kernels Signed-off-by: Denys Vlasenko --- include/libbb.h | 7 ++++++- libbb/procps.c | 8 ++++---- procps/pmap.c | 8 +++++++- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/include/libbb.h b/include/libbb.h index daa96728b..d2563999a 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1828,7 +1828,12 @@ struct smaprec { unsigned long stack; unsigned long smap_pss, smap_swap; unsigned long smap_size; - unsigned long smap_start; + // For mixed 32/64 userspace, 32-bit pmap still needs + // 64-bit field here to correctly show 64-bit processes: + unsigned long long smap_start; + // (strictly speaking, other fields need to be wider too, + // but they are in kbytes, not bytes, and they hold sizes, + // not start addresses, sizes tend to be less than 4 terabytes) char smap_mode[5]; char *smap_name; }; diff --git a/libbb/procps.c b/libbb/procps.c index 9d8a921df..af3ad86ff 100644 --- a/libbb/procps.c +++ b/libbb/procps.c @@ -120,11 +120,11 @@ void FAST_FUNC free_procps_scan(procps_status_t* sp) } #if ENABLE_FEATURE_TOPMEM || ENABLE_PMAP -static unsigned long fast_strtoul_16(char **endptr) +static unsigned long long fast_strtoull_16(char **endptr) { unsigned char c; char *str = *endptr; - unsigned long n = 0; + unsigned long long n = 0; /* Need to stop on both ' ' and '\n' */ while ((c = *str++) > ' ') { @@ -238,8 +238,8 @@ int FAST_FUNC procps_read_smaps(pid_t pid, struct smaprec *total, *tp = ' '; tp = buf; - currec.smap_start = fast_strtoul_16(&tp); - currec.smap_size = (fast_strtoul_16(&tp) - currec.smap_start) >> 10; + currec.smap_start = fast_strtoull_16(&tp); + currec.smap_size = (fast_strtoull_16(&tp) - currec.smap_start) >> 10; strncpy(currec.smap_mode, tp, sizeof(currec.smap_mode)-1); diff --git a/procps/pmap.c b/procps/pmap.c index c8fa0d280..9e541c707 100644 --- a/procps/pmap.c +++ b/procps/pmap.c @@ -37,6 +37,12 @@ # define DASHES "--------" #endif +#if ULLONG_MAX == 0xffffffff +# define AFMTLL "8" +#else +# define AFMTLL "16" +#endif + enum { OPT_x = 1 << 0, OPT_q = 1 << 1, @@ -46,7 +52,7 @@ static void print_smaprec(struct smaprec *currec, void *data) { unsigned opt = (uintptr_t)data; - printf("%0" AFMT "lx ", currec->smap_start); + printf("%0" AFMTLL "llx ", currec->smap_start); if (opt & OPT_x) printf("%7lu %7lu %7lu %7lu ", -- cgit v1.2.3-55-g6feb From 2747f6195b94db6c1adf2eae243df5c0a01d39f2 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 31 Dec 2018 18:48:10 +0100 Subject: bc: fold xc_lex_more_input() into peek_inbuf() function old new delta peek_inbuf 69 56 -13 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 31 +++++++++---------------------- 1 file changed, 9 insertions(+), 22 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index de6f9aab8..72c23542c 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -2727,20 +2727,6 @@ static BC_STATUS zxc_num_parse(BcNum *n, const char *val, unsigned base_t) } #define zxc_num_parse(...) (zxc_num_parse(__VA_ARGS__) COMMA_SUCCESS) -static bool xc_lex_more_input(void) -{ - BcParse *p = &G.prs; - - bc_vec_pop_all(&G.input_buffer); - - xc_read_line(&G.input_buffer, G.prs.lex_input_fp); - - p->lex_inbuf = G.input_buffer.v; -// bb_error_msg("G.input_buffer.len:%d '%s'", G.input_buffer.len, G.input_buffer.v); - - return G.input_buffer.len > 1; -} - // p->lex_inbuf points to the current string to be parsed. // if p->lex_inbuf points to '\0', it's either EOF or it points after // last processed line's terminating '\n' (and more reading needs to be done @@ -2774,10 +2760,13 @@ static bool xc_lex_more_input(void) // end" - ...prints "str#\end" static char peek_inbuf(void) { - if (*G.prs.lex_inbuf == '\0') { - if (G.prs.lex_input_fp) - if (!xc_lex_more_input()) - G.prs.lex_input_fp = NULL; + if (*G.prs.lex_inbuf == '\0' + && G.prs.lex_input_fp + ) { + xc_read_line(&G.input_buffer, G.prs.lex_input_fp); + G.prs.lex_inbuf = G.input_buffer.v; + if (G.input_buffer.len <= 1) // on EOF, len is 1 (NUL byte) + G.prs.lex_input_fp = NULL; } return *G.prs.lex_inbuf; } @@ -2796,7 +2785,7 @@ static void xc_lex_lineComment(void) // Try: echo -n '#foo' | bc p->lex = XC_LEX_WHITESPACE; - // We depend here on input being done in whole lines: + // Not peek_inbuf(): we depend on input being done in whole lines: // '\0' which isn't the EOF can only be seen after '\n'. while ((c = *p->lex_inbuf) != '\n' && c != '\0') p->lex_inbuf++; @@ -5281,17 +5270,15 @@ static BC_STATUS zxc_program_read(void) IF_DC(s = zdc_parse_exprs_until_eof()); } if (s) goto exec_err; - if (G.prs.lex != XC_LEX_NLINE && G.prs.lex != XC_LEX_EOF) { s = bc_error("bad read() expression"); goto exec_err; } + xc_parse_push(XC_INST_RET); ip.func = BC_PROG_READ; ip.inst_idx = 0; IF_BC(ip.results_len_before_call = G.prog.results.len;) - - xc_parse_push(XC_INST_RET); bc_vec_push(&G.prog.exestack, &ip); exec_err: -- cgit v1.2.3-55-g6feb From 680ccd357395ad081afe821ffbeef1ff338fe41d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 31 Dec 2018 19:42:13 +0100 Subject: bc: support ibase up to 36 (GNU compat) function old new delta zxc_program_num 995 1018 +23 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 50 +++++++++++++++++++++++++++++++------------------- testsuite/bc.tests | 5 +++++ 2 files changed, 36 insertions(+), 19 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 72c23542c..798bc0a3e 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -5,7 +5,6 @@ * Original code copyright (c) 2018 Gavin D. Howard and contributors. */ //TODO: GNU extensions: -// support ibase up to 36 // support "define void f()..." // support "define f(*param[])" - "pass array by reference" syntax @@ -231,7 +230,7 @@ typedef struct BcNum { bool neg; } BcNum; -#define BC_NUM_MAX_IBASE ((unsigned long) 16) +#define BC_NUM_MAX_IBASE 36 // larger value might speed up BIGNUM calculations a bit: #define BC_NUM_DEF_SIZE 16 #define BC_NUM_PRINT_WIDTH 69 @@ -2638,32 +2637,33 @@ static void bc_num_parseDecimal(BcNum *n, const char *val) static void bc_num_parseBase(BcNum *n, const char *val, unsigned base_t) { BcStatus s; - BcNum temp, mult, result; + BcNum mult, result; + BcNum temp; BcNum base; + BcDig temp_digs[ULONG_NUM_BUFSIZE]; BcDig base_digs[ULONG_NUM_BUFSIZE]; BcDig c = '\0'; - unsigned long v; - size_t i, digits; - - for (i = 0; ; ++i) { - if (val[i] == '\0') - return; - if (val[i] != '.' && val[i] != '0') - break; - } + size_t digits; - bc_num_init_DEF_SIZE(&temp); bc_num_init_DEF_SIZE(&mult); + + temp.cap = ARRAY_SIZE(temp_digs); + temp.num = temp_digs; + base.cap = ARRAY_SIZE(base_digs); base.num = base_digs; bc_num_ulong2num(&base, base_t); + base_t--; for (;;) { + unsigned v; + c = *val++; if (c == '\0') goto int_err; if (c == '.') break; - v = (unsigned long) (c <= '9' ? c - '0' : c - 'A' + 10); + v = (unsigned)(c <= '9' ? c - '0' : c - 'A' + 10); + if (v > base_t) v = base_t; s = zbc_num_mul(n, &base, &mult, 0); if (s) goto int_err; @@ -2678,11 +2678,14 @@ static void bc_num_parseBase(BcNum *n, const char *val, unsigned base_t) digits = 0; for (;;) { + unsigned v; + c = *val++; if (c == '\0') break; digits++; - v = (unsigned long) (c <= '9' ? c - '0' : c - 'A' + 10); + v = (unsigned)(c <= '9' ? c - '0' : c - 'A' + 10); + if (v > base_t) v = base_t; s = zbc_num_mul(&result, &base, &result, 0); if (s) goto err; @@ -2707,18 +2710,27 @@ static void bc_num_parseBase(BcNum *n, const char *val, unsigned base_t) bc_num_free(&result); int_err: bc_num_free(&mult); - bc_num_free(&temp); } static BC_STATUS zxc_num_parse(BcNum *n, const char *val, unsigned base_t) { + size_t i; + if (!xc_num_strValid(val)) RETURN_STATUS(bc_error("bad number string")); bc_num_zero(n); - while (*val == '0') val++; + while (*val == '0') + val++; + for (i = 0; ; ++i) { + if (val[i] == '\0') + RETURN_STATUS(BC_STATUS_SUCCESS); + if (val[i] != '.' && val[i] != '0') + break; + } - if (base_t == 10) + if (base_t == 10 || val[1] == '\0') + // Decimal, or single-digit number bc_num_parseDecimal(n, val); else bc_num_parseBase(n, val, base_t); @@ -5526,7 +5538,7 @@ static BC_STATUS zxc_num_printBase(BcNum *n) n->neg = false; - if (G.prog.ob_t <= BC_NUM_MAX_IBASE) { + if (G.prog.ob_t <= 16) { width = 1; print = bc_num_printHex; } else { diff --git a/testsuite/bc.tests b/testsuite/bc.tests index 3fbb49996..1d4545559 100755 --- a/testsuite/bc.tests +++ b/testsuite/bc.tests @@ -218,6 +218,11 @@ for(i=1; i<3; i++) { 99 " +testing "bc ibase" \ + "bc" \ + "99\n1295\n1224\n" \ + "" "a=ZZ;a;ibase=36;a=ZZ;a;ibase=Z;a=ZZ;a" + tar xJf bc_large.tar.xz for f in bc*.bc; do -- cgit v1.2.3-55-g6feb From 8797adc1c6e84789c261ee24afe5a1cbfaddba6b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 31 Dec 2018 19:50:06 +0100 Subject: bc: remove superfluous assigment Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 798bc0a3e..febf51cfd 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -2642,7 +2642,6 @@ static void bc_num_parseBase(BcNum *n, const char *val, unsigned base_t) BcNum base; BcDig temp_digs[ULONG_NUM_BUFSIZE]; BcDig base_digs[ULONG_NUM_BUFSIZE]; - BcDig c = '\0'; size_t digits; bc_num_init_DEF_SIZE(&mult); @@ -2657,6 +2656,7 @@ static void bc_num_parseBase(BcNum *n, const char *val, unsigned base_t) for (;;) { unsigned v; + char c; c = *val++; if (c == '\0') goto int_err; @@ -2679,6 +2679,7 @@ static void bc_num_parseBase(BcNum *n, const char *val, unsigned base_t) digits = 0; for (;;) { unsigned v; + char c; c = *val++; if (c == '\0') break; -- cgit v1.2.3-55-g6feb From 51b510a480b99d480bcf6919b8bae16eb1c61718 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 1 Jan 2019 02:19:02 +0100 Subject: bc: in xc_read_line(), check ^C on NUL input bytes too Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index febf51cfd..23b3521d4 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -2509,7 +2509,7 @@ static void xc_read_line(BcVec *vec, FILE *fp) i = 0; for (;;) { char c = line_buf[i++]; - if (!c) break; + if (c == '\0') break; if (bad_input_byte(c)) goto again; } bc_vec_string(vec, n, line_buf); @@ -2522,14 +2522,16 @@ static void xc_read_line(BcVec *vec, FILE *fp) bool bad_chars = 0; do { + get_char: #if ENABLE_FEATURE_BC_INTERACTIVE if (G_interrupt) { // ^C was pressed: ignore entire line, get another one - bc_vec_pop_all(vec); - goto intr; + goto again; } #endif - do c = fgetc(fp); while (c == '\0'); + c = fgetc(fp); + if (c == '\0') + goto get_char; if (c == EOF) { if (ferror(fp)) bb_perror_msg_and_die("input error"); -- cgit v1.2.3-55-g6feb From 37bdd8f8cb19b674485be1dec6e8ac96d930c87f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 1 Jan 2019 15:40:43 +0100 Subject: tls: pstm code shrink Optimize ABI calling convention and "dead code" cases where return value is known to be always "success". function old new delta pstm_mod 113 1227 +1114 pstm_exptmod 1463 1532 +69 pstm_montgomery_reduce 381 393 +12 pstm_sqr_comba 478 487 +9 pstm_mul_comba 447 452 +5 der_binary_to_pstm 42 45 +3 pstm_count_bits 48 46 -2 pstm_clear 72 70 -2 pstm_clamp 57 55 -2 pstm_zero 38 34 -4 pstm_init_size 46 42 -4 pstm_init_for_read_unsigned_bin 24 20 -4 pstm_grow 72 68 -4 pstm_unsigned_bin_size 37 32 -5 pstm_cmp_mag 78 72 -6 pstm_copy 92 84 -8 pstm_mul_d 224 215 -9 pstm_rshd 104 94 -10 pstm_mul_2 156 146 -10 tls_handshake 2085 2072 -13 psRsaEncryptPub 421 408 -13 pstm_lshd 109 95 -14 pstm_cmp 54 39 -15 s_pstm_sub 228 212 -16 pstm_init_copy 72 52 -20 pstm_read_unsigned_bin 109 88 -21 pstm_mulmod 120 99 -21 s_pstm_add 337 314 -23 pstm_add 108 84 -24 pstm_mul_2d 186 161 -25 pstm_sub 102 74 -28 pstm_to_unsigned_bin 151 120 -31 pstm_set 34 - -34 pstm_div_2d 409 373 -36 pstm_init 42 - -42 pstm_exch 50 - -50 pstm_montgomery_setup 89 - -89 pstm_2expt 96 - -96 pstm_montgomery_calc_normalization 140 - -140 pstm_div 1522 - -1522 ------------------------------------------------------------------------------ (add/remove: 0/7 grow/shrink: 6/27 up/down: 1212/-2343) Total: -1131 bytes Signed-off-by: Denys Vlasenko --- networking/tls_pstm.c | 109 ++++++++++++++++++++++---------- networking/tls_pstm.h | 86 ++++++++++++------------- networking/tls_pstm_montgomery_reduce.c | 2 +- networking/tls_pstm_mul_comba.c | 2 +- networking/tls_pstm_sqr_comba.c | 2 +- networking/tls_rsa.c | 4 +- 6 files changed, 126 insertions(+), 79 deletions(-) diff --git a/networking/tls_pstm.c b/networking/tls_pstm.c index e12e6c9d4..e5544ab11 100644 --- a/networking/tls_pstm.c +++ b/networking/tls_pstm.c @@ -47,13 +47,18 @@ //#include "../cryptoApi.h" #ifndef DISABLE_PSTM +#undef pstm_mul_2d static int32 pstm_mul_2d(pstm_int *a, int b, pstm_int *c); //bbox: was int16 b +#define pstm_mul_2d(a, b, c) (pstm_mul_2d(a, b, c), PSTM_OKAY) /******************************************************************************/ /* init an pstm_int for a given size */ -int32 pstm_init_size(psPool_t *pool, pstm_int * a, uint32 size) +#undef pstm_init_size +#define pstm_init_size(pool, a, size) \ + pstm_init_size( a, size) +int32 FAST_FUNC pstm_init_size(psPool_t *pool, pstm_int * a, uint32 size) { //bbox // uint16 x; @@ -75,12 +80,17 @@ int32 pstm_init_size(psPool_t *pool, pstm_int * a, uint32 size) // } return PSTM_OKAY; } +#undef pstm_init_size +#define pstm_init_size(pool, a, size) (pstm_init_size(a, size), PSTM_OKAY) /******************************************************************************/ /* Init a new pstm_int. */ -int32 pstm_init(psPool_t *pool, pstm_int * a) +#undef pstm_init +#define pstm_init(pool, a) \ + pstm_init( a) +static int32 pstm_init(psPool_t *pool, pstm_int * a) { //bbox // int32 i; @@ -106,12 +116,15 @@ int32 pstm_init(psPool_t *pool, pstm_int * a) return PSTM_OKAY; } +#undef pstm_init +#define pstm_init(pool, a) (pstm_init(a), PSTM_OKAY) /******************************************************************************/ /* Grow as required */ -int32 pstm_grow(pstm_int * a, int size) +#undef pstm_grow +int32 FAST_FUNC pstm_grow(pstm_int * a, int size) { int i; //bbox: was int16 pstm_digit *tmp; @@ -142,11 +155,13 @@ int32 pstm_grow(pstm_int * a, int size) } return PSTM_OKAY; } +#define pstm_grow(a, size) (pstm_grow(a, size), PSTM_OKAY) /******************************************************************************/ /* copy, b = a (b must be pre-allocated) */ +#undef pstm_copy int32 pstm_copy(pstm_int * a, pstm_int * b) { int32 res, n; @@ -195,6 +210,7 @@ int32 pstm_copy(pstm_int * a, pstm_int * b) b->sign = a->sign; return PSTM_OKAY; } +#define pstm_copy(a, b) (pstm_copy(a, b), PSTM_OKAY) /******************************************************************************/ /* @@ -204,7 +220,7 @@ int32 pstm_copy(pstm_int * a, pstm_int * b) leading "used" digit will be non-zero. Typically very fast. Also fixes the sign if there are no more leading digits */ -void pstm_clamp(pstm_int * a) +void FAST_FUNC pstm_clamp(pstm_int * a) { /* decrease used while the most significant digit is zero. */ while (a->used > 0 && a->dp[a->used - 1] == 0) { @@ -220,7 +236,7 @@ void pstm_clamp(pstm_int * a) /* clear one (frees). */ -void pstm_clear(pstm_int * a) +void FAST_FUNC pstm_clear(pstm_int * a) { int32 i; /* @@ -248,6 +264,7 @@ void pstm_clear(pstm_int * a) /* clear many (frees). */ +#if 0 //UNUSED void pstm_clear_multi(pstm_int *mp0, pstm_int *mp1, pstm_int *mp2, pstm_int *mp3, pstm_int *mp4, pstm_int *mp5, pstm_int *mp6, pstm_int *mp7) @@ -272,12 +289,13 @@ void pstm_clear_multi(pstm_int *mp0, pstm_int *mp1, pstm_int *mp2, } } } +#endif /******************************************************************************/ /* Set to zero. */ -void pstm_zero(pstm_int * a) +static void pstm_zero(pstm_int * a) { int32 n; pstm_digit *tmp; @@ -296,7 +314,7 @@ void pstm_zero(pstm_int * a) /* Compare maginitude of two ints (unsigned). */ -int32 pstm_cmp_mag(pstm_int * a, pstm_int * b) +int32 FAST_FUNC pstm_cmp_mag(pstm_int * a, pstm_int * b) { int n; //bbox: was int16 pstm_digit *tmpa, *tmpb; @@ -336,7 +354,7 @@ int32 pstm_cmp_mag(pstm_int * a, pstm_int * b) /* Compare two ints (signed) */ -int32 pstm_cmp(pstm_int * a, pstm_int * b) +int32 FAST_FUNC pstm_cmp(pstm_int * a, pstm_int * b) { /* compare based on sign @@ -364,7 +382,7 @@ int32 pstm_cmp(pstm_int * a, pstm_int * b) pstm_ints can be initialized more precisely when they will populated using pstm_read_unsigned_bin since the length of the byte stream is known */ -int32 pstm_init_for_read_unsigned_bin(psPool_t *pool, pstm_int *a, uint32 len) +int32 FAST_FUNC pstm_init_for_read_unsigned_bin(psPool_t *pool, pstm_int *a, uint32 len) { int32 size; /* @@ -385,7 +403,7 @@ int32 pstm_init_for_read_unsigned_bin(psPool_t *pool, pstm_int *a, uint32 len) called pstm_init_for_read_unsigned_bin first. There is some grow logic here if the default pstm_init was used but we don't really want to hit it. */ -int32 pstm_read_unsigned_bin(pstm_int *a, unsigned char *b, int32 c) +int32 FAST_FUNC pstm_read_unsigned_bin(pstm_int *a, unsigned char *b, int32 c) { /* zero the int */ pstm_zero (a); @@ -460,7 +478,7 @@ int32 pstm_read_unsigned_bin(pstm_int *a, unsigned char *b, int32 c) /******************************************************************************/ /* */ -int pstm_count_bits (pstm_int * a) +static int pstm_count_bits(pstm_int * a) { int r; //bbox: was int16 pstm_digit q; @@ -482,14 +500,14 @@ int pstm_count_bits (pstm_int * a) } /******************************************************************************/ -int32 pstm_unsigned_bin_size(pstm_int *a) +int32 FAST_FUNC pstm_unsigned_bin_size(pstm_int *a) { int32 size = pstm_count_bits (a); return (size / 8 + ((size & 7) != 0 ? 1 : 0)); } /******************************************************************************/ -void pstm_set(pstm_int *a, pstm_digit b) +static void pstm_set(pstm_int *a, pstm_digit b) { pstm_zero(a); a->dp[0] = b; @@ -500,7 +518,7 @@ void pstm_set(pstm_int *a, pstm_digit b) /* Right shift */ -void pstm_rshd(pstm_int *a, int x) +static void pstm_rshd(pstm_int *a, int x) { int y; //bbox: was int16 @@ -529,7 +547,8 @@ void pstm_rshd(pstm_int *a, int x) /* Shift left a certain amount of digits. */ -int32 pstm_lshd(pstm_int * a, int b) +#undef pstm_lshd +static int32 pstm_lshd(pstm_int * a, int b) { int x; //bbox: was int16 int32 res; @@ -577,12 +596,13 @@ int32 pstm_lshd(pstm_int * a, int b) } return PSTM_OKAY; } +#define pstm_lshd(a, b) (pstm_lshd(a, b), PSTM_OKAY) /******************************************************************************/ /* computes a = 2**b */ -int32 pstm_2expt(pstm_int *a, int b) +static int32 pstm_2expt(pstm_int *a, int b) { int z; //bbox: was int16 @@ -616,7 +636,7 @@ int32 pstm_2expt(pstm_int *a, int b) /* */ -int32 pstm_mul_2(pstm_int * a, pstm_int * b) +int32 FAST_FUNC pstm_mul_2(pstm_int * a, pstm_int * b) { int32 res; int x, oldused; //bbox: was int16 @@ -682,7 +702,7 @@ int32 pstm_mul_2(pstm_int * a, pstm_int * b) /* unsigned subtraction ||a|| >= ||b|| ALWAYS! */ -int32 s_pstm_sub(pstm_int *a, pstm_int *b, pstm_int *c) +int32 FAST_FUNC s_pstm_sub(pstm_int *a, pstm_int *b, pstm_int *c) { int oldbused, oldused; //bbox: was int16 int32 x; @@ -779,7 +799,7 @@ static int32 s_pstm_add(pstm_int *a, pstm_int *b, pstm_int *c) /* */ -int32 pstm_sub(pstm_int *a, pstm_int *b, pstm_int *c) +int32 FAST_FUNC pstm_sub(pstm_int *a, pstm_int *b, pstm_int *c) { int32 res; int sa, sb; //bbox: was int16 @@ -824,6 +844,7 @@ int32 pstm_sub(pstm_int *a, pstm_int *b, pstm_int *c) /* c = a - b */ +#if 0 //UNUSED int32 pstm_sub_d(psPool_t *pool, pstm_int *a, pstm_digit b, pstm_int *c) { pstm_int tmp; @@ -837,12 +858,13 @@ int32 pstm_sub_d(psPool_t *pool, pstm_int *a, pstm_digit b, pstm_int *c) pstm_clear(&tmp); return res; } +#endif /******************************************************************************/ /* setups the montgomery reduction */ -int32 pstm_montgomery_setup(pstm_int *a, pstm_digit *rho) +static int32 pstm_montgomery_setup(pstm_int *a, pstm_digit *rho) { pstm_digit x, b; @@ -878,7 +900,7 @@ int32 pstm_montgomery_setup(pstm_int *a, pstm_digit *rho) * computes a = B**n mod b without division or multiplication useful for * normalizing numbers in a Montgomery system. */ -int32 pstm_montgomery_calc_normalization(pstm_int *a, pstm_int *b) +static int32 pstm_montgomery_calc_normalization(pstm_int *a, pstm_int *b) { int32 x; int bits; //bbox: was int16 @@ -916,6 +938,7 @@ int32 pstm_montgomery_calc_normalization(pstm_int *a, pstm_int *b) /* c = a * 2**d */ +#undef pstm_mul_2d static int32 pstm_mul_2d(pstm_int *a, int b, pstm_int *c) { pstm_digit carry, carrytmp, shift; @@ -956,11 +979,13 @@ static int32 pstm_mul_2d(pstm_int *a, int b, pstm_int *c) pstm_clamp(c); return PSTM_OKAY; } +#define pstm_mul_2d(a, b, c) (pstm_mul_2d(a, b, c), PSTM_OKAY) /******************************************************************************/ /* c = a mod 2**d */ +#undef pstm_mod_2d static int32 pstm_mod_2d(pstm_int *a, int b, pstm_int *c) //bbox: was int16 b { int x; //bbox: was int16 @@ -991,13 +1016,15 @@ static int32 pstm_mod_2d(pstm_int *a, int b, pstm_int *c) //bbox: was int16 b pstm_clamp (c); return PSTM_OKAY; } +#define pstm_mod_2d(a, b, c) (pstm_mod_2d(a, b, c), PSTM_OKAY) /******************************************************************************/ /* c = a * b */ -int32 pstm_mul_d(pstm_int *a, pstm_digit b, pstm_int *c) +#undef pstm_mul_d +static int32 pstm_mul_d(pstm_int *a, pstm_digit b, pstm_int *c) { pstm_word w; int32 res; @@ -1027,12 +1054,16 @@ int32 pstm_mul_d(pstm_int *a, pstm_digit b, pstm_int *c) pstm_clamp(c); return PSTM_OKAY; } +#define pstm_mul_d(a, b, c) (pstm_mul_d(a, b, c), PSTM_OKAY) /******************************************************************************/ /* c = a / 2**b */ -int32 pstm_div_2d(psPool_t *pool, pstm_int *a, int b, pstm_int *c, +#undef pstm_div_2d +#define pstm_div_2d(pool, a, b, c, d) \ + pstm_div_2d( a, b, c, d) +static int32 pstm_div_2d(psPool_t *pool, pstm_int *a, int b, pstm_int *c, pstm_int *d) { pstm_digit D, r, rr; @@ -1113,11 +1144,14 @@ LBL_DONE: } return res; } +#undef pstm_div_2d +#define pstm_div_2d(pool, a, b, c, d) (pstm_div_2d(a, b, c, d), PSTM_OKAY) /******************************************************************************/ /* b = a/2 */ +#if 0 //UNUSED int32 pstm_div_2(pstm_int * a, pstm_int * b) { int x, oldused; //bbox: was int16 @@ -1161,12 +1195,16 @@ int32 pstm_div_2(pstm_int * a, pstm_int * b) pstm_clamp (b); return PSTM_OKAY; } +#endif /******************************************************************************/ /* Creates "a" then copies b into it */ -int32 pstm_init_copy(psPool_t *pool, pstm_int * a, pstm_int * b, int toSqr) +#undef pstm_init_copy +#define pstm_init_copy(pool, a, b, toSqr) \ + pstm_init_copy( a, b, toSqr) +static int32 pstm_init_copy(psPool_t *pool, pstm_int * a, pstm_int * b, int toSqr) { int x; //bbox: was int16 int32 res; @@ -1191,6 +1229,8 @@ int32 pstm_init_copy(psPool_t *pool, pstm_int * a, pstm_int * b, int toSqr) } return pstm_copy(b, a); } +#undef pstm_init_copy +#define pstm_init_copy(pool, a, b, toSqr) (pstm_init_copy(a, b, toSqr), PSTM_OKAY) /******************************************************************************/ /* @@ -1274,7 +1314,7 @@ static uint64 psDiv128(uint128 *numerator, uint64 denominator) /* a/b => cb + d == a */ -int32 pstm_div(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c, +static int32 pstm_div(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c, pstm_int *d) { pstm_int q, x, y, t1, t2; @@ -1487,7 +1527,7 @@ LBL_T1:pstm_clear (&t1); Swap the elements of two integers, for cases where you can't simply swap the pstm_int pointers around */ -void pstm_exch(pstm_int * a, pstm_int * b) +static void pstm_exch(pstm_int * a, pstm_int * b) { pstm_int t; @@ -1500,7 +1540,7 @@ void pstm_exch(pstm_int * a, pstm_int * b) /* c = a mod b, 0 <= c < b */ -int32 pstm_mod(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c) +static int32 pstm_mod(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c) { pstm_int t; int32 err; @@ -1527,7 +1567,7 @@ int32 pstm_mod(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c) /* d = a * b (mod c) */ -int32 pstm_mulmod(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c, +int32 FAST_FUNC pstm_mulmod(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c, pstm_int *d) { int32 res; @@ -1560,7 +1600,7 @@ int32 pstm_mulmod(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c, * y = g**x (mod b) * Some restrictions... x must be positive and < b */ -int32 pstm_exptmod(psPool_t *pool, pstm_int *G, pstm_int *X, pstm_int *P, +int32 FAST_FUNC pstm_exptmod(psPool_t *pool, pstm_int *G, pstm_int *X, pstm_int *P, pstm_int *Y) { pstm_int M[32], res; /* Keep this winsize based: (1 << max_winsize) */ @@ -1801,7 +1841,7 @@ LBL_RES:pstm_clear(&res); /* */ -int32 pstm_add(pstm_int *a, pstm_int *b, pstm_int *c) +int32 FAST_FUNC pstm_add(pstm_int *a, pstm_int *b, pstm_int *c) { int32 res; int sa, sb; //bbox: was int16 @@ -1862,6 +1902,7 @@ static void pstm_reverse (unsigned char *s, int len) //bbox: was int16 len No reverse. Useful in some of the EIP-154 PKA stuff where special byte order seems to come into play more often */ +#if 0 //UNUSED int32 pstm_to_unsigned_bin_nr(psPool_t *pool, pstm_int *a, unsigned char *b) { int32 res; @@ -1883,11 +1924,12 @@ int32 pstm_to_unsigned_bin_nr(psPool_t *pool, pstm_int *a, unsigned char *b) pstm_clear(&t); return PS_SUCCESS; } +#endif /******************************************************************************/ /* */ -int32 pstm_to_unsigned_bin(psPool_t *pool, pstm_int *a, unsigned char *b) +int32 FAST_FUNC pstm_to_unsigned_bin(psPool_t *pool, pstm_int *a, unsigned char *b) { int32 res; int x; //bbox: was int16 @@ -1910,11 +1952,12 @@ int32 pstm_to_unsigned_bin(psPool_t *pool, pstm_int *a, unsigned char *b) return PS_SUCCESS; } +#if 0 //UNUSED /******************************************************************************/ /* compare against a single digit */ -int32 pstm_cmp_d(pstm_int *a, pstm_digit b) +static int32 pstm_cmp_d(pstm_int *a, pstm_digit b) { /* compare based on sign */ if ((b && a->used == 0) || a->sign == PSTM_NEG) { @@ -2259,5 +2302,7 @@ LBL_Y: pstm_clear(&y); LBL_X: pstm_clear(&x); return res; } +#endif //UNUSED + #endif /* !DISABLE_PSTM */ /******************************************************************************/ diff --git a/networking/tls_pstm.h b/networking/tls_pstm.h index df705adce..bc7a0119a 100644 --- a/networking/tls_pstm.h +++ b/networking/tls_pstm.h @@ -136,148 +136,148 @@ typedef struct { #define pstm_isodd(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? PS_TRUE : PS_FALSE) #define pstm_abs(a, b) { pstm_copy(a, b); (b)->sign = 0; } -extern void pstm_set(pstm_int *a, pstm_digit b); +//made static:extern void pstm_set(pstm_int *a, pstm_digit b); -extern void pstm_zero(pstm_int * a); +//made static:extern void pstm_zero(pstm_int * a); //bbox: pool unused #define pstm_init(pool, a) \ pstm_init( a) -extern int32 pstm_init(psPool_t *pool, pstm_int * a); +//made static:extern int32 pstm_init(psPool_t *pool, pstm_int * a); //bbox: pool unused #define pstm_init_size(pool, a, size) \ pstm_init_size( a, size) -extern int32 pstm_init_size(psPool_t *pool, pstm_int * a, uint32 size); +extern int32 pstm_init_size(psPool_t *pool, pstm_int * a, uint32 size) FAST_FUNC; //bbox: pool unused #define pstm_init_copy(pool, a, b, toSqr) \ pstm_init_copy( a, b, toSqr) -extern int32 pstm_init_copy(psPool_t *pool, pstm_int * a, pstm_int * b, - int toSqr); //bbox: was int16 toSqr +//made static:extern int32 pstm_init_copy(psPool_t *pool, pstm_int * a, pstm_int * b, +//made static: int toSqr); //bbox: was int16 toSqr -extern int pstm_count_bits (pstm_int * a); //bbox: was returning int16 +//made static:extern int pstm_count_bits (pstm_int * a) FAST_FUNC; //bbox: was returning int16 //bbox: pool unused #define pstm_init_for_read_unsigned_bin(pool, a, len) \ pstm_init_for_read_unsigned_bin( a, len) extern int32 pstm_init_for_read_unsigned_bin(psPool_t *pool, pstm_int *a, - uint32 len); + uint32 len) FAST_FUNC; -extern int32 pstm_read_unsigned_bin(pstm_int *a, unsigned char *b, int32 c); +extern int32 pstm_read_unsigned_bin(pstm_int *a, unsigned char *b, int32 c) FAST_FUNC; -extern int32 pstm_unsigned_bin_size(pstm_int *a); +extern int32 pstm_unsigned_bin_size(pstm_int *a) FAST_FUNC; extern int32 pstm_copy(pstm_int * a, pstm_int * b); -extern void pstm_exch(pstm_int * a, pstm_int * b); +//made static:extern void pstm_exch(pstm_int * a, pstm_int * b); -extern void pstm_clear(pstm_int * a); +extern void pstm_clear(pstm_int * a) FAST_FUNC; extern void pstm_clear_multi(pstm_int *mp0, pstm_int *mp1, pstm_int *mp2, pstm_int *mp3, pstm_int *mp4, pstm_int *mp5, pstm_int *mp6, - pstm_int *mp7); + pstm_int *mp7) FAST_FUNC; -extern int32 pstm_grow(pstm_int * a, int size); //bbox: was int16 size +extern int32 pstm_grow(pstm_int * a, int size) FAST_FUNC; //bbox: was int16 size -extern void pstm_clamp(pstm_int * a); +extern void pstm_clamp(pstm_int * a) FAST_FUNC; -extern int32 pstm_cmp(pstm_int * a, pstm_int * b); +extern int32 pstm_cmp(pstm_int * a, pstm_int * b) FAST_FUNC; -extern int32 pstm_cmp_mag(pstm_int * a, pstm_int * b); +extern int32 pstm_cmp_mag(pstm_int * a, pstm_int * b) FAST_FUNC; -extern void pstm_rshd(pstm_int *a, int x); //bbox: was int16 x +//made static:extern void pstm_rshd(pstm_int *a, int x); //bbox: was int16 x -extern int32 pstm_lshd(pstm_int * a, int b); //bbox: was int16 b +//made static:extern int32 pstm_lshd(pstm_int * a, int b); //bbox: was int16 b //bbox: pool unused #define pstm_div(pool, a, b, c, d) \ pstm_div( a, b, c, d) -extern int32 pstm_div(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c, - pstm_int *d); +//made static:extern int32 pstm_div(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c, +//made static: pstm_int *d); //bbox: pool unused #define pstm_div_2d(pool, a, b, c, d) \ pstm_div_2d( a, b, c, d) -extern int32 pstm_div_2d(psPool_t *pool, pstm_int *a, int b, pstm_int *c, - pstm_int *d); //bbox: was int16 b +//made static:extern int32 pstm_div_2d(psPool_t *pool, pstm_int *a, int b, pstm_int *c, +//made static: pstm_int *d); //bbox: was int16 b -extern int32 pstm_div_2(pstm_int * a, pstm_int * b); +extern int32 pstm_div_2(pstm_int * a, pstm_int * b) FAST_FUNC; -extern int32 s_pstm_sub(pstm_int *a, pstm_int *b, pstm_int *c); +extern int32 s_pstm_sub(pstm_int *a, pstm_int *b, pstm_int *c) FAST_FUNC; -extern int32 pstm_sub(pstm_int *a, pstm_int *b, pstm_int *c); +extern int32 pstm_sub(pstm_int *a, pstm_int *b, pstm_int *c) FAST_FUNC; //bbox: pool unused #define pstm_sub_d(pool, a, b, c) \ pstm_sub_d( a, b, c) -extern int32 pstm_sub_d(psPool_t *pool, pstm_int *a, pstm_digit b, pstm_int *c); +extern int32 pstm_sub_d(psPool_t *pool, pstm_int *a, pstm_digit b, pstm_int *c) FAST_FUNC; -extern int32 pstm_mul_2(pstm_int * a, pstm_int * b); +extern int32 pstm_mul_2(pstm_int * a, pstm_int * b) FAST_FUNC; //bbox: pool unused #define pstm_mod(pool, a, b, c) \ pstm_mod( a, b, c) -extern int32 pstm_mod(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c); +//made static:extern int32 pstm_mod(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c); //bbox: pool unused #define pstm_mulmod(pool, a, b, c, d) \ pstm_mulmod( a, b, c, d) extern int32 pstm_mulmod(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c, - pstm_int *d); + pstm_int *d) FAST_FUNC; //bbox: pool unused #define pstm_exptmod(pool, G, X, P, Y) \ pstm_exptmod( G, X, P, Y) extern int32 pstm_exptmod(psPool_t *pool, pstm_int *G, pstm_int *X, pstm_int *P, - pstm_int *Y); + pstm_int *Y) FAST_FUNC; -extern int32 pstm_2expt(pstm_int *a, int b); //bbox: was int16 b +//made static:extern int32 pstm_2expt(pstm_int *a, int b); //bbox: was int16 b -extern int32 pstm_add(pstm_int *a, pstm_int *b, pstm_int *c); +extern int32 pstm_add(pstm_int *a, pstm_int *b, pstm_int *c) FAST_FUNC; //bbox: pool unused #define pstm_to_unsigned_bin(pool, a, b) \ pstm_to_unsigned_bin( a, b) extern int32 pstm_to_unsigned_bin(psPool_t *pool, pstm_int *a, - unsigned char *b); + unsigned char *b) FAST_FUNC; //bbox: pool unused #define pstm_to_unsigned_bin_nr(pool, a, b) \ pstm_to_unsigned_bin_nr( a, b) extern int32 pstm_to_unsigned_bin_nr(psPool_t *pool, pstm_int *a, - unsigned char *b); + unsigned char *b) FAST_FUNC; -extern int32 pstm_montgomery_setup(pstm_int *a, pstm_digit *rho); +//made static:extern int32 pstm_montgomery_setup(pstm_int *a, pstm_digit *rho); //bbox: pool unused #define pstm_montgomery_reduce(pool, a, m, mp, paD, paDlen) \ pstm_montgomery_reduce( a, m, mp, paD, paDlen) extern int32 pstm_montgomery_reduce(psPool_t *pool, pstm_int *a, pstm_int *m, - pstm_digit mp, pstm_digit *paD, uint32 paDlen); + pstm_digit mp, pstm_digit *paD, uint32 paDlen) FAST_FUNC; #define pstm_mul_comba(pool, A, B, C, paD, paDlen) \ pstm_mul_comba( A, B, C, paD, paDlen) extern int32 pstm_mul_comba(psPool_t *pool, pstm_int *A, pstm_int *B, - pstm_int *C, pstm_digit *paD, uint32 paDlen); + pstm_int *C, pstm_digit *paD, uint32 paDlen) FAST_FUNC; //bbox: pool unused #define pstm_sqr_comba(pool, A, B, paD, paDlen) \ pstm_sqr_comba( A, B, paD, paDlen) extern int32 pstm_sqr_comba(psPool_t *pool, pstm_int *A, pstm_int *B, - pstm_digit *paD, uint32 paDlen); + pstm_digit *paD, uint32 paDlen) FAST_FUNC; -extern int32 pstm_cmp_d(pstm_int *a, pstm_digit b); +//made static:extern int32 pstm_cmp_d(pstm_int *a, pstm_digit b); -extern int32 pstm_montgomery_calc_normalization(pstm_int *a, pstm_int *b); +//made static:extern int32 pstm_montgomery_calc_normalization(pstm_int *a, pstm_int *b); -extern int32 pstm_mul_d(pstm_int *a, pstm_digit b, pstm_int *c); +//made static:extern int32 pstm_mul_d(pstm_int *a, pstm_digit b, pstm_int *c); //bbox: pool unused #define pstm_invmod(pool, a, b, c) \ pstm_invmod( a, b, c) extern int32 pstm_invmod(psPool_t *pool, pstm_int * a, pstm_int * b, - pstm_int * c); + pstm_int * c) FAST_FUNC; #else /* DISABLE_PSTM */ typedef int32 pstm_int; diff --git a/networking/tls_pstm_montgomery_reduce.c b/networking/tls_pstm_montgomery_reduce.c index 3391755e1..d46e2aa2b 100644 --- a/networking/tls_pstm_montgomery_reduce.c +++ b/networking/tls_pstm_montgomery_reduce.c @@ -340,7 +340,7 @@ asm( \ #define LO 0 /* computes x/R == x (mod N) via Montgomery Reduction */ -int32 pstm_montgomery_reduce(psPool_t *pool, pstm_int *a, pstm_int *m, +int32 FAST_FUNC pstm_montgomery_reduce(psPool_t *pool, pstm_int *a, pstm_int *m, pstm_digit mp, pstm_digit *paD, uint32 paDlen) { pstm_digit *c, *_c, *tmpm, mu; diff --git a/networking/tls_pstm_mul_comba.c b/networking/tls_pstm_mul_comba.c index 6ba152bc1..ac4fcc3ef 100644 --- a/networking/tls_pstm_mul_comba.c +++ b/networking/tls_pstm_mul_comba.c @@ -754,7 +754,7 @@ static int32 pstm_mul_comba32(pstm_int *A, pstm_int *B, pstm_int *C) /******************************************************************************/ -int32 pstm_mul_comba(psPool_t *pool, pstm_int *A, pstm_int *B, pstm_int *C, +int32 FAST_FUNC pstm_mul_comba(psPool_t *pool, pstm_int *A, pstm_int *B, pstm_int *C, pstm_digit *paD, uint32 paDlen) { #ifdef USE_1024_KEY_SPEED_OPTIMIZATIONS diff --git a/networking/tls_pstm_sqr_comba.c b/networking/tls_pstm_sqr_comba.c index d5c74d2f0..8604132d6 100644 --- a/networking/tls_pstm_sqr_comba.c +++ b/networking/tls_pstm_sqr_comba.c @@ -1085,7 +1085,7 @@ static int32 pstm_sqr_comba32(pstm_int *A, pstm_int *B) /******************************************************************************/ /* */ -int32 pstm_sqr_comba(psPool_t *pool, pstm_int *A, pstm_int *B, pstm_digit *paD, +int32 FAST_FUNC pstm_sqr_comba(psPool_t *pool, pstm_int *A, pstm_int *B, pstm_digit *paD, uint32 paDlen) { #ifdef USE_1024_KEY_SPEED_OPTIMIZATIONS diff --git a/networking/tls_rsa.c b/networking/tls_rsa.c index 631397e4d..5fda1cb49 100644 --- a/networking/tls_rsa.c +++ b/networking/tls_rsa.c @@ -173,7 +173,9 @@ error: res = PS_FAILURE; done: if (type == PRIVKEY_TYPE && key->optimized) { - pstm_clear_multi(&tmpa, &tmpb, NULL, NULL, NULL, NULL, NULL, NULL); + //pstm_clear_multi(&tmpa, &tmpb, NULL, NULL, NULL, NULL, NULL, NULL); + pstm_clear(&tmpa); + pstm_clear(&tmpb); } pstm_clear(&tmp); return res; -- cgit v1.2.3-55-g6feb From ff65355b8a44d1d546443f69382459eb2176cb44 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 1 Jan 2019 16:54:30 +0100 Subject: single-applet build --help had extra \n, remove Signed-off-by: Denys Vlasenko --- libbb/appletlib.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libbb/appletlib.c b/libbb/appletlib.c index cd09b620c..c15014a34 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -123,16 +123,16 @@ void FAST_FUNC bb_show_usage(void) { if (ENABLE_SHOW_USAGE) { #ifdef SINGLE_APPLET_STR - /* Imagine that this applet is "true". Dont suck in printf! */ + /* Imagine that this applet is "true". Dont link in printf! */ const char *usage_string = unpack_usage_messages(); if (usage_string) { if (*usage_string == '\b') { - full_write2_str("No help available.\n\n"); + full_write2_str("No help available\n"); } else { full_write2_str("Usage: "SINGLE_APPLET_STR" "); full_write2_str(usage_string); - full_write2_str("\n\n"); + full_write2_str("\n"); } if (ENABLE_FEATURE_CLEAN_UP) dealloc_usage_messages((char*)usage_string); @@ -149,9 +149,9 @@ void FAST_FUNC bb_show_usage(void) ap--; } full_write2_str(bb_banner); - full_write2_str(" multi-call binary.\n"); + full_write2_str(" multi-call binary.\n"); /* common string */ if (*p == '\b') - full_write2_str("\nNo help available.\n\n"); + full_write2_str("\nNo help available\n"); else { full_write2_str("\nUsage: "); full_write2_str(applet_name); -- cgit v1.2.3-55-g6feb From 2231468a2f28e99cb6b65dc40da044e37af16ed1 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 1 Jan 2019 21:50:14 +0100 Subject: bc: upstream fixes function old new delta bc_parse_expr_empty_ok 1764 1843 +79 bc_error_at - 62 +62 bc_parse_inst_isLeaf - 30 +30 zbc_func_insert 100 120 +20 bc_error_bad_function_definition - 10 +10 bc_error_bad_assignment - 10 +10 zxc_lex_next 1608 1614 +6 ok_in_expr 30 - -30 zxc_vm_process 874 839 -35 ------------------------------------------------------------------------------ (add/remove: 4/1 grow/shrink: 3/1 up/down: 217/-65) Total: 152 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 177 ++++++++++++++++++++++++++++------------------------- testsuite/bc.tests | 16 +++++ 2 files changed, 110 insertions(+), 83 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 23b3521d4..1b9cdce5e 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -971,19 +971,42 @@ static ERRORFUNC int bc_error(const char *msg) { IF_ERROR_RETURN_POSSIBLE(return) bc_error_fmt("%s", msg); } +static ERRORFUNC int bc_error_at(const char *msg) +{ + const char *err_at = G.prs.lex_next_at; + if (err_at) { + IF_ERROR_RETURN_POSSIBLE(return) bc_error_fmt( + "%s at '%.*s'", + msg, + (int)(strchrnul(err_at, '\n') - err_at), + err_at + ); + } + IF_ERROR_RETURN_POSSIBLE(return) bc_error_fmt("%s", msg); +} static ERRORFUNC int bc_error_bad_character(char c) { if (!c) IF_ERROR_RETURN_POSSIBLE(return) bc_error("NUL character"); IF_ERROR_RETURN_POSSIBLE(return) bc_error_fmt("bad character '%c'", c); } +static ERRORFUNC int bc_error_bad_function_definition(void) +{ + IF_ERROR_RETURN_POSSIBLE(return) bc_error_at("bad function definition"); +} static ERRORFUNC int bc_error_bad_expression(void) { - IF_ERROR_RETURN_POSSIBLE(return) bc_error("bad expression"); + IF_ERROR_RETURN_POSSIBLE(return) bc_error_at("bad expression"); +} +static ERRORFUNC int bc_error_bad_assignment(void) +{ + IF_ERROR_RETURN_POSSIBLE(return) bc_error_at( + "bad assignment: left side must be variable or array element" + ); } static ERRORFUNC int bc_error_bad_token(void) { - IF_ERROR_RETURN_POSSIBLE(return) bc_error("bad token"); + IF_ERROR_RETURN_POSSIBLE(return) bc_error_at("bad token"); } static ERRORFUNC int bc_error_stack_has_too_few_elements(void) { @@ -2853,6 +2876,7 @@ static BC_STATUS zxc_lex_number(char last) if (c == '\\' && p->lex_inbuf[1] == '\n') { p->lex_inbuf += 2; p->lex_line++; + dbg_lex("++p->lex_line=%zd", p->lex_line); c = peek_inbuf(); // force next line to be read goto check_c; } @@ -2919,6 +2943,7 @@ static BC_STATUS zxc_lex_next(void) BcParse *p = &G.prs; BcStatus s; + G.err_line = p->lex_line; p->lex_last = p->lex; //why? // if (p->lex_last == XC_LEX_EOF) @@ -3031,8 +3056,10 @@ static BC_STATUS zbc_lex_string(void) } if (c == '"') break; - if (c == '\n') + if (c == '\n') { p->lex_line++; + dbg_lex("++p->lex_line=%zd", p->lex_line); + } bc_vec_push(&p->lex_strnumbuf, p->lex_inbuf); p->lex_inbuf++; } @@ -3079,8 +3106,10 @@ static BC_STATUS zbc_lex_comment(void) if (c == '\0') { RETURN_STATUS(bc_error("unterminated comment")); } - if (c == '\n') + if (c == '\n') { p->lex_line++; + dbg_lex("++p->lex_line=%zd", p->lex_line); + } } p->lex_inbuf++; // skip trailing '/' @@ -3105,6 +3134,7 @@ static BC_STATUS zbc_lex_token(void) // break; case '\n': p->lex_line++; + dbg_lex("++p->lex_line=%zd", p->lex_line); p->lex = XC_LEX_NLINE; break; case '\t': @@ -3341,8 +3371,10 @@ static BC_STATUS zdc_lex_string(void) if (c == ']') if (--depth == 0) break; - if (c == '\n') + if (c == '\n') { p->lex_line++; + dbg_lex("++p->lex_line=%zd", p->lex_line); + } bc_vec_push(&p->lex_strnumbuf, p->lex_inbuf); p->lex_inbuf++; } @@ -3399,6 +3431,7 @@ static BC_STATUS zdc_lex_token(void) // IOW: typing "1p" should print "1" _at once_, // not after some more input. p->lex_line++; + dbg_lex("++p->lex_line=%zd", p->lex_line); p->lex = XC_LEX_NLINE; break; case '\t': @@ -3960,8 +3993,7 @@ static BC_STATUS zbc_parse_scale(BcInst *type, uint8_t flags) } #define zbc_parse_scale(...) (zbc_parse_scale(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zbc_parse_incdec(BcInst *prev, bool *paren_expr, - size_t *nexprs, uint8_t flags) +static BC_STATUS zbc_parse_incdec(BcInst *prev, size_t *nexs, uint8_t flags) { BcParse *p = &G.prs; BcStatus s; @@ -3978,7 +4010,6 @@ static BC_STATUS zbc_parse_incdec(BcInst *prev, bool *paren_expr, s = zxc_lex_next(); } else { *prev = inst = BC_INST_INC_PRE + (p->lex != BC_LEX_OP_INC); - *paren_expr = true; s = zxc_lex_next(); if (s) RETURN_STATUS(s); @@ -3986,7 +4017,7 @@ static BC_STATUS zbc_parse_incdec(BcInst *prev, bool *paren_expr, // Because we parse the next part of the expression // right here, we need to increment this. - *nexprs = *nexprs + 1; + *nexs = *nexs + 1; switch (type) { case XC_LEX_NAME: @@ -4018,36 +4049,27 @@ static BC_STATUS zbc_parse_incdec(BcInst *prev, bool *paren_expr, } #define zbc_parse_incdec(...) (zbc_parse_incdec(__VA_ARGS__) COMMA_SUCCESS) -#if 0 -#define BC_PARSE_LEAF(p, rparen) \ - ((rparen) \ - || ((p) >= XC_INST_NUM && (p) <= XC_INST_SQRT) \ - || (p) == BC_INST_INC_POST \ - || (p) == BC_INST_DEC_POST \ - ) -#else -static int ok_in_expr(BcInst p) +static int bc_parse_inst_isLeaf(BcInst p) { return (p >= XC_INST_NUM && p <= XC_INST_SQRT) || p == BC_INST_INC_POST || p == BC_INST_DEC_POST ; } -#define BC_PARSE_LEAF(p, rparen) ((rparen) || ok_in_expr(p)) -#endif +#define BC_PARSE_LEAF(prev, bin_last, rparen) \ + (!(bin_last) && ((rparen) || bc_parse_inst_isLeaf(prev))) static BC_STATUS zbc_parse_minus(BcInst *prev, size_t ops_bgn, - bool rparen, size_t *nexprs) + bool rparen, bool bin_last, size_t *nexprs) { BcParse *p = &G.prs; BcStatus s; BcLexType type; - BcInst etype = *prev; s = zxc_lex_next(); if (s) RETURN_STATUS(s); - type = BC_PARSE_LEAF(etype, rparen) ? XC_LEX_OP_MINUS : XC_LEX_NEG; + type = BC_PARSE_LEAF(*prev, bin_last, rparen) ? XC_LEX_OP_MINUS : XC_LEX_NEG; *prev = BC_TOKEN_2_INST(type); // We can just push onto the op stack because this is the largest @@ -4334,8 +4356,11 @@ static BC_STATUS zbc_func_insert(BcFunc *f, char *name, bool var) autoid = (void*)f->autos.v; for (i = 0; i < f->autos.len; i++, autoid++) { - if (strcmp(name, autoid->name) == 0) + if (strcmp(name, autoid->name) == 0 + && var == autoid->idx + ) { RETURN_STATUS(bc_error("duplicate function parameter or auto name")); + } } a.idx = var; @@ -4358,7 +4383,7 @@ static BC_STATUS zbc_parse_funcdef(void) s = zxc_lex_next(); if (s) RETURN_STATUS(s); if (p->lex != XC_LEX_NAME) - RETURN_STATUS(bc_error("bad function definition")); + RETURN_STATUS(bc_error_bad_function_definition()); name = xstrdup(p->lex_strnumbuf.v); p->fidx = bc_program_addFunc(name); @@ -4367,13 +4392,13 @@ static BC_STATUS zbc_parse_funcdef(void) s = zxc_lex_next(); if (s) RETURN_STATUS(s); if (p->lex != BC_LEX_LPAREN) - RETURN_STATUS(bc_error("bad function definition")); + RETURN_STATUS(bc_error_bad_function_definition()); s = zxc_lex_next(); if (s) RETURN_STATUS(s); while (p->lex != BC_LEX_RPAREN) { if (p->lex != XC_LEX_NAME) - RETURN_STATUS(bc_error("bad function definition")); + RETURN_STATUS(bc_error_bad_function_definition()); ++p->func->nparams; @@ -4388,7 +4413,7 @@ static BC_STATUS zbc_parse_funcdef(void) if (s) goto err; if (p->lex != BC_LEX_RBRACKET) { - s = bc_error("bad function definition"); + s = bc_error_bad_function_definition(); goto err; } @@ -4406,7 +4431,7 @@ static BC_STATUS zbc_parse_funcdef(void) if (s) goto err; } - if (comma) RETURN_STATUS(bc_error("bad function definition")); + if (comma) RETURN_STATUS(bc_error_bad_function_definition()); s = zxc_lex_next(); if (s) RETURN_STATUS(s); @@ -4457,7 +4482,7 @@ static BC_STATUS zbc_parse_auto(void) bool var; if (p->lex != XC_LEX_NAME) - RETURN_STATUS(bc_error("bad 'auto' syntax")); + RETURN_STATUS(bc_error_at("bad 'auto' syntax")); name = xstrdup(p->lex_strnumbuf.v); s = zxc_lex_next(); @@ -4469,7 +4494,7 @@ static BC_STATUS zbc_parse_auto(void) if (s) goto err; if (p->lex != BC_LEX_RBRACKET) { - s = bc_error("bad 'auto' syntax"); + s = bc_error_at("bad 'auto' syntax"); goto err; } s = zxc_lex_next(); @@ -4486,7 +4511,7 @@ static BC_STATUS zbc_parse_auto(void) break; } if (p->lex != BC_LEX_COMMA) - RETURN_STATUS(bc_error("bad 'auto' syntax")); + RETURN_STATUS(bc_error_at("bad 'auto' syntax")); s = zxc_lex_next(); // skip comma if (s) RETURN_STATUS(s); } @@ -4643,12 +4668,12 @@ static BcStatus bc_parse_expr_empty_ok(uint8_t flags) BcInst prev = XC_INST_PRINT; size_t nexprs = 0, ops_bgn = p->ops.len; unsigned nparens, nrelops; - bool paren_first, paren_expr, rprn, assign, bin_last; + bool paren_first, rprn, assign, bin_last, incdec; dbg_lex_enter("%s:%d entered", __func__, __LINE__); paren_first = (p->lex == BC_LEX_LPAREN); nparens = nrelops = 0; - paren_expr = rprn = assign = false; + rprn = assign = incdec = false; bin_last = true; for (;;) { @@ -4666,16 +4691,19 @@ static BcStatus bc_parse_expr_empty_ok(uint8_t flags) case BC_LEX_OP_INC: case BC_LEX_OP_DEC: dbg_lex("%s:%d LEX_OP_INC/DEC", __func__, __LINE__); - s = zbc_parse_incdec(&prev, &paren_expr, &nexprs, flags); + if (incdec) return bc_error_bad_assignment(); + s = zbc_parse_incdec(&prev, &nexprs, flags); + incdec = true; rprn = bin_last = false; //get_token = false; - already is break; case XC_LEX_OP_MINUS: dbg_lex("%s:%d LEX_OP_MINUS", __func__, __LINE__); - s = zbc_parse_minus(&prev, ops_bgn, rprn, &nexprs); + s = zbc_parse_minus(&prev, ops_bgn, rprn, bin_last, &nexprs); rprn = false; //get_token = false; - already is bin_last = (prev == XC_INST_MINUS); + if (bin_last) incdec = false; break; case BC_LEX_OP_ASSIGN_POWER: case BC_LEX_OP_ASSIGN_MULTIPLY: @@ -4689,10 +4717,7 @@ static BcStatus bc_parse_expr_empty_ok(uint8_t flags) && prev != XC_INST_SCALE && prev != XC_INST_IBASE && prev != XC_INST_OBASE && prev != BC_INST_LAST ) { - return bc_error("bad assignment:" - " left side must be variable" - " or array element" - ); // note: shared string + return bc_error_bad_assignment(); } // Fallthrough. case XC_LEX_OP_POWER: @@ -4710,64 +4735,63 @@ static BcStatus bc_parse_expr_empty_ok(uint8_t flags) case BC_LEX_OP_BOOL_OR: case BC_LEX_OP_BOOL_AND: dbg_lex("%s:%d LEX_OP_xyz", __func__, __LINE__); - if (((t == BC_LEX_OP_BOOL_NOT) != bin_last) - || (t != BC_LEX_OP_BOOL_NOT && prev == XC_INST_BOOL_NOT) - ) { + if (t == BC_LEX_OP_BOOL_NOT) { + if (!bin_last && p->lex_last != BC_LEX_OP_BOOL_NOT) + return bc_error_bad_expression(); + } else if (prev == XC_INST_BOOL_NOT) { return bc_error_bad_expression(); } + nrelops += (t >= XC_LEX_OP_REL_EQ && t <= XC_LEX_OP_REL_GT); prev = BC_TOKEN_2_INST(t); bc_parse_operator(t, ops_bgn, &nexprs); - s = zxc_lex_next(); - rprn = false; - //get_token = false; - already is + rprn = incdec = false; + get_token = true; bin_last = (t != BC_LEX_OP_BOOL_NOT); break; case BC_LEX_LPAREN: dbg_lex("%s:%d LEX_LPAREN", __func__, __LINE__); - if (BC_PARSE_LEAF(prev, rprn)) + if (BC_PARSE_LEAF(prev, bin_last, rprn)) return bc_error_bad_expression(); bc_vec_push(&p->ops, &t); nparens++; get_token = true; - paren_expr = false; - rprn = bin_last = false; + rprn = incdec = false; break; case BC_LEX_RPAREN: dbg_lex("%s:%d LEX_RPAREN", __func__, __LINE__); + if (p->lex_last == BC_LEX_LPAREN) { + dbg_lex_done("%s:%d done (returning EMPTY_EXP)", __func__, __LINE__); + return BC_STATUS_PARSE_EMPTY_EXP; + } if (bin_last || prev == XC_INST_BOOL_NOT) return bc_error_bad_expression(); if (nparens == 0) { goto exit_loop; } - if (!paren_expr) { - dbg_lex_done("%s:%d done (returning EMPTY_EXP)", __func__, __LINE__); - return BC_STATUS_PARSE_EMPTY_EXP; - } s = zbc_parse_rightParen(ops_bgn, &nexprs); nparens--; get_token = true; - paren_expr = rprn = true; - bin_last = false; + rprn = true; + bin_last = incdec = false; break; case XC_LEX_NAME: dbg_lex("%s:%d LEX_NAME", __func__, __LINE__); - if (BC_PARSE_LEAF(prev, rprn)) + if (BC_PARSE_LEAF(prev, bin_last, rprn)) return bc_error_bad_expression(); s = zbc_parse_name(&prev, flags & ~BC_PARSE_NOCALL); - paren_expr = true; - rprn = bin_last = false; + rprn = (prev == BC_INST_CALL); + bin_last = false; //get_token = false; - already is nexprs++; break; case XC_LEX_NUMBER: dbg_lex("%s:%d LEX_NUMBER", __func__, __LINE__); - if (BC_PARSE_LEAF(prev, rprn)) + if (BC_PARSE_LEAF(prev, bin_last, rprn)) return bc_error_bad_expression(); xc_parse_pushNUM(); prev = XC_INST_NUM; get_token = true; - paren_expr = true; rprn = bin_last = false; nexprs++; break; @@ -4775,45 +4799,40 @@ static BcStatus bc_parse_expr_empty_ok(uint8_t flags) case BC_LEX_KEY_LAST: case BC_LEX_KEY_OBASE: dbg_lex("%s:%d LEX_IBASE/LAST/OBASE", __func__, __LINE__); - if (BC_PARSE_LEAF(prev, rprn)) + if (BC_PARSE_LEAF(prev, bin_last, rprn)) return bc_error_bad_expression(); prev = (char) (t - BC_LEX_KEY_IBASE + XC_INST_IBASE); xc_parse_push((char) prev); get_token = true; - paren_expr = true; rprn = bin_last = false; nexprs++; break; case BC_LEX_KEY_LENGTH: case BC_LEX_KEY_SQRT: dbg_lex("%s:%d LEX_LEN/SQRT", __func__, __LINE__); - if (BC_PARSE_LEAF(prev, rprn)) + if (BC_PARSE_LEAF(prev, bin_last, rprn)) return bc_error_bad_expression(); s = zbc_parse_builtin(t, flags, &prev); get_token = true; - paren_expr = true; - rprn = bin_last = false; + rprn = bin_last = incdec = false; nexprs++; break; case BC_LEX_KEY_READ: dbg_lex("%s:%d LEX_READ", __func__, __LINE__); - if (BC_PARSE_LEAF(prev, rprn)) + if (BC_PARSE_LEAF(prev, bin_last, rprn)) return bc_error_bad_expression(); s = zbc_parse_read(); prev = XC_INST_READ; get_token = true; - paren_expr = true; - rprn = bin_last = false; + rprn = bin_last = incdec = false; nexprs++; break; case BC_LEX_KEY_SCALE: dbg_lex("%s:%d LEX_SCALE", __func__, __LINE__); - if (BC_PARSE_LEAF(prev, rprn)) + if (BC_PARSE_LEAF(prev, bin_last, rprn)) return bc_error_bad_expression(); s = zbc_parse_scale(&prev, flags); - prev = XC_INST_SCALE; //get_token = false; - already is - paren_expr = true; rprn = bin_last = false; nexprs++; break; @@ -5286,7 +5305,7 @@ static BC_STATUS zxc_program_read(void) } if (s) goto exec_err; if (G.prs.lex != XC_LEX_NLINE && G.prs.lex != XC_LEX_EOF) { - s = bc_error("bad read() expression"); + s = bc_error_at("bad read() expression"); goto exec_err; } xc_parse_push(XC_INST_RET); @@ -5794,10 +5813,7 @@ static BC_STATUS zxc_program_assign(char inst) #endif if (left->t == XC_RESULT_CONSTANT || left->t == XC_RESULT_TEMP) - RETURN_STATUS(bc_error("bad assignment:" - " left side must be variable" - " or array element" - )); // note: shared string + RETURN_STATUS(bc_error_bad_assignment()); #if ENABLE_BC if (inst == BC_INST_ASSIGN_DIVIDE && !bc_num_cmp(r, &G.prog.zero)) @@ -6771,13 +6787,7 @@ static BC_STATUS zxc_vm_process(const char *text) && G.prs.lex != XC_LEX_NLINE && G.prs.lex != XC_LEX_EOF ) { - const char *err_at; -//TODO: commonalize for other parse errors: - err_at = G.prs.lex_next_at ? G.prs.lex_next_at : "UNKNOWN"; - bc_error_fmt("bad statement terminator at '%.*s'", - (int)(strchrnul(err_at, '\n') - err_at), - err_at - ); + bc_error_at("bad statement terminator"); goto err; } // The above logic is fragile. Check these examples: @@ -6871,6 +6881,7 @@ static BC_STATUS zxc_vm_execute_FILE(FILE *fp, const char *filename) G.prs.lex_filename = filename; G.prs.lex_input_fp = fp; G.err_line = G.prs.lex_line = 1; + dbg_lex("p->lex_line reset to 1"); do { s = zxc_vm_process(""); diff --git a/testsuite/bc.tests b/testsuite/bc.tests index 1d4545559..13525ea52 100755 --- a/testsuite/bc.tests +++ b/testsuite/bc.tests @@ -108,6 +108,11 @@ testing "bc define auto" \ "8\n9\n" \ "" "define w() { auto z; return 8; }; w(); 9" +testing "bc define auto array same name" \ + "bc" \ + "8\n9\n" \ + "" "define w(x) { auto x[]; return x; }; w(8); 9" + testing "bc define with body on next line" \ "bc" \ "8\n9\n" \ @@ -133,6 +138,17 @@ testing "bc ifz does not match if keyword" \ "1\n2\n2\n3\n" \ "" "ifz=1;ifz\n++ifz;ifz++\nifz" +# had parse error on "f()-N" +testing "bc -l 'e(0)-2'" \ + "bc -l" \ + "-1.00000000000000000000\n" \ + "" "e(0)-2" + +testing "bc (!a&&b)" \ + "bc" \ + "0\n" \ + "" "(!a&&b)" + testing "bc print 1,2,3" \ "bc" \ "123" \ -- cgit v1.2.3-55-g6feb From 266bec8ba76898c5602e54fb3460c4af42f38af0 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 2 Jan 2019 05:03:53 +0100 Subject: bc: speed up string printing, fix print "" function old new delta static.esc - 9 +9 zxc_program_print 681 683 +2 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 1/0 up/down: 11/0) Total: 11 bytes text data bss dec hex filename 979144 485 7296 986925 f0f2d busybox_old 979062 485 7296 986843 f0edb busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 66 ++++++++++++++++++------------------------------------ testsuite/bc.tests | 6 +++++ 2 files changed, 28 insertions(+), 44 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 1b9cdce5e..bb91216c2 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -5359,7 +5359,7 @@ static char *xc_program_name(char *code, size_t *bgn) static void xc_program_printString(const char *str) { #if ENABLE_DC - if (!str[0]) { + if (!str[0] && IS_DC) { // Example: echo '[]ap' | dc // should print two bytes: 0x00, 0x0A bb_putchar('\0'); @@ -5367,46 +5367,25 @@ static void xc_program_printString(const char *str) } #endif while (*str) { - int c = *str++; - if (c != '\\' || !*str) - bb_putchar(c); - else { + char c = *str++; + if (c == '\\') { + static const char esc[] ALIGN1 = "nabfrt""e\\"; + char *n; + c = *str++; - switch (c) { - case 'a': - bb_putchar('\a'); - break; - case 'b': - bb_putchar('\b'); - break; - case '\\': - case 'e': - bb_putchar('\\'); - break; - case 'f': - bb_putchar('\f'); - break; - case 'n': - bb_putchar('\n'); - G.prog.nchars = SIZE_MAX; - break; - case 'r': - bb_putchar('\r'); - break; - case 'q': - bb_putchar('"'); - break; - case 't': - bb_putchar('\t'); - break; - default: - // Just print the backslash and following character. + n = strchr(esc, c); // note: c can be NUL + if (!n) { + // Just print the backslash and following character bb_putchar('\\'); ++G.prog.nchars; - bb_putchar(c); - break; + } else { + if (n - esc == 0) // "\n" ? + G.prog.nchars = SIZE_MAX; + c = "\n\a\b\f\r\t""\\\\""\\"[n - esc]; + // n a b f r t e \ \ } } + putchar(c); ++G.prog.nchars; } } @@ -5631,16 +5610,15 @@ static BC_STATUS zxc_program_print(char inst, size_t idx) str = *xc_program_str(idx); if (inst == XC_INST_PRINT_STR) { - for (;;) { - char c = *str++; - if (c == '\0') break; - bb_putchar(c); - ++G.prog.nchars; - if (c == '\n') G.prog.nchars = 0; - } + char *nl; + G.prog.nchars += printf("%s", str); + nl = strrchr(str, '\n'); + if (nl) + G.prog.nchars = strlen(nl + 1); } else { xc_program_printString(str); - if (inst == XC_INST_PRINT) bb_putchar('\n'); + if (inst == XC_INST_PRINT) + bb_putchar('\n'); } } diff --git a/testsuite/bc.tests b/testsuite/bc.tests index 13525ea52..fbcfff2e4 100755 --- a/testsuite/bc.tests +++ b/testsuite/bc.tests @@ -149,6 +149,12 @@ testing "bc (!a&&b)" \ "0\n" \ "" "(!a&&b)" +# check that dc code is not messing this up (no NUL printing!) +testing "bc print \"\"" \ + "bc" \ + "" \ + "" "print \"\"" + testing "bc print 1,2,3" \ "bc" \ "123" \ -- cgit v1.2.3-55-g6feb From cb7c955aeb593abdde67fd919864185be2eb335d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 2 Jan 2019 14:00:20 +0100 Subject: bc: generate large bc tests on the fly, -5 mbytes in the git tree Signed-off-by: Denys Vlasenko --- testsuite/bc.tests | 54 ++++++++++++++++++++++++++++++++++++---------- testsuite/bc_large.tar.xz | Bin 5118896 -> 0 bytes 2 files changed, 43 insertions(+), 11 deletions(-) delete mode 100644 testsuite/bc_large.tar.xz diff --git a/testsuite/bc.tests b/testsuite/bc.tests index fbcfff2e4..7795183a7 100755 --- a/testsuite/bc.tests +++ b/testsuite/bc.tests @@ -208,17 +208,17 @@ testing "bc continue in if" \ "" "\ i=2 while(i--) { - 11 - if(i) { - 21 - continue - 22 - } else { - 31 - continue - 32 + 11 + if(i) { + 21 + continue + 22 + } else { + 31 + continue + 32 } - 12 + 12 } 99 " @@ -245,7 +245,39 @@ testing "bc ibase" \ "99\n1295\n1224\n" \ "" "a=ZZ;a;ibase=36;a=ZZ;a;ibase=Z;a=ZZ;a" -tar xJf bc_large.tar.xz +testing "bc parsing of numbers" \ + "bc 2>&1 | bc 2>&1 | md5sum 2>&1" \ + "465d8c01308d0863b6f5669e8a1c69fb -\n" \ + "" ' +for (b = 2; b <= 16; ++b) { + if (b == 10) continue + obase = 10 + print "ibase = A; ibase = ", b, "\n" + obase = b + for (i = 0; i <= 65536; ++i) { + i + print "0.", i, "\n" + print "1.", i, "\n" + print i, ".", i, "\n" + } +}' + +testing "bc printing of numbers" \ + "bc 2>&1 | bc 2>&1 | md5sum 2>&1" \ + "d884b35d251ca096410712743aeafb9e -\n" \ + "" ' +for (b = 2; b <= 101; ++b) { + if (b == 10) continue + s = b * b + print "obase = ", b, "\n" + for (i = 0; i <= s; ++i) { + i + print "0.", i, "\n" + print "1.", i, "\n" + print i, ".", i, "\n" + } + 2189432174861923048671023498128347619023487610234689172304.192748960128745108927461089237469018723460 +}' for f in bc*.bc; do r="`basename "$f" .bc`_results.txt" diff --git a/testsuite/bc_large.tar.xz b/testsuite/bc_large.tar.xz deleted file mode 100644 index b2e358a79..000000000 Binary files a/testsuite/bc_large.tar.xz and /dev/null differ -- cgit v1.2.3-55-g6feb From ae6c44ea15f4b73e8e5532f6392d1e6ce8c087e7 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 2 Jan 2019 16:30:24 +0100 Subject: bc: make error line number also size_t, like everything else Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index bb91216c2..e5726ca40 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -753,7 +753,7 @@ struct globals { // For error messages. Can be set to current parsed line, // or [TODO] to current executing line (can be before last parsed one) - unsigned err_line; + size_t err_line; BcVec input_buffer; @@ -916,7 +916,9 @@ static void bc_verror_msg(const char *fmt, va_list p) const char *sv = sv; // for compiler if (G.prs.lex_filename) { sv = applet_name; - applet_name = xasprintf("%s: %s:%u", applet_name, G.prs.lex_filename, G.err_line); + applet_name = xasprintf("%s: %s:%lu", applet_name, + G.prs.lex_filename, (unsigned long)G.err_line + ); } bb_verror_msg(fmt, p, NULL); if (G.prs.lex_filename) { @@ -3532,7 +3534,8 @@ static void xc_parse_pushIndex(size_t idx) dbg_lex("%s:%d pushing index %zd", __func__, __LINE__, idx); if (idx < SMALL_INDEX_LIMIT) { - goto push_idx; + xc_parse_push(idx); + return; } mask = ((size_t)0xff) << (sizeof(idx) * 8 - 8); @@ -3546,11 +3549,10 @@ static void xc_parse_pushIndex(size_t idx) xc_parse_push((SMALL_INDEX_LIMIT - 1) + amt); - while (idx != 0) { - push_idx: + do { xc_parse_push((unsigned char)idx); idx >>= 8; - } + } while (idx != 0); } #if ENABLE_BC -- cgit v1.2.3-55-g6feb From 96b5ec10fb8abdb8050a6af87330e6cf3d881d5a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 3 Jan 2019 23:34:36 +0100 Subject: bc: fix "...; return}" to work, disallow "return ()" function old new delta zbc_parse_expr 24 1865 +1841 zbc_parse_stmt_possibly_auto 1425 1413 -12 bc_parse_expr_empty_ok 1843 - -1843 ------------------------------------------------------------------------------ (add/remove: 0/1 grow/shrink: 1/1 up/down: 1841/-1855) Total: -14 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 13 +++++-------- testsuite/bc.tests | 5 +++++ testsuite/bc_misc1.bc | 4 +--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index e5726ca40..6d8e2d991 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -4121,18 +4121,15 @@ static BC_STATUS zbc_parse_return(void) if (s) RETURN_STATUS(s); t = p->lex; - if (t == XC_LEX_NLINE || t == BC_LEX_SCOLON) + if (t == XC_LEX_NLINE || t == BC_LEX_SCOLON || t == BC_LEX_RBRACE) xc_parse_push(BC_INST_RET0); else { - bool paren = (t == BC_LEX_LPAREN); - s = bc_parse_expr_empty_ok(0); - if (s == BC_STATUS_PARSE_EMPTY_EXP) { - xc_parse_push(BC_INST_RET0); - s = zxc_lex_next(); - } + s = zbc_parse_expr(0); if (s) RETURN_STATUS(s); - if (!paren || p->lex_last != BC_LEX_RPAREN) { + if (t != BC_LEX_LPAREN // "return EXPR", no () + || p->lex_last != BC_LEX_RPAREN // example: "return (a) + b" + ) { s = zbc_POSIX_requires("parentheses around return expressions"); if (s) RETURN_STATUS(s); } diff --git a/testsuite/bc.tests b/testsuite/bc.tests index 7795183a7..0a8222be6 100755 --- a/testsuite/bc.tests +++ b/testsuite/bc.tests @@ -103,6 +103,11 @@ testing "bc for (;;) {break}" \ "2\n9\n" \ "" "for (;;) {2;break}; 9" +testing "bc define {return}" \ + "bc" \ + "0\n9\n" \ + "" "define w() {return}\nw();9" + testing "bc define auto" \ "bc" \ "8\n9\n" \ diff --git a/testsuite/bc_misc1.bc b/testsuite/bc_misc1.bc index 7e9d96604..f666d701a 100644 --- a/testsuite/bc_misc1.bc +++ b/testsuite/bc_misc1.bc @@ -4,9 +4,7 @@ define x(x) { define y() { return; } -define z() { - return (); -} +define z() {return} scale = 0 x=2 x[0]=3 -- cgit v1.2.3-55-g6feb From 19c3eb0b049c46d365c89c6ff05295fbae0f40a8 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 4 Jan 2019 00:05:07 +0100 Subject: bc: remove extra div/0 test, remove test for string function parameter function old new delta zbc_program_call 354 332 -22 zxc_program_assign 426 385 -41 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-63) Total: -63 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 6d8e2d991..3bcda08a8 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -5793,9 +5793,6 @@ static BC_STATUS zxc_program_assign(char inst) RETURN_STATUS(bc_error_bad_assignment()); #if ENABLE_BC - if (inst == BC_INST_ASSIGN_DIVIDE && !bc_num_cmp(r, &G.prog.zero)) - RETURN_STATUS(bc_error("divide by zero")); - if (assign) bc_num_copy(l, r); else { @@ -5960,12 +5957,10 @@ static BC_STATUS zbc_program_call(char *code, size_t *idx) { BcInstPtr ip; size_t i, nparams; - BcFunc *func; BcId *a; - BcResult *arg; + BcFunc *func; nparams = xc_program_index(code, idx); - ip.inst_idx = 0; ip.func = xc_program_index(code, idx); func = xc_program_func(ip.func); @@ -5975,17 +5970,21 @@ static BC_STATUS zbc_program_call(char *code, size_t *idx) if (nparams != func->nparams) { RETURN_STATUS(bc_error_fmt("function has %u parameters, but called with %u", func->nparams, nparams)); } + ip.inst_idx = 0; ip.results_len_before_call = G.prog.results.len - nparams; for (i = 0; i < nparams; ++i) { + BcResult *arg; BcStatus s; a = bc_vec_item(&func->autos, nparams - 1 - i); arg = bc_vec_top(&G.prog.results); - if ((!a->idx) != (arg->t == XC_RESULT_ARRAY) || arg->t == XC_RESULT_STR) + if ((!a->idx) != (arg->t == XC_RESULT_ARRAY) // array/variable mismatch + // || arg->t == XC_RESULT_STR - impossible, f("str") is not a legal syntax (strings are not bc expressions) + ) { RETURN_STATUS(bc_error_variable_is_wrong_type()); - + } s = zxc_program_copyToVar(a->name, a->idx); if (s) RETURN_STATUS(s); } -- cgit v1.2.3-55-g6feb From 02c3d7a1c9ea82a8babf49f8a5305ec942b56dfa Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 4 Jan 2019 00:21:29 +0100 Subject: bc: add a palceholder comment for "void" return Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 3bcda08a8..0bbd53a65 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -5720,7 +5720,7 @@ static BC_STATUS zdc_program_assignStr(BcResult *r, BcVec *v, bool push) #define zdc_program_assignStr(...) (zdc_program_assignStr(__VA_ARGS__) COMMA_SUCCESS) #endif // ENABLE_DC -static BC_STATUS zxc_program_copyToVar(char *name, bool var) +static BC_STATUS zxc_program_popResultAndCopyToVar(char *name, bool var) { BcStatus s; BcResult *ptr, r; @@ -5761,7 +5761,7 @@ static BC_STATUS zxc_program_copyToVar(char *name, bool var) RETURN_STATUS(s); } -#define zxc_program_copyToVar(...) (zxc_program_copyToVar(__VA_ARGS__) COMMA_SUCCESS) +#define zxc_program_popResultAndCopyToVar(...) (zxc_program_popResultAndCopyToVar(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zxc_program_assign(char inst) { @@ -5985,7 +5985,7 @@ static BC_STATUS zbc_program_call(char *code, size_t *idx) ) { RETURN_STATUS(bc_error_variable_is_wrong_type()); } - s = zxc_program_copyToVar(a->name, a->idx); + s = zxc_program_popResultAndCopyToVar(a->name, a->idx); if (s) RETURN_STATUS(s); } @@ -6019,11 +6019,10 @@ static BC_STATUS zbc_program_return(char inst) size_t i; BcInstPtr *ip = bc_vec_top(&G.prog.exestack); +#if SANITY_CHECKS if (!STACK_HAS_EQUAL_OR_MORE_THAN(&G.prog.results, ip->results_len_before_call + (inst == XC_INST_RET))) RETURN_STATUS(bc_error_stack_has_too_few_elements()); - - f = xc_program_func(ip->func); - res.t = XC_RESULT_TEMP; +#endif if (inst == XC_INST_RET) { BcStatus s; @@ -6034,12 +6033,21 @@ static BC_STATUS zbc_program_return(char inst) if (s) RETURN_STATUS(s); bc_num_init(&res.d.n, num->len); bc_num_copy(&res.d.n, num); + //} else if (f->void_func) { + //prepare "void" result in res } else { bc_num_init_DEF_SIZE(&res.d.n); //bc_num_zero(&res.d.n); - already is } + res.t = XC_RESULT_TEMP; + + bc_vec_npop(&G.prog.results, G.prog.results.len - ip->results_len_before_call); + bc_vec_push(&G.prog.results, &res); + + bc_vec_pop(&G.prog.exestack); // We need to pop arguments as well, so this takes that into account. + f = xc_program_func(ip->func); a = (void*)f->autos.v; for (i = 0; i < f->autos.len; i++, a++) { BcVec *v; @@ -6047,10 +6055,6 @@ static BC_STATUS zbc_program_return(char inst) bc_vec_pop(v); } - bc_vec_npop(&G.prog.results, G.prog.results.len - ip->results_len_before_call); - bc_vec_push(&G.prog.results, &res); - bc_vec_pop(&G.prog.exestack); - RETURN_STATUS(BC_STATUS_SUCCESS); } #define zbc_program_return(...) (zbc_program_return(__VA_ARGS__) COMMA_SUCCESS) @@ -6679,7 +6683,7 @@ static BC_STATUS zxc_program_exec(void) } case DC_INST_PUSH_TO_VAR: { char *name = xc_program_name(code, &ip->inst_idx); - s = zxc_program_copyToVar(name, true); + s = zxc_program_popResultAndCopyToVar(name, true); free(name); break; } -- cgit v1.2.3-55-g6feb From 377cc97b193204595d00a0b8d0d2b52c2d596586 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 4 Jan 2019 00:34:52 +0100 Subject: bc: eliminate struct BcInstPtr::results_len_before_call, it is redundant function old new delta zbc_program_call 332 318 -14 zxc_program_exec 4147 4087 -60 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-74) Total: -74 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 0bbd53a65..ec3560c2b 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -378,7 +378,6 @@ typedef struct BcResult { typedef struct BcInstPtr { size_t func; size_t inst_idx; - IF_BC(size_t results_len_before_call;) } BcInstPtr; typedef enum BcLexType { @@ -5311,7 +5310,6 @@ static BC_STATUS zxc_program_read(void) ip.func = BC_PROG_READ; ip.inst_idx = 0; - IF_BC(ip.results_len_before_call = G.prog.results.len;) bc_vec_push(&G.prog.exestack, &ip); exec_err: @@ -5971,7 +5969,6 @@ static BC_STATUS zbc_program_call(char *code, size_t *idx) RETURN_STATUS(bc_error_fmt("function has %u parameters, but called with %u", func->nparams, nparams)); } ip.inst_idx = 0; - ip.results_len_before_call = G.prog.results.len - nparams; for (i = 0; i < nparams; ++i) { BcResult *arg; @@ -6019,11 +6016,6 @@ static BC_STATUS zbc_program_return(char inst) size_t i; BcInstPtr *ip = bc_vec_top(&G.prog.exestack); -#if SANITY_CHECKS - if (!STACK_HAS_EQUAL_OR_MORE_THAN(&G.prog.results, ip->results_len_before_call + (inst == XC_INST_RET))) - RETURN_STATUS(bc_error_stack_has_too_few_elements()); -#endif - if (inst == XC_INST_RET) { BcStatus s; BcNum *num; @@ -6033,6 +6025,7 @@ static BC_STATUS zbc_program_return(char inst) if (s) RETURN_STATUS(s); bc_num_init(&res.d.n, num->len); bc_num_copy(&res.d.n, num); + bc_vec_pop(&G.prog.results); //} else if (f->void_func) { //prepare "void" result in res } else { @@ -6040,8 +6033,6 @@ static BC_STATUS zbc_program_return(char inst) //bc_num_zero(&res.d.n); - already is } res.t = XC_RESULT_TEMP; - - bc_vec_npop(&G.prog.results, G.prog.results.len - ip->results_len_before_call); bc_vec_push(&G.prog.results, &res); bc_vec_pop(&G.prog.exestack); -- cgit v1.2.3-55-g6feb From 6842c6062a201cc34a262b4c450cf8e1374e9e3a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 4 Jan 2019 05:41:47 +0100 Subject: dc: fix '?' function old new delta zdc_parse_expr 470 479 +9 zxc_vm_process 839 814 -25 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/1 up/down: 9/-25) Total: -16 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 13 ++++--------- testsuite/dc.tests | 5 +++++ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index ec3560c2b..1e8056c01 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -5054,6 +5054,9 @@ static BC_STATUS zdc_parse_expr(void) BcParse *p = &G.prs; int i; + if (p->lex == XC_LEX_NLINE) + RETURN_STATUS(zxc_lex_next()); + i = (int)p->lex - (int)XC_LEX_OP_POWER; if (i >= 0) { BcInst inst = dc_LEX_to_INST[i]; @@ -6766,14 +6769,6 @@ static BC_STATUS zxc_vm_process(const char *text) #endif } else { #if ENABLE_DC - // Most of dc parsing assumes all whitespace, - // including '\n', is eaten. - while (G.prs.lex == XC_LEX_NLINE) { - s = zxc_lex_next(); - if (s) goto err; - if (G.prs.lex == XC_LEX_EOF) - goto done; - } s = zdc_parse_expr(); #endif } @@ -6836,7 +6831,7 @@ static BC_STATUS zxc_vm_process(const char *text) bc_vec_pop_all(&f->code); ip->inst_idx = 0; } - IF_DC(done:) + dbg_lex_done("%s:%d done", __func__, __LINE__); RETURN_STATUS(s); } diff --git a/testsuite/dc.tests b/testsuite/dc.tests index 29b413cad..87b1e71c3 100755 --- a/testsuite/dc.tests +++ b/testsuite/dc.tests @@ -41,6 +41,11 @@ testing "dc complex without spaces (multiple args)" \ "16\n" \ "" "" +testing "dc read" \ + "dc -finput" \ + "2\n9\n1\n" \ + "1?2\nf" "9\n" + optional FEATURE_DC_BIG # All tests below depend on FEATURE_DC_BIG -- cgit v1.2.3-55-g6feb From 1db367a8e65a74277360a89885ff7d377b5feb8b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 4 Jan 2019 06:18:00 +0100 Subject: dc: fit returning of string function old new delta zxc_program_exec 4087 4098 +11 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 18 +++++++++++++----- testsuite/dc.tests | 5 +++++ 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 1e8056c01..e497b0d02 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -6020,6 +6020,9 @@ static BC_STATUS zbc_program_return(char inst) BcInstPtr *ip = bc_vec_top(&G.prog.exestack); if (inst == XC_INST_RET) { + // bc needs this for e.g. RESULT_CONSTANT ("return 5") + // because bc constants are per-function. + // TODO: maybe avoid if value is already RESULT_TEMP? BcStatus s; BcNum *num; BcResult *operand = bc_vec_top(&G.prog.results); @@ -6458,7 +6461,17 @@ static BC_STATUS zxc_program_exec(void) dbg_exec("inst at %zd:%d results.len:%d", ip->inst_idx - 1, inst, G.prog.results.len); switch (inst) { + case XC_INST_RET: + if (IS_DC) { // end of '?' reached + bc_vec_pop(&G.prog.exestack); + goto read_updated_ip; + } + // bc: fall through #if ENABLE_BC + case BC_INST_RET0: + dbg_exec("BC_INST_RET[0]:"); + s = zbc_program_return(inst); + goto read_updated_ip; case BC_INST_JUMP_ZERO: { BcNum *num; bool zero; @@ -6495,11 +6508,6 @@ static BC_STATUS zxc_program_exec(void) dbg_exec("BC_INST_HALT:"); QUIT_OR_RETURN_TO_MAIN; break; - case XC_INST_RET: - case BC_INST_RET0: - dbg_exec("BC_INST_RET[0]:"); - s = zbc_program_return(inst); - goto read_updated_ip; case XC_INST_BOOL_OR: case XC_INST_BOOL_AND: #endif // ENABLE_BC diff --git a/testsuite/dc.tests b/testsuite/dc.tests index 87b1e71c3..1708a4835 100755 --- a/testsuite/dc.tests +++ b/testsuite/dc.tests @@ -46,6 +46,11 @@ testing "dc read" \ "2\n9\n1\n" \ "1?2\nf" "9\n" +testing "dc read string" \ + "dc -finput" \ + "2\nstr\n1\n" \ + "1?2\nf" "[str]\n" + optional FEATURE_DC_BIG # All tests below depend on FEATURE_DC_BIG -- cgit v1.2.3-55-g6feb From 54f5c1d6006ffbf03455a180ba6b7cbd5352b7f5 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 4 Jan 2019 13:58:46 +0100 Subject: bc: support void functions (GNU compat) function old new delta xc_program_print - 689 +689 zxc_vm_process 814 869 +55 zxc_program_exec 4098 4116 +18 zxc_program_assign 385 392 +7 bc_result_free 43 46 +3 zxc_program_binOpPrep 243 245 +2 zdc_program_execStr 518 520 +2 zxc_program_print 683 - -683 ------------------------------------------------------------------------------ (add/remove: 1/1 grow/shrink: 6/0 up/down: 776/-683) Total: 93 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 75 ++++++++++++++++++++++++++++++++++++++++-------------- testsuite/bc.tests | 17 +++++++++++++ 2 files changed, 73 insertions(+), 19 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index e497b0d02..69d3920c0 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -5,7 +5,6 @@ * Original code copyright (c) 2018 Gavin D. Howard and contributors. */ //TODO: GNU extensions: -// support "define void f()..." // support "define f(*param[])" - "pass array by reference" syntax #define DEBUG_LEXER 0 @@ -344,10 +343,12 @@ typedef struct BcFunc { IF_BC(BcVec strs;) IF_BC(BcVec consts;) IF_BC(size_t nparams;) + IF_BC(bool voidfunc;) } BcFunc; typedef enum BcResultType { XC_RESULT_TEMP, + IF_BC(BC_RESULT_VOID,) // same as TEMP, but INST_PRINT will ignore it XC_RESULT_VAR, XC_RESULT_ARRAY_ELEM, @@ -2451,11 +2452,12 @@ static void dc_result_copy(BcResult *d, BcResult *src) d->d.id.name = xstrdup(src->d.id.name); break; case XC_RESULT_CONSTANT: - IF_BC(case BC_RESULT_LAST:) - IF_BC(case BC_RESULT_ONE:) case XC_RESULT_STR: memcpy(&d->d.n, &src->d.n, sizeof(BcNum)); break; + default: // placate compiler + // BC_RESULT_VOID, BC_RESULT_LAST, BC_RESULT_ONE - do not happen + break; } } #endif // ENABLE_DC @@ -2466,6 +2468,7 @@ static FAST_FUNC void bc_result_free(void *result) switch (r->t) { case XC_RESULT_TEMP: + IF_BC(case BC_RESULT_VOID:) case XC_RESULT_IBASE: case XC_RESULT_SCALE: case XC_RESULT_OBASE: @@ -4123,6 +4126,7 @@ static BC_STATUS zbc_parse_return(void) if (t == XC_LEX_NLINE || t == BC_LEX_SCOLON || t == BC_LEX_RBRACE) xc_parse_push(BC_INST_RET0); else { +//TODO: if (p->func->voidfunc) ERROR s = zbc_parse_expr(0); if (s) RETURN_STATUS(s); @@ -4374,7 +4378,7 @@ static BC_STATUS zbc_parse_funcdef(void) { BcParse *p = &G.prs; BcStatus s; - bool var, comma = false; + bool var, comma, voidfunc; char *name; dbg_lex_enter("%s:%d entered", __func__, __LINE__); @@ -4383,17 +4387,34 @@ static BC_STATUS zbc_parse_funcdef(void) if (p->lex != XC_LEX_NAME) RETURN_STATUS(bc_error_bad_function_definition()); - name = xstrdup(p->lex_strnumbuf.v); - p->fidx = bc_program_addFunc(name); - p->func = xc_program_func(p->fidx); + // To be maximally both POSIX and GNU-compatible, + // "void" is not treated as a normal keyword: + // you can have variable named "void", and even a function + // named "void": "define void() { return 6; }" is ok. + // _Only_ "define void f() ..." syntax treats "void" + // specially. + voidfunc = (strcmp(p->lex_strnumbuf.v, "void") == 0); s = zxc_lex_next(); if (s) RETURN_STATUS(s); + + voidfunc = (voidfunc && p->lex == XC_LEX_NAME); + if (voidfunc) { + s = zxc_lex_next(); + if (s) RETURN_STATUS(s); + } + if (p->lex != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_function_definition()); + + p->fidx = bc_program_addFunc(xstrdup(p->lex_strnumbuf.v)); + p->func = xc_program_func(p->fidx); + p->func->voidfunc = voidfunc; + s = zxc_lex_next(); if (s) RETURN_STATUS(s); + comma = false; while (p->lex != BC_LEX_RPAREN) { if (p->lex != XC_LEX_NAME) RETURN_STATUS(bc_error_bad_function_definition()); @@ -4442,7 +4463,7 @@ static BC_STATUS zbc_parse_funcdef(void) // Prevent "define z()" from being interpreted as function with empty stmt as body s = zbc_lex_skip_if_at_NLINE(); if (s) RETURN_STATUS(s); - //GNU bc requires a {} block even if function body has single stmt, enforce this? + // GNU bc requires a {} block even if function body has single stmt, enforce this if (p->lex != BC_LEX_LBRACE) RETURN_STATUS(bc_error("function { body } expected")); @@ -5127,6 +5148,7 @@ static BC_STATUS zxc_program_num(BcResult *r, BcNum **num) switch (r->t) { case XC_RESULT_STR: case XC_RESULT_TEMP: + IF_BC(case BC_RESULT_VOID:) case XC_RESULT_IBASE: case XC_RESULT_SCALE: case XC_RESULT_OBASE: @@ -5584,22 +5606,32 @@ static BC_STATUS zxc_num_print(BcNum *n, bool newline) } #define zxc_num_print(...) (zxc_num_print(__VA_ARGS__) COMMA_SUCCESS) -static BC_STATUS zxc_program_print(char inst, size_t idx) +#if !ENABLE_DC +// for bc, idx is always 0 +#define xc_program_print(inst, idx) \ + xc_program_print(inst) +#endif +static BC_STATUS xc_program_print(char inst, size_t idx) { BcStatus s; BcResult *r; BcNum *num; - bool pop = (inst != XC_INST_PRINT); + IF_NOT_DC(size_t idx = 0); if (!STACK_HAS_MORE_THAN(&G.prog.results, idx)) RETURN_STATUS(bc_error_stack_has_too_few_elements()); r = bc_vec_item_rev(&G.prog.results, idx); +#if ENABLE_BC + if (inst == XC_INST_PRINT && r->t == BC_RESULT_VOID) + // void function's result on stack, ignore + RETURN_STATUS(BC_STATUS_SUCCESS); +#endif s = zxc_program_num(r, &num); if (s) RETURN_STATUS(s); if (BC_PROG_NUM(r, num)) { - s = zxc_num_print(num, !pop); + s = zxc_num_print(num, /*newline:*/ inst == XC_INST_PRINT); #if ENABLE_BC if (!s && IS_BC) bc_num_copy(&G.prog.last, num); #endif @@ -5622,11 +5654,11 @@ static BC_STATUS zxc_program_print(char inst, size_t idx) } } - if (!s && pop) bc_vec_pop(&G.prog.results); + if (!s && inst != XC_INST_PRINT) bc_vec_pop(&G.prog.results); RETURN_STATUS(s); } -#define zxc_program_print(...) (zxc_program_print(__VA_ARGS__) COMMA_SUCCESS) +#define zxc_program_print(...) (xc_program_print(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zxc_program_negate(void) { @@ -5790,8 +5822,12 @@ static BC_STATUS zxc_program_assign(char inst) } #endif - if (left->t == XC_RESULT_CONSTANT || left->t == XC_RESULT_TEMP) + if (left->t == XC_RESULT_CONSTANT + || left->t == XC_RESULT_TEMP + IF_BC(|| left->t == BC_RESULT_VOID) + ) { RETURN_STATUS(bc_error_bad_assignment()); + } #if ENABLE_BC if (assign) @@ -6019,6 +6055,9 @@ static BC_STATUS zbc_program_return(char inst) size_t i; BcInstPtr *ip = bc_vec_top(&G.prog.exestack); + f = xc_program_func(ip->func); + + res.t = XC_RESULT_TEMP; if (inst == XC_INST_RET) { // bc needs this for e.g. RESULT_CONSTANT ("return 5") // because bc constants are per-function. @@ -6032,19 +6071,17 @@ static BC_STATUS zbc_program_return(char inst) bc_num_init(&res.d.n, num->len); bc_num_copy(&res.d.n, num); bc_vec_pop(&G.prog.results); - //} else if (f->void_func) { - //prepare "void" result in res } else { + if (f->voidfunc) + res.t = BC_RESULT_VOID; bc_num_init_DEF_SIZE(&res.d.n); //bc_num_zero(&res.d.n); - already is } - res.t = XC_RESULT_TEMP; bc_vec_push(&G.prog.results, &res); bc_vec_pop(&G.prog.exestack); // We need to pop arguments as well, so this takes that into account. - f = xc_program_func(ip->func); a = (void*)f->autos.v; for (i = 0; i < f->autos.len; i++, a++) { BcVec *v; @@ -6568,7 +6605,7 @@ static BC_STATUS zxc_program_exec(void) case XC_INST_PRINT: case XC_INST_PRINT_POP: case XC_INST_PRINT_STR: - dbg_exec("XC_INST_PRINTxyz:"); + dbg_exec("XC_INST_PRINTxyz(%d):", inst - XC_INST_PRINT); s = zxc_program_print(inst, 0); break; case XC_INST_STR: diff --git a/testsuite/bc.tests b/testsuite/bc.tests index 0a8222be6..3fde60a2c 100755 --- a/testsuite/bc.tests +++ b/testsuite/bc.tests @@ -123,6 +123,23 @@ testing "bc define with body on next line" \ "8\n9\n" \ "" "define w()\n{ auto z; return 8; }\nw()\n9" +testing "bc void function" \ + "bc" \ + "void9\n" \ + "" "define void w() {print \"void\"}\nw()\n9" + +# Extra POSIX compat - GNU bc does not allow this +testing "bc function named 'void'" \ + "bc" \ + "void0\n9\n" \ + "" "define void() {print \"void\"}\nvoid()\n9" + +# Extra POSIX compat - GNU bc does not allow this +testing "bc variable named 'void'" \ + "bc" \ + "6\n9\n" \ + "" "void=6\nvoid\n9" + testing "bc if(cond)" \ "bc" \ "9\n" \ -- cgit v1.2.3-55-g6feb From f11b5b9864d6bf1b49aa16f45b855e86efbb60a5 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 4 Jan 2019 15:54:40 +0100 Subject: bc: formatting changes, added a FIXME comment, no logic changes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 69d3920c0..53e8d7306 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -643,11 +643,13 @@ dc_char_to_LEX[] ALIGN1 = { // IJKLMNOP DC_LEX_IBASE, XC_LEX_INVALID, DC_LEX_SCALE, DC_LEX_LOAD_POP, XC_LEX_INVALID, DC_LEX_OP_BOOL_NOT, DC_LEX_OBASE, DC_LEX_PRINT_STREAM, - // QRSTUVWXY - DC_LEX_NQUIT, DC_LEX_POP, DC_LEX_STORE_PUSH, XC_LEX_INVALID, XC_LEX_INVALID, - XC_LEX_INVALID, XC_LEX_INVALID, DC_LEX_SCALE_FACTOR, XC_LEX_INVALID, - // Z[\] - DC_LEX_LENGTH, XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, + // QRSTUVWX + DC_LEX_NQUIT, DC_LEX_POP, DC_LEX_STORE_PUSH, XC_LEX_INVALID, + XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, DC_LEX_SCALE_FACTOR, + // YZ + XC_LEX_INVALID, DC_LEX_LENGTH, + // [\] + XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, // ^_` XC_LEX_OP_POWER, XC_LEX_NEG, XC_LEX_INVALID, // abcdefgh @@ -4574,6 +4576,7 @@ static BC_STATUS zbc_parse_stmt_possibly_auto(bool auto_allowed) } while (p->lex != BC_LEX_RBRACE) { dbg_lex("%s:%d block parsing loop", __func__, __LINE__); +//FIXME: prevent wrong syntax such as "{ print 1 print 2 }" s = zbc_parse_stmt(); if (s) RETURN_STATUS(s); } -- cgit v1.2.3-55-g6feb From e05ec6ed3ecc00258e2ac7a897e640760ecf82c6 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 4 Jan 2019 16:26:19 +0100 Subject: bc: shorten "limits" output text data bss dec hex filename 979016 485 7296 986797 f0ead busybox_old 978959 485 7296 986740 f0e74 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index 53e8d7306..74884557a 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -824,10 +824,8 @@ struct globals { #define BC_MAX_STRING ((unsigned) UINT_MAX - 1) #define BC_MAX_NUM BC_MAX_STRING // Unused apart from "limits" message. Just show a "biggish number" there. -//#define BC_MAX_NAME BC_MAX_STRING //#define BC_MAX_EXP ((unsigned long) LONG_MAX) //#define BC_MAX_VARS ((unsigned long) SIZE_MAX - 1) -#define BC_MAX_NAME_STR "999999999" #define BC_MAX_EXP_STR "999999999" #define BC_MAX_VARS_STR "999999999" @@ -4629,8 +4627,7 @@ static BC_STATUS zbc_parse_stmt_possibly_auto(bool auto_allowed) "BC_DIM_MAX = "BC_MAX_DIM_STR "\n" "BC_SCALE_MAX = "BC_MAX_SCALE_STR "\n" "BC_STRING_MAX = "BC_MAX_STRING_STR"\n" - "BC_NAME_MAX = "BC_MAX_NAME_STR "\n" - "BC_NUM_MAX = "BC_MAX_NUM_STR "\n" + // "BC_NUM_MAX = "BC_MAX_NUM_STR "\n" - GNU bc does not show this "MAX Exponent = "BC_MAX_EXP_STR "\n" "Number of vars = "BC_MAX_VARS_STR "\n" ); -- cgit v1.2.3-55-g6feb From 64f35361f42946e6e19bcbaa5a8be7b58a159c42 Mon Sep 17 00:00:00 2001 From: Martin Lewis Date: Wed, 26 Dec 2018 16:28:45 +0100 Subject: wget: add -o flag function old new delta wget_main 2348 2412 +64 packed_usage 33062 33093 +31 static.wget_longopts 252 266 +14 progress_meter 158 159 +1 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 4/0 up/down: 110/0) Total: 110 bytes Signed-off-by: Martin Lewis Signed-off-by: Denys Vlasenko --- networking/wget.c | 52 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 15 deletions(-) diff --git a/networking/wget.c b/networking/wget.c index 30683dfc0..da629ccb9 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -123,14 +123,14 @@ //usage:#define wget_trivial_usage //usage: IF_FEATURE_WGET_LONG_OPTIONS( //usage: "[-c|--continue] [--spider] [-q|--quiet] [-O|--output-document FILE]\n" -//usage: " [--header 'header: value'] [-Y|--proxy on/off] [-P DIR]\n" +//usage: " [-o|--output-file FILE] [--header 'header: value'] [-Y|--proxy on/off]\n" /* Since we ignore these opts, we don't show them in --help */ /* //usage: " [--no-check-certificate] [--no-cache] [--passive-ftp] [-t TRIES]" */ /* //usage: " [-nv] [-nc] [-nH] [-np]" */ -//usage: " [-S|--server-response] [-U|--user-agent AGENT]" IF_FEATURE_WGET_TIMEOUT(" [-T SEC]") " URL..." +//usage: " [-P DIR] [-S|--server-response] [-U|--user-agent AGENT]" IF_FEATURE_WGET_TIMEOUT(" [-T SEC]") " URL..." //usage: ) //usage: IF_NOT_FEATURE_WGET_LONG_OPTIONS( -//usage: "[-cq] [-O FILE] [-Y on/off] [-P DIR] [-S] [-U AGENT]" +//usage: "[-cq] [-O FILE] [-o FILE] [-Y on/off] [-P DIR] [-S] [-U AGENT]" //usage: IF_FEATURE_WGET_TIMEOUT(" [-T SEC]") " URL..." //usage: ) //usage:#define wget_full_usage "\n\n" @@ -147,6 +147,7 @@ //usage: "\n -T SEC Network read timeout is SEC seconds" //usage: ) //usage: "\n -O FILE Save to FILE ('-' for stdout)" +//usage: "\n -o FILE Log messages to FILE" //usage: "\n -U STR Use STR for User-Agent header" //usage: "\n -Y on/off Use proxy" @@ -231,9 +232,11 @@ struct globals { unsigned char user_headers; /* Headers mentioned by the user */ #endif char *fname_out; /* where to direct output (-O) */ + char *fname_log; /* where to direct log (-o) */ const char *proxy_flag; /* Use proxies if env vars are set */ const char *user_agent; /* "User-Agent" header field */ int output_fd; + int log_fd; int o_flags; #if ENABLE_FEATURE_WGET_TIMEOUT unsigned timeout_seconds; @@ -262,16 +265,17 @@ enum { WGET_OPT_QUIET = (1 << 1), WGET_OPT_SERVER_RESPONSE = (1 << 2), WGET_OPT_OUTNAME = (1 << 3), - WGET_OPT_PREFIX = (1 << 4), - WGET_OPT_PROXY = (1 << 5), - WGET_OPT_USER_AGENT = (1 << 6), - WGET_OPT_NETWORK_READ_TIMEOUT = (1 << 7), - WGET_OPT_RETRIES = (1 << 8), - WGET_OPT_nsomething = (1 << 9), - WGET_OPT_HEADER = (1 << 10) * ENABLE_FEATURE_WGET_LONG_OPTIONS, - WGET_OPT_POST_DATA = (1 << 11) * ENABLE_FEATURE_WGET_LONG_OPTIONS, - WGET_OPT_SPIDER = (1 << 12) * ENABLE_FEATURE_WGET_LONG_OPTIONS, - WGET_OPT_NO_CHECK_CERT = (1 << 13) * ENABLE_FEATURE_WGET_LONG_OPTIONS, + WGET_OPT_LOGNAME = (1 << 4), + WGET_OPT_PREFIX = (1 << 5), + WGET_OPT_PROXY = (1 << 6), + WGET_OPT_USER_AGENT = (1 << 7), + WGET_OPT_NETWORK_READ_TIMEOUT = (1 << 8), + WGET_OPT_RETRIES = (1 << 9), + WGET_OPT_nsomething = (1 << 10), + WGET_OPT_HEADER = (1 << 11) * ENABLE_FEATURE_WGET_LONG_OPTIONS, + WGET_OPT_POST_DATA = (1 << 12) * ENABLE_FEATURE_WGET_LONG_OPTIONS, + WGET_OPT_SPIDER = (1 << 13) * ENABLE_FEATURE_WGET_LONG_OPTIONS, + WGET_OPT_NO_CHECK_CERT = (1 << 14) * ENABLE_FEATURE_WGET_LONG_OPTIONS, }; enum { @@ -287,6 +291,10 @@ static void progress_meter(int flag) if (option_mask32 & WGET_OPT_QUIET) return; + /* Don't save progress to log file */ + if (G.log_fd >= 0) + return; + if (flag == PROGRESS_START) bb_progress_init(&G.pmt, G.curfile); @@ -1401,6 +1409,7 @@ int wget_main(int argc UNUSED_PARAM, char **argv) "quiet\0" No_argument "q" "server-response\0" No_argument "S" "output-document\0" Required_argument "O" + "output-file\0" Required_argument "o" "directory-prefix\0" Required_argument "P" "proxy\0" Required_argument "Y" "user-agent\0" Required_argument "U" @@ -1444,7 +1453,7 @@ IF_DESKTOP( "no-parent\0" No_argument "\xf0") #if ENABLE_FEATURE_WGET_LONG_OPTIONS #endif GETOPT32(argv, "^" - "cqSO:P:Y:U:T:+" + "cqSO:o:P:Y:U:T:+" /*ignored:*/ "t:" /*ignored:*/ "n::" /* wget has exactly four -n opts, all of which we can ignore: @@ -1459,7 +1468,7 @@ IF_DESKTOP( "no-parent\0" No_argument "\xf0") "-1" /* at least one URL */ IF_FEATURE_WGET_LONG_OPTIONS(":\xff::") /* --header is a list */ LONGOPTS - , &G.fname_out, &G.dir_prefix, + , &G.fname_out, &G.fname_log, &G.dir_prefix, &G.proxy_flag, &G.user_agent, IF_FEATURE_WGET_TIMEOUT(&G.timeout_seconds) IF_NOT_FEATURE_WGET_TIMEOUT(NULL), NULL, /* -t RETRIES */ @@ -1521,12 +1530,25 @@ IF_DESKTOP( "no-parent\0" No_argument "\xf0") G.o_flags = O_WRONLY | O_CREAT | O_TRUNC; } + G.log_fd = -1; + if (G.fname_log) { /* -o FILE ? */ + if (!LONE_DASH(G.fname_log)) { /* not -o - ? */ + /* compat with wget: -o FILE can overwrite */ + G.log_fd = xopen(G.fname_log, O_WRONLY | O_CREAT | O_TRUNC); + /* Redirect only stderr to log file, so -O - will work */ + xdup2(G.log_fd, STDERR_FILENO); + } + } + while (*argv) download_one_url(*argv++); if (G.output_fd >= 0) xclose(G.output_fd); + if (G.log_fd >= 0) + xclose(G.log_fd); + #if ENABLE_FEATURE_CLEAN_UP && ENABLE_FEATURE_WGET_LONG_OPTIONS free(G.extra_headers); #endif -- cgit v1.2.3-55-g6feb From 46fc3290c20a0468c02bd771a8c548c0e1b23e47 Mon Sep 17 00:00:00 2001 From: Martin Lewis Date: Fri, 4 Jan 2019 18:26:04 +0100 Subject: wget: notify on download begin and end When using -o to file the progress meter is not displayed, so write that we started the download and that we finished it. function old new delta retrieve_file_data 465 561 +96 wget_main 2412 2432 +20 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 116/0) Total: 116 bytes text data bss dec hex filename 979022 485 7296 986803 f0eb3 busybox_old 979224 485 7296 987005 f0f7d busybox_unstripped Signed-off-by: Martin Lewis Signed-off-by: Denys Vlasenko --- networking/wget.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/networking/wget.c b/networking/wget.c index da629ccb9..3a02de6ca 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -876,6 +876,10 @@ static void NOINLINE retrieve_file_data(FILE *dfp) polldata.fd = fileno(dfp); polldata.events = POLLIN | POLLPRI; #endif + if (G.output_fd == 1) + fprintf(stderr, "writing to stdout\n"); + else + fprintf(stderr, "saving to '%s'\n", G.fname_out); progress_meter(PROGRESS_START); if (G.chunked) @@ -1021,6 +1025,10 @@ static void NOINLINE retrieve_file_data(FILE *dfp) G.chunked = 0; /* makes it show 100% even for chunked download */ G.got_clen = 1; /* makes it show 100% even for download of (formerly) unknown size */ progress_meter(PROGRESS_END); + if (G.output_fd == 1) + fprintf(stderr, "written to stdout\n"); + else + fprintf(stderr, "'%s' saved\n", G.fname_out); } static void download_one_url(const char *url) @@ -1380,6 +1388,8 @@ However, in real world it was observed that some web servers xclose(G.output_fd); G.output_fd = -1; } + } else { + fprintf(stderr, "remote file exists\n"); } if (dfp != sfp) { -- cgit v1.2.3-55-g6feb From f83292cfc44da5bd218c2be0602c89afed9e0959 Mon Sep 17 00:00:00 2001 From: Martijn Dekker Date: Fri, 4 Jan 2019 18:54:52 +0100 Subject: ls: make -i compatible with coreutils: don't follow symlink by default Signed-off-by: Martijn Dekker Signed-off-by: Denys Vlasenko --- coreutils/ls.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/coreutils/ls.c b/coreutils/ls.c index db3ddb944..b2adb0c06 100644 --- a/coreutils/ls.c +++ b/coreutils/ls.c @@ -1204,8 +1204,8 @@ int ls_main(int argc UNUSED_PARAM, char **argv) nfiles = 0; do { cur = my_stat(*argv, *argv, - /* follow links on command line unless -l, -s or -F: */ - !(option_mask32 & (OPT_l|OPT_s|OPT_F)) + /* follow links on command line unless -l, -i, -s or -F: */ + !(option_mask32 & (OPT_l|OPT_i|OPT_s|OPT_F)) /* ... or if -H: */ || (option_mask32 & OPT_H) /* ... or if -L, but my_stat always follows links if -L */ -- cgit v1.2.3-55-g6feb From 1c952ba2060780fce830d427420b9d819f08880e Mon Sep 17 00:00:00 2001 From: Kaarle Ritvanen Date: Mon, 31 Dec 2018 19:52:32 +0200 Subject: ip: print dadfailed flag Signed-off-by: Kaarle Ritvanen Signed-off-by: Denys Vlasenko --- networking/libiproute/ipaddress.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/networking/libiproute/ipaddress.c b/networking/libiproute/ipaddress.c index 9ec665b69..d088caf4c 100644 --- a/networking/libiproute/ipaddress.c +++ b/networking/libiproute/ipaddress.c @@ -327,6 +327,10 @@ static int FAST_FUNC print_addrinfo(const struct sockaddr_nl *who UNUSED_PARAM, ifa->ifa_flags &= ~IFA_F_TENTATIVE; printf("tentative "); } + if (ifa->ifa_flags & IFA_F_DADFAILED) { + ifa->ifa_flags &= ~IFA_F_DADFAILED; + printf("dadfailed "); + } if (ifa->ifa_flags & IFA_F_DEPRECATED) { ifa->ifa_flags &= ~IFA_F_DEPRECATED; printf("deprecated "); -- cgit v1.2.3-55-g6feb From 5bfc4a32fdae8f43e97588d5575249f896a17376 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 6 Jan 2019 18:41:11 +0100 Subject: telnet: speed up processing of network input function old new delta telnet_main 1482 1492 +10 Signed-off-by: Denys Vlasenko --- networking/telnet.c | 83 +++++++++++++++++++++++++++-------------------------- 1 file changed, 43 insertions(+), 40 deletions(-) diff --git a/networking/telnet.c b/networking/telnet.c index 7f65ff3e6..0ee65c532 100644 --- a/networking/telnet.c +++ b/networking/telnet.c @@ -94,19 +94,19 @@ enum { IACBUFSIZE = 128, CHM_TRY = 0, - CHM_ON = 1, + CHM_ON = 1, CHM_OFF = 2, UF_ECHO = 0x01, - UF_SGA = 0x02, + UF_SGA = 0x02, TS_NORMAL = 0, TS_COPY = 1, - TS_IAC = 2, - TS_OPT = 3, + TS_IAC = 2, + TS_OPT = 3, TS_SUB1 = 4, TS_SUB2 = 5, - TS_CR = 6, + TS_CR = 6, }; typedef unsigned char byte; @@ -244,25 +244,34 @@ static void handle_net_output(int len) static void handle_net_input(int len) { + byte c; int i; - int cstart = 0; - - for (i = 0; i < len; i++) { - byte c = G.buf[i]; - - if (G.telstate == TS_NORMAL) { /* most typical state */ - if (c == IAC) { - cstart = i; - G.telstate = TS_IAC; - } - else if (c == '\r') { - cstart = i + 1; - G.telstate = TS_CR; - } - /* No IACs were seen so far, no need to copy - * bytes within G.buf: */ - continue; + int cstart; + + i = 0; + //bb_error_msg("[%u,'%.*s']", G.telstate, len, G.buf); + if (G.telstate == TS_NORMAL) { /* most typical state */ + while (i < len) { + c = G.buf[i]; + i++; + if (c == IAC) /* unlikely */ + goto got_IAC; + if (c != '\r') /* likely */ + continue; + G.telstate = TS_CR; + cstart = i; + goto got_special; } + full_write(STDOUT_FILENO, G.buf, len); + return; + got_IAC: + G.telstate = TS_IAC; + cstart = i - 1; + got_special: ; + } + + for (; i < len; i++) { + c = G.buf[i]; switch (G.telstate) { case TS_CR: @@ -278,20 +287,19 @@ static void handle_net_input(int len) /* Similar to NORMAL, but in TS_COPY we need to copy bytes */ if (c == IAC) G.telstate = TS_IAC; - else + else { G.buf[cstart++] = c; - if (c == '\r') - G.telstate = TS_CR; + if (c == '\r') + G.telstate = TS_CR; + } break; case TS_IAC: /* Prev char was IAC */ - if (c == IAC) { /* IAC IAC -> one IAC */ + switch (c) { + case IAC: /* IAC IAC -> one IAC */ G.buf[cstart++] = c; G.telstate = TS_COPY; break; - } - /* else */ - switch (c) { case SB: G.telstate = TS_SUB1; break; @@ -320,17 +328,12 @@ static void handle_net_input(int len) } } - if (G.telstate != TS_NORMAL) { - /* We had some IACs, or CR */ - if (G.iaclen) - iac_flush(); - if (G.telstate == TS_COPY) /* we aren't in the middle of IAC */ - G.telstate = TS_NORMAL; - len = cstart; - } - - if (len) - full_write(STDOUT_FILENO, G.buf, len); + /* We had some IACs, or CR */ + iac_flush(); + if (G.telstate == TS_COPY) /* we aren't in the middle of IAC */ + G.telstate = TS_NORMAL; + if (cstart != 0) + full_write(STDOUT_FILENO, G.buf, cstart); } static void put_iac(int c) -- cgit v1.2.3-55-g6feb From 935afafcf37e38290e4cc126e328a02877d74fc0 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 6 Jan 2019 18:45:38 +0100 Subject: telnet: code shrink function old new delta put_iac3_IAC_x_y_merged - 21 +21 put_iac4_msb_lsb - 19 +19 put_iac2_msb_lsb - 19 +19 put_iac 20 34 +14 iac_flush 32 36 +4 put_iac2_merged 46 - -46 telnet_main 1492 1270 -222 ------------------------------------------------------------------------------ (add/remove: 3/1 grow/shrink: 2/1 up/down: 77/-268) Total: -191 bytes Signed-off-by: Denys Vlasenko --- networking/telnet.c | 119 +++++++++++++++++++++++----------------------------- 1 file changed, 53 insertions(+), 66 deletions(-) diff --git a/networking/telnet.c b/networking/telnet.c index 0ee65c532..6b4accd33 100644 --- a/networking/telnet.c +++ b/networking/telnet.c @@ -152,8 +152,10 @@ static void subneg(byte c); static void iac_flush(void) { - full_write(netfd, G.iacbuf, G.iaclen); - G.iaclen = 0; + if (G.iaclen != 0) { + full_write(netfd, G.iacbuf, G.iaclen); + G.iaclen = 0; + } } static void doexit(int ev) NORETURN; @@ -338,88 +340,73 @@ static void handle_net_input(int len) static void put_iac(int c) { - G.iacbuf[G.iaclen++] = c; + int iaclen = G.iaclen; + if (iaclen >= IACBUFSIZE) { + iac_flush(); + iaclen = 0; + } + G.iacbuf[iaclen] = c; /* "... & 0xff" is implicit */ + G.iaclen = iaclen + 1; } -static void put_iac2_merged(unsigned wwdd_and_c) +static void put_iac2_msb_lsb(unsigned x_y) { - if (G.iaclen + 3 > IACBUFSIZE) - iac_flush(); + put_iac(x_y >> 8); /* "... & 0xff" is implicit */ + put_iac(x_y); /* "... & 0xff" is implicit */ +} +#define put_iac2_x_y(x,y) put_iac2_msb_lsb(((x)<<8) + (y)) +static void put_iac4_msb_lsb(unsigned x_y_z_t) +{ + put_iac2_msb_lsb(x_y_z_t >> 16); + put_iac2_msb_lsb(x_y_z_t); /* "... & 0xffff" is implicit */ +} +#define put_iac4_x_y_z_t(x,y,z,t) put_iac4_msb_lsb(((x)<<24) + ((y)<<16) + ((z)<<8) + (t)) + +static void put_iac3_IAC_x_y_merged(unsigned wwdd_and_c) +{ put_iac(IAC); - put_iac(wwdd_and_c >> 8); - put_iac(wwdd_and_c & 0xff); + put_iac2_msb_lsb(wwdd_and_c); } -#define put_iac2(wwdd,c) put_iac2_merged(((wwdd)<<8) + (c)) +#define put_iac3_IAC_x_y(wwdd,c) put_iac3_IAC_x_y_merged(((wwdd)<<8) + (c)) #if ENABLE_FEATURE_TELNET_TTYPE static void put_iac_subopt(byte c, char *str) { - int len = strlen(str) + 6; // ( 2 + 1 + 1 + strlen + 2 ) - - if (G.iaclen + len > IACBUFSIZE) - iac_flush(); - - put_iac(IAC); - put_iac(SB); - put_iac(c); - put_iac(0); + put_iac4_x_y_z_t(IAC, SB, c, 0); while (*str) put_iac(*str++); - put_iac(IAC); - put_iac(SE); + put_iac2_x_y(IAC, SE); } #endif #if ENABLE_FEATURE_TELNET_AUTOLOGIN static void put_iac_subopt_autologin(void) { - int len = strlen(G.autologin) + 6; // (2 + 1 + 1 + strlen + 2) - const char *p = "USER"; - - if (G.iaclen + len > IACBUFSIZE) - iac_flush(); + const char *p; - put_iac(IAC); - put_iac(SB); - put_iac(TELOPT_NEW_ENVIRON); - put_iac(TELQUAL_IS); - put_iac(NEW_ENV_VAR); - - while (*p) - put_iac(*p++); - - put_iac(NEW_ENV_VALUE); + put_iac4_x_y_z_t(IAC, SB, TELOPT_NEW_ENVIRON, TELQUAL_IS); + put_iac4_x_y_z_t(NEW_ENV_VAR, 'U', 'S', 'E'); /* "USER" */ + put_iac2_x_y('R', NEW_ENV_VALUE); p = G.autologin; while (*p) put_iac(*p++); - put_iac(IAC); - put_iac(SE); + put_iac2_x_y(IAC, SE); } #endif #if ENABLE_FEATURE_TELNET_WIDTH static void put_iac_naws(byte c, int x, int y) { - if (G.iaclen + 9 > IACBUFSIZE) - iac_flush(); + put_iac3_IAC_x_y(SB, c); - put_iac(IAC); - put_iac(SB); - put_iac(c); - - /* "... & 0xff" implicitly done below */ - put_iac(x >> 8); - put_iac(x); - put_iac(y >> 8); - put_iac(y); + put_iac4_msb_lsb((x << 16) + y); - put_iac(IAC); - put_iac(SE); + put_iac2_x_y(IAC, SE); } #endif @@ -448,8 +435,8 @@ static void will_charmode(void) G.telflags |= (UF_ECHO | UF_SGA); setConMode(); - put_iac2(DO, TELOPT_ECHO); - put_iac2(DO, TELOPT_SGA); + put_iac3_IAC_x_y(DO, TELOPT_ECHO); + put_iac3_IAC_x_y(DO, TELOPT_SGA); iac_flush(); } @@ -459,24 +446,24 @@ static void do_linemode(void) G.telflags &= ~(UF_ECHO | UF_SGA); setConMode(); - put_iac2(DONT, TELOPT_ECHO); - put_iac2(DONT, TELOPT_SGA); + put_iac3_IAC_x_y(DONT, TELOPT_ECHO); + put_iac3_IAC_x_y(DONT, TELOPT_SGA); iac_flush(); } static void to_notsup(char c) { if (G.telwish == WILL) - put_iac2(DONT, c); + put_iac3_IAC_x_y(DONT, c); else if (G.telwish == DO) - put_iac2(WONT, c); + put_iac3_IAC_x_y(WONT, c); } static void to_echo(void) { /* if server requests ECHO, don't agree */ if (G.telwish == DO) { - put_iac2(WONT, TELOPT_ECHO); + put_iac3_IAC_x_y(WONT, TELOPT_ECHO); return; } if (G.telwish == DONT) @@ -492,9 +479,9 @@ static void to_echo(void) G.telflags ^= UF_ECHO; if (G.telflags & UF_ECHO) - put_iac2(DO, TELOPT_ECHO); + put_iac3_IAC_x_y(DO, TELOPT_ECHO); else - put_iac2(DONT, TELOPT_ECHO); + put_iac3_IAC_x_y(DONT, TELOPT_ECHO); setConMode(); full_write1_str("\r\n"); /* sudden modec */ @@ -512,9 +499,9 @@ static void to_sga(void) G.telflags ^= UF_SGA; /* toggle */ if (G.telflags & UF_SGA) - put_iac2(DO, TELOPT_SGA); + put_iac3_IAC_x_y(DO, TELOPT_SGA); else - put_iac2(DONT, TELOPT_SGA); + put_iac3_IAC_x_y(DONT, TELOPT_SGA); } #if ENABLE_FEATURE_TELNET_TTYPE @@ -522,9 +509,9 @@ static void to_ttype(void) { /* Tell server we will (or won't) do TTYPE */ if (G.ttype) - put_iac2(WILL, TELOPT_TTYPE); + put_iac3_IAC_x_y(WILL, TELOPT_TTYPE); else - put_iac2(WONT, TELOPT_TTYPE); + put_iac3_IAC_x_y(WONT, TELOPT_TTYPE); } #endif @@ -533,9 +520,9 @@ static void to_new_environ(void) { /* Tell server we will (or will not) do AUTOLOGIN */ if (G.autologin) - put_iac2(WILL, TELOPT_NEW_ENVIRON); + put_iac3_IAC_x_y(WILL, TELOPT_NEW_ENVIRON); else - put_iac2(WONT, TELOPT_NEW_ENVIRON); + put_iac3_IAC_x_y(WONT, TELOPT_NEW_ENVIRON); } #endif @@ -543,7 +530,7 @@ static void to_new_environ(void) static void to_naws(void) { /* Tell server we will do NAWS */ - put_iac2(WILL, TELOPT_NAWS); + put_iac3_IAC_x_y(WILL, TELOPT_NAWS); } #endif -- cgit v1.2.3-55-g6feb From 39b18196f89a6f595d47c2a9c3a62c50d413c054 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 6 Jan 2019 19:06:01 +0100 Subject: telnetd: fix bad interaction with vhangup() from login Signed-off-by: Denys Vlasenko --- networking/telnetd.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/networking/telnetd.c b/networking/telnetd.c index a6bafa21d..caef15181 100644 --- a/networking/telnetd.c +++ b/networking/telnetd.c @@ -865,11 +865,25 @@ int telnetd_main(int argc UNUSED_PARAM, char **argv) skip3: if (/*ts->size2 < BUFSIZE &&*/ FD_ISSET(ts->ptyfd, &rdfdset)) { /* Read from pty to buffer 2 */ + int eio = 0; + read_pty: count = MIN(BUFSIZE - ts->rdidx2, BUFSIZE - ts->size2); count = safe_read(ts->ptyfd, TS_BUF2(ts) + ts->rdidx2, count); if (count <= 0) { - if (count < 0 && errno == EAGAIN) - goto skip4; + if (count < 0) { + if (errno == EAGAIN) + goto skip4; + /* login process might call vhangup(), + * which causes intermittent EIOs on read above + * (observed on kernel 4.12.0). Try up to 10 ms. + */ + if (errno == EIO && eio < 10) { + eio++; + //bb_error_msg("EIO pty %u", eio); + usleep(1000); + goto read_pty; + } + } goto kill_session; } ts->size2 += count; -- cgit v1.2.3-55-g6feb From 3f4fac577a83146ac69bf617a29cf192099cded0 Mon Sep 17 00:00:00 2001 From: Danijel Tasov Date: Sun, 6 Jan 2019 19:20:05 +0100 Subject: telnet: provide feedback after successful connect The real telnet provides some feedback: Trying 127.0.0.1... Connected to localhost.localdomain. Escape character is '^]'. We should do this to, because people are sitting there and think a firewall is dropping packets. function old new delta telnet_main 1270 1279 +9 Signed-off-by: Danijel Tasov Signed-off-by: Denys Vlasenko --- networking/telnet.c | 1 + 1 file changed, 1 insertion(+) diff --git a/networking/telnet.c b/networking/telnet.c index 6b4accd33..94c7512fc 100644 --- a/networking/telnet.c +++ b/networking/telnet.c @@ -639,6 +639,7 @@ int telnet_main(int argc UNUSED_PARAM, char **argv) bb_show_usage(); xmove_fd(create_and_connect_stream_or_die(host, port), netfd); + printf("Connected to %s\n", host); setsockopt_keepalive(netfd); -- cgit v1.2.3-55-g6feb From 2d9e09796342ab202e780a6cb613b532c7356aec Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 6 Jan 2019 19:58:18 +0100 Subject: find: handle leading -- argument function old new delta find_main 464 478 +14 Signed-off-by: Denys Vlasenko --- findutils/find.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/findutils/find.c b/findutils/find.c index 6407c6c5a..06ad1b39c 100644 --- a/findutils/find.c +++ b/findutils/find.c @@ -1467,6 +1467,12 @@ int find_main(int argc UNUSED_PARAM, char **argv) break; if (!saved[1]) break; /* it is "-" */ + if (saved[1] == '-' && !saved[2]) { + /* it is "--" */ + /* Try: find -- /dev/null */ + saved = *++past_HLP; + break; + } if ((saved+1)[strspn(saved+1, "HLP")] != '\0') break; } -- cgit v1.2.3-55-g6feb From 4bdc914ff97df0cea8d2c7b42bf7f57d5ebb8dcb Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 6 Jan 2019 20:12:16 +0100 Subject: build system: fix compiler warnings Signed-off-by: Denys Vlasenko --- Config.in | 2 +- scripts/basic/split-include.c | 3 ++- scripts/kconfig/conf.c | 6 ++++-- scripts/kconfig/lxdialog/lxdialog.c | 2 +- scripts/kconfig/mconf.c | 7 +++++-- 5 files changed, 13 insertions(+), 7 deletions(-) diff --git a/Config.in b/Config.in index 01680af1f..1a44c5b6d 100644 --- a/Config.in +++ b/Config.in @@ -12,7 +12,7 @@ config HAVE_DOT_CONFIG menu "Settings" config DESKTOP - bool "Enable compatibility for full-blown desktop systems" + bool "Enable compatibility for full-blown desktop systems (8kb)" default y help Enable applet options and features which are not essential. diff --git a/scripts/basic/split-include.c b/scripts/basic/split-include.c index e328788e2..791d142a8 100644 --- a/scripts/basic/split-include.c +++ b/scripts/basic/split-include.c @@ -131,7 +131,8 @@ int main(int argc, const char * argv []) is_same = 0; if ((fp_target = fopen(ptarget, "r")) != NULL) { - fgets(old_line, buffer_size, fp_target); + if (!fgets(old_line, buffer_size, fp_target)) + ERROR_EXIT(ptarget); if (fclose(fp_target) != 0) ERROR_EXIT(ptarget); if (!strcmp(line, old_line)) diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c index 57734b590..866a7c544 100644 --- a/scripts/kconfig/conf.c +++ b/scripts/kconfig/conf.c @@ -142,7 +142,8 @@ static void conf_askvalue(struct symbol *sym, const char *def) check_stdin(); case ask_all: fflush(stdout); - fgets(line, 128, stdin); + if (!fgets(line, 128, stdin)) + exit(1); return; case set_default: printf("%s\n", def); @@ -390,7 +391,8 @@ static int conf_choice(struct menu *menu) check_stdin(); case ask_all: fflush(stdout); - fgets(line, 128, stdin); + if (!fgets(line, 128, stdin)) + exit(1); strip(line); if (line[0] == '?') { printf("\n%s\n", menu->sym->help ? diff --git a/scripts/kconfig/lxdialog/lxdialog.c b/scripts/kconfig/lxdialog/lxdialog.c index 79f6c5fb5..5b8e3e947 100644 --- a/scripts/kconfig/lxdialog/lxdialog.c +++ b/scripts/kconfig/lxdialog/lxdialog.c @@ -189,7 +189,7 @@ int j_inputbox(const char *t, int ac, const char *const *av) int ret = dialog_inputbox(t, av[2], atoi(av[3]), atoi(av[4]), ac == 6 ? av[5] : (char *)NULL); if (ret == 0) - fprintf(stderr, dialog_input_result); + fprintf(stderr, "%s", dialog_input_result); return ret; } diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c index adba1141b..c3a837a14 100644 --- a/scripts/kconfig/mconf.c +++ b/scripts/kconfig/mconf.c @@ -482,7 +482,8 @@ static int exec_conf(void) *argptr++ = NULL; - pipe(pipefd); + if (pipe(pipefd)) + _exit(EXIT_FAILURE); pid = fork(); if (pid == 0) { sigprocmask(SIG_SETMASK, &osset, NULL); @@ -846,9 +847,11 @@ static void conf(struct menu *menu) static void show_textbox(const char *title, const char *text, int r, int c) { int fd; + int len = strlen(text); fd = creat(".help.tmp", 0777); - write(fd, text, strlen(text)); + if (write(fd, text, len) != len) + exit(1); close(fd); show_file(".help.tmp", title, r, c); unlink(".help.tmp"); -- cgit v1.2.3-55-g6feb From edca770d11edcc5b5548a62c068b2e75f1ccb54a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 7 Jan 2019 15:20:56 +0100 Subject: sleep: support "inf" Signed-off-by: Denys Vlasenko --- coreutils/sleep.c | 5 +++++ miscutils/bc.c | 1 - 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/coreutils/sleep.c b/coreutils/sleep.c index 5c9cda9f0..7bfaab920 100644 --- a/coreutils/sleep.c +++ b/coreutils/sleep.c @@ -68,6 +68,11 @@ int sleep_main(int argc UNUSED_PARAM, char **argv) if (!*argv) bb_show_usage(); + /* GNU sleep accepts "inf", "INF", "infinity" and "INFINITY" */ + if (strncasecmp(argv[0], "inf", 3) == 0) + for (;;) + sleep(INT_MAX); + #if ENABLE_FEATURE_FANCY_SLEEP # if ENABLE_FLOAT_DURATION /* undo busybox.c setlocale */ diff --git a/miscutils/bc.c b/miscutils/bc.c index 74884557a..bf174dafb 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -7407,4 +7407,3 @@ int dc_main(int argc UNUSED_PARAM, char **argv) #endif #endif // DC_BIG - -- cgit v1.2.3-55-g6feb From b80bdeba0248e2742cf801e7429d5d7aad69d26d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 7 Jan 2019 15:23:18 +0100 Subject: udhcp: code shrink function old new delta attach_option 406 349 -57 Signed-off-by: Denys Vlasenko --- networking/udhcp/common.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c index 41b05b855..4c2221b77 100644 --- a/networking/udhcp/common.c +++ b/networking/udhcp/common.c @@ -422,6 +422,7 @@ static NOINLINE void attach_option( if (errno) bb_error_msg_and_die("malformed hex string '%s'", buffer); length = end - allocated; + buffer = allocated; } #if ENABLE_FEATURE_UDHCP_RFC3397 if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_DNS_STRING) { @@ -441,15 +442,14 @@ static NOINLINE void attach_option( new->data = xmalloc(length + OPT_DATA); new->data[OPT_CODE] = optflag->code; new->data[OPT_LEN] = length; - memcpy(new->data + OPT_DATA, (allocated ? allocated : buffer), - length); + memcpy(new->data + OPT_DATA, buffer, length); } else { new->data = xmalloc(length + D6_OPT_DATA); new->data[D6_OPT_CODE] = optflag->code >> 8; new->data[D6_OPT_CODE + 1] = optflag->code & 0xff; new->data[D6_OPT_LEN] = length >> 8; new->data[D6_OPT_LEN + 1] = length & 0xff; - memcpy(new->data + D6_OPT_DATA, (allocated ? allocated : buffer), + memcpy(new->data + D6_OPT_DATA, buffer, length); } @@ -472,6 +472,8 @@ static NOINLINE void attach_option( /* actually 255 is ok too, but adding a space can overlow it */ existing->data = xrealloc(existing->data, OPT_DATA + 1 + old_len + length); +// So far dhcp_optflags[] has no OPTION_STRING[_HOST] | OPTION_LIST items +#if 0 if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_STRING || (optflag->flags & OPTION_TYPE_MASK) == OPTION_STRING_HOST ) { @@ -479,7 +481,9 @@ static NOINLINE void attach_option( existing->data[OPT_DATA + old_len] = ' '; old_len++; } - memcpy(existing->data + OPT_DATA + old_len, (allocated ? allocated : buffer), length); +#endif + + memcpy(existing->data + OPT_DATA + old_len, buffer, length); existing->data[OPT_LEN] = old_len + length; } /* else, ignore the data, we could put this in a second option in the future */ } /* else, ignore the new data */ @@ -553,7 +557,7 @@ int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg, if (retval) retval = udhcp_str2nip(val, buffer + 4); break; -case_OPTION_STRING: + case_OPTION_STRING: case OPTION_STRING: case OPTION_STRING_HOST: #if ENABLE_FEATURE_UDHCP_RFC3397 -- cgit v1.2.3-55-g6feb From 74d9f1ba37010face4bd1449df4d60dd84450b06 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 7 Jan 2019 15:33:42 +0100 Subject: udhcpc: when decoding DHCP_SUBNET, ensure it is 4 bytes long function old new delta udhcp_run_script 795 801 +6 Signed-off-by: Denys Vlasenko --- networking/udhcp/common.c | 2 +- networking/udhcp/common.h | 2 +- networking/udhcp/dhcpc.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c index 4c2221b77..fc4de5716 100644 --- a/networking/udhcp/common.c +++ b/networking/udhcp/common.c @@ -302,7 +302,7 @@ uint8_t* FAST_FUNC udhcp_get_option32(struct dhcp_packet *packet, int code) { uint8_t *r = udhcp_get_option(packet, code); if (r) { - if (r[-1] != 4) + if (r[-OPT_DATA + OPT_LEN] != 4) r = NULL; } return r; diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h index 9511152ff..62f9a2a4a 100644 --- a/networking/udhcp/common.h +++ b/networking/udhcp/common.h @@ -119,7 +119,7 @@ enum { //#define DHCP_TIME_SERVER 0x04 /* RFC 868 time server (32-bit, 0 = 1.1.1900) */ //#define DHCP_NAME_SERVER 0x05 /* IEN 116 _really_ ancient kind of NS */ //#define DHCP_DNS_SERVER 0x06 -//#define DHCP_LOG_SERVER 0x07 /* port 704 UDP log (not syslog) +//#define DHCP_LOG_SERVER 0x07 /* port 704 UDP log (not syslog) */ //#define DHCP_COOKIE_SERVER 0x08 /* "quote of the day" server */ //#define DHCP_LPR_SERVER 0x09 #define DHCP_HOST_NAME 0x0c /* 12: either client informs server or server gives name to client */ diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index 5b3fd531c..dcec8cdfd 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c @@ -531,7 +531,7 @@ static char **fill_envp(struct dhcp_packet *packet) temp = udhcp_get_option(packet, code); *curr = xmalloc_optname_optval(temp, &dhcp_optflags[i], opt_name); putenv(*curr++); - if (code == DHCP_SUBNET) { + if (code == DHCP_SUBNET && temp[-OPT_DATA + OPT_LEN] == 4) { /* Subnet option: make things like "$ip/$mask" possible */ uint32_t subnet; move_from_unaligned32(subnet, temp); -- cgit v1.2.3-55-g6feb From 959b04bc0e9d23daa51f75130c7d3eeacd91e52c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 8 Jan 2019 16:09:41 +0100 Subject: tls: add comment about dl.fedoraproject.org needing secp256r1 ECC curve Signed-off-by: Denys Vlasenko --- networking/tls.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/networking/tls.c b/networking/tls.c index b90f45e8b..db0034e66 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -1531,9 +1531,17 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) 0x00,0x04, //ext len 0x00,0x02, //list len 0x00,0x1d, //curve_x25519 (RFC 7748) + //0x00,0x1e, //curve_x448 (RFC 7748) //0x00,0x17, //curve_secp256r1 //0x00,0x18, //curve_secp384r1 //0x00,0x19, //curve_secp521r1 +//TODO: implement secp256r1 (at least): dl.fedoraproject.org immediately aborts +//if only x25519/x448 are advertised, seems to support only secpNNNr1 curves: +// openssl s_client -connect dl.fedoraproject.org:443 -debug -tls1_2 -cipher ECDHE-RSA-AES128-GCM-SHA256 +//Peer signing digest: SHA512 +//Peer signature type: RSA +//Server Temp Key: ECDH, P-256, 256 bits +//TLSv1.2, Cipher is ECDHE-RSA-AES128-GCM-SHA256 }; //static const uint8_t signature_algorithms[] = { // 000d -- cgit v1.2.3-55-g6feb From ce51140664d82300d25b096b4a41f01fdfd766b3 Mon Sep 17 00:00:00 2001 From: Einar Jón Date: Tue, 8 Jan 2019 16:31:37 +0100 Subject: passwd: initialize pointers correctly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix for running passwd as root (or sudo passwd $USER). Crashed on call to free(orig) during cleanup. Fix regression from commit 17058a06c4333fc0c492c168c8a971ebd0fd5a5a Root user never changes the orig pointer, so when cleaning up, passwd tried to free orig=(char*)"" Example: sudo passwd $USER Changing password for xxx New password: Bad password: too short Retype password: Passwords don't match free(): invalid pointer Aborted function old new delta passwd_main 958 961 +3 Signed-off-by: Einar Jón Signed-off-by: Denys Vlasenko --- loginutils/passwd.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/loginutils/passwd.c b/loginutils/passwd.c index 59f47fc7b..30e096460 100644 --- a/loginutils/passwd.c +++ b/loginutils/passwd.c @@ -43,7 +43,7 @@ static char* new_password(const struct passwd *pw, uid_t myuid, const char *algo) { char salt[MAX_PW_SALT_LEN]; - char *orig = (char*)""; + char *orig = NULL; char *newp = NULL; char *cp = NULL; char *ret = NULL; /* failure so far */ @@ -51,7 +51,7 @@ static char* new_password(const struct passwd *pw, uid_t myuid, const char *algo if (myuid != 0 && pw->pw_passwd[0]) { char *encrypted; - orig = bb_ask_noecho_stdin("Old password: "); /* returns ptr to static */ + orig = bb_ask_noecho_stdin("Old password: "); /* returns malloced str */ if (!orig) goto err_ret; encrypted = pw_encrypt(orig, pw->pw_passwd, 1); /* returns malloced str */ @@ -64,11 +64,11 @@ static char* new_password(const struct passwd *pw, uid_t myuid, const char *algo if (ENABLE_FEATURE_CLEAN_UP) free(encrypted); } - newp = bb_ask_noecho_stdin("New password: "); /* returns ptr to static */ + newp = bb_ask_noecho_stdin("New password: "); /* returns malloced str */ if (!newp) goto err_ret; if (ENABLE_FEATURE_PASSWD_WEAK_CHECK - && obscure(orig, newp, pw) + && obscure(orig, newp, pw) /* NB: passing NULL orig is ok */ && myuid != 0 ) { goto err_ret; /* non-root is not allowed to have weak passwd */ -- cgit v1.2.3-55-g6feb From fc7aa7a296cf13d13aae5457f4f7cd2b73700234 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 8 Jan 2019 18:08:48 +0100 Subject: bc: disallow invalid syntax like "{ print 1 print 2 }" statement parsing must NOT eat the terminator: caller needs to know what it was, to correctly decide whether it is a valid one. function old new delta zxc_program_read - 234 +234 zdc_program_printStream - 144 +144 zbc_parse_stmt_possibly_auto 1413 1460 +47 zxc_vm_process 869 859 -10 zxc_program_exec 4116 4101 -15 zdc_program_asciify 368 - -368 ------------------------------------------------------------------------------ (add/remove: 2/1 grow/shrink: 1/2 up/down: 425/-393) Total: 32 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index bf174dafb..faf6226e1 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -4554,11 +4554,11 @@ static BC_STATUS zbc_parse_stmt_possibly_auto(bool auto_allowed) if (p->lex == XC_LEX_NLINE) { dbg_lex_done("%s:%d done (seen XC_LEX_NLINE)", __func__, __LINE__); - RETURN_STATUS(zxc_lex_next()); + RETURN_STATUS(s); } if (p->lex == BC_LEX_SCOLON) { dbg_lex_done("%s:%d done (seen BC_LEX_SCOLON)", __func__, __LINE__); - RETURN_STATUS(zxc_lex_next()); + RETURN_STATUS(s); } if (p->lex == BC_LEX_LBRACE) { @@ -4574,9 +4574,19 @@ static BC_STATUS zbc_parse_stmt_possibly_auto(bool auto_allowed) } while (p->lex != BC_LEX_RBRACE) { dbg_lex("%s:%d block parsing loop", __func__, __LINE__); -//FIXME: prevent wrong syntax such as "{ print 1 print 2 }" s = zbc_parse_stmt(); if (s) RETURN_STATUS(s); + // Check that next token is a correct stmt delimiter - + // disallows "print 1 print 2" and such. + if (p->lex == BC_LEX_RBRACE) + break; + if (p->lex != BC_LEX_SCOLON + && p->lex != XC_LEX_NLINE + ) { + RETURN_STATUS(bc_error_at("bad statement terminator")); + } + s = zxc_lex_next(); + if (s) RETURN_STATUS(s); } s = zxc_lex_next(); dbg_lex_done("%s:%d done (seen BC_LEX_RBRACE)", __func__, __LINE__); @@ -4665,9 +4675,11 @@ static BC_STATUS zbc_parse_stmt_or_funcdef(void) BcStatus s; dbg_lex_enter("%s:%d entered", __func__, __LINE__); - if (p->lex == XC_LEX_EOF) - s = bc_error("end of file"); - else if (p->lex == BC_LEX_KEY_DEFINE) { +//why? +// if (p->lex == XC_LEX_EOF) +// s = bc_error("end of file"); +// else + if (p->lex == BC_LEX_KEY_DEFINE) { dbg_lex("%s:%d p->lex:BC_LEX_KEY_DEFINE", __func__, __LINE__); s = zbc_parse_funcdef(); } else { @@ -6781,7 +6793,6 @@ static BC_STATUS zxc_vm_process(const char *text) s = zxc_parse_text_init(text); // does the first zxc_lex_next() if (s) RETURN_STATUS(s); - IF_BC(check_eof:) while (G.prs.lex != XC_LEX_EOF) { BcInstPtr *ip; BcFunc *f; @@ -6789,14 +6800,6 @@ static BC_STATUS zxc_vm_process(const char *text) dbg_lex("%s:%d G.prs.lex:%d, parsing...", __func__, __LINE__, G.prs.lex); if (IS_BC) { #if ENABLE_BC - if (G.prs.lex == BC_LEX_SCOLON - || G.prs.lex == XC_LEX_NLINE - ) { - s = zxc_lex_next(); - if (s) goto err; - goto check_eof; - } - s = zbc_parse_stmt_or_funcdef(); if (s) goto err; @@ -6855,6 +6858,9 @@ static BC_STATUS zxc_vm_process(const char *text) #endif IF_BC(bc_vec_pop_all(&f->strs);) IF_BC(bc_vec_pop_all(&f->consts);) + // We are at SCOLON/NLINE, skip it: + s = zxc_lex_next(); + if (s) goto err; } else { if (G.prog.results.len == 0 && G.prog.vars.len == 0 -- cgit v1.2.3-55-g6feb From 132d7c098b1f74ae9b85fc47c15ce4f35c9dd86a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 8 Jan 2019 19:29:35 +0100 Subject: bc: zbc_parse_expr_empty_ok() is unused except by zbc_parse_expr(), fold it in function old new delta zbc_parse_expr 1865 1848 -17 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 61 ++++++++++++++++++++++++---------------------------------- 1 file changed, 25 insertions(+), 36 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index faf6226e1..cf0fdd6d8 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -203,7 +203,6 @@ static uint8_t lex_indent; typedef enum BcStatus { BC_STATUS_SUCCESS = 0, BC_STATUS_FAILURE = 1, - BC_STATUS_PARSE_EMPTY_EXP = 2, // bc_parse_expr_empty_ok() uses this } BcStatus; #define BC_VEC_INVALID_IDX ((size_t) -1) @@ -3715,17 +3714,7 @@ static size_t bc_program_addFunc(char *name) // first in the expr enum. Note: This only works for binary operators. #define BC_TOKEN_2_INST(t) ((char) ((t) - XC_LEX_OP_POWER + XC_INST_POWER)) -static BcStatus bc_parse_expr_empty_ok(uint8_t flags); - -static BC_STATUS zbc_parse_expr(uint8_t flags) -{ - BcStatus s; - - s = bc_parse_expr_empty_ok(flags); - if (s == BC_STATUS_PARSE_EMPTY_EXP) - RETURN_STATUS(bc_error("empty expression")); - RETURN_STATUS(s); -} +static BC_STATUS zbc_parse_expr(uint8_t flags); #define zbc_parse_expr(...) (zbc_parse_expr(__VA_ARGS__) COMMA_SUCCESS) static BC_STATUS zbc_parse_stmt_possibly_auto(bool auto_allowed); @@ -4692,8 +4681,8 @@ static BC_STATUS zbc_parse_stmt_or_funcdef(void) } #define zbc_parse_stmt_or_funcdef(...) (zbc_parse_stmt_or_funcdef(__VA_ARGS__) COMMA_SUCCESS) -// This is not a "z" function: can also return BC_STATUS_PARSE_EMPTY_EXP -static BcStatus bc_parse_expr_empty_ok(uint8_t flags) +#undef zbc_parse_expr +static BC_STATUS zbc_parse_expr(uint8_t flags) { BcParse *p = &G.prs; BcInst prev = XC_INST_PRINT; @@ -4722,7 +4711,7 @@ static BcStatus bc_parse_expr_empty_ok(uint8_t flags) case BC_LEX_OP_INC: case BC_LEX_OP_DEC: dbg_lex("%s:%d LEX_OP_INC/DEC", __func__, __LINE__); - if (incdec) return bc_error_bad_assignment(); + if (incdec) RETURN_STATUS(bc_error_bad_assignment()); s = zbc_parse_incdec(&prev, &nexprs, flags); incdec = true; rprn = bin_last = false; @@ -4748,7 +4737,7 @@ static BcStatus bc_parse_expr_empty_ok(uint8_t flags) && prev != XC_INST_SCALE && prev != XC_INST_IBASE && prev != XC_INST_OBASE && prev != BC_INST_LAST ) { - return bc_error_bad_assignment(); + RETURN_STATUS(bc_error_bad_assignment()); } // Fallthrough. case XC_LEX_OP_POWER: @@ -4768,9 +4757,9 @@ static BcStatus bc_parse_expr_empty_ok(uint8_t flags) dbg_lex("%s:%d LEX_OP_xyz", __func__, __LINE__); if (t == BC_LEX_OP_BOOL_NOT) { if (!bin_last && p->lex_last != BC_LEX_OP_BOOL_NOT) - return bc_error_bad_expression(); + RETURN_STATUS(bc_error_bad_expression()); } else if (prev == XC_INST_BOOL_NOT) { - return bc_error_bad_expression(); + RETURN_STATUS(bc_error_bad_expression()); } nrelops += (t >= XC_LEX_OP_REL_EQ && t <= XC_LEX_OP_REL_GT); @@ -4783,7 +4772,7 @@ static BcStatus bc_parse_expr_empty_ok(uint8_t flags) case BC_LEX_LPAREN: dbg_lex("%s:%d LEX_LPAREN", __func__, __LINE__); if (BC_PARSE_LEAF(prev, bin_last, rprn)) - return bc_error_bad_expression(); + RETURN_STATUS(bc_error_bad_expression()); bc_vec_push(&p->ops, &t); nparens++; get_token = true; @@ -4792,11 +4781,10 @@ static BcStatus bc_parse_expr_empty_ok(uint8_t flags) case BC_LEX_RPAREN: dbg_lex("%s:%d LEX_RPAREN", __func__, __LINE__); if (p->lex_last == BC_LEX_LPAREN) { - dbg_lex_done("%s:%d done (returning EMPTY_EXP)", __func__, __LINE__); - return BC_STATUS_PARSE_EMPTY_EXP; + RETURN_STATUS(bc_error("empty expression")); } if (bin_last || prev == XC_INST_BOOL_NOT) - return bc_error_bad_expression(); + RETURN_STATUS(bc_error_bad_expression()); if (nparens == 0) { goto exit_loop; } @@ -4809,7 +4797,7 @@ static BcStatus bc_parse_expr_empty_ok(uint8_t flags) case XC_LEX_NAME: dbg_lex("%s:%d LEX_NAME", __func__, __LINE__); if (BC_PARSE_LEAF(prev, bin_last, rprn)) - return bc_error_bad_expression(); + RETURN_STATUS(bc_error_bad_expression()); s = zbc_parse_name(&prev, flags & ~BC_PARSE_NOCALL); rprn = (prev == BC_INST_CALL); bin_last = false; @@ -4819,7 +4807,7 @@ static BcStatus bc_parse_expr_empty_ok(uint8_t flags) case XC_LEX_NUMBER: dbg_lex("%s:%d LEX_NUMBER", __func__, __LINE__); if (BC_PARSE_LEAF(prev, bin_last, rprn)) - return bc_error_bad_expression(); + RETURN_STATUS(bc_error_bad_expression()); xc_parse_pushNUM(); prev = XC_INST_NUM; get_token = true; @@ -4831,7 +4819,7 @@ static BcStatus bc_parse_expr_empty_ok(uint8_t flags) case BC_LEX_KEY_OBASE: dbg_lex("%s:%d LEX_IBASE/LAST/OBASE", __func__, __LINE__); if (BC_PARSE_LEAF(prev, bin_last, rprn)) - return bc_error_bad_expression(); + RETURN_STATUS(bc_error_bad_expression()); prev = (char) (t - BC_LEX_KEY_IBASE + XC_INST_IBASE); xc_parse_push((char) prev); get_token = true; @@ -4842,7 +4830,7 @@ static BcStatus bc_parse_expr_empty_ok(uint8_t flags) case BC_LEX_KEY_SQRT: dbg_lex("%s:%d LEX_LEN/SQRT", __func__, __LINE__); if (BC_PARSE_LEAF(prev, bin_last, rprn)) - return bc_error_bad_expression(); + RETURN_STATUS(bc_error_bad_expression()); s = zbc_parse_builtin(t, flags, &prev); get_token = true; rprn = bin_last = incdec = false; @@ -4851,7 +4839,7 @@ static BcStatus bc_parse_expr_empty_ok(uint8_t flags) case BC_LEX_KEY_READ: dbg_lex("%s:%d LEX_READ", __func__, __LINE__); if (BC_PARSE_LEAF(prev, bin_last, rprn)) - return bc_error_bad_expression(); + RETURN_STATUS(bc_error_bad_expression()); s = zbc_parse_read(); prev = XC_INST_READ; get_token = true; @@ -4861,21 +4849,21 @@ static BcStatus bc_parse_expr_empty_ok(uint8_t flags) case BC_LEX_KEY_SCALE: dbg_lex("%s:%d LEX_SCALE", __func__, __LINE__); if (BC_PARSE_LEAF(prev, bin_last, rprn)) - return bc_error_bad_expression(); + RETURN_STATUS(bc_error_bad_expression()); s = zbc_parse_scale(&prev, flags); //get_token = false; - already is rprn = bin_last = false; nexprs++; break; default: - return bc_error_bad_token(); + RETURN_STATUS(bc_error_bad_token()); } if (s || G_interrupt) // error, or ^C: stop parsing - return BC_STATUS_FAILURE; + RETURN_STATUS(BC_STATUS_FAILURE); if (get_token) { s = zxc_lex_next(); - if (s) return s; + if (s) RETURN_STATUS(s); } } exit_loop: @@ -4885,7 +4873,7 @@ static BcStatus bc_parse_expr_empty_ok(uint8_t flags) assign = (top >= BC_LEX_OP_ASSIGN_POWER && top <= BC_LEX_OP_ASSIGN); if (top == BC_LEX_LPAREN || top == BC_LEX_RPAREN) - return bc_error_bad_expression(); + RETURN_STATUS(bc_error_bad_expression()); xc_parse_push(BC_TOKEN_2_INST(top)); @@ -4894,16 +4882,16 @@ static BcStatus bc_parse_expr_empty_ok(uint8_t flags) } if (prev == XC_INST_BOOL_NOT || nexprs != 1) - return bc_error_bad_expression(); + RETURN_STATUS(bc_error_bad_expression()); if (!(flags & BC_PARSE_REL) && nrelops) { BcStatus s; s = zbc_POSIX_does_not_allow("comparison operators outside if or loops"); - if (s) return s; + if (s) RETURN_STATUS(s); } else if ((flags & BC_PARSE_REL) && nrelops > 1) { BcStatus s; s = zbc_POSIX_requires("exactly one comparison operator per condition"); - if (s) return s; + if (s) RETURN_STATUS(s); } if (flags & BC_PARSE_PRINT) { @@ -4913,8 +4901,9 @@ static BcStatus bc_parse_expr_empty_ok(uint8_t flags) } dbg_lex_done("%s:%d done", __func__, __LINE__); - return BC_STATUS_SUCCESS; + RETURN_STATUS(BC_STATUS_SUCCESS); } +#define zbc_parse_expr(...) (zbc_parse_expr(__VA_ARGS__) COMMA_SUCCESS) #endif // ENABLE_BC -- cgit v1.2.3-55-g6feb From a1698a15dc93e429732d513ecfa3f1be723b51c5 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 8 Jan 2019 19:32:38 +0100 Subject: bc: remove "empty expression" check/message, parsing fails in these cases anyway function old new delta zbc_parse_expr 1848 1818 -30 Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index cf0fdd6d8..a34312851 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -4780,9 +4780,10 @@ static BC_STATUS zbc_parse_expr(uint8_t flags) break; case BC_LEX_RPAREN: dbg_lex("%s:%d LEX_RPAREN", __func__, __LINE__); - if (p->lex_last == BC_LEX_LPAREN) { - RETURN_STATUS(bc_error("empty expression")); - } +//why? +// if (p->lex_last == BC_LEX_LPAREN) { +// RETURN_STATUS(bc_error_at("empty expression")); +// } if (bin_last || prev == XC_INST_BOOL_NOT) RETURN_STATUS(bc_error_bad_expression()); if (nparens == 0) { -- cgit v1.2.3-55-g6feb From cfc2546ea4be9828acf936231386edc404cb502f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 9 Jan 2019 11:17:19 +0100 Subject: bc: code shrink function old new delta xc_parse_pushInst_and_Index - 16 +16 zbc_parse_expr 1818 1816 -2 xc_parse_pushIndex 65 61 -4 zbc_parse_pushSTR 63 58 -5 zbc_parse_name 448 442 -6 xc_parse_pushNUM 74 67 -7 zdc_parse_expr 479 470 -9 bc_parse_pushJUMP_ZERO 21 12 -9 bc_parse_pushJUMP 21 12 -9 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 0/8 up/down: 16/-51) Total: -35 bytes Signed-off-by: Denys Vlasenko --- miscutils/bc.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/miscutils/bc.c b/miscutils/bc.c index a34312851..7fecb264d 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -3497,11 +3497,11 @@ static BC_STATUS zdc_lex_token(void) #define zdc_lex_token(...) (zdc_lex_token(__VA_ARGS__) COMMA_SUCCESS) #endif // ENABLE_DC -static void xc_parse_push(char i) +static void xc_parse_push(unsigned i) { BcVec *code = &G.prs.func->code; dbg_compile("%s:%d pushing bytecode %zd:%d", __func__, __LINE__, code->len, i); - bc_vec_pushByte(code, i); + bc_vec_pushByte(code, (uint8_t)i); } static void xc_parse_pushName(char *name) @@ -3556,17 +3556,21 @@ static void xc_parse_pushIndex(size_t idx) } while (idx != 0); } +static void xc_parse_pushInst_and_Index(unsigned inst, size_t idx) +{ + xc_parse_push(inst); + xc_parse_pushIndex(idx); +} + #if ENABLE_BC static void bc_parse_pushJUMP(size_t idx) { - xc_parse_push(BC_INST_JUMP); - xc_parse_pushIndex(idx); + xc_parse_pushInst_and_Index(BC_INST_JUMP, idx); } static void bc_parse_pushJUMP_ZERO(size_t idx) { - xc_parse_push(BC_INST_JUMP_ZERO); - xc_parse_pushIndex(idx); + xc_parse_pushInst_and_Index(BC_INST_JUMP_ZERO, idx); } static BC_STATUS zbc_parse_pushSTR(void) @@ -3574,8 +3578,7 @@ static BC_STATUS zbc_parse_pushSTR(void) BcParse *p = &G.prs; char *str = xstrdup(p->lex_strnumbuf.v); - xc_parse_push(XC_INST_STR); - xc_parse_pushIndex(p->func->strs.len); + xc_parse_pushInst_and_Index(XC_INST_STR, p->func->strs.len); bc_vec_push(&p->func->strs, &str); RETURN_STATUS(zxc_lex_next()); @@ -3594,8 +3597,7 @@ static void xc_parse_pushNUM(void) #else // DC size_t idx = bc_vec_push(&G.prog.consts, &num); #endif - xc_parse_push(XC_INST_NUM); - xc_parse_pushIndex(idx); + xc_parse_pushInst_and_Index(XC_INST_NUM, idx); } static BC_STATUS zxc_parse_text_init(const char *text) @@ -3815,8 +3817,7 @@ static BC_STATUS zbc_parse_params(uint8_t flags) } } - xc_parse_push(BC_INST_CALL); - xc_parse_pushIndex(nparams); + xc_parse_pushInst_and_Index(BC_INST_CALL, nparams); RETURN_STATUS(BC_STATUS_SUCCESS); } @@ -4934,8 +4935,7 @@ static void dc_parse_string(void) dbg_lex_enter("%s:%d entered", __func__, __LINE__); str = xstrdup(p->lex_strnumbuf.v); - xc_parse_push(XC_INST_STR); - xc_parse_pushIndex(len); + xc_parse_pushInst_and_Index(XC_INST_STR, len); bc_vec_push(&G.prog.strs, &str); // Explanation needed here -- cgit v1.2.3-55-g6feb From ecf02e8b83056b2ac36d9e09c0a8c9bff8bfecd1 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 9 Jan 2019 12:58:52 +0100 Subject: date: improve help text for -D Signed-off-by: Denys Vlasenko --- coreutils/date.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/coreutils/date.c b/coreutils/date.c index 9cbc7302f..3414d38ae 100644 --- a/coreutils/date.c +++ b/coreutils/date.c @@ -54,7 +54,7 @@ //config: date -s (and other commands like touch -d) use more sensible //config: formats (for one, ISO format YYYY-MM-DD hh:mm:ss.ssssss). //config: -//config: With this option off, 'date DATE' is 'date -s DATE' support +//config: With this option off, 'date DATE' and 'date -s DATE' support //config: the same format. With it on, 'date DATE' additionally supports //config: MMDDhhmm[[YY]YY][.ss] format. @@ -121,7 +121,7 @@ //usage: "\n -d,--date TIME Display TIME, not 'now'" //usage: ) //usage: IF_FEATURE_DATE_ISOFMT( -//usage: "\n -D FMT Use FMT for -d TIME conversion" +//usage: "\n -D FMT Use FMT (strptime format) for -d TIME conversion" //usage: ) //usage: "\n" //usage: "\nRecognized TIME formats:" -- cgit v1.2.3-55-g6feb From 841912311252c861d34f5356cb32acc95f008b0f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 9 Jan 2019 13:12:58 +0100 Subject: telnet: placate compiler's warning Signed-off-by: Denys Vlasenko --- networking/telnet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/networking/telnet.c b/networking/telnet.c index 94c7512fc..fa1628723 100644 --- a/networking/telnet.c +++ b/networking/telnet.c @@ -248,7 +248,7 @@ static void handle_net_input(int len) { byte c; int i; - int cstart; + int cstart = cstart; /* for compiler */ i = 0; //bb_error_msg("[%u,'%.*s']", G.telstate, len, G.buf); -- cgit v1.2.3-55-g6feb From 6ca8e347fed8c24655df692f22694baf7c572770 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 9 Jan 2019 13:38:57 +0100 Subject: nslookup: return exitcode 1 on resolution errors function old new delta nslookup_main 757 760 +3 send_queries 1690 1677 -13 Signed-off-by: Denys Vlasenko --- networking/nslookup.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/networking/nslookup.c b/networking/nslookup.c index cd3c00003..24e09d4f0 100644 --- a/networking/nslookup.c +++ b/networking/nslookup.c @@ -257,7 +257,7 @@ int nslookup_main(int argc, char **argv) struct ns { const char *name; len_and_sockaddr *lsa; - int failures; + //UNUSED: int failures; int replies; }; @@ -320,6 +320,7 @@ struct globals { struct query *query; char *search; smalluint have_search_directive; + smalluint exitcode; } FIX_ALIASING; #define G (*(struct globals*)bb_common_bufsiz1) #define INIT_G() do { \ @@ -593,7 +594,7 @@ static int send_queries(struct ns *ns) /* Retry immediately on SERVFAIL */ if (rcode == 2) { - ns->failures++; + //UNUSED: ns->failures++; if (servfail_retry) { servfail_retry--; write(pfd.fd, G.query[qn].query, G.query[qn].qlen); @@ -612,9 +613,12 @@ static int send_queries(struct ns *ns) if (rcode != 0) { printf("** server can't find %s: %s\n", G.query[qn].name, rcodes[rcode]); + G.exitcode = EXIT_FAILURE; } else { - if (parse_reply(reply, recvlen) < 0) + if (parse_reply(reply, recvlen) < 0) { printf("*** Can't find %s: Parse error\n", G.query[qn].name); + G.exitcode = EXIT_FAILURE; + } } bb_putchar('\n'); n_replies++; @@ -988,7 +992,7 @@ int nslookup_main(int argc UNUSED_PARAM, char **argv) free(G.query); } - return EXIT_SUCCESS; + return G.exitcode; } #endif -- cgit v1.2.3-55-g6feb