/* -----------------------------------------------------------------------------
 * smalltalk.swg
 *
 * Smallalk typemaps
 *
 * This file originated from the Java version, so there are probably a few
 * places left where things don't make sense and need to be fixed up.
 * ----------------------------------------------------------------------------- */

%include "sthead.swg"

/* Primitive types */

/* The following is a carry over from the S# implementation.  Perhaps is it more appropriate
and 64-bit compatible to use names like st_Int instead of designating it's size? */

%typemap(stni) bool,               const bool &               "st_UInt8"
%typemap(stni) char,               const char &               "st_Char8"
%typemap(stni) signed char,        const signed char &        "st_Char8"
%typemap(stni) unsigned char,      const unsigned char &      "st_UInt8"
%typemap(stni) short,              const short &              "st_Int16"
%typemap(stni) unsigned short,     const unsigned short &     "st_UInt16"
%typemap(stni) int,                const int &                "st_Int32"
%typemap(stni) unsigned int,       const unsigned int &       "st_UInt32"
%typemap(stni) long,               const long &               "st_Int32"
%typemap(stni) unsigned long,      const unsigned long &      "st_UInt32"
%typemap(stni) long long,          const long long &          "st_Int64"
%typemap(stni) unsigned long long, const unsigned long long & "st_UInt64"
%typemap(stni) float,              const float &              "st_Float32"
%typemap(stni) double,             const double &             "st_Float64"
%typemap(stni) char *                                         "st_CharPtr"
%typemap(stni) void                                           "void"

/* these are the argument types used to map from the C types to the actual Smalltalk external interface */
%typemap(sttype) bool,               const bool &               "bool"
%typemap(sttype) char,               const char &               "char"
%typemap(sttype) signed char,        const signed char &        "char"
%typemap(sttype) unsigned char,      const unsigned char &      "uchar"
%typemap(sttype) short,              const short &              "short"
%typemap(sttype) unsigned short,     const unsigned short &     "ushort"
%typemap(sttype) int,                const int &                "int"
%typemap(sttype) unsigned int,       const unsigned int &       "uint"
%typemap(sttype) long,               const long &               "long"
%typemap(sttype) unsigned long,      const unsigned long &      "ulong"
%typemap(sttype) long long,          const long long &          "longlong"
%typemap(sttype) unsigned long long, const unsigned long long & "ulonglong"
%typemap(sttype) float,              const float &              "float"
%typemap(sttype) double,             const double &             "double"
%typemap(sttype) char *                                         "charPtr"
%typemap(sttype) void                                           "void"

/* these were deprecated in the S# implementation and may become obsolete */
%typemap(stitype) bool,               const bool &               "Boolean"
%typemap(stitype) char,               const char &               "Char"
%typemap(stitype) signed char,        const signed char &        "Char"
%typemap(stitype) unsigned char,      const unsigned char &      "Char"
%typemap(stitype) short,              const short &              "Integer"
%typemap(stitype) unsigned short,     const unsigned short &     "Integer"
%typemap(stitype) int,                const int &                "Integer"
%typemap(stitype) unsigned int,       const unsigned int &       "Integer"
%typemap(stitype) long,               const long &               "Integer"
%typemap(stitype) unsigned long,      const unsigned long &      "Integer"
%typemap(stitype) long long,          const long long &          "Integer"
%typemap(stitype) unsigned long long, const unsigned long long & "Integer"
%typemap(stitype) float,              const float &              "Float"
%typemap(stitype) double,             const double &             "Float"
%typemap(stitype) char *                                         "String"
%typemap(stitype) void                                           "Object"

%typemap(stni) char[ANY]                "st_CharPtr"
%typemap(sttype) char[ANY]                "charPtr"
%typemap(stitype) char[ANY]               "String"

typedef long ssobject;

%typemap(stni) stobject                         "ssobject"
%typemap(sttype) stobject                       "voidPtr"
%typemap(stitype) stobject               	"Object"

