Discussion:
[PATCH] bc Version 1.1
(too old to reply)
Gavin Howard
2018-11-03 17:17:09 UTC
Permalink
Hello,

After making changes to the bc for Denys' requests, I have a better
version of the bc.

This version, pasted at https://pastebin.com/0M9sMhtM and raw at
https://pastebin.com/raw/0M9sMhtM, has fulfilled every one of Denys'
requests except for a few.

First, I still did not use read_line_input. The reason for this is
because bc_read_line does some important error checking. I did,
however, #if guard signal handling and add a config for it. And I made
my signal handling function less buggy (in a single-threaded
environment).

I used getopt32 (and getopt32long behind a config option). I changed
CONFIG_foo to ENABLE_foo. I made everything but bc_main and dc_main
static. I called xmalloc_open_read_close in bc_read_file, but still
kept error handling.

I also tried to pull nested assignments out where I could, but there
were a few places where doing so introduced bugs. That said, all of
them are out (as far as I can tell), unless they could not be, so I
would not mess with them any further if I were you.

On that note, if you do mess with them, you want the full test suite
while reviewing this code, which you can get by cloning my repo at
https://github.com/gavinhoward/bc and then run the following commands:

$ $BC_ROOT/tests/all.sh bc $BUSYBOX_ROOT/busybox bc
$ $BC_ROOT/tests/all.sh dc $BUSYBOX_ROOT/busybox dc

If you also want to test the Linux kernel timeconst script, you can run:

$ $BC_ROOT/tests/bc/timeconst.sh ./path/to/timeconst.bc
$BUSYBOX_ROOT/busybox bc

I changed my code to call xmalloc and friends, which is actually what
allowed me to pull out assignments. The code ended up *much* smaller
than what I have already given to Landley for toybox, so I tried
pulling them out, and when I did, the code was *still* smaller. We'll
hope that is good enough for him. Also, because of clang-format, I was
able to change the braces in my release script, thus making it work
for both toybox and busybox.

With that said, after testing this thing as hard as I can, I am
supremely confident in it, and I believe that, barring any small bugs,
it is feature-complete and basically finished. Because of that, I am
willing to hand it completely over to busybox, if the maintainers so
desire, although I am willing to support it directly, as well as share
responsibility. I am good with whatever.

Thank you for your patience to this point.

Gavin Howard
Denys Vlasenko
2018-11-30 20:09:01 UTC
Permalink
Post by Gavin Howard
Hello,
After making changes to the bc for Denys' requests, I have a better
version of the bc.
This version, pasted at https://pastebin.com/0M9sMhtM and raw at
https://pastebin.com/raw/0M9sMhtM, has fulfilled every one of Denys'
requests except for a few.
First, I still did not use read_line_input. The reason for this is
because bc_read_line does some important error checking. I did,
however, #if guard signal handling and add a config for it. And I made
my signal handling function less buggy (in a single-threaded
environment).
I used getopt32 (and getopt32long behind a config option). I changed
CONFIG_foo to ENABLE_foo. I made everything but bc_main and dc_main
static. I called xmalloc_open_read_close in bc_read_file, but still
kept error handling.
I also tried to pull nested assignments out where I could, but there
were a few places where doing so introduced bugs. That said, all of
them are out (as far as I can tell), unless they could not be, so I
would not mess with them any further if I were you.
On that note, if you do mess with them, you want the full test suite
while reviewing this code, which you can get by cloning my repo at
$ $BC_ROOT/tests/all.sh bc $BUSYBOX_ROOT/busybox bc
$ $BC_ROOT/tests/all.sh dc $BUSYBOX_ROOT/busybox dc
$ $BC_ROOT/tests/bc/timeconst.sh ./path/to/timeconst.bc
$BUSYBOX_ROOT/busybox bc
I changed my code to call xmalloc and friends, which is actually what
allowed me to pull out assignments. The code ended up *much* smaller
than what I have already given to Landley for toybox, so I tried
pulling them out, and when I did, the code was *still* smaller. We'll
hope that is good enough for him. Also, because of clang-format, I was
able to change the braces in my release script, thus making it work
for both toybox and busybox.
With that said, after testing this thing as hard as I can, I am
supremely confident in it, and I believe that, barring any small bugs,
it is feature-complete and basically finished.
Sorry for the delay in reviewing.

Let's take a look at bc_vm_printf(). Basically:
bad = vfprintf(f, fmt, args) < 0;
if (bad) bc_vm_exit(BC_STATUS_IO_ERR);

What does bc_vm_exit() do? -
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);
}

This would enter infinite loop if you bc_vm_printf(stderr) and meet IO error.
Post by Gavin Howard
$ $BC_ROOT/tests/all.sh bc $BUSYBOX_ROOT/busybox bc
Trying.... does this output means tests failed or succeeded?? -

Running bc limits tests...


BC_BASE_MAX = 999
BC_DIM_MAX = 2147483647
BC_SCALE_MAX = 4294967295
BC_STRING_MAX = 4294967294
BC_NAME_MAX = 4294967294
BC_NUM_MAX = 4294967294
Max Exponent = 2147483647
Number of Vars = 4294967294


Running bc tests...

Running bc decimal...
Running bc add...
Running bc subtract...
Running bc multiply...
Running bc divide...
Running bc modulus...
Running bc power...
Running bc sqrt...
Running bc vars...
Running bc boolean...
Running bc strings...
Generating bc parse...
Generating bc parse results...
Running bc parse...
Generating bc print...
Generating bc print results...
Running bc print...
Running bc exponent...
Running bc log...
Running bc pi...
Running bc arctangent...
Running bc sine...
Running bc cosine...
Generating bc bessel...
Generating bc bessel results...
(standard_in) 1: syntax error
Running bc bessel...
Running bc arrays...
Running bc misc...
Running bc misc1...
Running bc misc2...
Running bc script: array.bc
Running bc script: atan.bc
Running bc script: bessel.bc
Running bc script: parse.bc
Running bc script: print.bc
Running bc script: screen.bc
Running errors...

Lex error: bad character
<stdin>:1


Lex error: bad character
<stdin>:1


Lex error: bad character
<stdin>:1


Lex error: bad character
<stdin>:1


Lex error: bad character
<stdin>:1


Lex error: bad character
<stdin>:1


Lex error: string end could not be found
<stdin>:1


Lex error: comment end could not be found
<stdin>:1


