/***************** WARNING ****************
*  DO NOT EDIT THIS FILE DIRECTLY - IT IS *
*  GENERATED AUTOMATICALLY BY THE CONFIG  *
*  PROCESS IN THE 'mframe' SUBDIRECTORY.  *
****************** WARNING ***************/
/* General purpose definitions for the GNU Objective-C Library.
   Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.

   Written by:  Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
   Created: May 1993

   This file is part of the GNUstep Base Library.

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.
   
   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public
   License along with this library; if not, write to the Free
   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ 

#ifndef __preface_h_OBJECTS_INCLUDE
#define __preface_h_OBJECTS_INCLUDE

#undef PACKAGE
#undef VERSION
#include <config.h>
#undef PACKAGE
#undef VERSION

#if defined(__hpux__) && defined(HAVE_SYS_SIGEVENT_H)
#include <sys/sigevent.h>
#endif

#include <stdarg.h>
#include <stdlib.h>
#include <string.h> /* memcpy */

#if 0
#include <base/objc-gnu2next.h>
#include <base/fake-main.h>
#endif


typedef struct  {
  int           offset;
  unsigned      size;
  const char    *type;
#ifndef NO_GNUSTEP
  unsigned      align;
  unsigned      qual;
  BOOL          isReg;
#endif
} NSArgumentInfo;

#define NSCParameterAssert(x) assert(x)

#if (defined(__WIN32__) || defined(_WIN32)) && 0
#include <windows.h>
#define GNUSTEP_BASE_SOCKET_MESSAGE (WM_USER + 1)
#endif

#if NeXT_runtime
 #include <objc/objc.h>
 #include <objc/objc-class.h>
 #include <objc/objc-runtime.h>
 #ifndef _C_ATOM
  #define _C_ATOM '%'
 #endif
 #define _F_CONST    0x01
 #define _F_IN       0x01
 #define _F_OUT      0x02
 #define _F_INOUT    0x03
 #define _F_BYCOPY   0x04
 #define _F_ONEWAY   0x08
 #define _C_CONST    'r'
 #define _C_IN       'n'
 #define _C_INOUT    'N'
 #define _C_OUT      'o'
 #define _C_BYCOPY   'O'
 #define _C_ONEWAY   'V'
#else				/* GNU Objective C Runtime */
 #include <objc/objc.h>
 #include <objc/objc-api.h>
 #include <objc/encoding.h>
 #include <objc/sarray.h>
 /* #include <objc/objc-list.h> */
#endif

#ifndef __WIN32__
#include <sys/param.h> /* Hack to get rid of warning in GNU libc 2.0.3. */
#endif

#if 0
#include <Foundation/NSObject.h>
#include <Foundation/NSObjCRuntime.h>
#endif

#define OBJC_MALLOC(VAR, TYPE, NUM) \
   ((VAR) = (TYPE *) objc_malloc ((unsigned)(NUM)*sizeof(TYPE))) 
#define OBJC_VALLOC(VAR, TYPE, NUM) \
   ((VAR) = (TYPE *) objc_valloc ((unsigned)(NUM)*sizeof(TYPE))) 
#define OBJC_ATOMIC_MALLOC(VAR, TYPE, NUM) \
   ((VAR) = (TYPE *) objc_atomic_malloc ((unsigned)(NUM)*sizeof(TYPE))) 
#define OBJC_REALLOC(VAR, TYPE, NUM) \
   ((VAR) = (TYPE *) objc_realloc ((VAR), (unsigned)(NUM)*sizeof(TYPE)))
#define OBJC_CALLOC(VAR, TYPE, NUM) \
   ((VAR) = (TYPE *) objc_calloc ((unsigned)(NUM), sizeof(TYPE)))
#define OBJC_FREE(PTR) objc_free (PTR)

#ifndef MAX
#define MAX(a,b) \
       ({typeof(a) _MAX_a = (a); typeof(b) _MAX_b = (b);  \
         _MAX_a > _MAX_b ? _MAX_a : _MAX_b; })
#endif

#ifndef MIN
#define MIN(a,b) \
       ({typeof(a) _MIN_a = (a); typeof(b) _MIN_b = (b);  \
         _MIN_a < _MIN_b ? _MIN_a : _MIN_b; })
#endif

#ifndef ABS
#define ABS(a) \
       ({typeof(a) _ABS_a = (a); \
         _ABS_a < 0 ? -_ABS_a : _ABS_a; })
#endif

#ifndef STRINGIFY
#define STRINGIFY(s) XSTRINGIFY(s)
#define XSTRINGIFY(s) #s
#endif

#ifndef OBJC_STRINGIFY
#define OBJC_STRINGIFY(s) OBJC_XSTRINGIFY(s)
#define OBJC_XSTRINGIFY(s) @#s
#endif

