diff options
author | Arun Prakash Jana <engineerarun@gmail.com> | 2019-10-13 20:30:26 +0530 |
---|---|---|
committer | Arun Prakash Jana <engineerarun@gmail.com> | 2019-10-13 20:30:26 +0530 |
commit | ecebd9f55983bca6beb883314fff888b04eab914 (patch) | |
tree | ad906467575bd5022d11ff9800a68e69eb573d77 | |
parent | 6c8d3257e7b6fc1ff770ecc1853fa39a34bc51b8 (diff) |
Alternatively use calc instead of bc
-rw-r--r-- | README.md | 10 | ||||
-rw-r--r-- | bcal.1 | 6 | ||||
-rw-r--r-- | src/bcal.c | 101 |
3 files changed, 82 insertions, 35 deletions
@@ -22,7 +22,7 @@ `bcal` (*Byte CALculator*) is a REPL CLI utility for storage expression evaluation, unit conversion and address calculation. If you can't calculate the hex address offset for (512 - 16) MiB, or the value when the 43<sup>rd</sup> bit of a 64-bit address is set mentally, `bcal` is for you. -It has a [`bc`](https://www.gnu.org/software/bc/manual/html_mono/bc.html) mode for general-purpose numerical calculations. +It has a [`bc`](https://www.gnu.org/software/bc/manual/html_mono/bc.html) mode for general-purpose numerical calculations. Alternatively, it can also use [`calc`](http://www.isthe.com/chongo/tech/comp/calc/) (helps with expressions involving multiple bases). `bcal` follows Ubuntu's standard unit conversion and notation [policy](https://wiki.ubuntu.com/UnitsPolicy). Only 64-bit operating systems are supported. @@ -65,7 +65,11 @@ It has a [`bc`](https://www.gnu.org/software/bc/manual/html_mono/bc.html) mode f #### Dependencies -`bcal` is written in C and depends on standard libc and libreadline. It invokes GNU `bc` for non-storage expressions. +`bcal` is written in C and depends on standard libc and libreadline. It invokes GNU `bc` or `calc` for non-storage expressions. + +To use `calc`: + + export BCAL_USE_CALC=1 #### From a package manager @@ -166,7 +170,7 @@ prompt keys: - sector size: 0x200 (512) - max heads per cylinder: 0x10 (16) - max sectors per track: 0x3f (63) -- **bc variables**: `scale` = 10, `ibase` = 10. `last` is synced to `r` when toggling from `bc` to `bcal`. Syncing `r` to `last` works with GNU `bc`. `bc` is not called in minimal output mode. +- **bc variables**: `scale` = 10, `ibase` = 10. `last` is synced to `r` when toggling from `bc` to `bcal`. Syncing `r` to `last` works with GNU `bc`. `bc` is not called in minimal output mode. Note that `r` works as usual with `calc`. ### Examples @@ -63,7 +63,7 @@ bcal \- Storage expression calculator. - max sectors per track: 0x3f (63) .PP .IP 10. 4 -\fBbc variables\fR: \fIscale\fR = 10, \fIibase\fR = 10. \fIlast\fR is synced to \fIr\fR when toggling from \fIbc\fR to \fBbcal\fR. Syncing \fIr\fR to \fIlast\fR works with GNU \fIbc\fR. \fIbc\fR is not called in minimal output mode. +\fBbc variables\fR: \fIscale\fR = 10, \fIibase\fR = 10. \fIlast\fR is synced to \fBr\fR when toggling from \fBbc\fR to \fBbcal\fR. Syncing \fBr\fR to \fIlast\fR works with GNU \fBbc\fR. \fBbc\fR is not called in minimal output mode. Note that \fBr\fR works as usual with \fBcalc\fR. To use \fBcalc\fR, \fIexport BCAL_USE_CALC=1\fR. .SH OPTIONS .TP .BI "-c=" N @@ -76,7 +76,7 @@ Convert CHS to LBA or LBA to CHS. \fIloc\fR is hyphen-separated representation o Sector size in bytes. Default value is 512. .TP .BI "-b=" [expr] -Start in \fIbc\fR mode. If expression is provided, evaluate in \fIbc\fR and quit. +Start in \fBbc\fR mode. If expression is provided, evaluate in \fBbc\fR and quit. .TP .BI "-m" Show minimal output (e.g. decimal bytes). @@ -89,7 +89,7 @@ Show program help, storage sizes on the system and exit. .SH PROMPT KEYS .TP .BI "b" -Toggle \fIbc\fR mode. +Toggle \fBbc\fR mode. .TP .BI "r" Show result from last operation. @@ -66,7 +66,8 @@ typedef struct { uchar bcmode : 1; uchar minimal : 1; uchar repl : 1; - uchar rsvd : 3; /* Reserved for future usage */ + uchar calc : 1; + uchar rsvd : 2; /* Reserved for future usage */ uchar loglvl : 2; } settings; @@ -83,7 +84,7 @@ static char uint_buf[UINT_BUF_LEN]; static char float_buf[FLOAT_BUF_LEN]; static Data lastres = {"\0", 0}; -static settings cfg = {0, 0, 0, 0, INFO}; +static settings cfg = {0, 0, 0, 0, 0, INFO}; static void debug_log(const char *func, int level, const char *format, ...) { @@ -174,6 +175,7 @@ static int try_bc(char *expr) int pipe_pc[2], pipe_cp[2]; size_t len, count = 0; ssize_t ret; + char *ptr = cfg.calc ? "calc" : "bc"; if (!expr) { if (curexpr) @@ -206,41 +208,66 @@ static int try_bc(char *expr) dup2(pipe_cp[1], STDOUT_FILENO); // Give stdout to parent dup2(pipe_cp[1], STDERR_FILENO); // Give stderr to parent - ret = execlp("bc", "bc", (char*) NULL); + ret = execlp(ptr, ptr, (char*) NULL); log(ERROR, "execlp() failed!\n"); exit(ret); } - /* parent */ - if (write(pipe_pc[1], "scale=10\n", 9) != 9) { - log(ERROR, "write(1)! [%s]\n", strerror(errno)); - exit(-1); - } + if (!cfg.calc) { + /* parent */ + if (write(pipe_pc[1], "scale=10\n", 9) != 9) { + log(ERROR, "write(1)! [%s]\n", strerror(errno)); + exit(-1); + } #ifdef __GNU_LIBRARY__ - if (write(pipe_pc[1], "last=", 5) != 5) { - log(ERROR, "write(2)! [%s]\n", strerror(errno)); - exit(-1); - } + if (write(pipe_pc[1], "last=", 5) != 5) { + log(ERROR, "write(2)! [%s]\n", strerror(errno)); + exit(-1); + } - if (lastres.p[0]) { - ret = (ssize_t)strlen(lastres.p); - if (write(pipe_pc[1], lastres.p, ret) != ret) { - log(ERROR, "write(3)! [%s]\n", strerror(errno)); + if (lastres.p[0]) { + ret = (ssize_t)strlen(lastres.p); + if (write(pipe_pc[1], lastres.p, ret) != ret) { + log(ERROR, "write(3)! [%s]\n", strerror(errno)); + exit(-1); + } + } else { + if (write(pipe_pc[1], "0", 1) != 1) { + log(ERROR, "write(4)! [%s]\n", strerror(errno)); + exit(-1); + } + } + + if (write(pipe_pc[1], "\n", 1) != 1) { + log(ERROR, "write(5)! [%s]\n", strerror(errno)); exit(-1); } +#endif } else { - if (write(pipe_pc[1], "0", 1) != 1) { - log(ERROR, "write(4)! [%s]\n", strerror(errno)); + if (write(pipe_pc[1], "r=", 2) != 2) { + log(ERROR, "write(2)! [%s]\n", strerror(errno)); exit(-1); } - } - if (write(pipe_pc[1], "\n", 1) != 1) { - log(ERROR, "write(5)! [%s]\n", strerror(errno)); - exit(-1); + if (lastres.p[0]) { + ret = (ssize_t)strlen(lastres.p); + if (write(pipe_pc[1], lastres.p, ret) != ret) { + log(ERROR, "write(3)! [%s]\n", strerror(errno)); + exit(-1); + } + } else { + if (write(pipe_pc[1], "0", 1) != 1) { + log(ERROR, "write(4)! [%s]\n", strerror(errno)); + exit(-1); + } + } + + if (write(pipe_pc[1], "\n", 1) != 1) { + log(ERROR, "write(5)! [%s]\n", strerror(errno)); + exit(-1); + } } -#endif ret = (ssize_t)strlen(expr); if (write(pipe_pc[1], expr, ret) != ret) { @@ -264,8 +291,12 @@ static int try_bc(char *expr) buffer[ret] = '\0'; if (buffer[0] != '(') { - printf("%s", buffer); - len = bstrlcpy(lastres.p, buffer, NUM_LEN); + ptr = buffer; + while (isspace(*ptr)) /* calc results have space before them */ + ++ptr; + + printf("%s", ptr); + len = bstrlcpy(lastres.p, ptr, NUM_LEN); /* remove newline appended at the end of result by bc */ (len >= 2) ? (len -= 2) : (len = 0); @@ -2018,6 +2049,9 @@ int main(int argc, char **argv) int opt = 0, operation = 0; ulong sectorsz = SECTOR_SIZE; + if (getenv("BCAL_USE_CALC")) + cfg.calc = TRUE; + opterr = 0; rl_bind_key('\t', rl_insert); @@ -2066,7 +2100,10 @@ int main(int argc, char **argv) break; case 'b': cfg.bcmode = 1; - strncpy(prompt, "bc> ", 5); + if (cfg.calc) + strncpy(prompt, "calc> ", 7); + else + strncpy(prompt, "bc> ", 5); break; case 'd': cfg.loglvl = DEBUG; @@ -2141,12 +2178,18 @@ int main(int argc, char **argv) case 'b': cfg.bcmode ^= 1; if (cfg.bcmode) { + if (cfg.calc) + strncpy(prompt, "calc> ", 7); + else { #ifdef __GNU_LIBRARY__ - printf("bc vars: scale = 10, ibase = 10, last = r\n"); + printf("bc vars: scale = 10, \ + ibase = 10, last = r\n"); #else - printf("bc vars: scale = 10, ibase = 10, last = 0\n"); + printf("bc vars: scale = 10, \ + ibase = 10, last = 0\n"); #endif - strncpy(prompt, "bc> ", 5); + strncpy(prompt, "bc> ", 5); + } } else strncpy(prompt, "bcal> ", 7); |