Coherent4.2.10/include/common/_ccompat.h

/* (-lgl
 *	Coherent 386 release 4.2
 *	Copyright (c) 1982, 1993 by Mark Williams Company.
 *	All rights reserved. May not be copied without permission.
 *	For copying permission and licensing info, write licensing@mwc.com
 -lgl) */

#ifndef	__COMMON__CCOMPAT_H__
#define	__COMMON__CCOMPAT_H__

/*
 * Define some handy things that allow us to work with K&R, ANSI and C++
 * compilers in a way that is at least less painful than not working. This
 * file does mandate an ANSI C pre-processing environment.
 *
 * While ANSI allows us to not define function prototypes, C++ mandates that
 * they exist, and it's a *really* good idea to use them whereever possible.
 *
 * This file also deals with some compiler-specific features that are either
 * in the C or C++ language standards but not always available, and some
 * language extensions that are very widely available, if only because they
 * are part of the C++ standard and have been incorporated into C compilers.
 *
 * This file specifically excludes specifics about target machines and
 * compiler interactions. Such definitions belong in another file.
 */

#include <common/feature.h>
#include <common/__offset.h>


/*
 * There is some complexity on the way __STDC__ is used in practice: the ANSI
 * committee merely says that if __STDC__ is defined and value 1, then the
 * implementation is ISO-conforming.
 *
 * Unfortunately, much existing code uses #ifdef as the only test, which
 * means that some non-conforming compilers which defined __STDC__ as zero
 * caused problems (the Coherent 3.x compiler is one such; the 4.x compiler
 * uses the alternate convention). The #if test is preferable in programs,
 * since in preprocessor tests undefined symbols assume value 0, but still
 * many programs use the alternate form.
 *
 * For compilers with an intermediate status, eg. with an ISO preprocessor,
 * or support for "const" but not prototypes, or prototypes but not "const"
 * we perform individual featurectomies below.
 *
 * A general rule for future extensions: use double-underscores before and
 * after for non-parameterized macros, double-underscores before for macros
 * that take parameters. If this file's definitions are to be used by user-
 * level code, create a header that exports the definitions into the user
 * namespace.
 *
 * Jun '93 - split profile in two sections in anticipation of future growth.
 * We can't assume more than 16-bit arithmetic because of some extremely
 * losing preprocessors out there.
 */

/* __STD_PROFILE__ bits */
#define	__STRINGIZE_M__	0x0001	/* supports ISO C "stringize" */
#define	__PASTE_M__	0x0002	/* support ISO C token-pasting */
#define	__PROTODECL_M__	0x0004	/* supports prototype declarations */
#define	__PROTODEFN_M__	0x0008	/* supports prototype definitions */
#define	__CONST_M__	0x0010	/* supports "const" construct */
#define	__VOLATILE_M__	0x0020	/* supports "volatile" construct */
#define	__VOIDSTAR_M__	0x0040	/* supports "void *" type */

#define	__STD_PROFILE_MASK__	0x007F

/* __MISC_PROFILE__ bits */
#define	__NOTUSED_M__	0x0001	/* allows "not used" warning suppression */
#define	__REGISTER_M__	0x0002	/* requires "register" declaration */
#define	__LINKID_M__	0x0004	/* requires linkage specifier (e.g. C++) */
#define	__INLINE_M__	0x0008	/* allows inline functions */
#define	__INLINEL_M__	0x0010	/* allows inline functions with loops */
#define	__DOTDOTDOT_M__	0x0020	/* requires (...) rather than () */
#define	__NOMERGESTR_M__ 0x0040	/* cannot merge identical strings */
#define	__ANONUNION_M__	0x0080	/* allows anonymous unions (e.g. C++) */

#define	__MISC_PROFILE_MASK__	0x00FF


/*
 * The Standard C language features in one definition for simplicity. This may
 * not be all the bits in __STD_PROFILE_MASK__ once C++ standards start
 * hitting the streets. Normative addenda to ISO C will complicate this, too.
 */

#define	__STDC_M__	(__STD_PROFILE_MASK__)