Lex error: bad character
<stdin>:1


Parse error: bad token
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: empty expression
<stdin>:1


Parse error: empty expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad assignment: left side must be scale, ibase, obase,
last, var, or array element
<stdin>:1


Parse error: bad assignment: left side must be scale, ibase, obase,
last, var, or array element
<stdin>:1


Parse error: bad assignment: left side must be scale, ibase, obase,
last, var, or array element
<stdin>:1


Parse error: bad assignment: left side must be scale, ibase, obase,
last, var, or array element
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad token
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad token
<stdin>:1


Parse error: bad token
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad token
<stdin>:1


Parse error: bad token
<stdin>:1


Parse error: bad token
<stdin>:1


Parse error: bad token
<stdin>:1


Parse error: bad token
<stdin>:1


Parse error: bad token
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad token
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad function definition
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad token
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Runtime error: variable is wrong type
<stdin>


Parse error: bad expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad token
<stdin>:1


Parse error: bad token
<stdin>:1


Parse error: bad token
<stdin>:1


Parse error: bad token
<stdin>:1


Parse error: bad token
<stdin>:1


Parse error: bad token
<stdin>:1


Parse error: bad token
<stdin>:1


Parse error: function parameter or auto var has the same name as another
<stdin>:1


Parse error: function parameter or auto var has the same name as another
<stdin>:1


Parse error: bad token
<stdin>:1


Parse error: bad function definition
<stdin>:1


Parse error: bad function definition
<stdin>:1


Parse error: bad function definition
<stdin>:1


Parse error: bad function definition
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad token
<stdin>:1


Parse error: bad token
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad token
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad assignment: left side must be scale, ibase, obase,
last, var, or array element
<stdin>:1


Parse error: bad assignment: left side must be scale, ibase, obase,
last, var, or array element
<stdin>:1


Parse error: bad assignment: left side must be scale, ibase, obase,
last, var, or array element
<stdin>:1


Parse error: bad assignment: left side must be scale, ibase, obase,
last, var, or array element
<stdin>:1


Parse error: bad assignment: left side must be scale, ibase, obase,
last, var, or array element
<stdin>:1


Parse error: bad assignment: left side must be scale, ibase, obase,
last, var, or array element
<stdin>:1


Parse error: bad assignment: left side must be scale, ibase, obase,
last, var, or array element
<stdin>:1


Parse error: bad token
<stdin>:1


Parse error: bad token
<stdin>:1


Math error: overflow
<stdin>


Runtime error: mismatched parameters
<stdin>


Runtime error: variable is wrong type
<stdin>


Runtime error: undefined function
<stdin>


Parse error: bad token
<stdin>:1


Math error: overflow
<stdin>


Math error: overflow
<stdin>


Math error: overflow
<stdin>


Lex error: bad character
<stdin>:1


Math error: negative number
<stdin>


Math error: negative number
<stdin>


Math error: divide by zero
<stdin>


Math error: divide by zero
<stdin>


Math error: divide by zero
<stdin>


Math error: divide by zero
<stdin>


Math error: divide by zero
<stdin>


Math error: divide by zero
<stdin>


Math error: overflow
<stdin>


Math error: overflow
<stdin>


Math error: overflow
<stdin>


Math error: overflow
<stdin>


Math error: overflow
<stdin>


Math error: divide by zero
<stdin>


Math error: non integer number
<stdin>


Parse error: bad expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Runtime error: variable is wrong type
<stdin>


Runtime error: variable is wrong type
<stdin>


Runtime error: variable is wrong type
<stdin>


Runtime error: variable is wrong type
<stdin>


Parse error: bad expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad token
<stdin>:1


Parse error: bad token
<stdin>:1


Parse error: bad token
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad expression
<stdin>:1


Parse error: bad print statement
<stdin>:1


Parse error: bad token
<stdin>:1


Parse error: bad token
<stdin>:1


Parse error: bad token
<stdin>:1


Parse error: bad function definition
<stdin>:1


Parse error: bad token
<stdin>:1


Parse error: bad token
<stdin>:1


Parse error: bad token
<stdin>:1


Parse error: bad token
<stdin>:1


Parse error: bad token
<stdin>:1


Math error: divide by zero
<stdin>


Math error: bad number string
<stdin>


Math error: bad number string
<stdin>


Math error: bad number string
<stdin>


Math error: bad number string
<stdin>


Math error: bad number string
<stdin>


Math error: bad number string
<stdin>


Math error: bad number string
<stdin>


Math error: bad number string
<stdin>


Math error: bad number string
<stdin>


Math error: bad number string
<stdin>


Math error: bad number string
<stdin>


Math error: bad number string
<stdin>


Math error: bad number string
<stdin>


Math error: bad number string
<stdin>


Math error: bad number string
<stdin>


Math error: bad number string
<stdin>


Math error: bad number string
<stdin>


Math error: bad number string
<stdin>


Math error: bad number string
<stdin>


Math error: bad number string
<stdin>


Math error: bad number string
<stdin>


Math error: bad number string
<stdin>


Math error: bad number string
<stdin>


Math error: bad number string
<stdin>


Math error: bad number string
<stdin>


Math error: bad number string
<stdin>


Math error: bad number string
<stdin>


Math error: bad number string
<stdin>


Lex error: bad character
<stdin>:1


Lex error: bad character
<stdin>:1


VM error: I/O error
<stdin>


POSIX warning: POSIX does not allow the following keyword:
last
<stdin>:1

Running posix_errors...

Vector error: POSIX only allows one character names; the following is bad:
aa = 0

<stdin>:1


POSIX error: POSIX does not allow '#' script comments
<stdin>:1


POSIX error: POSIX does not allow the following keyword:
continue
<stdin>:1


POSIX error: POSIX does not allow the following keyword:
last
<stdin>:1


POSIX error: POSIX does not allow the following keyword:
print
<stdin>:1


POSIX error: POSIX does not allow the following keyword:
halt
<stdin>:1


POSIX error: POSIX requires parentheses around return expressions
<stdin>:1


POSIX error: POSIX requires parentheses around return expressions
<stdin>:1


POSIX error: POSIX requires parentheses around return expressions
<stdin>:1


POSIX error: POSIX does not allow the following keyword:
limits
<stdin>:1


POSIX error: POSIX does not allow a period ('.') as a shortcut for the
last result
<stdin>:1


