158 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			158 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
#define GLUE_HELPER(x, y) x ## _ ## y
 | 
						|
#define GLUE(x, y) GLUE_HELPER(x, y)
 | 
						|
#define TOSTRING(x) #x
 | 
						|
 | 
						|
static const char *GLUE(make_string, TYPE_FUNC)(TYPE value, int base)
 | 
						|
{
 | 
						|
	static char buffer[66];
 | 
						|
	char *s; /* allows 64-bit base 2 value with minus and null */
 | 
						|
	TYPEU valuetemp;
 | 
						|
	
 | 
						|
	/* build number string in proper base, work backwards, starting with null */
 | 
						|
	s = buffer + sizeof(buffer);
 | 
						|
	*--s = 0;
 | 
						|
 | 
						|
	/* fill in the digits */
 | 
						|
	valuetemp = (value < 0) ? -value : value;
 | 
						|
	do
 | 
						|
	{
 | 
						|
		*--s = "0123456789abcdefghijklmnopqrstuvwxyz"[valuetemp % base];
 | 
						|
		valuetemp /= base;
 | 
						|
	} while (valuetemp);
 | 
						|
 | 
						|
	/* add sign if needed */
 | 
						|
	if (value < 0)
 | 
						|
		*--s = '-';
 | 
						|
 | 
						|
	return s;
 | 
						|
}
 | 
						|
 | 
						|