/*
 * Below, we attempt to determine a configuration suitable for the translator
 * that is working on the current program. Each group of macros attempts to
 * set a preprocessor macro __PROFILE__ with a bit-mask of the features
 * supported by the current translator.
 *
 * This approach has been taken since it considerably simplifies both the
 * task of adding new features to test for and adding new translators. Many
 * other programs intermingle the tasks of determining the translator and
 * defining the responses to that determination; in general, such programs
 * fail to be maintainable when the matrix of features and translators grows
 * larger than about 3x3.
 *
 * Jun '93 - With the split into two parts, we still let people use the single
 * __PROFILE__ definition if their translator's preprocessor can deal with
 * 32-bit arithmetic.
 */

#if  	defined (__PROFILE__)				/* user-overridden */

# if	(1 << 31) == 0
#  error Your preprocessor cannot handle 32-bit arithmetic!
# endif
# if	__PROFILE__ & ~ (__STD_PROFILE_MASK__ | (__MISC_PROFILE_MASK << 16))
#  error __PROFILE__ contains unknown flag bits.
# endif

# define  __STD_PROFILE__	(__PROFILE__ & __STD_PROFILE_MASK__)
# define  __MISC_PROFILE__	((__PROFILE__ >> 16) & __MISC_PROFILE_MASK__)

#elif	defined (__STD_PROFILE__) || defined (__MISC_PROFILE__)

# ifndef __STD_PROFILE__
#  error If you defined __MISC_PROFILE__, you must also define __STD_PROFILE__
# elif   __STD_PROFILE__ & ~ __STD_PROFILE_MASK__
#  error Unknown bits set in __STD_PROFILE__
# endif

# ifndef __MISC_PROFILE__
#  error If you defined __STD_PROFILE__, you must also define __MISC_PROFILE__
# elif   __MISC_PROFILE__ & ~ __MISC_PROFILE_MASK__
#  error Unknown bits set in __MISC_PROFILE__
# endif

#elif	defined (__cplusplus)				/* C++ */

# ifdef	__GNUC__
#  define __STD_PROFILE__	__STDC_M__
#  define __MISC_PROFILE__	(__NOTUSED_M__ | __LINKID_M__ | \
				 __INLINE_M__ | __INLINEL_M__ | \
				 __DOTDOTDOT_M__ | __ANONUNION_M__)
# else
#  define __STD_PROFILE__	__STDC_M__
#  define __MISC_PROFILE__	(__NOTUSED_M__ | __LINKID_M__ | \
				 __INLINE_M__ | __DOTDOTDOT_M__ | \
				 __ANONUNION_M__)
# endif

#elif	__BORLANDC__					/* Borland C */

# if	__BORLANDC__ >= 0x410
#  define __STD_PROFILE__	__STDC_M__
#  define __MISC_PROFILE__	0	/* features restricted to C++ */
# else
#  define __STD_PROFILE__	__STDC_M__
#  define __MISC_PROFILE__	(__NOTUSED_M__ | __INLINE_M__)
# endif

#elif	defined (__GNUC__)				/* GCC w/o C++ */

# define  __MISC_PROFILE__	(__INLINE_M__ | __INLINEL_M__ | \
				 __ANONUNION_M__)

# if	__STDC__ + 0					/* regular */
#  define  __STD_PROFILE__	__STDC_M__
# else							/* -traditional */
#  define  __STD_PROFILE__	(__STDC_M__ & ~ __PASTE_M__ & \
				 ~ __STRINGIZE_M__)
#  define  __CONST__		__NON_ISO (const)
#  define  __VOLATILE__		__NON_ISO (volatile)
# endif

#elif	__STDC__ + 0					/* minimal ANSI C */

# define  __STD_PROFILE__	__STDC_M__
# define  __MISC_PROFILE__	0

#elif	__COHERENT__					/* MWC Coherent */

# define  __STD_PROFILE__	(__STRINGIZE_M__ | __PASTE_M__)
# define  __MISC_PROFILE__	(__REGISTER_M__ | __NOMERGESTR_M__)

#else							/* VANILLA */

# define  __STD_PROFILE__	0
# define  __MISC_PROFILE__	__REGISTER_M__

#endif


