bcalc

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

bcalc.c (2421B)


      1 
      2 #include <stdlib.h>
      3 #include <stdio.h>
      4 #include <string.h>
      5 #include "commander/commander.h"
      6 #include "num.h"
      7 
      8 extern int yy_scan_string(const char *str);
      9 extern void yy_delete_buffer(int);
     10 extern int yylex();
     11 extern int yyparse();
     12 extern enum unit g_output_format;
     13 extern int g_print_unit;
     14 struct num g_other;
     15 char *g_other_name = "other";
     16 
     17 void yyerror(const char* s);
     18 
     19 struct settings {
     20   enum unit format;
     21   int print_unit;
     22 };
     23 
     24 static void no_print_unit(command_t *self) { \
     25   ((struct settings*)self->data)->print_unit = 0; \
     26 }
     27 
     28 static void
     29 setprice(command_t *cmd) {
     30   const char *p = cmd->arg;
     31   char *endptr;
     32   g_other.unit = UNIT_OTHER;
     33   g_other.type = TYPE_INT;
     34   g_other.intval = strtoull(p, &endptr, 10);
     35 
     36   // float?
     37   if (endptr) {
     38     if (*endptr == '.') {
     39       g_other.floatval = atof(p);
     40       g_other.type = TYPE_FLOAT;
     41       if (g_other.floatval == 0) {
     42         fprintf(stderr, "error: invalid --price value '%s'", p);
     43         exit(1);
     44       }
     45     }
     46   }
     47 }
     48 
     49 char *
     50 join(char *strs[], int len, char *sep) {
     51   char *buf, *p;
     52   size_t alloc = 0;
     53 
     54   for(int i = 0; i < len; ++i)
     55     alloc += strlen(strs[i]);
     56 
     57   // 5 for some wiggle room
     58   alloc += len * strlen(sep) + 5;
     59   p = buf = (char*)malloc(alloc);
     60 
     61   for(int i = 0; i < len; ++i) {
     62     strcpy(p, strs[i]);
     63     p += strlen(strs[i]);
     64     if (i != len-1) {
     65       strcpy(p, sep);
     66       p += strlen(sep);
     67     }
     68   }
     69 
     70   return buf;
     71 }
     72 
     73 int main(int argc, char *argv[]) {
     74   command_t cmd;
     75   char *buffer, *p;
     76   int yybuffer;
     77   struct settings settings = { .print_unit = 1, .format = UNIT_SATOSHI };
     78   cmd.data = (void*)&settings;
     79   g_other.unit = UNIT_NONE;
     80 
     81   command_init(&cmd, argv[0], "0.0.1");
     82 
     83   command_option(&cmd, "-P", "--price <arg>", "set price for arbitrary unit per BTC", setprice);
     84   command_option(&cmd, "-n", "--no-unit", "dont output the selected unit at the end",
     85                  no_print_unit);
     86 
     87   command_parse(&cmd, argc, argv);
     88 
     89   g_output_format = settings.format;
     90   g_print_unit = settings.print_unit;
     91 
     92   if (cmd.argc) {
     93     buffer = join(cmd.argv, cmd.argc, " ");
     94     p = &buffer[strlen(buffer)];
     95     *p++ = '\n';
     96     *p++ = '\0';
     97     yybuffer = yy_scan_string(buffer);
     98     yyparse();
     99     yy_delete_buffer(yybuffer);
    100     free(buffer);
    101   }
    102   else {
    103     do {
    104       yyparse();
    105     } while(!feof(stdin));
    106   }
    107 
    108   command_free(&cmd);
    109   return 0;
    110 }
    111 
    112 void yyerror(const char* s) {
    113   fprintf(stderr, "Parse error: %s\n", s);
    114   exit(1);
    115 }