#include <stdio.h>
#include <errno.h>
extern int errno;

#define CONVRT strtoul



#if __STDC__
#include <stdlib.h>
#include <limits.h>
#else
#define const /* */
extern unsigned long CONVRT();
#define LONG_MAX 2147483647L
#define LONG_MIN (-2147483648L)
#define ULONG_MAX (4294967295U)
#endif
#ifndef OK
#define OK 0
#endif

struct test {
  const char	*string;	/* the string 		*/
  unsigned long  val;		/* expected result 	*/
  int		err;		/* expected errno 	*/
  int		endp;		/* index of expected end ptr	*/
} tests [] = {
  { "0",		0L,		OK,      1	 },
  { "-12345",		-12345L,	OK,      6	 },
  { "12345",		12345L,		OK,      5	 },
  { "-0x12345",		-0x12345L,	OK,      8	 },
  { "0x12345",		0x12345L,	OK,      7	 },
  { "-012345",		-012345L,	OK,      7	 },
  { "012345",		012345L,	OK,      6	 },
  { "10]",	     	 10L,		OK,      2	 },
					         
  { "2147483645L",	2147483645L,	OK,      10	 },
  { "2147483646L",	2147483646L,	OK,      10	 },
  { "2147483647L",	2147483647L,	OK,      10	 },
  { "2147483648L",	2147483648L,	OK,	 10	 },
  { "2147483649L",	2147483649L,	OK,	 10	 },
					         
  { "-2147483646L",	2147483650L,	OK,      11	 },
  { "-2147483647L",	2147483649L,	OK,      11	 },
  { "-2147483648L",	2147483648L,	OK,      11	 },
  { "-2147483649L",	2147483647L,	OK,	 11	 },
  { "-2147484648L",	2147482648L,	OK,	 11	 },
					         
  { "       567L",	567L,		OK,      10	 },
  { "\t      567 ",	567L,		OK,      10	 },
  { "      -567]",     -567L,		OK,      10	 },
					         
  { "ZZZZZZ",		  0L,		OK,      0	 },
  { "0xGZZZZZ",		  0L,		OK,      1	 },
  { "08ZZZZZZ",		  0L,		OK,      1	 },
  { "+0x1ZZZZZZ",	  1L,		OK,      4	 },
  { " -07188888",      -071L,		OK,      5	 },
					         
  { " +017777777777+",	LONG_MAX,	OK,      14	 },
  { " +027777777777+",	3221225471,	OK,      14	 },
  { " -017777777777+",	LONG_MIN+1,	OK,      14	 },
  { " -020000000000+",	LONG_MIN,	OK,      14	 },
  { " -037777777777+",	1,		OK,	 14	 },
  { "-037777777777+",	1,		OK, 	 13	 },
  { "037777777777+",	ULONG_MAX,	OK,	 12	 },
					         
  { ""		    ,          0,       OK,      0	 },
  { "\t\t"	    ,          0,       OK,      0	 },
  { "+"		    ,          0,       OK,      0	 },
  { "-"		    ,          0,       OK,      0	 },
  { NULL,		       0,	OK,      0	 }
};

void fail(i, test, res, err, endp)
int i;
struct test *test;
long res;
int err;
char *endp;
{
    printf("Test %d (\"%s\") failed\n", i, test->string);
    printf("\tExpecting:\t%10lu\t%3d\t%x\n", test->val, test->err,
 &(test->string[(test->endp)]));
    printf("\tGot:\t\t%10lu\t%3d\t%x\n", res, err, endp);
}

int main()
{
    int i, errs = 0;
    unsigned long res;
    char *endp;

    for(i = 0; tests[i].string; i++)
    {
	errno = OK;
	res = CONVRT(tests[i].string, &endp, 0);
	if(res != tests[i].val)
	{
	   fail(i, &tests[i], res, errno, endp);
	   errs++;
	}
	else if(tests[i].err != errno)
	{
	   fail(i, &tests[i], res, errno, endp);
	   errs++;
	}
	else if( &(tests[i].string[(tests[i].endp)]) != endp)
	{
	   fail(i, &tests[i], res, errno, endp);
	   errs++;
	}
    }

    if (errs) printf("%d error(s)\n", errs);
    return errs ?  EXIT_FAILURE : EXIT_SUCCESS;
}