/* stni types */
%typemap(stni) st_UInt8                 "st_UInt8"
%typemap(stni) st_Char8                 "st_Char8"
%typemap(stni) st_UInt8                 "st_UInt8"
%typemap(stni) st_Int16                 "st_Int16"
%typemap(stni) st_UInt16                "st_UInt16"
%typemap(stni) st_Int32                 "st_Int32"
%typemap(stni) st_UInt32                "st_UInt32"
%typemap(stni) st_Int64                 "st_Int64"
%typemap(stni) st_UInt64                "st_UInt64"
%typemap(stni) st_Float32               "st_Float32"
%typemap(stni) st_Float64               "st_Float64"
%typemap(stni) st_CharPtr               "st_LPCSTR"

%typemap(stni) st_intArray     "st_intArray"
%typemap(stni) st_longArray    "st_longArray"
%typemap(stni) st_floatArray   "st_floatArray"
%typemap(stni) st_doubleArray  "st_doubleArray"
%typemap(stni) st_objectArray  "st_objectArray"

%typemap(sttype) st_char         "char"
%typemap(sttype) st_int          "int"
%typemap(sttype) st_long         "long"
%typemap(sttype) st_float        "float"
%typemap(sttype) st_double       "double"
%typemap(sttype) st_string       "String"
%typemap(sttype) st_object       "Object"
%typemap(sttype) st_booleanArray "boolean[]"
%typemap(sttype) st_charArray    "char[]"
%typemap(sttype) st_byteArray    "byte[]"
%typemap(sttype) st_shortArray   "short[]"
%typemap(sttype) st_intArray     "int[]"
%typemap(sttype) st_longArray    "long[]"
%typemap(sttype) st_floatArray   "float[]"
%typemap(sttype) st_doubleArray  "double[]"
%typemap(sttype) st_objectArray  "Object[]"

/* Non primitive types */
%typemap(stni) SWIGTYPE "st_SwigPtr"
%typemap(sttype) SWIGTYPE "voidPtr"
%typemap(stitype) SWIGTYPE "$&stclassname"

%typemap(stni) SWIGTYPE [] "st_SwigPtr"
%typemap(sttype) SWIGTYPE [] "voidPtr"
%typemap(stitype) SWIGTYPE [] "$stclassname"

%typemap(stni) SWIGTYPE * "st_SwigPtr"
%typemap(sttype) SWIGTYPE * "voidPtr"
%typemap(stitype) SWIGTYPE * "$stclassname"

%typemap(stni) SWIGTYPE & "st_SwigPtr"
%typemap(sttype) SWIGTYPE & "voidPtr"
%typemap(stitype) SWIGTYPE & "$stclassname"

%typemap(stni) enum SWIGTYPE "st_Int32"
%typemap(sttype) enum SWIGTYPE "int"
%typemap(stitype) enum SWIGTYPE "Int32"

/* pointer to a class member */
%typemap(stni) SWIGTYPE (CLASS::*) "st_SwigPtr"
%typemap(sttype) SWIGTYPE (CLASS::*) "voidPtr"
%typemap(stitype) SWIGTYPE (CLASS::*) "$stclassname"

/* The following are the in, out, freearg, argout typemaps. These are the stni code generating
typemaps for converting from Smalltalk to C and visa versa. */

/* primitive types */
%typemap(in) bool
%{ $1 = $input ? true : false; %}

%typemap(in) char,
             signed char,
             unsigned char,
             short,
             unsigned short,
             int,
             unsigned int,
             long,
             unsigned long,
             long long,
             float,
             double,
             enum SWIGTYPE
%{ $1 = ($1_ltype)$input; %}

%typemap(out) bool           %{ $result = (st_UInt8)$1; %}
%typemap(out) char           %{ $result = (st_Char8)$1; %}
%typemap(out) signed char    %{ $result = (st_Char8)$1; %}
%typemap(out) unsigned char  %{ $result = (st_UInt8)$1; %}
%typemap(out) short          %{ $result = (st_Int16)$1; %}
%typemap(out) signed short   %{ $result = (st_Int16)$1; %}
%typemap(out) unsigned short %{ $result = (st_UInt16)$1; %}
%typemap(out) int            %{ $result = (st_Int32)$1; %}
%typemap(out) signed int     %{ $result = (st_Int32)$1; %}
%typemap(out) unsigned int   %{ $result = (st_UInt32)$1; %}
%typemap(out) long           %{ $result = (st_Int32)$1; %}
%typemap(out) signed long    %{ $result = (st_Int32)$1; %}
%typemap(out) unsigned long  %{ $result = (st_UInt32)$1; %}
%typemap(out) long long      %{ $result = (st_Int64)$1; %}
%typemap(out) signed long long          %{ $result = (st_Int64)$1; %}
%typemap(out) unsigned long long        %{ $result = (st_UInt64)$1; %}
%typemap(out) float          %{ $result = (st_Float32)$1; %}
%typemap(out) double         %{ $result = (st_Float64)$1; %}
%typemap(out) enum SWIGTYPE  %{ $result = (st_Int32)$1; %}

