commit 32134b635f98b971c520ec5d9396bd74977c2ffa
parent a5e45a2b7e84f6f3076f3a021fd2adbb137c44d9
Author: William Casarin <jb55@jb55.com>
Date: Sat, 16 Dec 2017 22:37:34 -0800
working nicely
Diffstat:
M | Makefile | | | 9 | +++++---- |
A | bcalc.c | | | 76 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | num.c | | | 93 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------- |
M | num.h | | | 15 | +++++++++------ |
M | parser.y | | | 28 | ++++------------------------ |
5 files changed, 170 insertions(+), 51 deletions(-)
diff --git a/Makefile b/Makefile
@@ -3,9 +3,10 @@ BIN=bcalc
DEPS=$(wildcard deps/*/*.c) $(GEN)
PREFIX ?= /usr/local
-DEPS = $(wildcard deps/*/*.c)
+SRC = num.c
+DEPS = $(wildcard deps/*/*.c) $(SRC)
OBJS = $(DEPS:.c=.o) parser.tab.o lex.yy.o
-GEN=parser.tab.c parser.tab.h lex.yy.c $(OBJS)
+GEN = parser.tab.c parser.tab.h lex.yy.c $(OBJS)
all: $(BIN)
@@ -20,8 +21,8 @@ install: $(BIN)
mkdir -p $(PREFIX)/bin
cp $(BIN) $(PREFIX)/bin
-$(BIN): $(OBJS)
- $(CC) -o $@ num.c $(OBJS)
+$(BIN): $(OBJS) bcalc.c
+ $(CC) -Ideps -o $@ bcalc.c $(OBJS)
clean:
rm -f $(GEN)
diff --git a/bcalc.c b/bcalc.c
@@ -0,0 +1,76 @@
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "commander/commander.h"
+#include "num.h"
+
+extern int yylex();
+extern int yyparse();
+extern enum unit g_output_format;
+
+void yyerror(const char* s);
+
+struct settings {
+ enum unit format;
+ int print_unit;
+};
+
+#define format_setting(name, unit) static void name(command_t *self) { \
+ ((struct settings*)self->data)->format = unit; \
+}
+
+static void print_unit(command_t *self) { \
+ ((struct settings*)self->data)->print_unit = 1; \
+}
+
+
+format_setting(btc, UNIT_BTC)
+format_setting(mbtc, UNIT_MBTC)
+format_setting(bits, UNIT_BITS)
+format_setting(finney, UNIT_FINNEY)
+format_setting(satoshis, UNIT_SATOSHI)
+format_setting(msatoshis, UNIT_MSATOSHI)
+
+
+
+int main(int argc, char *argv[argc]) {
+ command_t cmd;
+ struct settings settings = { .print_unit = 0, .format = UNIT_SATOSHI };
+ cmd.data = (void*)&settings;
+
+ command_init(&cmd, argv[0], "0.0.1");
+
+ command_option(&cmd, "-B", "--btc", "output BTC", btc);
+ command_option(&cmd, "-M", "--mbtc", "output mBTC", mbtc);
+ command_option(&cmd, "-b", "--bits", "output bits", bits);
+ command_option(&cmd, "-f", "--finneys", "output finneys", finney);
+ command_option(&cmd, "-s", "--satoshis", "output satoshis (default)", satoshis);
+ command_option(&cmd, "-m", "--millisatoshis", "output millisatoshis", msatoshis);
+ command_option(&cmd, "-p", "--print-unit", "output the selected unit at the end",
+ print_unit);
+
+ command_parse(&cmd, argc, argv);
+ /* printf("additional args:\n"); */
+ /* for (int i = 0; i < cmd.argc; ++i) { */
+ /* printf(" - '%s'\n", cmd.argv[i]); */
+ /* } */
+ command_free(&cmd);
+
+ g_output_format = settings.format;
+
+ do {
+ yyparse();
+ } while(!feof(stdin));
+
+ if (settings.print_unit)
+ printf(" %s\n", unit_name(settings.format));
+ else
+ putchar('\n');
+
+ return 0;
+}
+
+void yyerror(const char* s) {
+ fprintf(stderr, "Parse error: %s\n", s);
+ exit(1);
+}
diff --git a/num.c b/num.c
@@ -3,6 +3,7 @@
#include <assert.h>
#include <math.h>
#include <inttypes.h>
+#include <string.h>
#include "num.h"
void
@@ -21,15 +22,15 @@ num_to_msat(struct num *num) {
assert("fractional millisatoshis are not yet supported");
return (int64_t)val;
case UNIT_SATOSHI:
- return (int64_t)(val * 1000);
+ return (int64_t)(val * SATOSHI);
case UNIT_FINNEY:
- return (int64_t)(val * 10000);
+ return (int64_t)(val * FINNEY);
case UNIT_BITS:
- return (int64_t)(val * 100000);
+ return (int64_t)(val * BITS);
case UNIT_MBTC:
- return (int64_t)(val * 100000000);
+ return (int64_t)(val * MBTC);
case UNIT_BTC:
- return (int64_t)(val * 100000000000);
+ return (int64_t)(val * BTC);
}
}
@@ -38,15 +39,15 @@ num_to_msat(struct num *num) {
case UNIT_MSATOSHI:
return val;
case UNIT_SATOSHI:
- return val * 1000;
+ return val * SATOSHI;
case UNIT_FINNEY:
- return val * 10000;
+ return val * FINNEY;
case UNIT_BITS:
- return val * 100000;
+ return val * BITS;
case UNIT_MBTC:
- return val * 100000000;
+ return val * MBTC;
case UNIT_BTC:
- return val * 100000000000;
+ return val * BTC;
}
}
@@ -79,8 +80,6 @@ num_div(struct num *dst, struct num *a, struct num *b) {
dst->type = TYPE_INT;
dst->unit = UNIT_MSATOSHI;
dst->intval = num_to_msat(a) / num_to_msat(b);
- assert(fabs((double)dst->intval -
- ((double)num_to_msat(a) / (double)num_to_msat(b))) <= 0.00005);
}
void
@@ -92,10 +91,70 @@ num_assign(struct num *dst, struct num *a) {
*dst = num;
}
+int64_t
+unit_msat_multiple(enum unit format) {
+ switch (format) {
+ case UNIT_MSATOSHI: return MSATOSHI;
+ case UNIT_SATOSHI: return SATOSHI;
+ case UNIT_FINNEY: return FINNEY;
+ case UNIT_BITS: return BITS;
+ case UNIT_MBTC: return MBTC;
+ case UNIT_BTC: return BTC;
+ }
+}
+
+
+static void
+trim_zeros (char *s, int n)
+{
+ char *p;
+ int count;
+
+ p = strchr (s,'.'); // Find decimal point, if any.
+ if (p != NULL) {
+ count = n; // Adjust for more or less decimals.
+ while (count >= 0) { // Maximum decimals allowed.
+ count--;
+ if (*p == '\0') // If there's less than desired.
+ break;
+ p++; // Next character.
+ }
+
+ *p-- = '\0'; // Truncate string.
+ while (*p == '0') // Remove trailing zeros.
+ *p-- = '\0';
+
+ if (*p == '.') { // If all decimals were zeros, remove ".".
+ *p = '\0';
+ }
+ }
+}
+
void
-num_print(struct num *num) {
- if (num->type == TYPE_FLOAT)
- printf("%f ", num->floatval);
- else
- printf("%" PRId64, num->intval);
+num_print(struct num *num, enum unit format) {
+ static char buffer[255];
+ int64_t msat_multiple = unit_msat_multiple(format);
+
+ if (format) {
+ }
+
+ double d = num->type == TYPE_FLOAT? num->floatval : (double)num->intval;
+ d /= (double)msat_multiple;
+ sprintf (buffer, "%.11f", d);
+ trim_zeros(buffer, 1);
+ printf("%s", buffer);
+}
+
+
+
+char *
+unit_name(enum unit unit) {
+ switch (unit) {
+ case UNIT_MSATOSHI: return "msat";
+ case UNIT_SATOSHI: return "sat";
+ case UNIT_FINNEY: return "finney";
+ case UNIT_BITS: return "bits";
+ case UNIT_MBTC: return "mBTC";
+ case UNIT_BTC: return "BTC";
+ }
}
diff --git a/num.h b/num.h
@@ -4,11 +4,13 @@
#include <stdint.h>
-#define MSATOSHI 100000000000LL
-#define SATOSHI 100000000LL
-#define FINNEY 10000000LL
-#define BITS 1000000LL
-#define MBTC 1000LL
+// multiples of msat
+#define MSATOSHI 1LL
+#define SATOSHI 1000LL
+#define FINNEY 10000LL
+#define BITS 100000LL
+#define MBTC 100000000LL
+#define BTC 100000000000LL
enum unit {
UNIT_BTC,
@@ -42,6 +44,7 @@ void num_mul(struct num *dst, struct num *a, struct num *b);
void num_div(struct num *dst, struct num *a, struct num *b);
void num_assign(struct num *dst, struct num *a);
void num_init(struct num *num);
-void num_print(struct num *num);
+void num_print(struct num *num, enum unit unit);
+char *unit_name(enum unit unit);
#endif /* UNIT_H */
diff --git a/parser.y b/parser.y
@@ -5,13 +5,8 @@
#include "num.h"
-extern int yylex();
-extern int yyparse();
-extern FILE* yyin;
+enum unit g_output_format;
-char buffer[255];
-
-void yyerror(const char* s);
%}
%union {
@@ -41,11 +36,10 @@ calc:
;
line: T_NEWLINE
- | expr T_NEWLINE { num_print(&$1); printf("\n"); }
-;
+ | expr T_NEWLINE { num_print(&$1, g_output_format); }
+ ;
-expr:
- | T_INT T_UNIT { num_init(&$$);
+expr: T_INT T_UNIT { num_init(&$$);
$$.intval = $1;
$$.type = TYPE_INT;
$$.unit = $2;
@@ -74,17 +68,3 @@ expr:
%%
-int main() {
- yyin = stdin;
-
- do {
- yyparse();
- } while(!feof(yyin));
-
- return 0;
-}
-
-void yyerror(const char* s) {
- fprintf(stderr, "Parse error: %s\n", s);
- exit(1);
-}