POSIX error: POSIX does not allow the following keyword:
else
<stdin>:1


POSIX error: POSIX does not allow comparison operators outside if or loops
<stdin>:1


POSIX error: POSIX does not allow boolean operators; the following is bad:
&&
<stdin>:1


POSIX error: POSIX does not allow boolean operators; the following is bad:
||
<stdin>:1


POSIX error: POSIX does not allow boolean operators; the following is bad:
!
<stdin>:1


POSIX error: POSIX does not allow an empty init expression in a for loop
<stdin>:1


POSIX error: POSIX does not allow an empty condition expression in a for loop
<stdin>:1


POSIX error: POSIX does not allow an empty update expression in a for loop
<stdin>:1


POSIX error: POSIX does not allow an empty condition expression in a for loop
<stdin>:1


POSIX error: POSIX does not allow an empty init expression in a for loop
<stdin>:1


POSIX error: POSIX does not allow an empty init expression in a for loop
<stdin>:1


POSIX error: POSIX does not allow an empty init expression in a for loop
<stdin>:1

Running error file tests/bc/errors/01.txt...

Parse error: bad assignment: left side must be scale, ibase, obase,
last, var, or array element
tests/bc/errors/01.txt:349

Running error file tests/bc/errors/01.txt through cat...
Running error file tests/bc/errors/02.txt...

VM error: file is not text:
tests/bc/errors/02.txt

Running error file tests/bc/errors/02.txt through cat...
Running error file tests/bc/errors/03.txt...

Parse error: bad expression
tests/bc/errors/03.txt:2

Running error file tests/bc/errors/03.txt through cat...
Running error file tests/bc/errors/04.txt...

Lex error: string end could not be found
tests/bc/errors/04.txt:1

Running error file tests/bc/errors/04.txt through cat...
Running error file tests/bc/errors/05.txt...

Lex error: comment end could not be found
tests/bc/errors/05.txt:1

Running error file tests/bc/errors/05.txt through cat...
Running error file tests/bc/errors/06.txt...

Parse error: bad token
<stdin>:2

Running error file tests/bc/errors/06.txt through cat...

Running quit test...
Denys Vlasenko
2018-11-30 20:38:29 UTC
Permalink
Post by Denys Vlasenko
Sorry for the delay in reviewing.
bad = vfprintf(f, fmt, args) < 0;
if (bad) bc_vm_exit(BC_STATUS_IO_ERR);
What does bc_vm_exit() do? -
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);
}
In fact, all calls of bc_vm_exit() are called with s == BC_STATUS_IO_ERR.

Thus, bc_errs[bc_err_ids[s]], bc_err_msgs[s] are constants.
Denys Vlasenko
2018-11-30 21:34:29 UTC
Permalink
Post by Gavin Howard
Hello,
After making changes to the bc for Denys' requests, I have a better
version of the bc.
This version, pasted at https://pastebin.com/0M9sMhtM and raw at
https://pastebin.com/raw/0M9sMhtM, has fulfilled every one of Denys'
requests except for a few.
static void bc_vm_info(const char *const help)
{
printf("%s "BB_VER"\n", applet_name);
fputs(bc_copyright, stdout);
if (help) printf(help, applet_name);
}

In all callsites, help is NULL.
Denys Vlasenko
2018-11-30 22:11:21 UTC
Permalink
Post by Gavin Howard
Hello,
After making changes to the bc for Denys' requests, I have a better
version of the bc.
This version, pasted at https://pastebin.com/0M9sMhtM and raw at
https://pastebin.com/raw/0M9sMhtM, has fulfilled every one of Denys'
requests except for a few.
return s == BC_STATUS_QUIT ? BC_STATUS_SUCCESS : s;

You can write it in more straightforward way:

if (s == BC_STATUS_QUIT)
s = BC_STATUS_SUCCESS;
return s;
Gavin Howard
2018-12-02 01:24:20 UTC
Permalink
I have an updated patch for the comments: https://pastebin.com/ZCvPitQ0

Raw is at: https://pastebin.com/raw/ZCvPitQ0
Post by Denys Vlasenko
Sorry for the delay in reviewing.
bad = vfprintf(f, fmt, args) < 0;
if (bad) bc_vm_exit(BC_STATUS_IO_ERR);
What does bc_vm_exit() do? -
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);
}
This would enter infinite loop if you bc_vm_printf(stderr) and meet
IO error.
Agreed. That line is hard to test. Sorry that I missed that obvious
mistake when adding xmalloc support. It has been fixed in the patch in
this email.
Post by Denys Vlasenko
Post by Gavin Howard
$ $BC_ROOT/tests/all.sh bc $BUSYBOX_ROOT/busybox bc
Trying.... does this output means tests failed or succeeded?? -
Succeeded. The important bit is what the return value ("$?") is. If it
returned 0, no errors. Non-zero: an error.

The reason for this is because the test suite also tests that the bc
will not crash when given invalid input. Obviously, error messages
will be printed in that case, but it means that the bc is working
well.
Post by Denys Vlasenko
In fact, all calls of bc_vm_exit() are called with
s == BC_STATUS_IO_ERR.
Thus, bc_errs[bc_err_ids[s]], bc_err_msgs[s] are constants.
Changed. Be aware that I still used the arrays because they are used
for other statuses, so it was better to keep the strings in the
arrays.

By the way, the original reason it was this way was because in order
to call xmalloc and friends, I had to implement versions for the
non-busybox bc, and they call bc_vm_exit as well, making the parameter
necessary in the standalone version of bc. However, I couldn't find
analogous busybox versions of bc_vm_printf and friends, so I had to
keep those in the busybox version. In the original patch, I just
didn't remove the parameters.
Post by Denys Vlasenko
static void bc_vm_info(const char *const help)
{
printf("%s "BB_VER"\n", applet_name);
fputs(bc_copyright, stdout);
if (help) printf(help, applet_name);
}
In all callsites, help is NULL.
Changed in the patch to your BB_VER print statement, and the help is removed.
Post by Denys Vlasenko
return s == BC_STATUS_QUIT ? BC_STATUS_SUCCESS : s;
if (s == BC_STATUS_QUIT)
s = BC_STATUS_SUCCESS;
return s;
I must admit that I disagree, but it is changed in the patch.

