/* <gnu_hacks.h>
 *
 * This header file contains hacks that will simulate the effects of certain
 * parts of VAX-C that are not implemented in GNU-C.  This header file is
 * written in such a way that there are macros for both GNU-C and VAX-C.
 * Thus if you use the macros defined here in your program, you should be
 * able to compile your program with either compiler with no source
 * modifications.
 *
 * Note:  The globalvalue implementation is a little bit different than it
 * is on VAX-C.  You can declare a data variable to be a globalvalue, but
 * the data type that the compiler will see will be a pointer to that data
 * type, not that data type.  If you find the warning messages intollerable,
 * you can define a macro to type cast the globalvalue variable back to the
 * expected type.  Since it is impossible to define a macro while expanding
 * another macro, this was not done here.
 *
 * Also, globaldef/ref/value of enum is not implemented.  To simulate this
 * in GNU-C, you can globaldef an integer variable, and then define all of
 * the values that this variable can take to be globalvalue.
 *
 * The arguments to these macros are "fragile" (in the LaTeX sense).  This
 * means that you cannot use type casts or expressions in the name field.
 */
#ifndef _GNU_HACKS_H
#define _GNU_HACKS_H
#define __GNU_HACKS_H_

/* internal macros for traditional vs ANSI */
#ifdef __STDC__
#define __GNU_HACKS_string(foo) #foo
#define __GNU_HACKS_const __const
#else	/* => -traditional, or VAXC (just "stringizing", not 'const') */
#define __GNU_HACKS_string(foo) "foo"
#define __GNU_HACKS_const
#endif

#ifdef __GNUC__

/* Store the data in a psect by the same name as the variable name */
#define GLOBALREF(TYPE,NAME) \
 TYPE NAME __asm("_$$PsectAttributes_GLOBALSYMBOL$$" __GNU_HACKS_string(NAME))
#define GLOBALDEF(TYPE,NAME,VALUE) \
 TYPE NAME __asm("_$$PsectAttributes_GLOBALSYMBOL$$" __GNU_HACKS_string(NAME)) = VALUE

#define GLOBALVALUEREF(TYPE,NAME) \
 __GNU_HACKS_const TYPE NAME[1] __asm("_$$PsectAttributes_GLOBALVALUE$$" __GNU_HACKS_string(NAME))
#define GLOBALVALUEDEF(TYPE,NAME,VALUE) \
 __GNU_HACKS_const TYPE NAME[1] __asm("_$$PsectAttributes_GLOBALVALUE$$" __GNU_HACKS_string(NAME)) = {VALUE}

/* Store the data in a psect by a different name than the variable name */
#define GBLREF_ALIAS(TYPE,NAME,ALIAS) \
 TYPE NAME __asm("_$$PsectAttributes_GLOBALSYMBOL$$" __GNU_HACKS_string(ALIAS))
#define GBLDEF_ALIAS(TYPE,NAME,ALIAS,VALUE) \
 TYPE NAME __asm("_$$PsectAttributes_GLOBALSYMBOL$$" __GNU_HACKS_string(ALIAS)) = VALUE

/* Other non-standard qualifiers */
#define _NOSHARE(NAME) NAME __asm("_$$PsectAttributes_NOSHR$$" __GNU_HACKS_string(NAME))
#define _READONLY(NAME) NAME __asm("_$$PsectAttributes_NOWRT$$" __GNU_HACKS_string(NAME))
	/* as of gcc 2.0, this does not work, so do not use it... */
#define _ALIGN(NAME,BASE) NAME __attributes((aligned(1<<(BASE))))

#else	/* assume VAXC */
/* These are the equivalent definitions that will work in VAX-C */

#define GLOBALREF(TYPE,NAME) globalref TYPE NAME
#define GLOBALDEF(TYPE,NAME,VALUE) globaldef TYPE NAME = VALUE

#define GLOBALVALUEREF(TYPE,NAME) globalvalue TYPE NAME
#define GLOBALVALUEDEF(TYPE,NAME,VALUE) globalvalue TYPE NAME = VALUE

#define GBLREF_ALIAS(TYPE,NAME,ALIAS) globalref{__GNU_HACKS_string(ALIAS)} TYPE NAME
#define GBLDEF_ALIAS(TYPE,NAME,ALIAS,VALUE) globaldef{__GNU_HACKS_string(ALIAS)} TYPE NAME = VALUE

#define _NOSHARE(NAME) noshare NAME
#define _READONLY(NAME) readonly NAME
#define _ALIGN(NAME,BASE) _align(BASE) NAME

#endif	/*__GNUC__*/

#endif	/*_GNU_HACKS_H*/