/*
 * In the following sections we determine the responses to take on the basis
 * of whether or not each feature/misfeature is supported by the current
 * translator.
 *
 * In cases where the feature requires considerable change to source code,
 * such as prototyping and inline functions, we define both an existence
 * feature-test and a value macro.
 *
 * For the case of inline functions, this is because the function should not
 * appear at all in the souce code unless unlining is supported (and because
 * often a macro may suffice in place, although with less safety).
 *
 * In addition, the tests below always check to see whether a particular
 * symbol is defined already, allowing almost any feature to be turned on or
 * off at will from the command-line. This is useful when testing the
 * characteristics of a new translator, and may often be useful to suppress
 * certain features to aid in debugging.
 */

/*
 * Some old Reiser preprocessors looked for macro-expansions unside quoted
 * strings; this was useful, but dangerous, so ISO C defined a new operator
 * for doing just this job. A tip of the hat to P.J. Plauger for the form of
 * these macros.
 */

#ifndef	__STRING
# if	__STD_PROFILE__ & __STRINGIZE_M__

#  define	__STRING(x)		#x
#  define	__STRINGVAL(x)		__STRING(x)
#  define	_HAVE_STRINGIZE		1

# else

#  define	__STRING(x)		"x"
#  define	__STRINGVAL(x)		__STRING(x)

# endif
#endif


/*
 * As above, this is a feature supported in old systems by ill-advised hacks,
 * so ISO C has a special operator just for the job. We define __CONCAT3 ()
 * and __CONCAT4 () as primitives just for fun; it's handy, and nested calls
 * to __CONCAT () are just too messy to be practical. Furthermore, many of the
 * users of token-pasting need to be very careful about avoiding extra
 * rescanning when building a composite token, since some of the intermediate
 * steps may match other macros; sometimes this is useful, sometimes not.
 */

#ifndef	__CONCAT
# if	__STD_PROFILE__ & __PASTE_M__

#  define	__CONCAT(x,y)		x##y
#  define	__CONCAT3(x,y,z)	x##y##z
#  define	__CONCAT4(a,b,c,d)	a##b##c##d

# else

#  define	__CONCAT(x,y)		x/**/y
#  define	__CONCAT3(x,y,z)	x/**/y/**/z
#  define	__CONCAT4(a,b,c,d)	a/**/b/**/c/**/d

# endif
#endif


/*
 * __USE_PROTO__ is a general test which can be performed in .c files to see
 * whether to use a prototype form or a K&R form, since the two are so
 * different. This has the advantage that some tools which are hard-wired for
 * K&R source code can get confused by macros in the function header, so
 * keeping a real K&R header around can help.
 *
 * __PROTO () is a macro that can be used in header files, since all that
 * differs between K&R and ANSI external declarations is whether the types
 * are present.
 *
 * The difference between the two is important, especially when "lint"-like
 * tools are used. In order to check for consistency between the prototype
 * and K&R-style definitions, it may be necessary to enable prototypes in
 * the header files while suppressing them in the C files.
 */

#ifndef	__PROTO
# if 	__STD_PROFILE__ & __PROTODECL_M__

#  define	__PROTO(p)		p

# else	/* prototypes are not supported */

#  define	__PROTO(p)		()

# endif
# if	__STD_PROFILE__ & __PROTODEFN_M__

#  define	__USE_PROTO__		1

# endif
#endif	/* ! defined (__PROTO) */


/*
 * There are several existing compilers still in use which either do not
 * support the notion of a "const" language element or implement the feature
 * incorrectly with respect to the C standard.
 *
 * For these compilers, we allow the "const" specifier in prototypes, local
 * variables and structure declarations to be suppressed. Note that "const"
 * will never appear in a K&R function header.
 */

#ifndef	__CONST__
# if	__STD_PROFILE__ & __CONST_M__

#  define  	__CONST__		const

# else	/* const is not supported */

#  define	__CONST__

# endif
#endif	/* ! defined (__CONST__) */


/*
 * For symmetry with the "const" definition, we provide a wrapper for the
 * "volatile" feature. Note that for some reason "volatile" is available in
 * some compilers that do not implement "const", probably because the feature
 * was defined in simpler terms.
 *
 * For these compilers, we allow the "volatile" specifier in prototypes,
 * local variables, and structure declarations to be suppressed.
 */

#ifndef	__VOLATILE__
# if	__STD_PROFILE__ & __VOLATILE_M__