#ifndef PTR2LONG
#define PTR2LONG(P) (((char*)(P))-(char*)0)
#endif
#ifndef LONG2PTR
#define LONG2PTR(L) (((char*)0)+(L))
#endif

#if VSPRINTF_RETURNS_LENGTH 
#define VSPRINTF_LENGTH(VSPF_CALL) (VSPF_CALL)
#else
#define VSPRINTF_LENGTH(VSPF_CALL) strlen((VSPF_CALL))
#endif /* VSPRINTF_RETURNS_LENGTH */


#endif /* __preface_h_OBJECTS_INCLUDE */
/* Interface for functions that dissect/make method calls 
   Copyright (C) 1994, 1996, 1998 Free Software Foundation, Inc.
   
   Written by:  Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
   Created: Oct 1994
   
   This file is part of the GNUstep Base Library.

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.
   
   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.
   
   You should have received a copy of the GNU Library General Public
   License along with this library; if not, write to the Free
   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   */ 

#ifndef __mframe_h_GNUSTEP_BASE_INCLUDE
#define __mframe_h_GNUSTEP_BASE_INCLUDE

#if NeXT_runtime
typedef union {
  char *arg_ptr;
  char arg_regs[sizeof (char*)];
} *arglist_t;
#endif

/* These functions are used to pull apart method calls, and put them
   back together again.  They are useful for things like distributed
   objects, and cross-language communication glue between Objective C
   and other languages. */

/* xxx Currently these function only work with the GNU Objective C
   runtime, not the NeXT runtime. */


/* Extract the arguments to a method call, as found in ARGFRAME,
   according to type string TYPES, and encode them by calling ENCODER.
   Return YES if and only if the method has some pass-by-reference
   arguments. */

BOOL
mframe_dissect_call (arglist_t argframe, const char *types,
		     void (*encoder)(int,void*,const char*,int));
BOOL
mframe_dissect_call_opts (arglist_t argframe, const char *types,
		     void (*encoder)(int,void*,const char*,int),
			BOOL pass_pointers);

/* Decode the arguments to a method call by calling DECODER, knowing
   what to decode by looking at type string ENCODED_TYPES.  Build an
   argframe of type arglist_t, and invoke the method.  Then encode the
   return value and the pass-by-reference values using ENCODER. */

void
mframe_do_call (const char *encoded_types,
		void(*decoder)(int,void*,const char*),
		void(*encoder)(int,void*,const char*,int));
void
mframe_do_call_opts (const char *encoded_types,
		void(*decoder)(int,void*,const char*),
		void(*encoder)(int,void*,const char*,int),
		BOOL pass_pointers);

/* Decode the return value and pass-by-reference arguments using
   DECODER, knowning what to decode by looking at type string TYPES
   and OUT_PARAMETERS, and put then into ARGFRAME.  Return the
   retval_t structure that can be passed to __builtin_return(). */

retval_t 
mframe_build_return (arglist_t argframe, const char *types, 
		     BOOL out_parameters,
		     void(*decoder)(int,void*,const char*,int));
retval_t 
mframe_build_return_opts (arglist_t argframe, const char *types, 
		     BOOL out_parameters,
		     void(*decoder)(int,void*,const char*,int),
		     BOOL pass_pointers);

/*
 *	Copy the return value from retframe into the specified buffer.
 */
BOOL
mframe_decode_return(const char *type, void* buffer, void* retframe);

/*
 *	Return the value of the specified type in 'retval' using argFrame.
 */
void*
mframe_handle_return(const char* type, void* retval, arglist_t argFrame);

/*
 *	Step through method encoding information extracting details.
 */
const char *
mframe_next_arg(const char *typePtr, NSArgumentInfo *info);

/*
 *	Generate method encoding with stack/register offsets from a simple
 *	type encoding string.  Store results in 'buf' or allocate memory
 *	using objc_malloc() if 'buf' is a nul pointer.
 */
char*
mframe_build_signature(const char *typePtr, int *size, int *narg, char *buf);


arglist_t
mframe_create_argframe(const char *types, void** retbuf);

void
mframe_destroy_argframe(const char *types, arglist_t argframe);

#define ROUND(V, A) \
  ({ typeof(V) __v=(V); typeof(A) __a=(A); \
     __a*((__v+__a-1)/__a); })

/* See ../README for copyright */

#define	MFRAME_STACK_STRUCT	1
#define	MFRAME_STRUCT_BYREF	0
#define MFRAME_SMALL_STRUCT	0
#define MFRAME_ARGS_SIZE	8
#define MFRAME_RESULT_SIZE	116

#define MFRAME_GET_STRUCT_ADDR(ARGS, TYPES) \
((*(TYPES)==_C_STRUCT_B || *(TYPES)==_C_UNION_B || *(TYPES)==_C_ARY_B) ? \
      *(void**)(ARGS)->arg_ptr : (void*)0)

