summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArun Prakash Jana <engineerarun@gmail.com>2019-10-13 20:30:26 +0530
committerArun Prakash Jana <engineerarun@gmail.com>2019-10-13 20:30:26 +0530
commitecebd9f55983bca6beb883314fff888b04eab914 (patch)
treead906467575bd5022d11ff9800a68e69eb573d77
parent6c8d3257e7b6fc1ff770ecc1853fa39a34bc51b8 (diff)
Alternatively use calc instead of bc
-rw-r--r--README.md10
-rw-r--r--bcal.16
-rw-r--r--src/bcal.c101
3 files changed, 82 insertions, 35 deletions
diff --git a/README.md b/README.md
index 6470783..870e5ea 100644
--- a/README.md
+++ b/README.md
@@ -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
diff --git a/bcal.1 b/bcal.1
index c2ccfcd..c6ec5cf 100644
--- a/bcal.1
+++ b/bcal.1
@@ -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.
diff --git a/src/bcal.c b/src/bcal.c
index a4fd9a3..97cfaf2 100644
--- a/src/bcal.c
+++ b/src/bcal.c
@@ -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);