#  define	__VOLATILE__		volatile

# else	/* const is not supported */

#  define	__VOLATILE__

# endif
#endif	/* ! defined (__VOLATILE__) */


/*
 * Some compilers support the "void" type, but not the semantics of "void *".
 *
 * The following definition is similar to a usage in System V documentation
 * which probably exists for the same reason, except that we use two
 * underscores in ours before and after, where theirs is called _VOID.
 *
 * A word of explanation; what we are doing here is declaring an incomplete
 * type; pointers to this incomplete type should function more-or-less as
 * a pointer to "void" would except for lacking the implicit conversions that
 * are special to "void *", because "void" is an "incomplete type that cannot
 * be completed". Read the standard if you don't know about incomplete types.
 */

#ifndef	__VOID__
# if	__STD_PROFILE__ & __VOIDSTAR_M__

#  define	__VOID__		void

# else	/* void with a pointer is not supported */

#  if	__COHERENT__ && __MWC__	/* stroke a bug in Coherent 'cc' */

#   define	__VOID__		char

#else

typedef	struct __deep_magic__		__void__;
#   define	__VOID__		__void__

#  endif

# endif
#endif	/* ! defined (__VOID__) */


/*
 * In order for some of the useful compiler extensions below to be kept
 * available during a "strict" compile (assuming that the feature-tests above
 * enable their use) then the convention is to prepend compiler-specific
 * keywords with double-underscores.
 *
 * This also serves to document which usages are not ISO C. Note that this
 * may have to change a little for a potential standardized C++. Also note
 * that as with __NON_POSIX () below, we do not use __CONCAT () but directly
 * use whatever style of token-pasting is available to avoid the effects of
 * macro-rescanning.
 */

#ifndef	__NON_ISO
# if	__GNUC__ || __STDC__ + 0
#  if	__STD_PROFILE__ & __PASTE_M__
#   define	__NON_ISO(name)		__##name
#  else
#   define	__NON_ISO(name)		__/**/name
#  endif
# else
#  define	__NON_ISO(k)		k
# endif
#endif	/* ! defined (__NON_ISO) */


/*
 * A feature defined as part of the C++ language that also exists in many
 * C implementations is the ability to suppress "argument not used" warnings
 * in some cases by omitting the name of the variable in the function
 * prototype and merely giving the type.
 *
 * This feature is common in type-checking compilers since the checking of
 * function pointer arguments and other extra checks mean that functions
 * must be declared with unused arguments to match the shape of some function
 * pointer.
 *
 * Of course, it is desirable to leave the original name of the variable in
 * the same place for documentation purposes, often commented out, but this
 * usage chokes some compilers. It seems preferable use the following
 * definition to explicitly state the intention, even in cases where the
 * compiler generates spurious warnings.
 */

#ifndef	__NOTUSED
# if	__MISC_PROFILE__ & __NOTUSED_M__

#  define	__NOTUSED(name)		/* name */

# else	/* does not understand name suppression */

#  define	__NOTUSED(name)		__CONCAT (unused_, name)

# endif
#endif	/* ! defined (__NOTUSED) */


/*
 * Most modern compilers perform their own register allocation and ignore
 * the "register" directive from K&R C. Such compilers usually have debugging
 * tools that know how to deal with variables that spend at least part of
 * their lifetime in a machine register (or at worst, the option to suppress
 * the auto-register allocation).
 *
 * For compilers that require a register declaration for a variable to be
 * placed in a machine register, often it is desirable to suppress the use
 * of registers when debugging.
 *
 * Of course, most uses of "register" are machine-specific, and using such
 * declarations without information gained from profiling is foolish.
 */

#ifndef	__REGISTER__
# if	__MISC_PROFILE__ & __REGISTER_M__

#  define	__REGISTER__		register

# else

#  define	__REGISTER__

# endif
#endif	/* ! defined (__REGISTER__) */


/*
 * Some compilers for C-like languages such as C++, Objective-C or even
 * conceivably Pascal/Modula-2/Fortran support cross-language linkage.
 *
 * The standard way of doing this within the C family is to use a special
 * form of "extern" which names the language a function is implemented in.
 * Functions which are implemented in C in a library should be declared as
 * such in the exported header.
 *
 * Currently, this is most important for C++.
 */

