On Mon, Oct 29, 2018 at 4:46 PM Denys Vlasenko <vda.li...@googlemail.com> wrote: > > On Mon, Oct 29, 2018 at 4:55 PM Gavin Howard <gavin.d.how...@gmail.com> wrote: > > > > Hello, > > > > Because my patch is so large, I cannot get it through the mailing list > > filter. Therefore, I have pasted it on pastebin, instead. > > > > The link is https://pastebin.com/PJa2vaUR and the raw version can be > > found at https://pastebin.com/raw/PJa2vaUR > > Probably could send it bzipped.
I tried, unfortunately. Even though it was under the limit, the mailing list software rejected. > All functions except bc_main() should be static. > Check with nm --size-sort bc.o I will see what I can do about that. > Use <libbb.h>: the entire > > +BcStatus bc_read_file(const char *path, char **buf) { > + > + BcStatus s = BC_STATUS_IO_ERR; > + FILE *f; > + size_t size, read; > + long res; > + struct stat pstat; > + > + if (!(f = fopen(path, "r"))) return BC_STATUS_EXEC_FILE_ERR; > + > + if (fstat(fileno(f), &pstat) == -1) goto malloc_err; > + > + if (S_ISDIR(pstat.st_mode)) { > + s = BC_STATUS_PATH_IS_DIR; > + goto malloc_err; > + } > + > + if (fseek(f, 0, SEEK_END) == -1) goto malloc_err; > + if ((res = ftell(f)) < 0) goto malloc_err; > + if (fseek(f, 0, SEEK_SET) == -1) goto malloc_err; > + > + if (!(*buf = malloc((size = (size_t) res) + 1))) { > + s = BC_STATUS_ALLOC_ERR; > + goto malloc_err; > + } > + > + if ((read = fread(*buf, 1, size, f)) != size) goto read_err; > > can be replaced by single xmalloc_open_read_close()! Will do. > (The entire > +#include <ctype.h> > +#include <errno.h> > +#include <stdbool.h> > +#include <stddef.h> > +#include <stdint.h> > +#include <stdio.h> > +#include <stdlib.h> > +#include <string.h> > + > +#include <fcntl.h> > +#include <limits.h> > +#include <signal.h> > +#include <unistd.h> > +#include <sys/stat.h> > +#include <sys/types.h> > + > +#include <getopt.h> > should be replaced by > #include "libbb.h" > #include <if_you_need_anything_not_already_included_by_libbb.h> > ) Sorry about that. I tried to follow the documentation as exactly as I could. > + while ((c = getopt_long(argc, argv, bc_args_opt, bc_args_lopt, > &idx)) != -1) > + { > > Use getopt32() ? Okay. Will do. > +typedef struct BcResult { > + > + BcResultType t; > + BcResultData d; > + > +} BcResult; > > Lets drop these extra empty lines. Will do. > +#ifdef CONFIG_BC > +BcStatus bc_vm_posixError(BcStatus s, const char *file, > + size_t line, const char *msg); > +#endif // CONFIG_BC > > "ifdef CONFIG_foo" is unsafe versus typos. Use "if ENABLE_foo" - it > gives warnings > for typos. Oh? Did not know that. > +#ifdef CONFIG_BC > + > +#endif // CONFIG_BC > > Why these empty ifdef blocks? This was caused by bugs in my release script that have been fixed. > +const char bc_name[] = "bc"; > > static > > > +const char *bc_errs[] = { > > static const char *const bc_errs[] = { Will do. > + if (!(v->v = malloc(esize * BC_VEC_START_CAP))) return > BC_STATUS_ALLOC_ERR; > > (1) Please do not nest assignments: > > v->v = malloc(esize * BC_VEC_START_CAP); > if (!v->v) > return BC_STATUS_ALLOC_ERR; Oh boy. I was afraid of this. The problem is that I am also trying to get this bc into toybox (might as well reduce duplication of effort), and as I am sure you know, Landley is very particular about the line count of commands. To be honest, I would prefer your style (except for putting if statements that on one line if possible), but this reduces line count. I don't really know what to do here. > (2) Use xmalloc/xzalloc/xrealloc which never return NULL. > We do not try to survive out-of-memory. No check is necessary. Will do. I was not aware of those functions. bc does have to print a diagnostic message (see http://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html#tag_20_09_15), but I checked that those procedures do that. > +BcStatus bc_vec_pushByte(BcVec *v, uint8_t data) { > + return bc_vec_push(v, &data); > +} > > The entire bbox code base uses this formatting of function body: > > BcStatus bc_vec_pushByte(BcVec *v, uint8_t data) > { > return bc_vec_push(v, &data); > } This one might be a little harder. > + if (!v->len && (s = bc_vec_pushByte(v, '\0'))) return s; > > len is not boolean or a pointer. !foo is usually used with those. > len is an integer. You are testing whether it's zero. Why obfuscate? > For readability, should be: > if (v->len == 0) { > s = bc_vec_pushByte(v, '\0'); > if (s) > return s; > } > > > + if (a == b) return 0; > + else if (!a->len) return BC_NUM_NEG(!!b->len, !b->neg); > + else if (!b->len) return BC_NUM_NEG(1, a->neg); > + else if (a->neg) { > + if (b->neg) neg = true; > + else return -1; > + } > + else if (b->neg) return 1; > > "else" after exiting code in preceding "if" is not necessary. > Can rewrite as: > > if (a == b) return 0; > if (!a->len) return BC_NUM_NEG(!!b->len, !b->neg); > if (!b->len) return BC_NUM_NEG(1, a->neg); > if (a->neg) { > if (!b->neg) return -1; > neg = true; > } > else if (b->neg) return 1; You are correct. > +static void bc_vm_sig(int sig) { > + if (sig == SIGINT) { > + size_t len = strlen(bcg.sig_msg); > + if (write(2, bcg.sig_msg, len) == (ssize_t) len) > + bcg.sig += (bcg.signe = bcg.sig == bcg.sigc); > + } > + else bcg.sig_other = 1; > +} > > + sa.sa_handler = bc_vm_sig; > + sa.sa_flags = 0; > + > + if (sigaction(SIGINT, &sa, NULL) < 0 || sigaction(SIGPIPE, &sa, > NULL) < 0 || > + sigaction(SIGHUP, &sa, NULL) < 0 || sigaction(SIGTERM, &sa, NULL) < > 0) > + { > + return BC_STATUS_EXEC_SIGACTION_FAIL; > + } > > Calculator has signal handling?! > siganction() never fails - no need to check result. GNU bc has signal handling. It is so users can stop long-running calculations. This bc is meant to be compatible. > Better yet, use read_line_input() from libbb.h: > /* > * maxsize must be >= 2. > * Returns: > * -1 on read errors or EOF, or on bare Ctrl-D, > * 0 on ctrl-C (the line entered is still returned in 'command'), > * >0 length of input string, including terminating '\n' > */ > int read_line_input(line_input_t *st, const char *prompt, char > *command, int maxsize) FAST_FUNC; > > - it already has Ctrl-C handling, and drop entire signal handling mess. > (It's buggy: write() can modify errno). Oh, thanks for the heads up about write. I will take care of that, but to remain compatible with GNU, I will still have to do a write. > Let bc just die on SIGPIPE, SIGTERM and SIGHUP. I guess I could do that. Okay, as it stands, I see one big showstopper for getting this into busybox: code style. I don't know how to fix code style with a script, so if it is a showstopper for you (and if it is, I don't blame you), I guess I have to respectfully withdraw my patch and apologize for wasting your time. If, however, it is not, we can talk about what to do about it. And I will get started on changing the other things. Gavin Howard _______________________________________________ busybox mailing list busybox@busybox.net http://lists.busybox.net/mailman/listinfo/busybox