static void GLUE(e, TYPE_FUNC)(int n, const char *s, TYPE result, int base)
 | 
						|
{
 | 
						|
	/* watch out: don't overwrite the static buffer in make_string */
 | 
						|
	printf("Subtest %s, error %d, errno=%d, s=\"%s\", base=%d, ", TOSTRING(TYPE_FUNC), n, errno, s, base);
 | 
						|
	printf("result=%s\n", GLUE(make_string, TYPE_FUNC)(result, base));
 | 
						|
	if (errct++ > MAX_ERROR) 
 | 
						|
	{
 | 
						|
		printf("Too many errors; test aborted\n");
 | 
						|
		exit(1);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
static void GLUE(test_string, TYPE_FUNC)(const char *s, TYPE value, int base)
 | 
						|
{
 | 
						|
	char *end;
 | 
						|
	TYPE result;
 | 
						|
 | 
						|
	/* must convert the entire string, resulting in the requested value */
 | 
						|
	result = TYPE_FUNC(s, &end, base);
 | 
						|
	if (result != value) GLUE(e, TYPE_FUNC)(1, s, result, base);
 | 
						|
	if (*end) GLUE(e, TYPE_FUNC)(2, s, result, base);
 | 
						|
}
 | 
						|
 | 
						|
static void GLUE(test_value_with_base, TYPE_FUNC)(TYPE value, int base)
 | 
						|
{
 | 
						|
	const char *s;
 | 
						|
 | 
						|
	/* convert to string, then convert back */
 | 
						|
	s = GLUE(make_string, TYPE_FUNC)(value, base);
 | 
						|
	GLUE(test_string, TYPE_FUNC)(s, value, base);
 | 
						|
}
 | 
						|
 | 
						|
static void GLUE(test_value, TYPE_FUNC)(TYPE value)
 | 
						|
{
 | 
						|
	int base;
 | 
						|
 | 
						|
	/* let's get all our bases covered */
 | 
						|
	for (base = 2; base <= 36; base++)
 | 
						|
		GLUE(test_value_with_base, TYPE_FUNC)(value, base);
 | 
						|
}
 | 
						|
 | 
						|
static void GLUE(test, TYPE_FUNC)(void)
 | 
						|
{
 | 
						|
	int base, i;
 | 
						|
	TYPE value, valuenext;
 | 
						|
 | 
						|
	/* check 0x0000.... and 0xffff.... */
 | 
						|
	value = 0;
 | 
						|
	for (i = 0; i < 0x10000; i++)
 | 
						|
	{
 | 
						|
		/* test current value */
 | 
						|
		GLUE(test_value, TYPE_FUNC)(value);
 | 
						|
		GLUE(test_value, TYPE_FUNC)(-value);
 | 
						|
		value++;
 | 
						|
	}
 | 
						|
 | 
						|
	/* check 0x8000.... and 0x7fff.... */
 | 
						|
	value = 0;
 | 
						|
	value = ((~value) << 1) >> 1;
 | 
						|
	for (i = 0; i < 0x10000; i++)
 | 
						|
	{
 | 
						|
		/* test current value */
 | 
						|
		GLUE(test_value, TYPE_FUNC)(value);
 | 
						|
		GLUE(test_value, TYPE_FUNC)(-value);
 | 
						|
		value++;
 | 
						|
	}
 | 
						|
 | 
						|
	/* check powers of possible bases */
 | 
						|
	for (base = 2; base <= 36; base++)
 | 
						|
	{
 | 
						|
		value = 1;
 | 
						|
		while (1)
 | 
						|
		{
 | 
						|
			/* test current value with offsets */
 | 
						|
			for (i = -36; i <= 36; i++)
 | 
						|
			{
 | 
						|
				GLUE(test_value, TYPE_FUNC)(value + i);
 | 
						|
				GLUE(test_value, TYPE_FUNC)(-value + i);
 | 
						|
			}
 | 
						|
 | 
						|
			/* stop after overflow */
 | 
						|
			valuenext = value * base;
 | 
						|
			if (valuenext <= value)
 | 
						|
				break;
 | 
						|
 | 
						|
			value = valuenext;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	/* automatic base */
 | 
						|
	GLUE(test_string, TYPE_FUNC)("10",  10,  0);
 | 
						|
	GLUE(test_string, TYPE_FUNC)("010", 010, 0);
 | 
						|
	GLUE(test_string, TYPE_FUNC)("010", 010, 8);
 | 
						|
	GLUE(test_string, TYPE_FUNC)("0x10", 0x10, 0);
 | 
						|
	GLUE(test_string, TYPE_FUNC)("0X10", 0X10, 0);
 | 
						|
	GLUE(test_string, TYPE_FUNC)("0x10", 0x10, 16);
 | 
						|
	GLUE(test_string, TYPE_FUNC)("0X10", 0X10, 16);
 | 
						|
 | 
						|
	/* ignore plus sign, leading spaces and zeroes */
 | 
						|
	GLUE(test_string, TYPE_FUNC)("10", 10, 10);
 | 
						|
	GLUE(test_string, TYPE_FUNC)("010", 10, 10);
 | 
						|
	GLUE(test_string, TYPE_FUNC)("0010", 10, 10);
 | 
						|
	GLUE(test_string, TYPE_FUNC)(" 10", 10, 10);
 | 
						|
	GLUE(test_string, TYPE_FUNC)(" 010", 10, 10);
 | 
						|
	GLUE(test_string, TYPE_FUNC)(" 0010", 10, 10);
 | 
						|
	GLUE(test_string, TYPE_FUNC)("\t10", 10, 10);
 | 
						|
	GLUE(test_string, TYPE_FUNC)("\t010", 10, 10);
 | 
						|
	GLUE(test_string, TYPE_FUNC)("\t0010", 10, 10);
 | 
						|
	GLUE(test_string, TYPE_FUNC)(" \t10", 10, 10);
 | 
						|
	GLUE(test_string, TYPE_FUNC)(" \t010", 10, 10);
 | 
						|
	GLUE(test_string, TYPE_FUNC)(" \t0010", 10, 10);
 | 
						|
	GLUE(test_string, TYPE_FUNC)("+10", 10, 10);
 | 
						|
	GLUE(test_string, TYPE_FUNC)("+010", 10, 10);
 | 
						|
	GLUE(test_string, TYPE_FUNC)("+0010", 10, 10);
 | 
						|
	GLUE(test_string, TYPE_FUNC)(" +10", 10, 10);
 | 
						|
	GLUE(test_string, TYPE_FUNC)(" +010", 10, 10);
 | 
						|
	GLUE(test_string, TYPE_FUNC)(" +0010", 10, 10);
 | 
						|
	GLUE(test_string, TYPE_FUNC)("\t+10", 10, 10);
 | 
						|
	GLUE(test_string, TYPE_FUNC)("\t+010", 10, 10);
 | 
						|
	GLUE(test_string, TYPE_FUNC)("\t+0010", 10, 10);
 | 
						|
	GLUE(test_string, TYPE_FUNC)(" \t+10", 10, 10);
 | 
						|
	GLUE(test_string, TYPE_FUNC)(" \t+010", 10, 10);
 | 
						|
	GLUE(test_string, TYPE_FUNC)(" \t+0010", 10, 10);
 | 
						|
}
 | 
						|
 | 
						|
#undef GLUE_HELPER
 | 
						|
#undef GLUE
 | 
						|
#undef TOSTRING
 |