#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int usage(char *prog){
  printf("Usage: %s [-i base] [-o out] number\n", prog);
}

int tonum(char c, int b){
  int num;
  if(c >= '0' && c <= '9'){
    num = c - '0';
  }
  else if(c >= 'a' && c <= 'z'){
    num = c - 'a' + 10;
  }
  else{
    num = c - 'A' + 10;
  }
#ifdef DEBUG
  printf("%c(%d) -> %d\n", c, b, num);
#endif

  return num;
}

char *reverse(char *out){
  int length = strlen(out);
  int half = length / 2;
  int i;

  for(i = 0; i < half; i++){
    char c = out[i];
    out[i] = out[length - i - 1];
    out[length - i - 1] = c;
  }

  return out;
}

char *convert(char *num, int ibase, char *out, int obase){
  int decimal = 0;
  int i;

  for(i = 0; i < strlen(num); i++){
    decimal = decimal * ibase + tonum(num[i], ibase);
  }

  if(obase == 16){
    sprintf(out, "%x", decimal);
  }
  else if(obase == 8){
    sprintf(out, "%o", decimal);
  }
  else{
    for(i = 0; decimal != 0; i++){
#ifdef DEBUG
      printf("decimal: %d\n", decimal);
#endif
      int r = decimal % obase;
      if(r < 10){
        out[i] = '0' + r;
      }
      else{
        out[i] = 'A' + r - 10;
      }
      decimal = decimal / obase;
#ifdef DEBUG
      printf("decimal: %d\n", decimal);
#endif
    }
    out[i] = '\0';
    out = reverse(out);
  }

  return out;
}

int main(int argc, char *argv[]){
  int input_base = 10;
  int output_base = 16;
  char *num;
  char out[256];
  int c;

  while((c = getopt(argc, argv, "i:o:")) != -1){
    switch(c){
    case 'i':
      input_base = atoi(optarg);
      break;
    case 'o':
      output_base = atoi(optarg);
      break;
    }
  }

  if(argc <= optind){
    usage(argv[0]);
    exit(1);
  }
  num = argv[optind];
#ifdef DEBUG
  printf("%s(%d) to %d radix\n", num, input_base, output_base);
#endif
  convert(num, input_base, out, output_base);
  
  printf("%s(%d) -> %s(%d)\n", num, input_base, out, output_base);
}