To make things easier on you for reviewing the changes in the patch,
which do include changes that I made myself in the time between my
last submission and now, I have added a patch below to show the
changes from the previous version. This patch is not valid; it's only
for your convenience.

Also, I have put the new output for all 3 make bloatcheck runs below the patch.

From 519962511fec6e1794a79cdab8b3a0a3529b11c0 Mon Sep 17 00:00:00 2001
From: Gavin Howard <***@gmail.com>
Date: Sat, 1 Dec 2018 18:08:28 -0700
Subject: [PATCH] Update patch

---
miscutils/bc.c | 113 ++++++++++++++++++++++++-------------------------
1 file changed, 55 insertions(+), 58 deletions(-)

diff --git a/miscutils/bc.c b/miscutils/bc.c
index 4969cd9cd..007d2cea5 100644
--- a/miscutils/bc.c
+++ b/miscutils/bc.c
@@ -7,7 +7,7 @@
* ** Do not edit unless you know what you are doing. **
*/
//config:config BC
-//config: bool "bc (45.73 kb; 49.84 kb when combined with dc)"
+//config: bool "bc (45.77 kb; 49.88 kb when combined with dc)"
//config: default n
//config: help
//config: bc is a command-line, arbitrary-precision calculator with a
@@ -58,7 +58,7 @@
//config: enabled.
//config:
//config:config DC
-//config: bool "dc (38.28 kb; 49.84 kb when combined with bc)"
+//config: bool "dc (38.32 kb; 49.88 kb when combined with bc)"
//config: default n
//config: help
//config: dc is a reverse-polish notation command-line calculator which
@@ -168,7 +168,7 @@

typedef enum BcStatus {

- BC_STATUS_SUCCESS,
+ BC_STATUS_SUCCESS = 0,

BC_STATUS_ALLOC_ERR,
BC_STATUS_IO_ERR,
@@ -234,11 +234,11 @@ typedef enum BcStatus {
BC_STATUS_POSIX_BRACE,
#endif // ENABLE_BC

+ BC_STATUS_INVALID_OPTION,
+
BC_STATUS_QUIT,
BC_STATUS_LIMITS,

- BC_STATUS_INVALID_OPTION,
-
} BcStatus;

#define BC_ERR_IDX_VM (0)
@@ -697,7 +697,7 @@ typedef struct BcParse {

#ifdef ENABLE_BC

-BcStatus bc_main(int argc, char *argv[]);
+int bc_main(int argc, char *argv[]);

typedef struct BcLexKeyword {
const char name[9];
@@ -731,7 +731,7 @@ 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[]);
+int dc_main(int argc, char *argv[]);

static BcStatus dc_lex_token(BcLex *l);

@@ -849,11 +849,11 @@ typedef struct BcGlobals {
unsigned long sigc;
unsigned long signe;

- long tty;
+ long i;
long ttyin;
- long posix;
- long warn;
- long exreg;
+ long s;
+ long w;
+ long x;

const char *name;
#if ENABLE_FEATURE_BC_SIGNALS
@@ -869,13 +869,13 @@ 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_exit(void);
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);

@@ -935,7 +935,6 @@ static const uint8_t bc_err_ids[] = {
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,
@@ -1013,6 +1012,8 @@ static const char *bc_err_msgs[] = {
"POSIX requires the left brace be on the same line as the function header",
#endif // ENABLE_BC

+ "Bad command-line option",
+
};

static const char bc_func_main[] = "(main)";
@@ -1396,7 +1397,7 @@ static BcStatus bc_read_line(BcVec *vec, const
char *prompt)
int i;
signed char c = 0;

- if (bcg.ttyin && !bcg.posix) {
+ if (bcg.ttyin && !bcg.s) {
bc_vm_puts(prompt, stderr);
bc_vm_fflush(stderr);
}
@@ -1417,7 +1418,7 @@ static BcStatus bc_read_line(BcVec *vec, const
char *prompt)

if (bcg.ttyin) {
bc_vm_puts(bc_program_ready_msg, stderr);
- if (!bcg.posix) bc_vm_puts(prompt, stderr);
+ if (!bcg.s) bc_vm_puts(prompt, stderr);
bc_vm_fflush(stderr);
}

@@ -1483,8 +1484,8 @@ static BcStatus bc_args(int argc, char *argv[],
uint32_t *flags, BcVec *files)
*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 ((*flags) & BC_FLAG_V) bc_vm_info();
+ if (do_exit) exit((int) BC_STATUS_IO_ERR);
if (argv[optind] && !strcmp(argv[optind], "--")) ++optind;

for (i = optind; i < argc; ++i) bc_vec_push(files, argv + i);
@@ -3504,7 +3505,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 (!bcg.x)
s = BC_STATUS_LEX_EXTENDED_REG;
else
s = bc_lex_name(l);
@@ -4092,15 +4093,11 @@ static BcStatus bc_parse_minus(BcParse *p,
BcInst *prev, size_t ops_bgn,
{
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;
+ type = BC_PARSE_LEAF(*prev, rparen) ? 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
@@ -4846,6 +4843,7 @@ static BcStatus bc_parse_expr(BcParse *p,
uint8_t flags, BcParseNext next)
bin_last = true;

for (; !bcg.signe && !s && !done && bc_parse_exprs[t]; t = p->l.t.t) {
+
switch (t) {

case BC_LEX_OP_INC:
@@ -6689,7 +6687,7 @@ 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 && bcg.signe && !bcg.i) return BC_STATUS_QUIT;

bcg.sigc += bcg.signe;
bcg.signe = bcg.sig != bcg.sigc;
@@ -7040,11 +7038,10 @@ static void bc_vm_sig(int sig)
}
#endif // ENABLE_FEATURE_BC_SIGNALS

-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");
+ printf("%s " BB_VER "\n", applet_name);
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)
@@ -7062,7 +7059,7 @@ 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) bcg.posix, w = (int) bcg.warn;
+ int p = (int) bcg.s, w = (int) bcg.w;
const char *const fmt = p ? bc_err_fmt : bc_warn_fmt;

if (!(p || w) || s < BC_STATUS_POSIX_NAME_LEN) return BC_STATUS_SUCCESS;
@@ -7128,10 +7125,11 @@ static size_t bc_vm_envLen(const char *var)
return len;
}

-static void bc_vm_exit(BcStatus s)
+static void bc_vm_exit(void)
{
- bc_vm_printf(stderr, bc_err_fmt, bc_errs[bc_err_ids[s]], bc_err_msgs[s]);
- exit((int) s);
+ fprintf(stderr, bc_err_fmt, bc_errs[bc_err_ids[BC_STATUS_IO_ERR]],
+ bc_err_msgs[BC_STATUS_IO_ERR]);
+ exit((int) BC_STATUS_IO_ERR);
}

static void bc_vm_printf(FILE *restrict f, const char *fmt, ...)
@@ -7143,22 +7141,22 @@ static void bc_vm_printf(FILE *restrict f,
const char *fmt, ...)
bad = vfprintf(f, fmt, args) < 0;
va_end(args);

- if (bad) bc_vm_exit(BC_STATUS_IO_ERR);
+ if (bad) bc_vm_exit();
}

static void bc_vm_puts(const char *str, FILE *restrict f)
{
- if (fputs(str, f) == EOF) bc_vm_exit(BC_STATUS_IO_ERR);
+ if (fputs(str, f) == EOF) bc_vm_exit();
}

static void bc_vm_putchar(int c)
{
- if (putchar(c) == EOF) bc_vm_exit(BC_STATUS_IO_ERR);
+ if (putchar(c) == EOF) bc_vm_exit();
}

static void bc_vm_fflush(FILE *restrict f)
{
- if (fflush(f) == EOF) bc_vm_exit(BC_STATUS_IO_ERR);
+ if (fflush(f) == EOF) bc_vm_exit();
}

static BcStatus bc_vm_process(BcVm *vm, const char *text)
@@ -7196,7 +7194,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.i) 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);
}
@@ -7342,7 +7340,9 @@ static BcStatus bc_vm_exec(BcVm *vm)
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;
+ if (s == BC_STATUS_QUIT) s = BC_STATUS_SUCCESS;
+
+ return s;
}

