mirror of
https://github.com/cc65/cc65.git
synced 2024-11-18 15:05:14 +00:00
133 lines
3.6 KiB
C
133 lines
3.6 KiB
C
|
/* A small test for strtuol. Assumes twos complement */
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <limits.h>
|
||
|
#include <errno.h>
|
||
|
|
||
|
|
||
|
|
||
|
#define outfile stderr
|
||
|
|
||
|
|
||
|
|
||
|
#define ERROR 0
|
||
|
#define OK 1
|
||
|
|
||
|
|
||
|
|
||
|
static unsigned int Failures = 0;
|
||
|
|
||
|
|
||
|
|
||
|
static void IncStr (char* Buf)
|
||
|
/* Increment a number represented as a string by one. The string MUST not
|
||
|
* start with a '9', we cannot handle overflow in this case.
|
||
|
*/
|
||
|
{
|
||
|
int Len = strlen (Buf);
|
||
|
|
||
|
while (--Len >= 0) {
|
||
|
switch (Buf[Len]) {
|
||
|
case '9':
|
||
|
Buf[Len] = '0';
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
++(Buf[Len]);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
static void CheckStrToUL (const char* Str, int Base, unsigned long Val, unsigned char Ok)
|
||
|
{
|
||
|
char* EndPtr;
|
||
|
unsigned long Res = strtoul (Str, &EndPtr, Base);
|
||
|
if (Ok) {
|
||
|
if (Res != Val) {
|
||
|
fprintf (outfile,
|
||
|
"strtol error in \"%s\":\n"
|
||
|
" result = %lu, should be %lu, chars = %d\n",
|
||
|
Str, Res, Val, EndPtr - Str);
|
||
|
++Failures;
|
||
|
}
|
||
|
} else {
|
||
|
if (errno != ERANGE) {
|
||
|
fprintf (outfile,
|
||
|
"strtol error in \"%s\":\n"
|
||
|
" should not convert, but errno = %d\n",
|
||
|
Str, errno);
|
||
|
++Failures;
|
||
|
}
|
||
|
if (Res != Val) {
|
||
|
fprintf (outfile,
|
||
|
"strtol error in \"%s\":\n"
|
||
|
" result = %lu, should be %lu, chars = %d\n",
|
||
|
Str, Res, Val, EndPtr - Str);
|
||
|
++Failures;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
int main (void)
|
||
|
{
|
||
|
char Buf[80];
|
||
|
|
||
|
/* Prefixed allowed if base = 0 */
|
||
|
CheckStrToUL ("\t 0x10G ", 0, 16UL, OK);
|
||
|
CheckStrToUL ("\t 0X10G ", 0, 16UL, OK);
|
||
|
CheckStrToUL (" \t0377\t", 0, 255UL, OK);
|
||
|
CheckStrToUL (" 377", 0, 377UL, OK);
|
||
|
|
||
|
CheckStrToUL ("\t -0x10G ", 0, (unsigned long) -16L, OK);
|
||
|
CheckStrToUL ("\t -0X10G ", 0, (unsigned long) -16L, OK);
|
||
|
CheckStrToUL (" \t-0377\t", 0, (unsigned long) -255L, OK);
|
||
|
CheckStrToUL (" -377", 0, (unsigned long) -377L, OK);
|
||
|
|
||
|
/* No prefixes if base = 10 */
|
||
|
CheckStrToUL ("\t 1234 ", 10, 1234UL, OK);
|
||
|
CheckStrToUL ("\t -1234 ", 10, (unsigned long) -1234L, OK);
|
||
|
CheckStrToUL ("\t -0x10G ", 10, 0UL, OK);
|
||
|
CheckStrToUL ("\t -0X10G ", 10, 0UL, OK);
|
||
|
CheckStrToUL (" \t-0377\t", 10, (unsigned long) -377L, OK);
|
||
|
CheckStrToUL (" 0377", 10, 377UL, OK);
|
||
|
|
||
|
/* 0x prefix is allowed if base = 16 */
|
||
|
CheckStrToUL ("\t 0x1234 ", 16, 0x1234UL, OK);
|
||
|
CheckStrToUL ("\t -0x1234 ", 16, (unsigned long) -0x1234L, OK);
|
||
|
CheckStrToUL ("\t -010G ", 16, (unsigned long) -16L, OK);
|
||
|
CheckStrToUL ("\t 10G ", 16, 16UL, OK);
|
||
|
|
||
|
/* Check ULONG_MAX */
|
||
|
sprintf (Buf, "%lu", ULONG_MAX);
|
||
|
CheckStrToUL (Buf, 0, ULONG_MAX, OK);
|
||
|
|
||
|
/* Check value one larger */
|
||
|
sprintf (Buf+1, "%lu", ULONG_MAX);
|
||
|
Buf[0] = '0';
|
||
|
IncStr (Buf);
|
||
|
if (Buf[0] == '0') {
|
||
|
Buf[0] = ' ';
|
||
|
}
|
||
|
CheckStrToUL (Buf, 0, ULONG_MAX, ERROR);
|
||
|
|
||
|
/* Check numbers that are much too large or small */
|
||
|
CheckStrToUL ("-999999999999999999999999999999999999999999999999999999999", 0, ULONG_MAX, ERROR);
|
||
|
CheckStrToUL ("+999999999999999999999999999999999999999999999999999999999", 0, ULONG_MAX, ERROR);
|
||
|
CheckStrToUL (" 999999999999999999999999999999999999999999999999999999999", 0, ULONG_MAX, ERROR);
|
||
|
|
||
|
/* Check a few other bases */
|
||
|
CheckStrToUL ("aBcD", 36, 481261UL, OK);
|
||
|
CheckStrToUL ("zyaB", 35, 0UL, ERROR);
|
||
|
CheckStrToUL ("zyaB", 36, 1677395UL, ERROR);
|
||
|
|
||
|
fprintf (outfile, "Failures: %u\n", Failures);
|
||
|
return (Failures != 0);
|
||
|
}
|
||
|
|