iff	AST_COMMON
hdr	pthread
hdr	stdarg
hdr	varargs
hdr	stddef
hdr	types
sys	types
typ	size_t,ssize_t
typ	long.double

mac SF_CLOSE    sys/socket.h
mac SF_APPEND   sys/stat.h

proto	stdc note{ Standard-C prototypes ok }end compile{
	extern int foo(int, int);
	bar()
	{	foo(1, 1);
	}
}end

dll	import note{ Microsoft import/export nonsense }end execute{
	__declspec(dllimport) int foo;
	main() { return foo == 5 ? 0 : 1; }
	int	bar = 5;
	int*	_imp__foo = &bar;
}end

xopen	stdio note{ Stdio fseek/fflush are X/Open-compliant }end execute{
	#include	<stdio.h>
	#define Failed(file)	(unlink(file),1)
	main(int argc, char** argv)
	{	FILE	*f1, *f2;
		char	file[1024], buf[1024], *f, *t;
		int	i, fd;

		/* create file */
		for(f = argv[0], t = file; (*t = *f++) != 0; )
			t++;
		*t++ = '.'; *t++ = 'D'; *t++ = 0;
		if((fd = creat(file,0666)) < 0)
			return 1;

		for (i = 0; i < sizeof(buf); ++i)
			buf[i] = '0' + (i%10);
		for (i = 0; i < 16; ++i)
			if (write(fd,buf,sizeof(buf)) != sizeof(buf))
				return Failed(file);
		close(fd);

		if(!(f1 = fopen(file,"r+")) ||
		   (fd = dup(fileno(f1))) < 0 ||
		   !(f2 = fdopen(fd,"r+")) )
			return Failed(file);

		if(fread(buf, 1, 7, f2) != 7 || ftell(f2) != 7)
			return Failed(file);

		if(fseek(f1, 1010, 0) < 0 || ftell(f1) != 1010)
			return Failed(file);

		fflush(f2); /* this should set the seek location to 1010 */
		if(ftell(f2) != 1010)
			return Failed(file);

		unlink(file);
		return 0;
	}
}end

cat{
	
	/* __STD_C indicates that the language is ANSI-C or C++ */
	#if !defined(__STD_C) && __STDC__
	#define	__STD_C		1
	#endif
	#if !defined(__STD_C) && (__cplusplus || c_plusplus)
	#define __STD_C		1
	#endif
	#if !defined(__STD_C) && _proto_stdc
	#define __STD_C		1
	#endif
	#if !defined(__STD_C)
	#define __STD_C		0
	#endif

	/* extern symbols must be protected against C++ name mangling */
	#ifndef _BEGIN_EXTERNS_
	#if __cplusplus || c_plusplus
	#define _BEGIN_EXTERNS_	extern "C" {
	#define _END_EXTERNS_	}
	#else
	#define _BEGIN_EXTERNS_
	#define _END_EXTERNS_
	#endif
	#endif /*_BEGIN_EXTERNS_*/

	/* _ARG_ simplifies function prototyping among flavors of C */
	#ifndef _ARG_
	#if __STD_C
	#define _ARG_(x)	x
	#else
	#define _ARG_(x)	()
	#endif
	#endif /*_ARG_*/

	/* __INLINE__ is the inline keyword */
	#if !defined(__INLINE__) && defined(__cplusplus)
	#define __INLINE__	inline
	#endif
	#if !defined(__INLINE__) && defined(_WIN32) && !defined(__GNUC__)
	#define __INLINE__	__inline
	#endif

	/* Void_t is defined so that Void_t* can address any type */
	#ifndef Void_t
	#if __STD_C
	#define Void_t		void
	#else
	#define Void_t		char
	#endif
	#endif /*Void_t*/

	/* dynamic linked library external scope handling */
	#undef extern
	#if _dll_import && !defined(__EXPORT__) && _DLL_BLD
	#define __EXPORT__	__declspec(dllexport)
	#endif
	#if _dll_import && !defined(__IMPORT__)
	#define __IMPORT__	__declspec(dllimport)
	#endif
	#if !defined(_astimport)
	#if defined(__IMPORT__) && _DLL_BLD
	#define _astimport	__IMPORT__
	#else
	#define _astimport	extern
	#endif
	#endif /*_astimport*/
}end

