/*
    Copyright (C) 2005, 2006      Robin Redeker <elmex@ta-sa.org>, <r.redeker@gmail.com>
*/

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

void reverse (char *in, size_t l)
{
  char c[l];
  int i = 0;
  memcpy (c, in, l);

  for (i = (l - 1); i >= 0; i--)
    in[(l - 1) - i] = c[i];
}

char *to_base (int base, long z, const char *charset)
{
  char *out = (char *) malloc (sizeof (char) * 1000);
  memset (out, 0, sizeof (char) * 1000);
  int idx = 0;

  long n = z;
  long tmp = n;
  int rest = 0;

  size_t chst_len = charset ? strlen (charset) : 0;

  while (n > 0)
    {
      tmp = n / base;
      rest = n - (tmp * base);
      n = tmp;

      if (charset && chst_len <= rest)
        {
          printf ("error: charset too small to display '%d'\n", rest);
          exit (1);
        }
      else if (charset)
        out[idx++] = charset[rest];
      else
        if (rest <= 9)
          out[idx++] = '0' + rest;
        else
          out[idx++] = 'A' + (rest - 10);
    }

  reverse (out, strlen (out));
  return out;
}

int main (int argc, char *argv[])
{
   int max_b = 20;
   const char *charset = 0;

   if (argc < 3)
     {
       printf ("baseclc <number> <base> [<maxbase> [<charset>]]\n");
       printf ("tobase  <number> <base> <outbase> [<charset>]\n");
       exit (1);
     }

   if (argc > 3)
     max_b = atoi (argv[3]);

   if (argc > 4)
     charset = argv[4];

   long z = strtoul (argv[1], NULL, atoi (argv[2]));

   if (argv[0][0] == 't')
     {
       printf ("%s", to_base (max_b, z, charset));
     }
   else
     {
       int b = 2;
       for (b = 2; b <= max_b; b++)
         {
           char *c = to_base (b, z, charset);
           printf ("%2d: %20s\n", b, c);
           free (c);
         }
     }
}
