/* NumToStr.c Copyright © 1993 Fergus Duniho */

#include <ctype.h>

char *itoa (int num, int base);
char *roman (int num, int up);
char *romdig (char *, int, char, char, char, int);

char *itoa (int num, int base) {
    int i, len, neg = (num < 0);
    static char *digits = "0123456789ABCDEF";
    char *str;

    if (base > 16)
	base = 16;
    if (base < 2)
	base = 2;
    if (neg)
	num = -num;
    for (i = num, len = neg; i > 0; i /= base, len++);
    str = (char *)malloc(len+1);

    str += len;
    *str = '\0';
    for (i = num; i > 0; i /= base)
	*(--str) = digits[i % base];
    if (neg)
	*(--str) = '-';
    return str;
}

char *roman (int num, int up) {
    int i;
    char *numeral = (char *)malloc(16);
    char *var = numeral;

    if (num > 999) {
	i = num / 1000;
	while (i--)
	    *var++ = 'm';
	num %= 1000;
    }
    if (num > 99) {
	var = romdig(var, num / 100, 'c', 'd', 'm', up);
	num %= 100;
    }
    if (num > 9) {
	var = romdig(var, num / 10, 'x', 'l', 'c', up);
	num %= 10;
    }
    if (num)
	var = romdig(var, num, 'i', 'v', 'x', up);
    *var = 0;
    return numeral;
}

char *romdig (char *var, int num, char i, char v, char x, int up) {
    if (up) {
	i = toupper(i);
	v = toupper(v);
	x = toupper(x);
    }

    switch (num) {
	case 3:
	    *var++ = i;
	case 2:
	    *var++ = i;
	case 1:
	    *var++ = i;
	    break;
	case 4:
	    *var++ = i;
	case 5:
	    *var++ = v;
	    break;
	case 6:
	    *var++ = v;
	    *var++ = i;
	    break;
	case 7:
	    *var++ = v;
	    *var++ = i;
	    *var++ = i;
	    break;
	case 8:
	    *var++ = v;
	    *var++ = i;
	    *var++ = i;
	    *var++ = i;
	    break;
	case 9:
	    *var++ = i;
	    *var++ = x;
	    break;
    }
    return var;
}