cat{
	#if !_DLL_BLD && _dll_import
	#define __EXTERN__(T,obj)	extern T obj; T* _imp__ ## obj = &obj
	#define __DEFINE__(T,obj,val)	T obj = val; T* _imp__ ## obj = &obj
	#else
	#define __EXTERN__(T,obj)	extern T obj
	#define __DEFINE__(T,obj,val)	T obj = val
	#endif
}end

cat{
	#ifndef _AST_STD_H
	#	if _hdr_stddef
	#	include	<stddef.h>
	#	endif
	#	if _hdr_stdarg
	#	include <stdarg.h>
	#	elif _hdr_varargs
	#	include <varargs.h>
	#	endif
	#	if _sys_types
	#	include	<sys/types.h>
	#	endif
	#endif
	#if !_typ_size_t
	#	define _typ_size_t	1
		typedef int size_t;
	#endif
	#if !_typ_ssize_t
	#	define _typ_ssize_t	1
		typedef int ssize_t;
	#endif
}end

tst	- -DN=0 - -DN=1 - -DN=2 - -DN=3 - -DN=4 - -DN=5 - -DN=6 - -DN=7 - -DN=8 output{
	#define _BYTESEX_H

	#if _STD_
	#include	<stddef.h>
	#else
	#include	<sys/types.h>
	#endif

	_BEGIN_EXTERNS_
	extern int	printf _ARG_((const char*, ...));
	_END_EXTERNS_
	
	#if N == 0
	#define _ast_int8_t	long
	#define _ast_int8_str	"long"
	#endif
	#if N == 1
	#define _ast_int8_t	long long
	#define _ast_int8_str	"long long"
	#endif
	#if N == 2
	#define _ast_int8_t	__int64_t
	#define _ast_int8_str	"__int64_t"
	#endif
	#if N == 3
	#define _ast_int8_t	_int64_t
	#define _ast_int8_str	"_int64_t"
	#endif
	#if N == 4
	#define _ast_int8_t	int64_t
	#define _ast_int8_str	"int64_t"
	#endif
	#if N == 5
	#define _ast_int8_t	__int64
	#define _ast_int8_str	"__int64"
	#endif
	#if N == 6
	#define _ast_int8_t	_int64
	#define _ast_int8_str	"_int64"
	#endif
	#if N == 7
	#define _ast_int8_t	int64
	#define _ast_int8_str	"int64"
	#endif

	#define elementsof(x)	(sizeof(x)/sizeof(x[0]))
	
	static char		i_char = 1;
	static short		i_short = 1;
	static int		i_int = 1;
	static long		i_long = 1;
	#ifdef _ast_int8_t
	static _ast_int8_t	i_long_long = 1;
	#endif
	
	static struct
	{
		char*	name;
		int	size;
		char*	swap;
	} int_type[] = 
	{
		"char",		sizeof(char),		(char*)&i_char,
		"short",	sizeof(short),		(char*)&i_short,
		"int",		sizeof(int),		(char*)&i_int,
		"long",		sizeof(long),		(char*)&i_long,
	#ifdef _ast_int8_t
		_ast_int8_str,	sizeof(_ast_int8_t),	(char*)&i_long_long,
	#endif
	};
	
	static struct
	{
		char*	name;
		int	size;
	} flt_type[] = 
	{
		"float",	sizeof(float),
		"double",	sizeof(double),
	#ifdef _typ_long_double
		"long double",	sizeof(long double),
	#endif
	};
	
	static int	int_size[] = { 1, 2, 4, 8 };
	
	main()
	{
		register int	t;
		register int	s;
		register int	m = 1;
		register int	b = 1;
		register int	w = 0;
	
	#ifdef _ast_int8_t
		if (int_type[elementsof(int_type)-1].size <= 4)
			return 1;
	#endif
		for (s = 0; s < elementsof(int_size); s++)
		{
			for (t = 0; t < elementsof(int_type); t++)
				if(int_type[t].size >= int_size[s])
					break;
			if (t < elementsof(int_type))
			{
				m = int_size[s];
				printf("#define _ast_int%d_t\t\t%s\n",
					m, int_type[t].name);
				if (m > 1)
				{
					if (*int_type[t].swap)
						w |= b;
					b <<= 1;
				}
			}
		}
		printf("#define _ast_intmax_t		_ast_int%d_t\n", m);
		if (m == sizeof(long))
			printf("#define _ast_intmax_long		1\n");
		printf("#define _ast_intswap		%d\n", w);
		printf("\n");
		for (t = 0; t < elementsof(flt_type); t++)
		{
			for(; t < elementsof(flt_type); t++)
				if(flt_type[t].size != flt_type[t + 1].size)
					break;
			m = flt_type[t].size;
			printf("#define _ast_flt%d_t\t\t%s\n",
				flt_type[t].size, flt_type[t].name);
		}
		printf("#define _ast_fltmax_t		_ast_flt%d_t\n", m);
		if (m == sizeof(double))
			printf("#define _ast_fltmax_double		1\n");
		return 0;
	}
}end