/* char * - treat as String */

%typemap(in) char * %{ $1 = $input; %}
%typemap(out) char * %{ $result = $1; %}

%typemap(out) void ""

/* this maps the output type of a char* */
%typemap(out) char * { if($1) $result = $1; }

%typemap(out) void ""

/* primitive types by reference */
%typemap(in) const bool & (bool temp)
%{ temp = $input ? true : false;
   $1 = &temp; %}

%typemap(in) const char & (char temp),
             const signed char & (signed char temp),
             const unsigned char & (unsigned char temp),
             const short & (short temp),
             const unsigned short & (unsigned short temp),
             const int & (int temp),
             const unsigned int & (unsigned int temp),
             const long & (long temp),
             const unsigned long & (unsigned long temp),
             const long long & ($*1_ltype temp),
             const float & (float temp),
             const double & (double temp)
%{ temp = ($*1_ltype)$input;
   $1 = &temp; %}

/* Default handling. Object passed by value. Convert to a pointer */
%typemap(in) SWIGTYPE ($&1_type argp)
%{ argp = *($&1_ltype*)&$input;
   $1 = *argp; %}

%typemap(out) SWIGTYPE

#ifdef __cplusplus
%{*($&1_ltype*)&$result = new $1_ltype(($1_ltype &)$1); %}
#else
{
  $&1_ltype $1ptr = ($&1_ltype) malloc(sizeof($1_ltype));
  memmove($1ptr, &$1, sizeof($1_type));
  *($&1_ltype*)&$result = $1ptr;
}
#endif

/* Generic pointers and references */
%typemap(in) SWIGTYPE *, SWIGTYPE (CLASS::*) %{ $1 = *($&1_ltype)&$input; %}
%typemap(in) SWIGTYPE & %{ $1 = *($&1_ltype)&$input;
  if(!$1) {
    //We could throw an Smalltalk exception here
    return $null;
  } %}
%typemap(out) SWIGTYPE *, SWIGTYPE (CLASS::*)
%{ *($&1_ltype)&$result = $1; %}
%typemap(out) SWIGTYPE &
%{ *($&1_ltype)&$result = $1; %}

/* Default array handling */
%typemap(in) SWIGTYPE [] %{ $1 = *($&1_ltype)&$input; %}
%typemap(out) SWIGTYPE [] %{ *($&1_ltype)&$result = $1; %}

/* char[ANY] - treat as String */

%typemap(in) char[ANY] %{ $1 = $input; %}
%typemap(out) char[ANY] %{ $result = $1; %}

%typemap(freearg) char[ANY] ""
%typemap(argout) char[ANY] ""

/* STNI types */

%typecheck(SWIG_TYPECHECK_POINTER) /* Default */
    SWIGTYPE,
    SWIGTYPE *,
    SWIGTYPE &,
    SWIGTYPE [],
    SWIGTYPE (CLASS::*)
    ""

/* Typemaps for code generation in proxy classes and Smalltalk type wrapper classes */

/* The stin typemap is used for converting function parameter types from the type
 * used in the proxy, module or type wrapper class to the type used in the stni class. */

%typemap(stin)
                 signed char,        const signed char &,
                 unsigned char,      const unsigned char &,
                 short,              const short &,
                 unsigned short,     const unsigned short &,
                 int,                const int &,
                 unsigned int,       const unsigned int &,
                 long,               const long &,
                 unsigned long,      const unsigned long &,
                 long long,          const long long &,
                 unsigned long long, const unsigned long long &,
                 float,              const float &,
                 double,             const double &,
                 enum SWIGTYPE
    "$stinput"

