bcalc

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

bcalc.c (2342B)


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