#ifndef	__EXTERN_C__
# if	__MISC_PROFILE__ & __LINKID_M__

#  define	__EXTERN_C__		extern "C"
#  define	__EXTERN_C_BEGIN__	__EXTERN_C__ {
#  define	__EXTERN_C_END__	}

# else	/* this is being compiled by a C compiler */

#  define	__EXTERN_C__
#  define	__EXTERN_C_BEGIN__
#  define	__EXTERN_C_END__

# endif
#endif	/* ! defined (__EXTERN_C__) */


/*
 * All C++ compilers and many C compilers support the notion of "inline
 * functions" as an alternative to macros that (i) can be used to wrap up
 * casts so they are only used in safe contexts, (ii) can be used as an
 * alternative to macros that allow arguments with side-effects.
 *
 * This comes in two strengths: can inline anything, and can inline anything
 * that does not contain a loop. GNU C has extra strength, can inline tail-
 * recursive inline function, but that facility is not sufficiently widespread
 * to be useful as yet.
 *
 * The question is, what should the default setting of the client tests be?
 * #if ! __NO_INLINE__ is a double-negative, so don't use that. The
 * possibility of defining __INLINE__ as "static" so that inline functions
 * appear in the module separately breakpointable from other modules is a
 * desirable facility (assuming the debug namespace is separate from the
 * linkage namespace, likely in a system sophisticated enough to support
 * inlining). Furthermore, be aware of any interactions with the __LOCAL__
 * macro defined in <common/xdebug.h>
 */

#ifndef __INLINE__
# if	__MISC_PROFILE__ & __INLINE_M__

#  if	__cplusplus
#   define	__INLINE__		inline
#  else
#   define	__INLINE__		__NON_ISO (inline)
#  endif
#  define	__USE_INLINE__		1

# else

#  define	__INLINE__

# endif
#endif

#ifndef __INLINEL__
# if	__MISC_PROFILE__ & __INLINEL_M__

#  define	__INLINEL__		__NON_ISO (inline)
#  define	__USE_INLINEL__	1

# else

#  define	__INLINEL__

# endif
#endif


/*
 * One particular incompatibility between ANSI C and C++ code exists in the
 * way in which prototypes which do not specify any types at all are handled.
 * Under C++, the () form is used to imply (void), since such declarations
 * are extremely common and because early versions of the C++ translators did
 * not allow any declarations in the argument lists of constructors or
 * destructors, not even void, so this form was used to syntactically imply
 * (void).
 *
 * The ANSI C committe declared that a prototype of the form
 *	extern char * malloc ();
 * said nothing whatsoever about the types of it's arguments, since such
 * declarations were extremely common in K&R C code, and doing anything else
 * would gratuitously require considerable rewriting.
 *
 * Unfortunately, the ANSI C committee decided that the special form "..." to
 * introduce variable arguments was not valid unless preceeded by a regular
 * argument type declaration, so that there is no way of being unambiguous
 * that will compile under both transators.
 *
 *		ANSI		C++
 *
 * ()		(...)		(void)		ambiguous
 *
 * (void)	(void)		(void)		unambiguous
 *
 * (...)	error		(...)		thanks, X3J11
 *
 * Use the preprocessor symbol __ANY_ARGS__ in this context to expand to
 * whatever the current translator needs to see for it to make no assumptions
 * about the number and type of any function arguments.
 */

#ifndef	__ANY_ARGS__
# if	__MISC_PROFILE__ & __DOTDOTDOT__

#  define	__ANY_ARGS__		...

# else

#  define	__ANY_ARGS__

# endif
#endif	/* ! defined (__ANY_ARGS__) */


/*
 * String constants have been mightily botched in C, largely because K&R C
 * always treated strings as unique, writeable data. The introduction of the
 * 'const' qualifier should have made things simpler by allowing compilers to
 * figure out whether a string is being used in a 'const' or non-'const'
 * way. However, the precedent of just making all strings which are not being
 * used as character array initializers into shareable constants has already
 * been established.
 *
 * This has an effect on complex macros, because a string in a macro may
 * cause a host of anonymous, identical string constants to be created, which
 * have to be suppressed by using a static declaration. On the other hand,
 * this does worse than a compiler which does share strings, because if the
 * macro is not actually used then the data space is still taken up.
 *
 * Here we give a hint to those macros that care.
 */