tst - -DTRY=1 - -DTRY=1 -Dvoid=char - -DTRY=2 - -DTRY=3 - -DTRY=4 output{
	#define printf	______printf
	#ifdef __STDC__
	#include <stdarg.h>
	#else
	#include <varargs.h>
	#endif
	#undef	printf
	_BEGIN_EXTERNS_
	extern int	printf _ARG_((const char*, ...));
	_END_EXTERNS_
	static va_list ap;
	main()
	{
	#if TRY == 4
		printf("\n#ifndef va_listref\n");
		printf("#define va_listref(p) (&(p))\t");
			printf("/* pass va_list to varargs function */\n");
		printf("#define va_listval(p) (*(p))\t");
			printf("/* retrieve va_list from va_arg(ap,va_listarg) */\n");
		printf("#define va_listarg va_list*\t");
			printf("/* va_arg() va_list type */\n");
	#else
	#if TRY == 1
		*ap++;
	#endif /*TRY == 1*/
	#if TRY == 2
		*ap;
	#endif /*TRY == 2*/
	#if TRY == 3
		ap++;
	#endif /*TRY == 3*/

		printf("\n#ifndef va_listref\n");
		printf("#define va_listref(p) (p)\t");
			printf("/* pass va_list to varargs function */\n");
		printf("#define va_listval(p) (p)\t");
			printf("/* retrieve va_list from va_arg(ap,va_listarg) */\n");
	#if TRY == 2
		printf("#define va_listarg va_list*\t");
	#else
		printf("#define va_listarg va_list\t");
	#endif /*TRY == 2*/
			printf("/* va_arg() va_list type */\n");
	#endif /*TRY == 4*/

	#if defined(_WIN32) || !defined(va_copy)
		printf("#ifndef va_copy\n");
	#if TRY == 2
		printf("#define va_copy(to,fr) memcpy(to,fr,sizeof(va_list))\t");
			printf("/* copy va_list fr -> to */\n");
	#else
		printf("#define va_copy(to,fr) ((to)=(fr))\t");
			printf("/* copy va_list fr -> to */\n");
	#endif
		printf("#endif\n");
	#endif

	printf("#undef	_ast_va_list\n");
	printf("#ifdef	va_start\n");
	printf("#define _ast_va_list va_list\n");
	printf("#else\n");
	#if TRY == 1 || TRY == 2
		printf("#define _ast_va_list void*\t");
	#else
	#if TRY == 3
		if (sizeof(va_list) == sizeof(long))
			printf("#define _ast_va_list long\t");
		else if (sizeof(va_list) == sizeof(short))
			printf("#define _ast_va_list short\t");
		else
			printf("#define _ast_va_list int\t");
	#else
		printf("#define _ast_va_list ...\t");
	#endif
	#endif
		printf("/* va_list that avoids #include */\n");
		printf("#endif\n\n");
		printf("#endif\n");
		return 0;
	}
}end