/* The typemap stout is used for converting function return types from the return type
 * used in the stni class to the type returned by the proxy, module or type wrapper class. */

%typemap(stout)   signed char,        const signed char &,
                  unsigned char,      const unsigned char &,
                  short,              const short &,
                  unsigned short,     const unsigned short &,
                  int,                const int &,
                  unsigned int,       const unsigned int &,
                  long,               const long &,
                  unsigned long,      const unsigned long &,
                  long long,          const long long &,
                  unsigned long long, const unsigned long long &,
                  float,              const float &,
                  double,             const double &,
                  enum SWIGTYPE %{
    ^$stnicall
%}

%typemap(stout) void %{
    $stnicall
%}

%typemap(stin) char, const char & "$stinput asCharacterParameter"
%typemap(stout) char, const char & %{
	^($stnicall) asCharacter
%}

%typemap(stin) bool, const bool & "$stinput asBooleanParameter"
%typemap(stout) bool, const bool & %{
	^($stnicall) asBoolean
%}

%typemap(stin) char *, char[ANY] "$stinput asNullTermStringParameter"
%typemap(stout) char *, char[ANY] %{
	^($stnicall) asNullTermString
%}

%typemap(stin) SWIGTYPE "($&stclassname getCPtr: $stinput)"
%typemap(stin) SWIGTYPE *, SWIGTYPE &, SWIGTYPE [], SWIGTYPE (CLASS::*) "($stclassname getCPtr: $stinput)"

%typemap(stout) SWIGTYPE %{
    ^$&stclassname fromPointer: $stnicall memoryOwn: true
%}

%typemap(stout) SWIGTYPE & %{
    ^$stclassname fromPointer: $stnicall memoryOwn: $owner
%}

%typemap(stout) SWIGTYPE *, SWIGTYPE [], SWIGTYPE (CLASS::*) %{
    |cPtr|
    cPtr := $stnicall.
    ^(cPtr == 0) ifTrue:[ nil ] ifFalse:[ $stclassname fromPointer: cPtr memoryOwn: $owner ]
%}

/* Typemaps used for the generation of proxy and type wrapper class code */
%typemap(stextracode) SWIGTYPE, SWIGTYPE *, SWIGTYPE &, SWIGTYPE [], SWIGTYPE (CLASS::*) ""
%typemap(stbase) SWIGTYPE, SWIGTYPE *, SWIGTYPE &, SWIGTYPE [], SWIGTYPE (CLASS::*) ""

%typemap(stfinalize) SWIGTYPE %{
  Method[ swigFinalize
    super swigFinalize.
    self delete.
  ]
%}

%typemap(stdestruct, methodname="delete") SWIGTYPE %{
    (swigCMemoryOwn and:[ swigCPtrFor$stclassname ~~ 0 ]) ifTrue:[
      swigCMemoryOwn := false.
      $stnicall.
    ].
    swigCPtrFor$stclassname := 0.
%}

%typemap(stdestruct_derived, methodname="delete") SWIGTYPE %{
    (swigCMemoryOwn and:[ swigCPtrFor$stclassname ~~ 0 ]) ifTrue:[
      swigCMemoryOwn := false.
      $stnicall.
    ].
    swigCPtrFor$stclassname := 0.
    super delete.
%}

%typemap(stgetcptr) SWIGTYPE, SWIGTYPE *, SWIGTYPE &, SWIGTYPE [], SWIGTYPE (CLASS::*) %{
  Function[ getCPtr: obj
     obj isNil ifTrue:[^0].
     ^obj getCPtrFor$stclassname
  ]
%}

/* Smalltalk specific directives */

#define %stconst(flag)                      			%feature("smalltalk:const","flag")
#define %stconstembed(flag)         				%feature("smalltalk:constembed","flag")
#define %st_preserve_class_case                                 %pragma(smalltalk) upcaseclasses="1"
#define %st_preserve_method_case                                %pragma(smalltalk) downcasemethods="1"

/* Some ANSI C typemaps */

%apply long { size_t };