#define MFRAME_SET_STRUCT_ADDR(ARGS, TYPES, ADDR) \
({if (*(TYPES)==_C_STRUCT_B || *(TYPES)==_C_UNION_B || *(TYPES)==_C_ARY_B) \
      *(void**)(ARGS)->arg_ptr = (ADDR);})

#define MFRAME_ARGS int

#define MFRAME_INIT_ARGS(CUM, RTYPE)	\
((CUM) = (*(RTYPE)==_C_STRUCT_B || *(RTYPE)==_C_UNION_B || \
    *(RTYPE)==_C_ARY_B) ? sizeof(void*) : 0)

#define MFRAME_ARG_ENCODING(CUM, TYPE, STACK, DEST) \
({  \
  const char* type = (TYPE); \
  int align = objc_alignof_type(type); \
  int size = objc_sizeof_type(type); \
\
  (CUM) = ROUND((CUM), align); \
  (TYPE) = objc_skip_typespec(type); \
  sprintf((DEST), "%.*s%d", (TYPE)-type, type, (CUM)); \
  if (*(TYPE) == '+') \
    { \
      (TYPE)++; \
    } \
  while (isDigit (*(TYPE))) \
    { \
      (TYPE)++; \
    } \
  (DEST)=&(DEST)[strlen(DEST)]; \
  if ((*type==_C_STRUCT_B||*type==_C_UNION_B||*type==_C_ARY_B)&&size>2) \
    { \
      (STACK) = (CUM) + ROUND(size, align); \
    } \
  else \
    { \
      (STACK) = (CUM) + size; \
    } \
  (CUM) += ROUND(size, sizeof(void*)); \
})


inline static void*
mframe_arg_addr(arglist_t argf, NSArgumentInfo *info)
{
  int offset = info->offset;
#if WORDS_BIGENDIAN
  if (info->size < sizeof (int))
    {
      offset += sizeof(int) - info->size;
    }
#endif
  if (info->isReg)
    {
      return(argf->arg_regs + offset);
    }
  else
    {
      return(argf->arg_ptr + offset);
    }
}

inline static void
mframe_get_arg(arglist_t argf, NSArgumentInfo *info, void* buffer)
{
#if MFRAME_STRUCT_BYREF || MFRAME_FLT_IN_FRAME_AS_DBL
  const char	*typ = info->type;
#endif

#if MFRAME_STRUCT_BYREF
  /*
   *	If structures are passed in the stack frame by reference - we need
   *	to copy the actual structure, rather than it's pointer.
   */
  if (*typ == _C_STRUCT_B || *typ == _C_UNION_B || *typ == _C_ARY_B)
    {
      memcpy(buffer, *(void**)mframe_arg_addr(argf, info), info->size);
    }
  else
#endif
#if MFRAME_FLT_IN_FRAME_AS_DBL
  if (*typ == _C_FLT)
    {
      *(float*)buffer = (float)*(double*)mframe_arg_addr(argf, info);
    }
  else
#endif
  memcpy(buffer, mframe_arg_addr(argf, info), info->size);
}

inline static void
mframe_set_arg(arglist_t argf, NSArgumentInfo *info, void* buffer)
{
#if MFRAME_STRUCT_BYREF || MFRAME_FLT_IN_FRAME_AS_DBL
  const char	*typ = info->type;
#endif

#if MFRAME_STRUCT_BYREF
  /*
   *	If structures are passed in the stack frame by reference - we need
   *	to copy a pointer onto the stack rather than the actual structure.
   */
  if (*typ == _C_STRUCT_B || *typ == _C_UNION_B || *typ == _C_ARY_B)
    {
      memcpy(mframe_arg_addr(argf, info), &buffer, sizeof(void*));
    }
  else
#endif
#if MFRAME_FLT_IN_FRAME_AS_DBL
  if (*typ == _C_FLT)
    {
      *(double*)mframe_arg_addr(argf, info) = *(float*)buffer;
    }
  else
#endif
  memcpy(mframe_arg_addr(argf, info), buffer, info->size);
}

inline static void
mframe_cpy_arg(arglist_t dst, arglist_t src, NSArgumentInfo *info)
{
#if MFRAME_STRUCT_BYREF
  const char	*typ = info->type;

  /*
   *	If structures are passed in the stack frame by reference - we need
   *	to copy a pointer onto the stack rather than the actual structure.
   */
  if (*typ == _C_STRUCT_B || *typ == _C_UNION_B || *typ == _C_ARY_B)
    {
      memcpy(mframe_arg_addr(dst, info), mframe_arg_addr(src, info), sizeof(void*));
    }
  else
#endif
    memcpy(mframe_arg_addr(dst, info), mframe_arg_addr(src, info), info->size);
}

#endif /* __mframe_h_GNUSTEP_BASE_INCLUDE */
