/* ansidef.h -- compatibility macros for C++ / ANSI C / traditional C
 *
 * Usage:
 *  IF_CPLUSPLUS(extern "C" {, EMPTY_ARG)	/ * For anti-#if fanatics * /
 *	extern int    printf ARGDCL((CONST char * VA_DOTS));
 *	extern VOIDFN foo ARGDCL((VOIDDATA *, int)), bar (NOARGS);
 *  IF_CPLUSPLUS(}, EMPTY_ARG)
 *
 *  VOIDFN foo ARGDEF((a, b),			/ * traditional-C args   * /
 *		      VOIDDATA *a ARG int b)	/ * Argument definitions * /
 *  {
 *	bar();
 *	return VOIDVAL;			/ * Avoid 'no returnvalue' warning * /
 *  }
 *  / * Definitions as above can become ugly.  You may prefer ARGDCL to
 *	*declare* functions and traditional C syntax to *define* them.
 *	To check that definition, #include the file with the matching ARGDCL.
 *	WARNING: traditional short/char args must be ARGDCLed as int, and
 *	float as double.  Avoid *unsigned* short/char args if possible. * /
 *
 *  #if HAS_STDARG
 *  #  include <stdarg.h>
 *  #else
 *  #  include <varargs.h>	/ * Sorry, varargs is not really portable * /
 *  #endif
 *  int xprintf VA_ARGDEF((format, va_alist),
 *			  CONST char *format)
 *  {...va_list ap; VA_START(ap,format); ... va_end(ap); ...}
 *
 * Macros CONST, VOLATILE, SIGNED, INLINE are defined as const... or empty.
 * VOIDDATA, VOIDFN and VOIDCAST are void, void, (void) or char int, empty.
 *
 * You may predefine the IS_xxx/HAS_xxx macros (define as 0 or 1),
 * VA_DOTS, VOIDxxx macros, CONST/VOLATILE/SIGNED, and INLINE.
 * HAS_STDARG is reset if !HAS_PROTOTYPES.
 * Defaults come from defined(__cplusplus) and __STDC__!=0.
 *	(No defined(__STDC__).  __STDC__ == 0 is nonANSI.)
 * For example, many non-ANSI compilers have void, so could set HAS_VOID.  Or
 * the other way around: because system headers on some machines declare
 * char* instead of void* functions, you may want to reset HAS_VOID or define
 * VOIDDATA/VOIDFN to make your declarations match the system headers.
 *
 * Extract the commented lines in the code for more documentation.
 *
 * Version 1.4, modified 23 Oct 1992
 *
 * Please add to this file to rope in more machine types/compilers.
 *   -- Hallvard B Furuseth <H.B.Furuseth@usit.uio.no>
 */

#ifndef ANSIDEF_H_
#define ANSIDEF_H_

#define EMPTY_ARG /* Use this as empty macro arg; some cpp''s fail otherwise */

/* C++ */
#  define IF_CPLUSPLUS(cplpl,c)	c


/* ANSI C */
#if defined(IS_ANSI) ? IS_ANSI : ((__STDC__) || IS_CPLUSPLUS)
#  define IS_ANSI		1
#  define IF_ANSI(ansi,trad)	ansi
#else
#  define IF_ANSI(ansi,trad)	trad
#endif

/* Prototypes */
#  define HAS_PROTOTYPES	1	/* True if ANSI C prototypes work    */
#  define ARGDCL(args)		args	/* Arguments in function declaration */
#  define ARGDEF(args,defs)	(defs)	/* Arguments in function definition  */
#  define ARG			,	/* Argument separator in definition  */
#  define NOARGS		void	/* "Argument" to func. without args  */

/* Stdarg/varargs protypes */
#  undef  HAS_STDARG
#  define HAS_STDARG		0
#  define VA_ARGDCL(args)	()
#  define VA_ARGDEF(args,defs)	args defs; va_dcl
#  define VA_START(ptr,last)	va_start(ptr)

/* Void */
#  define	HAS_VOID	1	/* True if 'void' exists */
#  ifndef	VOIDFN
#    define	VOIDFN		void	/* Return type of void functions */
#  endif
#  ifndef	VOIDDATA
#    define	VOIDDATA	void	/* Data type of void* "contents" */
#  endif
#  ifndef	VOIDCAST
#    define	VOIDCAST	(void)	/* Ignore value of expression */
#  endif

/* CONST/VOLATILE/SIGNED.  They need a type as well, do not default to 'int' */
#ifndef		CONST
#  define	CONST		IF_ANSI(const,EMPTY_ARG)
#endif
#ifndef		VOLATILE
#  define	VOLATILE	IF_ANSI(volatile,EMPTY_ARG)
#endif
#ifndef		SIGNED
#  define	SIGNED		IF_ANSI(signed,EMPTY_ARG)
#endif

#endif