#ifndef	_SHARED_STRINGS
# if	(__MISC_PROFILE__ & __NOMERGESTR_M__) == 0

#  define	_SHARED_STRINGS		1

# endif
#endif	/* ! defined (_SHARED_STRINGS) */


/*
 * The use of anonymous unions in C++ greatly simplifies the problems caused
 * by attempts to forward structure tags into unions with use of #define. This
 * use of unions is the primary reason why names which would normally be
 * properly scope-controlled in C are given over to the preprocessor to wreak
 * havok globally.
 *
 * Below, we expand __ANON__ into empty if such items need no tag, and
 * leave it undefined otherwise, and make _ANONYMOUS a feature-test .
 */

#ifndef	_ANONYMOUS
# if	(__MISC_PROFILE__ & __ANONUNION_M__) != 0

#  define	__ANONYMOUS__
#  define	_ANONYMOUS		1

# endif
#endif


/*
 * It is frequently convenient to be able to map a pointer to a member of a
 * structure back to a pointer to the parent structure. Unfortunately, while
 * ISO C mandates that conversions between pointer types and will not cause
 * loss of information, there are few things that can portably be done with
 * such a converted pointer. In particular, the easy way of mapping back from
 * a structure member pointer to the containing structure performs address
 * arithmetic on character pointers using offsetof (). It appears that this
 * puts us in the realm of implementation-defined behaviour, except when the
 * offsetof () the member is 0.
 */

#ifndef	__DOWNCAST

# define	__DOWNCAST(str,mem,ptomem) \
			((str *) ((char *) (ptomem) - \
				  __offsetof (str, mem)))

#endif


/*
 * This is a minor K&R compatibility issue: certain K&R compilers reject the
 * ISO C idiom of enclosing a macro name in parentheses to suppress macro
 * expansion when this idiom is used in function declarations. To get around
 * this, we can use the ISO preprocessor in a clumsy fashion by providing an
 * identity macro to provide the same overall effect of making the name we
 * wish to suppress expansion for not be immediately followed by a left
 * parenthesis (it will be followed by a parenthesis eventually, but since the
 * proprocessor won't revisit the text it has seen before the expansion of
 * the identity macro we get the behaviour we want).
 */

#define	__ARGS(x)	x


/*
 * The POSIX.1 standard discusses a special namespace issue; how can standard
 * structures be portably extended, given that the structure tags are in the
 * user namespace. For structures which have members with regular names and
 * which are likely to be extended, the POSIX.1 standard deals with this by
 * implicitly reserving all names of that form (something which further
 * underscores the restrictions on standard headers not including each other).
 *
 * However, for situations where we wish to extend a structure not covered by
 * the namespace reservation rules, or we wish to name a member according to
 * some other usage, we must take care to not define the member such that it
 * might conflict with some macro name which the user is permitted to define.
 * See POSIX.1 B.2.7.2 for discussion of this point.
 *
 * The following definition can be used to wrap the definition of structure
 * member names such that those names will not conflict with user macros if
 * _POSIX_SOURCE is defined, or if _POSIX_C_SOURCE is defined. This form can
 * be used in references to the member name which may be encapsulated in
 * macros so that there is no loss of functionality or alteration of behaviour
 * when POSIX compilation is used.
 *
 * Note that we do not use __CONCAT () here; the aim of this is to not cause
 * accidental conflicts with user-defined macros, but using __CONCAT () would
 * result in an extra layer of macro processing, causing the "name" argument
 * to be expanded anyway.
 */

#if	_POSIX_C_SOURCE
# if	__STD_PROFILE__ & __PASTE_M__
#  define	__NON_POSIX(name)	__##name
# else
#  define	__NON_POSIX(name)	__/**/name
# endif
#else
# define	__NON_POSIX(name)	name
#endif


/*
 * GCC has a special feature for declaring functions as not ever returning.
 * Also note that GCC versions from 2.5.x support an alternate syntax for this
 * operation, __attribute ((noreturn)), which we will support migration to.
 */

