1iff	AST_COMMON
2hdr	pthread,stdarg,stddef,stdint,inttypes,types,unistd
3sys	types
4typ	long.double,size_t,ssize_t
5typ	__va_list stdio.h
6
7mac	SF_APPEND,SF_CLOSE	sys/stat.h sys/socket.h
8
9dll	import note{ Microsoft import/export nonsense }end execute{
10	__declspec(dllimport) int foo;
11	int main() { return foo == 5 ? 0 : 1; }
12	int	bar = 5;
13	int*	_imp__foo = &bar;
14}end
15
16std	proto note{ standard C prototypes ok }end compile{
17	extern int foo(int, int);
18	bar() { foo(1, 1); }
19}end
20
21tst	ptr_void note{ standard C void* ok }end compile{
22	extern void* foo();
23	void* bar() { return foo(); }
24}end
25
26cat{
27	/* disable non-standard linux/gnu inlines */
28	#ifdef __GNUC__
29	#	undef	__OPTIMIZE_SIZE__
30	#	define	__OPTIMIZE_SIZE__	1
31	#endif
32
33	/* __STD_C indicates that the language is ANSI-C or C++ */
34	#if !defined(__STD_C) && __STDC__
35	#	define	__STD_C		1
36	#endif
37	#if !defined(__STD_C) && (__cplusplus || c_plusplus)
38	#	define __STD_C		1
39	#endif
40	#if !defined(__STD_C) && _std_proto
41	#	define __STD_C		1
42	#endif
43	#if !defined(__STD_C)
44	#	define __STD_C		0
45	#endif
46
47	/* extern symbols must be protected against C++ name mangling */
48	#ifndef _BEGIN_EXTERNS_
49	#	if __cplusplus || c_plusplus
50	#		define _BEGIN_EXTERNS_	extern "C" {
51	#		define _END_EXTERNS_	}
52	#	else
53	#		define _BEGIN_EXTERNS_
54	#		define _END_EXTERNS_
55	#	endif
56	#endif
57
58	/* _ARG_ simplifies function prototyping among flavors of C */
59	#ifndef _ARG_
60	#	if __STD_C
61	#		define _ARG_(x)	x
62	#	else
63	#		define _ARG_(x)	()
64	#	endif
65	#endif
66
67	/* _NIL_ simplifies defining nil pointers to a given type */
68	#ifndef _NIL_
69	#	define _NIL_(x)	((x)0)
70	#endif
71
72	/* __INLINE__, if defined, is the inline keyword */
73	#if !defined(__INLINE__) && defined(__cplusplus)
74	#	define __INLINE__	inline
75	#endif
76	#if !defined(__INLINE__) && defined(_WIN32) && !defined(__GNUC__)
77	#	define __INLINE__	__inline
78	#endif
79
80	/* Void_t is defined so that Void_t* can address any type */
81	#ifndef Void_t
82	#	if __STD_C
83	#		define Void_t		void
84	#	else
85	#		define Void_t		char
86	#	endif
87	#endif
88
89	/* windows variants and veneers */
90	#if !defined(_WINIX) && (_UWIN || __CYGWIN__ || __EMX__)
91	#	define _WINIX		1
92	#endif
93
94	/* dynamic linked library external scope handling */
95	#ifdef __DYNAMIC__
96	#	undef	__DYNAMIC__
97	#	ifndef _DLL
98	#		define _DLL		1
99	#	endif
100	#endif
101	#if _dll_import
102	#	if _BLD_STATIC && !_BLD_DLL
103	#		undef	_DLL
104	#	else
105	#		if !_UWIN && !defined(_DLL)
106	#			define _DLL		1
107	#		endif
108	#	endif
109	#	if !defined(__EXPORT__) && _BLD_DLL
110	#		define __EXPORT__	__declspec(dllexport)
111	#	endif
112	#	if !defined(__IMPORT__) && ( _BLD_DLL || defined(_DLL) )
113	#		define __IMPORT__	__declspec(dllimport)
114	#	endif
115	#	if _BLD_DLL && _UWIN
116	#	define __DYNAMIC__(v)		(_ast_getdll()->_ast_ ## v)
117	#	endif
118	#endif
119	#if !defined(_astimport)
120	#	if defined(__IMPORT__) && defined(_DLL)
121	#		define _astimport	__IMPORT__
122	#	else
123	#		define _astimport	extern
124	#	endif
125	#endif
126	#if _dll_import && ( !_BLD_DLL || _WINIX && !_UWIN )
127	#	ifdef __STDC__
128	#	define __EXTERN__(T,obj)	extern T obj; T* _imp__ ## obj = &obj
129	#	define __DEFINE__(T,obj,val)	T obj = val; T* _imp__ ## obj = &obj
130	#	else
131	#	define __EXTERN__(T,obj)	extern T obj; T* _imp__/**/obj = &obj
132	#	define __DEFINE__(T,obj,val)	T obj = val; T* _imp__/**/obj = &obj
133	#	endif
134	#else
135	#	define __EXTERN__(T,obj)	extern T obj
136	#	define __DEFINE__(T,obj,val)	T obj = val
137	#endif
138}end
139
140if	tst - note{ <stdarg.h>+<wchar.h> works }end compile{
141		/*<NOSTDIO>*/
142		#include <stdarg.h>
143		#include <wchar.h>
144	}end
145elif	tst - note{ explicit <sys/va_list.h> before <stdarg.h>+<wchar.h> }end compile{
146		/*<NOSTDIO>*/
147		#include <sys/va_list.h>
148		#include <stdarg.h>
149		#include <wchar.h>
150	}end {
151		#include <sys/va_list.h>
152	}
153endif
154
155tst	ast_LL note{ LL numeric suffix supported }end compile{
156	int i = 1LL;
157	unsigned int u = 1ULL; /* NOTE: some compilers choke on 1LLU */
158}end
159
160tst	- -DN=1 - -DN=2 - -DN=3 - -DN=4 - -DN=5 - -DN=6 - -DN=7 - -DN=8 - -DN=0 output{
161	#define _BYTESEX_H
162
163	#include <string.h>
164	#include <sys/types.h>
165
166	#if _STD_
167	#if N == 1
168	#define _ast_int8_t	long
169	#define _ast_int8_str	"long"
170	#endif
171	#if N == 2
172	#define _ast_int8_t	long long
173	#define _ast_int8_str	"long long"
174	#endif
175	#if N == 3
176	#define _ast_int8_t	__int64
177	#define _ast_int8_str	"__int64"
178	#endif
179	#if N == 4
180	#define _ast_int8_t	__int64_t
181	#define _ast_int8_str	"__int64_t"
182	#endif
183	#if N == 5
184	#define _ast_int8_t	_int64_t
185	#define _ast_int8_str	"_int64_t"
186	#endif
187	#if N == 6
188	#define _ast_int8_t	int64_t
189	#define _ast_int8_str	"int64_t"
190	#endif
191	#if N == 7
192	#define _ast_int8_t	_int64
193	#define _ast_int8_str	"_int64"
194	#endif
195	#if N == 8
196	#define _ast_int8_t	int64
197	#define _ast_int8_str	"int64"
198	#endif
199	#endif
200
201	#define elementsof(x)	(sizeof(x)/sizeof(x[0]))
202
203	static char			i_char = 1;
204	static short			i_short = 1;
205	static int			i_int = 1;
206	static long			i_long = 1L;
207	#ifdef _ast_int8_t
208	#if _ast_LL
209	static _ast_int8_t		i_long_long = 1LL;
210	static unsigned _ast_int8_t	u_long_long = 18446744073709551615ULL;
211	#else
212	static _ast_int8_t		i_long_long = 1;
213	static unsigned _ast_int8_t	u_long_long = 18446744073709551615;
214	#endif
215	#endif
216
217	static struct
218	{
219		char*	name;
220		int	size;
221		char*	swap;
222	} int_type[] =
223	{
224		"char",		sizeof(char),		(char*)&i_char,
225		"short",	sizeof(short),		(char*)&i_short,
226		"int",		sizeof(int),		(char*)&i_int,
227		"long",		sizeof(long),		(char*)&i_long,
228	#ifdef _ast_int8_t
229		_ast_int8_str,	sizeof(_ast_int8_t),	(char*)&i_long_long,
230	#endif
231	};
232
233	static int	int_size[] = { 1, 2, 4, 8 };
234
235	int
236	main()
237	{
238		register int	t;
239		register int	s;
240		register int	m = 1;
241		register int	b = 1;
242		register int	w = 0;
243
244	#ifdef _ast_int8_t
245		unsigned _ast_int8_t	p;
246		char			buf[64];
247
248		if (int_type[elementsof(int_type)-1].size <= 4)
249			return 1;
250		p = 0x12345678;
251		p <<= 32;
252		p |= 0x9abcdef0;
253		sprintf(buf, "0x%016llx", p);
254		if (strcmp(buf, "0x123456789abcdef0"))
255			return 1;
256	#endif
257		for (s = 0; s < elementsof(int_size); s++)
258		{
259			for (t = 0; t < elementsof(int_type) && int_type[t].size < int_size[s]; t++);
260			if (t < elementsof(int_type))
261			{
262				m = int_size[s];
263	#if __INTERIX
264				if (m == 8)
265				{
266					printf("#ifdef _MSC_VER\n");
267					printf("#define _ast_int8_t	__int64\n");
268					printf("#else\n");
269					printf("#define _ast_int8_t	long long\n");
270					printf("#endif\n");
271				}
272				else
273	#endif
274				printf("#define _ast_int%d_t		%s\n", m, int_type[t].name);
275				if (m > 1)
276				{
277					if (*int_type[t].swap)
278						w |= b;
279					b <<= 1;
280				}
281			}
282		}
283		printf("#define _ast_intmax_t		_ast_int%d_t\n", m);
284		if (m == sizeof(long))
285			printf("#define _ast_intmax_long	1\n");
286		printf("#define _ast_intswap		%d\n", w);
287		printf("\n");
288		printf("#define _ast_sizeof_intmax_t	%d	/* sizeof(intmax_t) */\n", m);
289		return 0;
290	}
291}end
292
293tst	- output{
294	#include <string.h>
295	#include <sys/types.h>
296
297	#if _X86_ || _X64_
298	#define COND		1
299	#define CONDNAME	"_X64_"
300	#else
301	#define COND		0
302	#endif
303
304	#define elementsof(x)	(sizeof(x)/sizeof(x[0]))
305
306	static struct
307	{
308		char*	name;
309		int	size;
310		int	cond;
311	} types[] =
312	{
313		"short",	sizeof(short),		0,
314		"int",		sizeof(int),		0,
315		"long",		sizeof(long),		0,
316		"size_t",	sizeof(size_t),		0,
317		"off_t",	sizeof(off_t),		0,
318		"pointer",	sizeof(void*),		COND * 4,
319		"float",	sizeof(float),		0,
320		"double",	sizeof(double),		0,
321	#ifdef _typ_long_double
322		"long_double",	sizeof(long double),	0,
323	#endif
324	};
325
326	int
327	main()
328	{
329		register int	t;
330
331		for (t = 0; t < elementsof(types); t++)
332	#if COND
333			if (types[t].cond)
334			{
335				printf("#if %s\n", CONDNAME);
336				printf("#define _ast_sizeof_%s%s	%d	/* sizeof(%s) */\n", types[t].name, strlen(types[t].name) < 4 ? "\t" : "", types[t].cond * 2, types[t].name);
337				printf("#else\n");
338				printf("#define _ast_sizeof_%s%s	%d	/* sizeof(%s) */\n", types[t].name, strlen(types[t].name) < 4 ? "\t" : "", types[t].cond, types[t].name);
339				printf("#endif\n");
340			}
341			else
342	#endif
343				printf("#define _ast_sizeof_%s%s	%d	/* sizeof(%s) */\n", types[t].name, strlen(types[t].name) < 4 ? "\t" : "", types[t].size, types[t].name);
344		printf("\n");
345		return 0;
346	}
347}end
348
349tst	- -DN=1 - -DN=0 output{
350	#define _BYTESEX_H
351
352	#include <string.h>
353	#include <sys/types.h>
354
355	#if !N || !_STD_
356	#undef	_typ_long_double
357	#endif
358
359	#define elementsof(x)	(sizeof(x)/sizeof(x[0]))
360
361	static struct
362	{
363		char*	name;
364		int	size;
365	} flt_type[] =
366	{
367		"float",	sizeof(float),
368		"double",	sizeof(double),
369	#ifdef _typ_long_double
370		"long double",	sizeof(long double),
371	#endif
372	};
373
374	int
375	main()
376	{
377		register int	t;
378		register int	m = 1;
379
380	#ifdef _typ_long_double
381		long double	p;
382		char		buf[64];
383
384		if (flt_type[elementsof(flt_type)-1].size <= sizeof(double))
385			return 1;
386		p = 1.12345E-55;
387		sprintf(buf, "%1.5LE", p);
388		if (strcmp(buf, "1.12345E-55"))
389			return 1;
390	#endif
391		for (t = 0; t < elementsof(flt_type); t++)
392		{
393			while (t < (elementsof(flt_type) - 1) && flt_type[t].size == flt_type[t + 1].size)
394				t++;
395			m = flt_type[t].size;
396			printf("#define _ast_flt%d_t		%s\n", flt_type[t].size, flt_type[t].name);
397		}
398		printf("#define _ast_fltmax_t		_ast_flt%d_t\n", m);
399		if (m == sizeof(double))
400			printf("#define _ast_fltmax_double		1\n");
401		return 0;
402	}
403}end
404
405typ int8_t stdint.h inttypes.h no{
406	#undef	_typ_int8_t
407	#define	_typ_int8_t	1
408	typedef _ast_int1_t int8_t;
409}end
410typ uint8_t stdint.h inttypes.h no{
411	#undef	_typ_uint8_t
412	#define	_typ_uint8_t	1
413	typedef unsigned _ast_int1_t uint8_t;
414}end
415typ int16_t stdint.h inttypes.h no{
416	#undef	_typ_int16_t
417	#define	_typ_int16_t	1
418	typedef _ast_int2_t int16_t;
419}end
420typ uint16_t stdint.h inttypes.h no{
421	#undef	_typ_uint16_t
422	#define	_typ_uint16_t	1
423	typedef unsigned _ast_int2_t uint16_t;
424}end
425typ int32_t stdint.h inttypes.h no{
426	#undef	_typ_int32_t
427	#define	_typ_int32_t	1
428	typedef _ast_int4_t int32_t;
429}end
430typ uint32_t stdint.h inttypes.h no{
431	#undef	_typ_uint32_t
432	#define	_typ_uint32_t	1
433	typedef unsigned _ast_int4_t uint32_t;
434}end
435typ int64_t stdint.h inttypes.h no{
436	#ifdef _ast_int8_t
437	#undef	_typ_int64_t
438	#define	_typ_int64_t	1
439	typedef _ast_int8_t int64_t;
440	#endif
441}end
442typ uint64_t stdint.h inttypes.h no{
443	#ifdef _ast_int8_t
444	#undef	_typ_uint64_t
445	#define	_typ_uint64_t	1
446	typedef unsigned _ast_int8_t uint64_t;
447	#endif
448}end
449typ intmax_t stdint.h inttypes.h no{
450	#undef	_typ_intmax_t
451	#define	_typ_intmax_t	1
452	typedef _ast_intmax_t intmax_t;
453}end
454typ uintmax_t stdint.h inttypes.h no{
455	#undef	_typ_uintmax_t
456	#define	_typ_uintmax_t	1
457	typedef unsigned _ast_intmax_t uintmax_t;
458}end
459typ uintptr_t stdint.h inttypes.h no{
460	#undef	_typ_uintptr_t
461	#define	_typ_uintptr_t	1
462	#if _ast_sizeof_pointer == 8 && defined(_ast_int8_t)
463	typedef unsigned _ast_int8_t uintptr_t;
464	#else
465	typedef unsigned _ast_int4_t uintptr_t;
466	#endif
467}end
468typ _Bool = uint8_t
469cat{
470	#if defined(_STDC_C99) || __STDC_VERSION__ >= 199901L
471	#include <stdbool.h>
472	#else
473	#define bool	_Bool
474	#define false	0
475	#define true	1
476	#endif
477}end
478if	tst key___thread -lpthread note{ __thread keyword exists and works with -lpthread }end execute{
479		#if defined(__APPLE__) || defined(__APPLE_CC__) || defined(__MACH__)
480		(	/* __thread does not work in dlls */
481		#endif
482
483		#include	<pthread.h>
484
485		#define INITIAL		1
486		#define LOOP		100
487
488		static __thread int	specific = INITIAL;
489		static int		global = 0;
490
491		static void* worker(void* arg)
492		{
493			int	k;
494			int	v;
495			v = (int)(arg - 0);
496			for (k = 0; k < LOOP; ++k)
497			{
498				specific += v;
499				usleep(1);
500			}
501			if (specific != (INITIAL + LOOP * v))
502				global = 1;
503			return 0;
504		}
505		int main()
506		{
507			pthread_t	th[2];
508
509			if (pthread_create(&th[0], 0, worker, (void*)0 + 5) ||
510			    pthread_create(&th[1], 0, worker, (void*)0 + 7))
511			{
512				NOTE("pthread_create failed");
513				return 1;
514			}
515			pthread_join(th[0], 0);
516			pthread_join(th[1], 0);
517			if (global)
518			{
519				NOTE("__thread variable not thread specific");
520				return 1;
521			}
522			if (specific != INITIAL)
523			{
524				NOTE("main __thread variable changed by another thread");
525				return 1;
526			}
527			return 0;
528		}
529	}end
530elif	tst - note{ msvc __declspec(thread) works }end compile{
531		__declspec(thread) tls = 1;
532	}end
533else	cat{
534		#define __thread		/* __thread keyword does not exist or does not work with -lpthread */
535	}end
536endif
537
538tst	- -DTRY=1 - -DTRY=1 -Dvoid=char - -DTRY=2 - -DTRY=3 - -DTRY=4 output{
539	#if _STD_ && _hdr_stdarg
540	#include <stdarg.h>
541	static void
542	varyfunny(int* p, ...)
543	{
544		va_list	ap;
545		va_start(ap, p);
546	#if TRY == 1
547		*p = *ap++ != 0;
548	#endif /*TRY == 1*/
549	#if TRY == 2
550		*p = *ap != 0;
551	#endif /*TRY == 2*/
552	#if TRY == 3
553		*p = ap++ != 0;
554	#endif /*TRY == 3*/
555		va_end(ap);
556	}
557	#else
558	#include <varargs.h>
559	static void
560	varyfunny(va_alist)
561	va_dcl
562	{
563		va_list	ap;
564		int*	p;
565		va_start(ap);
566		p = va_arg(ap, int*);
567	#if TRY == 1
568		*p = *ap++ != 0;
569	#endif /*TRY == 1*/
570	#if TRY == 2
571		*p = *ap != 0;
572	#endif /*TRY == 2*/
573	#if TRY == 3
574		*p = ap++ != 0;
575	#endif /*TRY == 3*/
576		va_end(ap);
577	}
578	#endif
579	int
580	main()
581	{
582		int	r;
583
584		printf("\n#ifndef va_listref\n");
585		printf("#ifndef	va_start\n");
586		printf("#if __STD_C\n");
587		printf("#include <stdarg.h>\n");
588		printf("#else\n");
589		printf("#include <varargs.h>\n");
590		printf("#endif\n");
591		printf("#endif\n");
592	#if TRY == 4
593		printf("#define va_listref(p) (&(p))\t");
594			printf("/* pass va_list to varargs function */\n");
595		printf("#define va_listval(p) (*(p))\t");
596			printf("/* retrieve va_list from va_arg(ap,va_listarg) */\n");
597		printf("#define va_listarg va_list*\t");
598			printf("/* va_arg() va_list type */\n");
599	#else
600		varyfunny(&r);
601		printf("#define va_listref(p) (p)\t");
602			printf("/* pass va_list to varargs function */\n");
603		if (sizeof(va_list) > sizeof(void*))
604			printf("#define va_listval(p) (*(p))\t");
605		else
606			printf("#define va_listval(p) (p)\t");
607			printf("/* retrieve va_list from va_arg(ap,va_listarg) */\n");
608	#if TRY == 2
609		printf("#define va_listarg va_list*\t");
610	#else
611		printf("#define va_listarg va_list\t");
612	#endif /*TRY == 2*/
613			printf("/* va_arg() va_list type */\n");
614	#endif /*TRY == 4*/
615
616	#if _UWIN
617		printf("#ifndef va_copy\n");
618		printf("#define va_copy(to,fr) ((to)=(fr))\t");
619			printf("/* copy va_list fr -> to */\n");
620		printf("#endif\n");
621	#else
622	#if !defined(va_copy)
623	#if defined(__va_copy)
624		printf("#ifndef va_copy\n");
625		printf("#define va_copy(to,fr) __va_copy(to,fr)\t");
626			printf("/* copy va_list fr -> to */\n");
627		printf("#endif\n");
628	#else
629	#if TRY == 2
630		printf("#ifndef va_copy\n");
631		printf("#define va_copy(to,fr) memcpy(to,fr,sizeof(va_list))\t");
632			printf("/* copy va_list fr -> to */\n");
633		printf("#endif\n");
634	#else
635		printf("#ifndef va_copy\n");
636		printf("#define va_copy(to,fr) ((to)=(fr))\t");
637			printf("/* copy va_list fr -> to */\n");
638		printf("#endif\n");
639	#endif
640	#endif
641	#endif
642	#endif
643
644		printf("#endif\n");
645		return 0;
646	}
647}end
648
649cat{
650	#ifndef _AST_STD_H
651	#	if __STD_C && _hdr_stddef
652	#	include	<stddef.h>
653	#	endif
654	#	if _sys_types
655	#	include	<sys/types.h>
656	#	endif
657	#	if _hdr_stdint
658	#	include	<stdint.h>
659	#	else
660	#		if _hdr_inttypes
661	#		include	<inttypes.h>
662	#		endif
663	#	endif
664	#endif
665	#if !_typ_size_t
666	#	define _typ_size_t	1
667		typedef int size_t;
668	#endif
669	#if !_typ_ssize_t
670	#	define _typ_ssize_t	1
671		typedef int ssize_t;
672	#endif
673	#ifndef _AST_STD_H
674	#	define _def_map_ast	1
675	#	if !_def_map_ast
676	#		include <ast_map.h>
677	#	endif
678	#endif
679}end
680
681run{
682	grep __NO_INCLUDE_WARN__ /usr/include/stat.h >/dev/null 2>&1 &&
683	grep '<name.h>' /usr/include/sys/stat.h >/dev/null 2>&1 &&
684	grep __name_h /usr/include/name.h >/dev/null 2>&1 &&
685	cat <<!
686	/* disable ${HOSTTYPE} <sys/foo.h> vs. <foo.h> clash warnings */
687	#ifndef __NO_INCLUDE_WARN__
688	#define __NO_INCLUDE_WARN__	1
689	#endif
690	/* disable ${HOSTTYPE} <sys/stat.h> <name.h> hijack */
691	#ifndef __name_h
692	#define __name_h		1
693	#endif
694	!
695}end
696