/*****************************************************************
*               BaseConv v1.1 © 1993, Xavier Sirvent             *
* This is a little program able to convert numbers from one base *
* to another. The bases must be lower or equal to 36             *
*****************************************************************/

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

/* prototypes */

void Usage(char *);
unsigned int rank(char charac, unsigned int base);
unsigned long ToBase10(char *number, unsigned int base);
char *FromBase10(unsigned long number, unsigned int base);

/* program */

void Usage(char *name)
{
   printf("Usage: %s <BaseFrom> <BaseTo> <number> [<number>...]\n\n",name);
   exit(0);
} /* Usage */

unsigned int rank(char charac, unsigned int BaseFrom)
/* returns the value of the "charac" given in base "BaseFrom" */
{
   int i = -1;

   if (charac >= '0' && charac <= '9')
      i = charac - '0';
   else if (charac >= 'a' && charac <= 'z')
           i = charac - 'a' + 10;
        else if (charac >='A' && charac <= 'Z')
                i = charac - 'A' + 10;

   if ( (i == -1) || (i >= BaseFrom) ) {
      printf("Error: %c is forbidden in base %d\n\n",charac,BaseFrom);
      exit(1);
   } /* if */

   return((unsigned)i);
} /* rank */

unsigned long ToBase10(char *number, unsigned int BaseFrom)
/* returns the value in base 10 of "number" given in base "BaseFrom" */
{
   unsigned long res=0,res2=0;
   int i;

   for (i = 0 ; i < strlen(number) ; i++) {
      res2 = res*BaseFrom+rank(number[i],BaseFrom);
      if (res2 <= res) {
         printf("%s is higher than 2^32\n",number);
         exit(1);
      } /* if */
      res = res2;
   } /* for */

   return(res);
} /* ToBase10 */

char *FromBase10(unsigned long number, unsigned int BaseTo)
/* display the number in BaseTo */
{
   char *result;
   int i=0,j=0,mod=0;
	char temp;

   result = (char *)calloc(33,1);
   /* the result is generated in reverse order*/
   while ((number != 0) && (i<80) ) {
      mod = (number % BaseTo);
      result[i++] = (mod <= 9)?(mod+'0'):(mod-10+'A');
      number = number / BaseTo;
   } /* while */

   /* making the result right order */

   while (j < i / 2) {
	   temp = result[j];
		result[j] = result[i - j - 1];
		result[i - j++ - 1] = temp;
	}
	return(result);	
} /* FromBase10 */

void main(int argc, char *argv[])
{
   unsigned int BaseFrom, BaseTo, i=3;

   printf("\nBase Converter v1.1, © 1993 Xavier Sirvent\n");

   if (argc < 4)
      Usage(argv[0]);

   BaseFrom = (unsigned)atol(argv[1]);
   BaseTo = (unsigned)atol(argv[2]);

   if ((BaseFrom>36)||(BaseTo>36)||(BaseFrom<2)||(BaseTo<2)) {
      printf("Error: <BaseFrom> and <BaseTo> must be in [2..36]\n\n");
      exit(1);
   } /* if */

   while (i < argc) {
      printf("%s = %s\n",
			argv[i],FromBase10(ToBase10(argv[i++],BaseFrom),BaseTo)
			   );
	   } /* while */
} /* main */
