Implementation of strto(u)ll, documentation and tests for strto(u)l(l)
This commit is contained in:
@@ -1,19 +1,22 @@
|
||||
# Makefile for the tests.
|
||||
|
||||
CC = exec cc
|
||||
GCC = /usr/gnu/bin/gcc
|
||||
CFLAGS= -O -D_MINIX -D_POSIX_SOURCE
|
||||
CFLAGS-GCC= $(CFLAGS) -Wall
|
||||
|
||||
OBJ= test1 test2 test3 test4 test5 test6 test7 test8 test9 \
|
||||
test10 test12 test13 test14 test15 test16 test17 test18 test19 \
|
||||
test21 test22 test23 test25 test26 test27 test28 test29 \
|
||||
test30 test31 test32 test34 test35 test36 test37 test38 \
|
||||
test39 t10a t11a t11b test40 t40a t40b t40c t40d t40e t40f test41 \
|
||||
test42 test44
|
||||
test42 test44 test45
|
||||
|
||||
BIGOBJ= test20 test24
|
||||
ROOTOBJ= test11 test33 test43
|
||||
GCCOBJ= test45-gcc
|
||||
|
||||
all: $(OBJ) $(BIGOBJ) $(ROOTOBJ)
|
||||
all: $(OBJ) $(BIGOBJ) $(GCCOBJ) $(ROOTOBJ)
|
||||
chmod 755 *.sh run
|
||||
|
||||
$(OBJ):
|
||||
@@ -22,6 +25,9 @@ $(OBJ):
|
||||
$(BIGOBJ):
|
||||
$(CC) $(CFLAGS) -o $@ $@.c
|
||||
|
||||
$(GCCOBJ):
|
||||
[ ! -x $(GCC) ] || $(GCC) $(CFLAGS-GCC) -o $@ $<
|
||||
|
||||
$(ROOTOBJ):
|
||||
$(CC) $(CFLAGS) $@.c
|
||||
@install -c -o root -m 4755 a.out $@
|
||||
@@ -29,7 +35,7 @@ $(ROOTOBJ):
|
||||
|
||||
clean:
|
||||
cd select && make clean
|
||||
-rm -rf *.o *.s *.bak test? test?? t10a t11a t11b \
|
||||
-rm -rf *.o *.s *.bak test? test?? test??-gcc t10a t11a t11b \
|
||||
t40a t40b t40c t40d t40e t40f t43 DIR*
|
||||
|
||||
test1: test1.c
|
||||
@@ -85,3 +91,6 @@ test41: test41.c
|
||||
test42: test42.c
|
||||
test43: test43.c
|
||||
test44: test44.c
|
||||
test45: test45.c test45.h
|
||||
test45-gcc: test45.c test45.h
|
||||
|
||||
|
||||
35
test/run
35
test/run
@@ -7,6 +7,7 @@ export PATH
|
||||
rm -rf DIR* # remove any old junk lying around
|
||||
passed=`expr 0` # count number of tests run correctly
|
||||
failed=`expr 0` # count number of tests that failed
|
||||
skipped=`expr 0` # count number of tests that were skipped
|
||||
total=`expr 0` # total number of tests tried
|
||||
badones= # list of tests that failed
|
||||
|
||||
@@ -18,26 +19,32 @@ echo " "
|
||||
# Run all the tests, keeping track of who failed.
|
||||
for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \
|
||||
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \
|
||||
41 42 43 44 sh1.sh sh2.sh
|
||||
do total=`expr $total + 1`
|
||||
FAIL=0
|
||||
if [ $USER = root -a \( $i = 11 -o $i = 33 \) ]
|
||||
then su - ast -c "cd `pwd`; ./test$i" || FAIL=1
|
||||
else ./test$i || FAIL=1
|
||||
fi
|
||||
|
||||
if [ $FAIL -eq 0 ]
|
||||
then passed=`expr $passed + 1`
|
||||
else failed=`expr $failed + 1`
|
||||
badones=`echo $badones " " $i`
|
||||
41 42 43 44 45 45-gcc sh1.sh sh2.sh
|
||||
do
|
||||
if [ -x ./test$i ]
|
||||
then
|
||||
total=`expr $total + 1`
|
||||
FAIL=0
|
||||
if [ $USER = root -a \( $i = 11 -o $i = 33 \) ]
|
||||
then su - ast -c "cd `pwd`; ./test$i" || FAIL=1
|
||||
else ./test$i || FAIL=1
|
||||
fi
|
||||
if [ $FAIL -eq 0 ]
|
||||
then passed=`expr $passed + 1`
|
||||
else failed=`expr $failed + 1`
|
||||
badones=`echo $badones " " $i`
|
||||
fi
|
||||
else
|
||||
skipped=`expr $skipped + 1`
|
||||
fi
|
||||
done
|
||||
|
||||
# Print results of the tests.
|
||||
echo " "
|
||||
if test $total = $passed
|
||||
then echo All $passed tests completed without error.
|
||||
else echo Testing completed. Score: $passed passed, $failed failed
|
||||
then echo All $passed tests completed without error \($skipped skipped\).
|
||||
else echo Testing completed. Score: $passed passed, $failed failed, \
|
||||
skipped $skipped
|
||||
echo The following tests failed: $badones
|
||||
fi
|
||||
|
||||
|
||||
85
test/test45.c
Normal file
85
test/test45.c
Normal file
@@ -0,0 +1,85 @@
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define MAX_ERROR 4
|
||||
static int errct;
|
||||
|
||||
/* test strtol */
|
||||
#define TYPE long
|
||||
#define TYPEU unsigned long
|
||||
#define TYPE_FUNC strtol
|
||||
#include "test45.h"
|
||||
#undef TYPE
|
||||
#undef TYPEU
|
||||
#undef TYPE_FUNC
|
||||
|
||||
/* test strtoul */
|
||||
#define TYPE unsigned long
|
||||
#define TYPEU unsigned long
|
||||
#define TYPE_FUNC strtoul
|
||||
#include "test45.h"
|
||||
#undef TYPE
|
||||
#undef TYPEU
|
||||
#undef TYPE_FUNC
|
||||
|
||||
#ifdef __LONG_LONG_SUPPORTED
|
||||
|
||||
/* test strtoll */
|
||||
#define TYPE long long
|
||||
#define TYPEU unsigned long long
|
||||
#define TYPE_FUNC strtoll
|
||||
#include "test45.h"
|
||||
#undef TYPE
|
||||
#undef TYPEU
|
||||
#undef TYPE_FUNC
|
||||
|
||||
/* test strtoull */
|
||||
#define TYPE long long
|
||||
#define TYPEU unsigned long long
|
||||
#define TYPE_FUNC strtoull
|
||||
#include "test45.h"
|
||||
#undef TYPE
|
||||
#undef TYPEU
|
||||
#undef TYPE_FUNC
|
||||
|
||||
#endif /* defined(__LONG_LONG_SUPPORTED) */
|
||||
|
||||
static void quit(void)
|
||||
{
|
||||
if (errct == 0)
|
||||
{
|
||||
printf("ok\n");
|
||||
exit(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("%d errors\n", errct);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
#ifdef __LONG_LONG_SUPPORTED
|
||||
printf("Test 45 (GCC) ");
|
||||
#else
|
||||
printf("Test 45 (ACK) ");
|
||||
#endif
|
||||
fflush(stdout);
|
||||
|
||||
/* run long/unsigned long tests */
|
||||
test_strtol();
|
||||
test_strtoul();
|
||||
|
||||
/* run long long/unsigned long long tests (GCC only) */
|
||||
#ifdef __LONG_LONG_SUPPORTED
|
||||
test_strtoll();
|
||||
test_strtoull();
|
||||
#endif /* defined(__LONG_LONG_SUPPORTED) */
|
||||
|
||||
quit();
|
||||
return -1; /* never happens */
|
||||
}
|
||||
157
test/test45.h
Normal file
157
test/test45.h
Normal file
@@ -0,0 +1,157 @@
|
||||
#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
|
||||
Reference in New Issue
Block a user