bcalc

cli bitcoin unit calculator
git clone git://jb55.com/bcalc
Log | Files | Refs | README | LICENSE

commit d61fae8affb2316b0a175fc9a5423253b7d87788
parent f0198314a1678d11a4e8cbc6381b5682536f099d
Author: William Casarin <jb55@jb55.com>
Date:   Sat, 23 Dec 2017 19:01:11 -0800

grammar: fix up remaining `in` grammar issues

Start to remove switches

Diffstat:
MREADME.md | 18+++++++++---------
Mbcalc.c | 29-----------------------------
Mlexer.l | 15++++++++++-----
Mnum.c | 5+++--
Mnum.h | 7++++++-
Mparser.y | 14++++++++------
Mtest/tests.csv | 61+++++++++++++++++++++++++++++++------------------------------
7 files changed, 67 insertions(+), 82 deletions(-)

diff --git a/README.md b/README.md @@ -9,7 +9,7 @@ Basic example - $ bcalc --msat 1 msat + 2 sats + 3 bits + $ bcalc 1 msat + 2 sats + 3 bits in msats 302001 msat BTC to satoshis @@ -17,37 +17,37 @@ $ bcalc 0.02 BTC 2000000 sat - satoshis to millisatoshis (for payment channels) + satoshis to millisatoshis (for payment channels), also dont print unit - $ bcalc --no-unit --msat 100 sat + $ bcalc --no-unit 100 sat in msats 100000 mBTC + bits to BTC - $ bcalc --btc 100 mBTC + 20 bits + $ bcalc 100 mBTC + 20 bits in btc 0.10002 BTC Division - $ bcalc --bits 1 BTC / 100 + $ bcalc 1 BTC / 100 in bits 10000 bits Multiplication - $ bcalc -b '10 mbtc * 30' + $ bcalc '10 mbtc * 30 in bits' 300000 bits Fiat currencies - $ bcalc --price 20000 --bits 30 usd + $ bcalc --price 20000 30 usd in bits 1500 bits - $ bcalc --price 16000 --usd 780 bits + $ bcalc --price 16000 780 bits in fiat 12.48 usd The Bitcoin pizzas - $ bcalc --price 0.0041 --btc 41 usd + $ bcalc --price 0.0041 41 usd in btc 10000 BTC ## Install diff --git a/bcalc.c b/bcalc.c @@ -19,28 +19,10 @@ struct settings { int print_unit; }; -#define format_setting(name, unit) static void name(command_t *self) { \ - ((struct settings*)self->data)->format = unit; \ -} - static void no_print_unit(command_t *self) { \ ((struct settings*)self->data)->print_unit = 0; \ } -format_setting(btc, UNIT_BTC) -format_setting(mbtc, UNIT_MBTC) -format_setting(bits, UNIT_BITS) -format_setting(finney, UNIT_FINNEY) -format_setting(sat, UNIT_SATOSHI) -format_setting(msat, UNIT_MSATOSHI) -format_setting(optother, UNIT_OTHER) - -static void optusd(command_t *self) { - struct settings *set = (struct settings*)self->data; - set->format = UNIT_OTHER; - g_other_name = "USD"; -} - static void setprice(command_t *cmd) { const char *p = cmd->arg; @@ -96,18 +78,7 @@ int main(int argc, char *argv[argc]) { 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", "--finney", "output finneys", finney); - command_option(&cmd, "-f", "--finneys", "output finneys", finney); - command_option(&cmd, "-s", "--sat", "output satoshis (default)", sat); - command_option(&cmd, "-s", "--sats", "output satoshis (default)", sat); - command_option(&cmd, "-m", "--msat", "output millisatoshis", msat); - command_option(&cmd, "-m", "--msats", "output millisatoshis", msat); command_option(&cmd, "-P", "--price <arg>", "set price for arbitrary unit per BTC", setprice); - command_option(&cmd, "-o", "--other", "output arbitrary unit, set by --price", optother); - command_option(&cmd, "-u", "--usd", "output arbitrary usd units", optusd); command_option(&cmd, "-n", "--no-unit", "dont output the selected unit at the end", no_print_unit); diff --git a/lexer.l b/lexer.l @@ -15,7 +15,8 @@ [ \t] ; // ignore all whitespace [bB][iI][tT][sS]? { - yylval.unit = UNIT_BITS; + yylval.lexunit.unit = UNIT_BITS; + yylval.lexunit.name = "bits"; return T_UNIT; } @@ -25,23 +26,27 @@ in|IN { [mM]?[bB][tT][cC] { int ism = yytext[0] == 'm' || yytext[0] == 'M'; - yylval.unit = ism? UNIT_MBTC : UNIT_BTC; + yylval.lexunit.unit = ism? UNIT_MBTC : UNIT_BTC; + yylval.lexunit.name = ism? "mBTC" : "BTC"; return T_UNIT; } fiat|FIAT|alt|ALT|usd|USD|cur|CUR|other|OTHER { - yylval.unit = UNIT_OTHER; + yylval.lexunit.unit = UNIT_OTHER; + yylval.lexunit.name = yytext; return T_UNIT; } [fF][iI][nN][nN][eE][yY]?[sS]? { - yylval.unit = UNIT_FINNEY; + yylval.lexunit.unit = UNIT_FINNEY; + yylval.lexunit.name = "finneys"; return T_UNIT; } [mM]?[sS][aA][tT][sS]? { int ism = yytext[0] == 'm' || yytext[0] == 'M'; - yylval.unit = ism ? UNIT_MSATOSHI : UNIT_SATOSHI; + yylval.lexunit.unit = ism ? UNIT_MSATOSHI : UNIT_SATOSHI; + yylval.lexunit.name = ism ? "msats" : "sats"; return T_UNIT; } diff --git a/num.c b/num.c @@ -200,7 +200,7 @@ trim_zeros (char *s, int n) } void -num_print(struct num *num, enum unit format, int print_unit) { +num_print(struct num *num, enum unit format, char *unitname, int print_unit) { static char buffer[255]; int64_t msat_multiple = unit_msat_multiple(format); @@ -212,7 +212,8 @@ num_print(struct num *num, enum unit format, int print_unit) { printf("%s", buffer); if (print_unit) - printf(" %s", unit_name(format)); + printf(" %s", unitname? unitname : unit_name(format)); + printf("\n"); } diff --git a/num.h b/num.h @@ -28,6 +28,11 @@ enum num_type { TYPE_FLOAT }; +struct lexunit { + char *name; + enum unit unit; +}; + struct num { enum num_type type; @@ -48,7 +53,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, enum unit unit, int print_unit); +void num_print(struct num *num, enum unit unit, char *unitname, int print_unit); void num_init_float(struct num *num, double val, enum unit unit); void num_init_int(struct num *num, int64_t val, enum unit unit); diff --git a/parser.y b/parser.y @@ -13,13 +13,13 @@ int g_print_unit; %union { int64_t intval; double floatval; - enum unit unit; + struct lexunit lexunit; struct num num; } %token<intval> T_INT %token<floatval> T_FLOAT -%token<unit> T_UNIT +%token<lexunit> T_UNIT %token T_PLUS T_MINUS T_MULTIPLY T_DIVIDE T_LEFT T_RIGHT T_IN %token T_NEWLINE T_QUIT @@ -37,13 +37,15 @@ calc: ; line: T_NEWLINE - | expr T_NEWLINE { num_print(&$1, g_output_format, g_print_unit); } - | expr T_IN T_UNIT T_NEWLINE { num_print(&$1, $3, g_print_unit); } + | expr T_NEWLINE { num_print(&$1, g_output_format, NULL, g_print_unit); } + | expr T_IN T_UNIT T_NEWLINE { + num_print(&$1, $3.unit, $3.name, g_print_unit); + } ; unit_number: - T_INT T_UNIT { num_init_int(&$$, $1, $2); } - | T_FLOAT T_UNIT { num_init_float(&$$, $1, $2); } + T_INT T_UNIT { num_init_int(&$$, $1, $2.unit); } + | T_FLOAT T_UNIT { num_init_float(&$$, $1, $2.unit); } ; diff --git a/test/tests.csv b/test/tests.csv @@ -1,35 +1,36 @@ description,args,input,expected output -scalar division,--btc,1 BTC / 10,0.1 BTC -scalar multiplication,--btc -n,10 * 1 BTC,10 -multiply 1 BTC to the smallest unit,-m,1 BTC * 0.00000000001,1 msat -multiply 10 BTC to the smallest unit,-m,10 BTC * 0.000000000001,1 msat -multiply 100 BTC to the smallest unit,-m,100 BTC * 0.0000000000001,1 msat -multiply 1000 BTC to the smallest unit,-m,1000 BTC * 0.00000000000001,1 msat -multiply 100000 BTC to the smallest unit,-m,100000 BTC * 0.0000000000000001,1 msat -lots of msats,-nB,2 msat * 100000000000,2 -chained multiply,-nB,2100 btc * 0.1 * 0.1,21 -10000 satoshis in bits,-n --bits,10000 sats,100 -satoshis in bits to smallest bit,-b,10000 sats * 0.01,1 bits -parens,-nB,(10 finney * 1000) / 10,0.0001 -finney plural,-nf,10 finneys,10 -finney singular,-nf,10 finney,10 -satoshi singular,-s,10 sat,10 sat -satoshi plural,-s,10 sats,10 sat -msat singular,-m,1 msat,1 msat -msat plural,-m,1 msats,1 msat -arg tokens work,--mbtc 1 BTC,,1000 mBTC -simple fiat test,--price 15000 --msat,1 fiat,6666666 msat -simple fiat test with bits,--price 15000 --bits,1 fiat,66.66666 bits -1 usd is 1 BTC,--price 1 --btc,1 usd,1 BTC -1 BTC is 10 usd,--price 10 --usd,1 btc,10 USD -1 BTC is 1000000 other,--price 1000000 --other,100 mbtc,100000 other -1 other @15k is 66.66666 bits,--price 15000 --bits,1 other,66.66666 bits -1 btc/2 should work,--btc -n,1 btc / 2,0.5 -60 usd at 25000 in bits,--bits --price 25000,60 fiat,2400 bits -penny usd to msats,--price 20000 --msats,0.01 usd,50000 msat +scalar division,,1 BTC / 10 in btc,0.1 BTC +scalar multiplication,-n,10 * 1 BTC in btc,10 +multiply 1 BTC to the smallest unit,,1 BTC * 0.00000000001 in msats,1 msats +multiply 10 BTC to the smallest unit,,10 BTC * 0.000000000001 in msats,1 msats +multiply 100 BTC to the smallest unit,,100 BTC * 0.0000000000001 in msats,1 msats +multiply 1000 BTC to the smallest unit,,1000 BTC * 0.00000000000001 in msats,1 msats +multiply 100000 BTC to the smallest unit,,100000 BTC * 0.0000000000000001 in msats,1 msats +lots of msats,-n,2 msat * 100000000000 in btc,2 +chained multiply,-n,2100 btc * 0.1 * 0.1 in btc,21 +10000 satoshis in bits,-n,10000 sats in bits,100 +satoshis in bits to smallest bit,,10000 sats * 0.01 in bits,1 bits +parens,-n,(10 finney * 1000) / 10 in btc,0.0001 +finney plural,-n,10 finneys in finneys,10 +finney singular,-n,10 finney in finneys,10 +satoshi singular,,10 sat,10 sat +satoshi plural,,10 sats,10 sat +msat singular,,1 msat in msat,1 msats +msat plural,,1 msats in msat,1 msats +arg tokens work,1 BTC in mbtc,,1000 mBTC +simple fiat test,--price 15000,1 fiat in msats,6666666 msats +simple fiat test with bits,--price 15000,1 fiat in bits,66.66666 bits +1 usd is 1 BTC,--price 1,1 usd in btc,1 BTC +1 BTC is 10 usd,--price 10,1 btc in usd,10 usd +1 BTC is 1000000 fiat,--price 1000000,100 mbtc in fiat,100000 fiat +1 other @15k is 66.66666 bits,--price 15000,1 other in bits,66.66666 bits +1 btc/2 should work,-n,1 btc / 2 in btc,0.5 +60 usd at 25000 in bits,--price 25000,60 fiat in bits,2400 bits +penny usd to msats,--price 20000,0.01 usd in msats,50000 msats 100 mbtc in bits grammar,,100 mbtc in bits,100000 bits 100 mbtc in bits grammar with arith,,100 mbtc + 2 btc in btc,2.1 BTC +set usb in grammar,--price 16000,780 bits in usd,12.48 usd # failing -1 BTC is 15000 usd,--price 15000 --usd,1 btc,15000 USD +1 BTC is 15000 usd,--price 15000,1 btc in usd,15000 USD # needs implementation -1/2 btc should work,--btc,1/2 btc,0.5 +1/2 btc should work,,1/2 btc,0.5