static void bc_vm_free(BcVm *vm)
@@ -7357,20 +7357,9 @@ 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);

@@ -7390,6 +7379,14 @@ static BcStatus bc_vm_run(int argc, char
*argv[], BcVmExe exe,
{
BcStatus st;
BcVm vm;
+#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

st = bc_vm_init(&vm, exe, env_len);
if (st) goto exit;
@@ -7397,17 +7394,17 @@ static BcStatus bc_vm_run(int argc, char
*argv[], BcVmExe exe,
if (st) goto exit;

bcg.ttyin = isatty(0);
- bcg.tty = bcg.ttyin || (vm.flags & BC_FLAG_I) || isatty(1);
+ bcg.i = 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;
+ bcg.s = vm.flags & BC_FLAG_S;
+ bcg.w = vm.flags & BC_FLAG_W;
#endif // ENABLE_BC
#ifdef ENABLE_DC
- bcg.exreg = vm.flags & BC_FLAG_X;
+ bcg.x = vm.flags & BC_FLAG_X;
#endif // ENABLE_DC

- 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:
@@ -7416,7 +7413,7 @@ exit:
}

#ifdef ENABLE_BC
-BcStatus bc_main(int argc, char *argv[])
+int bc_main(int argc, char *argv[])
{
BcVmExe exec;

@@ -7430,12 +7427,12 @@ BcStatus bc_main(int argc, char *argv[])
exec.exp = bc_parse_expression;
exec.sbgn = exec.send = '"';

- return bc_vm_run(argc, argv, exec, "BC_LINE_LENGTH");
+ return (int) bc_vm_run(argc, argv, exec, "BC_LINE_LENGTH");
}
#endif // ENABLE_BC

#ifdef ENABLE_DC
-BcStatus dc_main(int argc, char *argv[])
+int dc_main(int argc, char *argv[])
{
BcVmExe exec;

@@ -7450,6 +7447,6 @@ BcStatus dc_main(int argc, char *argv[])
exec.sbgn = '[';
exec.send = ']';

- return bc_vm_run(argc, argv, exec, "DC_LINE_LENGTH");
+ return (int) bc_vm_run(argc, argv, exec, "DC_LINE_LENGTH");
}
#endif // ENABLE_DC
--
2.17.1

bc make bloatcheck

function old new delta
bc_program_exec - 7098 +7098
.rodata 151040 156876 +5836
bc_vm_run - 2807 +2807
bc_parse_expr - 2464 +2464
bc_parse_stmt - 2370 +2370
bc_lib - 1878 +1878
bc_lex_token - 1430 +1430
bc_program_num - 1363 +1363
bc_num_k - 1144 +1144
bc_program_print - 968 +968
bc_parse_name - 714 +714
bc_num_d - 703 +703
bc_num_p - 687 +687
bc_num_printNum - 675 +675
bc_program_assign - 537 +537
bc_parse_endBody - 532 +532
bc_parse_parse - 479 +479
bc_program_copyToVar - 449 +449
bc_vm_process - 446 +446
bc_err_msgs - 440 +440
bc_lex_number - 406 +406
bc_num_a - 377 +377
bc_num_m - 361 +361
bc_program_binOpPrep - 357 +357
bc_parse_auto - 311 +311
bc_num_r - 310 +310
bc_program_addFunc - 304 +304
bc_program_pushVar - 296 +296
bc_num_cmp - 295 +295
bc_num_s - 283 +283
bc_parse_operator - 266 +266
bc_parse_create - 254 +254
bc_vm_posixError - 241 +241
bc_parse_reset - 241 +241
bc_num_divmod - 237 +237
bc_program_search - 224 +224
bc_read_line - 221 +221
bc_lex_kws - 220 +220
bc_parse_else - 217 +217
bc_program_reset - 210 +210
bc_num_binary - 206 +206
bc_vm_printf - 194 +194
bc_program_assignStr - 192 +192
bc_vm_error - 187 +187
bc_num_rem - 180 +180
bc_map_insert - 176 +176
bc_parse_string - 172 +172
bc_num_printDigits - 172 +172
bc_parse_text - 162 +162
bc_parse_number - 161 +161
bc_copyright - 155 +155
bc_args - 153 +153
bc_func_insert - 149 +149
bc_array_expand - 147 +147
static.bc_parse_pushName - 139 +139
static.bc_parse_pushIndex - 139 +139
bc_vec_concat - 129 +129
bc_parse_body - 129 +129
bc_num_split - 128 +128
bc_vec_string - 117 +117
bc_lex_name - 114 +114
bc_program_prep - 113 +113
bc_num_ulong2num - 112 +112
bc_program_name - 96 +96
bc_num_printHex - 95 +95
bc_num_ulong - 89 +89
bcg - 88 +88
bc_map_find - 88 +88
bc_num_shift - 85 +85
bc_num_sub - 78 +78
bc_parse_noElse - 77 +77
bc_main - 77 +77
bc_num_add - 75 +75
bc_num_compare - 74 +74
bc_map_index - 74 +74
bc_lex_next - 74 +74
bc_num_extend - 70 +70
bc_num_retireMul - 69 +69
bc_vec_push - 66 +66
bc_vec_npop - 65 +65
bc_num_copy - 65 +65
bc_num_subArrays - 64 +64
bc_program_binOpRetire - 62 +62
bc_parse_exprs - 60 +60
bc_vec_grow - 59 +59
bc_parse_free - 59 +59
bc_err_ids - 57 +57
bc_errs - 56 +56
bc_program_index - 55 +55
bc_vm_exit - 54 +54
bc_parse_startBody - 54 +54
bc_parse_addFunc - 54 +54
bc_num_mul - 52 +52
bc_num_mod - 52 +52
bc_num_div - 52 +52
bc_num_init - 51 +51
bc_lex_whitespace - 51 +51
bc_vm_info - 50 +50
bc_parse_ops - 50 +50
bc_num_expand - 50 +50
bc_array_init - 50 +50
bc_num_clean - 49 +49
bc_program_ops - 48 +48
bc_vec_expand - 46 +46
bc_result_free - 46 +46
bc_vec_init - 45 +45
bc_program_retire - 45 +45
packed_usage 32757 32799 +42
bc_num_printNewline - 42 +42
bc_lex_lineComment - 42 +42
bc_program_len - 41 +41
bc_parse_expression - 39 +39
bc_num_truncate - 37 +37
bc_num_printChar - 28 +28
bc_lex_assign - 28 +28
bc_func_free - 28 +28
bc_num_one - 27 +27
bc_num_pow - 24 +24
bc_vec_free - 22 +22
bc_program_ready_msg - 22 +22
bc_num_zero - 21 +21
bc_vm_puts - 20 +20
bc_vm_putchar - 20 +20
bc_vm_fflush - 20 +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_vec_item_rev - 19 +19
bc_parse_init - 19 +19
bc_warn_fmt - 17 +17
bc_num_hex_digits - 17 +17
bc_err_fmt - 15 +15
bc_string_free - 8 +8
bc_program_stdin_name - 8 +8
bc_num_free - 8 +8
bc_id_free - 8 +8
bc_args_opt - 8 +8
bc_args_env_name - 8 +8
applet_main 3120 3128 +8
bc_func_read - 7 +7
bc_func_main - 7 +7
bc_err_line - 7 +7
bc_program_scale - 5 +5
bc_name - 3 +3
applet_names 2692 2695 +3
applet_install_loc 195 196 +1
------------------------------------------------------------------------------
(add/remove: 146/0 grow/shrink: 5/0 up/down: 45772/0) Total: 45772 bytes
text data bss dec hex filename
973460 17559 1888 992907 f268b busybox_old
1017523 18143 1984 1037650 fd552 busybox_unstripped

dc make bloatcheck

function old new delta
bc_program_exec - 7098 +7098
.rodata 151040 156738 +5698
bc_vm_run - 2807 +2807
bc_lib - 1878 +1878
bc_program_num - 1363 +1363
bc_num_k - 1144 +1144
bc_program_print - 968 +968
dc_parse_expr - 930 +930
dc_lex_token - 816 +816
bc_num_d - 703 +703
bc_num_p - 687 +687
bc_num_printNum - 675 +675
bc_program_assign - 537 +537
bc_program_copyToVar - 449 +449
bc_vm_process - 446 +446
bc_err_msgs - 440 +440
bc_lex_number - 406 +406
bc_num_a - 377 +377
dc_lex_tokens - 364 +364
bc_num_m - 361 +361
bc_program_binOpPrep - 357 +357
dc_parse_insts - 332 +332
bc_num_r - 310 +310
bc_program_addFunc - 304 +304
bc_program_pushVar - 296 +296
bc_num_cmp - 295 +295
bc_num_s - 283 +283
bc_parse_create - 254 +254
bc_parse_reset - 241 +241
bc_num_divmod - 237 +237
bc_program_search - 224 +224
bc_read_line - 221 +221
bc_program_reset - 210 +210
bc_num_binary - 206 +206
bc_vm_printf - 194 +194
bc_program_assignStr - 192 +192
bc_vm_error - 187 +187
dc_parse_mem - 185 +185
bc_num_rem - 180 +180
bc_map_insert - 176 +176
bc_num_printDigits - 172 +172
packed_usage 32757 32923 +166
bc_parse_text - 162 +162
bc_parse_number - 161 +161
bc_copyright - 155 +155
bc_args - 153 +153
bc_array_expand - 147 +147
static.bc_parse_pushName - 139 +139
static.bc_parse_pushIndex - 139 +139
bc_vec_concat - 129 +129
bc_num_split - 128 +128
bc_vec_string - 117 +117
bc_lex_name - 114 +114
bc_program_prep - 113 +113
bc_num_ulong2num - 112 +112
bc_program_name - 96 +96
bc_num_printHex - 95 +95
bc_num_ulong - 89 +89
bcg - 88 +88
bc_map_find - 88 +88
bc_num_shift - 85 +85
bc_num_sub - 78 +78
dc_main - 77 +77
bc_num_add - 75 +75
bc_num_compare - 74 +74
bc_lex_next - 74 +74
bc_num_extend - 70 +70
bc_num_retireMul - 69 +69
dc_parse_register - 67 +67
bc_vec_push - 66 +66
bc_vec_npop - 65 +65
bc_num_copy - 65 +65
bc_num_subArrays - 64 +64
bc_program_binOpRetire - 62 +62
bc_vec_grow - 59 +59
bc_parse_free - 59 +59
bc_err_ids - 57 +57
bc_errs - 56 +56
bc_program_index - 55 +55
bc_vm_exit - 54 +54
bc_parse_addFunc - 54 +54
dc_parse_parse - 53 +53
dc_lex_regs - 52 +52
bc_num_mul - 52 +52
bc_num_mod - 52 +52
bc_num_div - 52 +52
bc_num_init - 51 +51
bc_lex_whitespace - 51 +51
bc_vm_info - 50 +50
bc_num_expand - 50 +50
bc_array_init - 50 +50
bc_num_clean - 49 +49
bc_program_ops - 48 +48
bc_vec_expand - 46 +46
bc_result_free - 46 +46
bc_vec_init - 45 +45
bc_program_retire - 45 +45
bc_num_printNewline - 42 +42
bc_lex_lineComment - 42 +42
bc_program_len - 41 +41
bc_num_truncate - 37 +37
bc_num_printChar - 28 +28
bc_func_free - 28 +28
bc_num_one - 27 +27
bc_num_pow - 24 +24
bc_vec_free - 22 +22
bc_program_ready_msg - 22 +22
bc_num_zero - 21 +21
bc_vm_puts - 20 +20
bc_vm_putchar - 20 +20
bc_vm_fflush - 20 +20
dc_parse_init - 19 +19
bc_vec_item_rev - 19 +19
bc_num_hex_digits - 17 +17
bc_err_fmt - 15 +15
bc_string_free - 8 +8
bc_program_stdin_name - 8 +8
bc_num_free - 8 +8
bc_id_free - 8 +8
bc_args_opt - 8 +8
bc_args_env_name - 8 +8
applet_main 3120 3128 +8
bc_func_read - 7 +7
bc_func_main - 7 +7
bc_err_line - 7 +7
bc_program_scale - 5 +5
dc_name - 3 +3
applet_names 2692 2695 +3
applet_install_loc 195 196 +1
------------------------------------------------------------------------------
(add/remove: 125/0 grow/shrink: 5/0 up/down: 38324/0) Total: 38324 bytes
text data bss dec hex filename
973460 17559 1888 992907 f268b busybox_old
1009690 18143 1984 1029817 fb6b9 busybox_unstripped

both make bloatcheck

function old new delta
bc_program_exec - 7098 +7098
.rodata 151040 157890 +6850
bc_vm_run - 2807 +2807
bc_parse_expr - 2464 +2464
bc_parse_stmt - 2370 +2370
bc_lib - 1878 +1878
bc_lex_token - 1430 +1430
bc_program_num - 1363 +1363
bc_num_k - 1144 +1144
bc_program_print - 968 +968
dc_parse_expr - 930 +930
dc_lex_token - 816 +816
bc_parse_name - 714 +714
bc_num_d - 703 +703
bc_num_p - 687 +687
bc_num_printNum - 675 +675
bc_program_assign - 537 +537
bc_parse_endBody - 532 +532
bc_parse_parse - 479 +479
bc_program_copyToVar - 449 +449
bc_vm_process - 446 +446
bc_err_msgs - 440 +440
bc_lex_number - 406 +406
bc_num_a - 377 +377
dc_lex_tokens - 364 +364
bc_num_m - 361 +361
bc_program_binOpPrep - 357 +357
dc_parse_insts - 332 +332
bc_parse_auto - 311 +311
bc_num_r - 310 +310
bc_program_addFunc - 304 +304
bc_program_pushVar - 296 +296
bc_num_cmp - 295 +295
bc_num_s - 283 +283
bc_parse_operator - 266 +266
bc_parse_create - 254 +254
bc_vm_posixError - 241 +241
bc_parse_reset - 241 +241
bc_num_divmod - 237 +237
packed_usage 32757 32986 +229
bc_program_search - 224 +224
bc_read_line - 221 +221
bc_lex_kws - 220 +220
bc_parse_else - 217 +217
bc_program_reset - 210 +210
bc_num_binary - 206 +206
bc_vm_printf - 194 +194
bc_program_assignStr - 192 +192
bc_vm_error - 187 +187
dc_parse_mem - 185 +185
bc_num_rem - 180 +180
bc_map_insert - 176 +176
bc_parse_string - 172 +172
bc_num_printDigits - 172 +172
bc_parse_text - 162 +162
bc_parse_number - 161 +161
bc_copyright - 155 +155
bc_args - 153 +153
bc_func_insert - 149 +149
bc_array_expand - 147 +147
static.bc_parse_pushName - 139 +139
static.bc_parse_pushIndex - 139 +139
bc_vec_concat - 129 +129
bc_parse_body - 129 +129
bc_num_split - 128 +128
bc_vec_string - 117 +117
bc_lex_name - 114 +114
bc_program_prep - 113 +113
bc_num_ulong2num - 112 +112
bc_program_name - 96 +96
bc_num_printHex - 95 +95
bc_num_ulong - 89 +89
bcg - 88 +88
bc_map_find - 88 +88
bc_num_shift - 85 +85
bc_num_sub - 78 +78
dc_main - 77 +77
bc_parse_noElse - 77 +77
bc_main - 77 +77
bc_num_add - 75 +75
bc_num_compare - 74 +74
bc_map_index - 74 +74
bc_lex_next - 74 +74
bc_num_extend - 70 +70
bc_num_retireMul - 69 +69
dc_parse_register - 67 +67
bc_vec_push - 66 +66
bc_vec_npop - 65 +65
bc_num_copy - 65 +65
bc_num_subArrays - 64 +64
bc_program_binOpRetire - 62 +62
bc_parse_exprs - 60 +60
bc_vec_grow - 59 +59
bc_parse_free - 59 +59
bc_err_ids - 57 +57
bc_errs - 56 +56
bc_program_index - 55 +55
bc_vm_exit - 54 +54
bc_parse_startBody - 54 +54
bc_parse_addFunc - 54 +54
dc_parse_parse - 53 +53
dc_lex_regs - 52 +52
bc_num_mul - 52 +52
bc_num_mod - 52 +52
bc_num_div - 52 +52
bc_num_init - 51 +51
bc_lex_whitespace - 51 +51
bc_vm_info - 50 +50
bc_parse_ops - 50 +50
bc_num_expand - 50 +50
bc_array_init - 50 +50
bc_num_clean - 49 +49
bc_program_ops - 48 +48
bc_vec_expand - 46 +46
bc_result_free - 46 +46
bc_vec_init - 45 +45
bc_program_retire - 45 +45
bc_num_printNewline - 42 +42
bc_lex_lineComment - 42 +42
bc_program_len - 41 +41
bc_parse_expression - 39 +39
bc_num_truncate - 37 +37
bc_num_printChar - 28 +28
bc_lex_assign - 28 +28
bc_func_free - 28 +28
bc_num_one - 27 +27
bc_num_pow - 24 +24
bc_vec_free - 22 +22
bc_program_ready_msg - 22 +22
bc_num_zero - 21 +21
bc_vm_puts - 20 +20
bc_vm_putchar - 20 +20
bc_vm_fflush - 20 +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
dc_parse_init - 19 +19
bc_vec_item_rev - 19 +19
bc_parse_init - 19 +19
bc_warn_fmt - 17 +17
bc_num_hex_digits - 17 +17
applet_main 3120 3136 +16
bc_err_fmt - 15 +15
bc_string_free - 8 +8
bc_program_stdin_name - 8 +8
bc_num_free - 8 +8
bc_id_free - 8 +8
bc_args_opt - 8 +8
bc_args_env_name - 8 +8
bc_func_read - 7 +7
bc_func_main - 7 +7
bc_err_line - 7 +7
applet_names 2692 2698 +6
bc_program_scale - 5 +5
dc_name - 3 +3
bc_name - 3 +3
applet_install_loc 195 196 +1
Denys Vlasenko
2018-12-02 13:24:01 UTC
Permalink
Post by Gavin Howard
I have an updated patch for the comments: https://pastebin.com/ZCvPitQ0
Raw is at: https://pastebin.com/raw/ZCvPitQ0
Post by Denys Vlasenko
Sorry for the delay in reviewing.
bad = vfprintf(f, fmt, args) < 0;
if (bad) bc_vm_exit(BC_STATUS_IO_ERR);
What does bc_vm_exit() do? -
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);
}
This would enter infinite loop if you bc_vm_printf(stderr) and meet
IO error.
Agreed. That line is hard to test. Sorry that I missed that obvious
mistake when adding xmalloc support. It has been fixed in the patch in
this email.
Post by Denys Vlasenko
Post by Gavin Howard
$ $BC_ROOT/tests/all.sh bc $BUSYBOX_ROOT/busybox bc
Trying.... does this output means tests failed or succeeded?? -
Succeeded. The important bit is what the return value ("$?") is. If it
returned 0, no errors. Non-zero: an error.
The reason for this is because the test suite also tests that the bc
will not crash when given invalid input. Obviously, error messages
will be printed in that case, but it means that the bc is working
well.
Post by Denys Vlasenko
In fact, all calls of bc_vm_exit() are called with
s == BC_STATUS_IO_ERR.
Thus, bc_errs[bc_err_ids[s]], bc_err_msgs[s] are constants.
Changed. Be aware that I still used the arrays because they are used
for other statuses, so it was better to keep the strings in the
arrays.
By the way, the original reason it was this way was because in order
to call xmalloc and friends, I had to implement versions for the
non-busybox bc, and they call bc_vm_exit as well, making the parameter
necessary in the standalone version of bc. However, I couldn't find
analogous busybox versions of bc_vm_printf and friends, so I had to
keep those in the busybox version. In the original patch, I just
didn't remove the parameters.
Post by Denys Vlasenko
static void bc_vm_info(const char *const help)
{
printf("%s "BB_VER"\n", applet_name);
fputs(bc_copyright, stdout);
if (help) printf(help, applet_name);
}
In all callsites, help is NULL.
Changed in the patch to your BB_VER print statement, and the help is removed.
Post by Denys Vlasenko
return s == BC_STATUS_QUIT ? BC_STATUS_SUCCESS : s;
if (s == BC_STATUS_QUIT)
s = BC_STATUS_SUCCESS;
return s;
I must admit that I disagree, but it is changed in the patch.
To make things easier on you for reviewing the changes in the patch,
which do include changes that I made myself in the time between my
last submission and now, I have added a patch below to show the
changes from the previous version. This patch is not valid; it's only
for your convenience.
I'm currently working on the code you sent me. I'll
post my updated version (or push it to git) later.