#if	__IS_GCC_FROM (2, 5)
# define	__NO_RETURN__		void
# if	! __cplusplus
#  define	__NO_RETURN_ATTR__	__attribute__ ((noreturn))
# else
#  define	__NO_RETURN_ATTR__
# endif
#elif	__GNUC__ && ! __PEDANTIC__
# define	__NO_RETURN__		__VOLATILE__ void
# define	__NO_RETURN_ATTR__
#else
# define	__NO_RETURN__		void
# define	__NO_RETURN_ATTR__
#endif


/*
 * With some systems, structure alignment is configured as a compiler global
 * via #pragma, whereas GCC deals with alignment on a per-item basic via
 * keyword extensions. The GCC way is preferable (since #pragma is not only
 * non-portable, it can't be conditionally wrapped in a macro) and so we wrap
 * it up in a macro.
 *
 * Note that in GCC, the maximum member alignment determines the size to which
 * the structure is rounded. Coherent 'cc' instead pads structures based on the
 * largest default alignment, ignoring the actual item alignment; if a non-
 * default alignment is in effect at the end of the structure (the exact way
 * to do that is not defined, but at the moment that is the alignment in
 * effect at the next token *after* the '}' at the end of the structure), then
 * that alignment is used as the amount to round the structure size to.
 *
 * Furthermore, GCC aligns structures based on the strictest actual alignment
 * of any member. Coherent 'cc' aligns structures based on the strictest
 * *default* alignment of any member, and this can only be overridden when the
 * structure is later used.
 */

#if	__IS_GCC_FROM (2, 3)
# define	__ALIGN(n)		__attribute__ ((packed, aligned (n)))
#else
# define	__ALIGN(n)
#endif


/*
 * A feature of both GCC and many "lint" packages is the ability to specify
 * that a user-defined function should have special type-checking based on a
 * printf () or scanf () format string. 
 */

#if	__IS_GCC_FROM (2, 3)
# define	__PRINTF_LIKE(fmt, first) \
				__attribute__ ((format (printf, fmt, first)))
# define	__SCANF_LIKE(fmt, first) \
				__attribute__ ((format (scanf, fmt, first)))
#else
# define	__PRINTF_LIKE(fmt, first)
# define	__SCANF_LIKE(fmt, first)
#endif


/*
 * GNU C provides a special built-in primitive for returning the alignment
 * requirements of any object. In the absence of this, we can reasonably
 * safely derive an alignment estimate for any type using a similar trick to
 * that commonly used to implement offsetof ()... namely, to compute the
 * offsetof () a member of the required type embedded in a structure preceded
 * by a single character member.
 *
 * Note that C++ does not permit type declarations to appear embedded inside
 * expressions, so that C expression for this is not valid C++. However, one
 * can use templates to gain the equivalent effect.
 */

#if	__GNUC__

# define	__ALIGNOF(type)		__alignof (type)

#elif	__cplusplus

template <class T> class __alignof {
private:
	struct _foo {
		char	_a;
		T	_b;
	};

public:
static	__size_t	_align ()	{ return __offsetof (_foo, _b); }
};

# define	__ALIGNOF(type)		(__alignof <type> :: _align ())

#else

# define	__ALIGNOF(type)	\
				__offsetof (struct { char _a; type _b; }, _b)
#endif


/*
 * Undefine all our internal symbols... why pollute the namespace?
 */

#undef	__STRINGIZE_M__
#undef	__PASTE_M__
#undef	__PROTODECL_M__
#undef	__PROTODEFN_M__
#undef	__CONST_M__
#undef	__VOLATILE_M__
#undef	__VOIDSTAR_M__
#undef	__STD_PROFILE_MASK__

#undef	__NOTUSED_M__
#undef	__REGISTER_M__
#undef	__LINKID_M__
#undef	__INLINE_M__
#undef	__INLINEL_M__
#undef	__DOTDOTDOT_M__
#undef	__NOMERGESTR_M__
#undef	__MISC_PROFILE_MASK__

#undef	__STDC_M__
#undef	__PROFILE__
#undef	__STD_PROFILE__
#undef	__MISC_PROFILE__

#endif	/* ! defined (__COMMON__CCOMPAT_H__) */