It might be a good idea for you to wait for that to happen
before sending patches.

Current observations: bc_args() never fails, no need to return status.
Therefore, bc_vm_envArgs() never fails, no need to return status.
Therefore, bc_vm_init() never fails, no need to return status.
Therefore, in bc_vm_run() jumps to "exit:" never happen.
Denys Vlasenko
2018-12-02 13:18:17 UTC
Permalink
Post by Gavin Howard
Hello,
After making changes to the bc for Denys' requests, I have a better
version of the bc.
This version, pasted at https://pastebin.com/0M9sMhtM and raw at
https://pastebin.com/raw/0M9sMhtM, has fulfilled every one of Denys'
requests except for a few.
typedef int (*BcVecCmp)(const void *, const void *);

is unused
Denys Vlasenko
2018-12-03 17:49:29 UTC
Permalink
Post by Gavin Howard
Hello,
After making changes to the bc for Denys' requests, I have a better
version of the bc.
This version, pasted at https://pastebin.com/0M9sMhtM and raw at
https://pastebin.com/raw/0M9sMhtM, has fulfilled every one of Denys'
requests except for a few.
+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] == '/';
+ }


This is rather unreadable.
Denys Vlasenko
2018-12-03 18:02:39 UTC
Permalink
Post by Denys Vlasenko
Post by Gavin Howard
After making changes to the bc for Denys' requests, I have a better
version of the bc.
This version, pasted at https://pastebin.com/0M9sMhtM and raw at
https://pastebin.com/raw/0M9sMhtM, has fulfilled every one of Denys'
requests except for a few.
+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] == '/';
+ }
This is rather unreadable.
After untangling unreadable for() statements and 'end' variable,
this is what it actually does:

{
size_t i, nls = 0;
const char *buf = l->buf;

l->t.t = BC_LEX_WHITESPACE;
i = ++l->i;
for (;;) {
for (;;) {
char c = buf[i];
if (c == '*')
break;
if (c == '\0') {
l->i = i;
return BC_STATUS_LEX_NO_COMMENT_END;
}
nls += (c == '\n');
i++;
}
i++;
if (buf[i] == '\0') {
l->i = i - 1;
return BC_STATUS_LEX_NO_COMMENT_END;
}
if (buf[i] == '/')
break;
}

and now, since inner for() has only one break, I can put
'/' check directly there, eliminating one for() altogether:

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;
}
nls += (c == '\n');
i++;
}

Now l->i on error might be different (+1) but this is likely should be that way.
Continue reading on narkive:
Loading...