Merge pull request #1471 from ZackerySpytz/OCaml-segfaults-list-args

[OCaml] Fix segfaults when too few arguments are passed to a function
diff --git a/CHANGES.current b/CHANGES.current
index 91f63e6..5c1f00f 100644
--- a/CHANGES.current
+++ b/CHANGES.current
@@ -45,6 +45,9 @@
 
             *** POTENTIAL INCOMPATIBILITY ***
 
+2019-02-13: ZackerySpytz
+            #1469 Add support for C++17 hexadecimal floating literals.
+
 2019-02-11: wsfulton
             [OCaml] #1437 OCaml has been give the 'Experimental' language status. The examples work
             and most of the test-suite is also working, so it is quite close to being a 'Supported' language.
@@ -53,8 +56,8 @@
 	    #1464 Add support for C++14 binary integer literals.
 
 2019-02-10: ZackerySpytz
-	    #1450 Add support for C++11 UCS-2 and UCS-4 character literals. Also add support for
-            C++17 UTF8 character literals.
+	    #1450 Add support for C++11 UCS-2 and UCS-4 character literals. Also, add support for
+            C++17 UTF-8 character literals.
 
 2019-02-10: wsfulton
 	    [MzScheme] #1437 MzScheme/Racket is now an 'Experimental' language. The examples work
@@ -211,7 +214,7 @@
             int64_t instead of int64.
 
 2019-01-11: ZackerySpytz
-            [OCaml] #1400 Fix getters and setters.
+            [OCaml] #1400 Fix the getters and setters of non-static member variables.
 
 2019-01-07: wsfulton
             #358 Add VOID to windows.i
@@ -233,7 +236,7 @@
             prevent accepting a conversion to a NULL pointer.
 
 2019-01-03: ZackerySpytz
-            [OCaml] #1386 Fix OCaml out-of-source test-suite
+            [OCaml] #1386 Fix the OCaml examples and test suite for out-of-source builds.
 
 2019-01-01: wsfulton
             [Python] #639 remove duplicate proxy method definitions for global function wrappers.
diff --git a/Doc/Manual/CPlusPlus17.html b/Doc/Manual/CPlusPlus17.html
index ae3ca5c..a234666 100644
--- a/Doc/Manual/CPlusPlus17.html
+++ b/Doc/Manual/CPlusPlus17.html
@@ -16,6 +16,7 @@
 <ul>
 <li><a href="#CPlusPlus17_nested_namespaces">Nested namespace definitions</a>
 <li><a href="#CPlusPlus17_u8_char_literals">UTF-8 character literals</a>
+<li><a href="#CPlusPlus17_hexadecimal_floating_literals">Hexadecimal floating literals</a>
 </ul>
 <li><a href="#CPlusPlus17_standard_library_changes">Standard library changes</a>
 </ul>
@@ -87,6 +88,20 @@
 </pre>
 </div>
 
+<H3><a name="CPlusPlus17_hexadecimal_floating_literals">9.2.3 Hexadecimal floating literals</a></H3>
+
+
+<p>
+C++17 added hexadecimal floating literals.
+For example:
+</p>
+
+<div class="code">
+<pre>
+double f = 0xF.68p2;
+</pre>
+</div>
+
 <H2><a name="CPlusPlus17_standard_library_changes">9.3 Standard library changes</a></H2>
 
 
diff --git a/Doc/Manual/Contents.html b/Doc/Manual/Contents.html
index d303370..fa1ef9b 100644
--- a/Doc/Manual/Contents.html
+++ b/Doc/Manual/Contents.html
@@ -365,6 +365,7 @@
 <ul>
 <li><a href="CPlusPlus17.html#CPlusPlus17_nested_namespaces">Nested namespace definitions</a>
 <li><a href="CPlusPlus17.html#CPlusPlus17_u8_char_literals">UTF-8 character literals</a>
+<li><a href="CPlusPlus17.html#CPlusPlus17_hexadecimal_floating_literals">Hexadecimal floating literals</a>
 </ul>
 <li><a href="CPlusPlus17.html#CPlusPlus17_standard_library_changes">Standard library changes</a>
 </ul>
diff --git a/Doc/Manual/Ocaml.html b/Doc/Manual/Ocaml.html
index 6da8661..92b5260 100644
--- a/Doc/Manual/Ocaml.html
+++ b/Doc/Manual/Ocaml.html
@@ -991,9 +991,88 @@
 
 
 <p>
-Catching exceptions is now supported using SWIG's %exception feature.  A simple
-but not too useful example is provided by the throw_exception testcase in
-Examples/test-suite.  You can provide your own exceptions, too.
+If an error occurs in a C or C++ function, you may want to convert that error into an OCaml
+exception.  To do this, you can use the <tt>%exception</tt> directive.  The <tt>%exception</tt>
+directive simply lets you rewrite part of the generated wrapper code to include an error check.
+It is detailed in full in the <a href="Customization.html#Customization_exception">Exception handling with %exception</a> section.
+</p>
+
+<p>
+In C, a function often indicates an error by returning a status code (e.g. a negative number
+or a NULL pointer).  Here is a simple example of how you might handle that:
+</p>
+
+<div class="code">
+<pre>
+%exception malloc {
+  $action
+  if (result == NULL) {
+    caml_failwith("Not enough memory");
+  }
+}
+void *malloc(size_t nbytes);
+</pre>
+</div>
+
+<p>
+In OCaml:
+</p>
+
+<div class="code">
+<pre>
+# let a = _malloc (C_int 20000000000);;
+Exception: Failure "Not enough memory".
+#
+</pre>
+</div>
+
+<p>
+If a library provides some kind of general error handling framework, you can also use
+that.  For example:
+</p>
+
+<div class="code">
+<pre>
+%exception {
+  $action
+  if (err_occurred()) {
+    caml_failwith(err_message());
+  }
+}
+</pre>
+</div>
+
+<p>
+If no declaration name is given to <tt>%exception</tt>, it is applied to all wrapper functions.
+<tt>$action</tt> is a SWIG special variable and is replaced by the C/C++ function call being wrapped.
+</p>
+
+<p>
+C++ exceptions are also easy to handle.  We can catch a C++ exception and rethrow it as
+an OCaml exception like this:
+</p>
+
+<div class="code">
+<pre>
+%exception getitem {
+  try {
+    $action
+  } catch (std::out_of_range &amp;e) {
+    caml_failwith(e.what());
+  }
+}
+
+class FooClass {
+  public:
+    int getitem(int index);      // Exception handling added
+    ...
+};
+</pre>
+</div>
+
+<p>
+The language-independent <tt>exception.i</tt> library file can also be used
+to raise exceptions.  See the <a href="Library.html#Library">SWIG Library</a> chapter.
 </p>
 
 <H2><a name="Ocaml_nn32">38.3 Documentation Features</a></H2>
diff --git a/Examples/ocaml/argout_ref/example.i b/Examples/ocaml/argout_ref/example.i
index 5ea6777..472a838 100644
--- a/Examples/ocaml/argout_ref/example.i
+++ b/Examples/ocaml/argout_ref/example.i
@@ -1,6 +1,11 @@
 /* File : example.i */
 %module example
 
+%typemap(argout) (int &x, int &y) {
+  swig_result = caml_list_append(swig_result, caml_val_int(*$1));
+  swig_result = caml_list_append(swig_result, caml_val_int(*$2));
+}
+
 %{
 extern "C" void   factor(int &x, int &y);
 %}
diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk
index 944f682..04b39e7 100644
--- a/Examples/test-suite/common.mk
+++ b/Examples/test-suite/common.mk
@@ -163,6 +163,7 @@
 	cpp_static \
 	cpp_typedef \
 	cpp14_binary_integer_literals \
+	cpp17_hex_floating_literals \
 	cpp17_nested_namespaces \
 	cpp17_nspace_nested_namespaces \
 	cpp17_u8_char_literals \
diff --git a/Examples/test-suite/cpp17_hex_floating_literals.i b/Examples/test-suite/cpp17_hex_floating_literals.i
new file mode 100644
index 0000000..dfc1dc0
--- /dev/null
+++ b/Examples/test-suite/cpp17_hex_floating_literals.i
@@ -0,0 +1,43 @@
+%module cpp17_hex_floating_literals
+
+// Tests are designed so that code compiles with C++98 compilers
+
+%{
+#if __cplusplus >= 201703L
+#define CPP17 1
+#endif
+%}
+
+double f1 = 0x.0p1;
+double f2 = 0x0.p1;
+double f3 = 0x0.0p-1;
+double f4 = 0xf.p-1;
+double f5 = 0xA.0p1;
+double f6 = 0x0.10P+10;
+double f7 = 0xb2F.p2;
+float f8 = 0x1234AP1F;
+float f9 = 0x45A1.D1A2p+10f;
+
+%{
+#if defined(CPP17)
+double f1 = 0x.0p1;
+double f2 = 0x0.p1;
+double f3 = 0x0.0p-1;
+double f4 = 0xf.p-1;
+double f5 = 0xA.0p1;
+double f6 = 0x0.10P+10;
+double f7 = 0xb2F.p2;
+float f8 = 0x1234AP1F;
+float f9 = 0x45A1.D1A2p+10f;
+#else
+double f1 = 0.;
+double f2 = 0.;
+double f3 = 0.;
+double f4 = 7.5;
+double f5 = 20.;
+double f6 = 64.;
+double f7 = 11452.;
+float f8 = 149140.f;
+float f9 = 18253638.f;
+#endif
+%}
diff --git a/Examples/test-suite/ocaml/dynamic_cast_runme.ml b/Examples/test-suite/ocaml/dynamic_cast_runme.ml
new file mode 100644
index 0000000..54391d9
--- /dev/null
+++ b/Examples/test-suite/ocaml/dynamic_cast_runme.ml
@@ -0,0 +1,9 @@
+open Swig
+open Dynamic_cast
+
+let f = new_Foo '()
+let b = new_Bar '()
+
+let x = f -> blah ()
+let y = b -> blah ()
+assert (_do_test '(y) as string = "Bar::test")
diff --git a/Examples/test-suite/ocaml/funcptr_cpp_runme.ml b/Examples/test-suite/ocaml/funcptr_cpp_runme.ml
new file mode 100644
index 0000000..bdc077d
--- /dev/null
+++ b/Examples/test-suite/ocaml/funcptr_cpp_runme.ml
@@ -0,0 +1,13 @@
+open Swig
+open Funcptr_cpp
+
+let _ =
+  let fp = _ADD_BY_VALUE '() in
+  assert (_call1 '(fp, 10, 11) as int = 21);
+  let fp = _ADD_BY_POINTER '() in
+  assert (_call2 '(fp, 12, 13) as int = 25);
+  let fp = _ADD_BY_REFERENCE '() in
+  assert (_call3 '(fp, 14, 15) as int = 29);
+  let fp = _ADD_BY_VALUE_C '() in
+  assert (_call1 '(fp, 2, 3) as int = 5);
+;;
diff --git a/Examples/test-suite/ocaml/overload_bool_runme.ml b/Examples/test-suite/ocaml/overload_bool_runme.ml
index ce0ce9e..fefd074 100644
--- a/Examples/test-suite/ocaml/overload_bool_runme.ml
+++ b/Examples/test-suite/ocaml/overload_bool_runme.ml
@@ -12,4 +12,15 @@
   assert (_boolfunction '(false) as string = "false");
   assert (_intfunction '(true) as string = "int");
   assert (_intfunction '(false) as string = "int");
+
+  assert (_overloaded_ref '(true) as string = "bool");
+  assert (_overloaded_ref '(false) as string = "bool");
+  assert (_overloaded_ref '(0) as string = "int");
+  assert (_overloaded_ref '(1) as string = "int");
+  assert (_overloaded_ref '(2) as string = "int");
+  assert (_overloaded_ref '("1234") as string = "string");
+  assert (_boolfunction_ref '(true) as string = "true");
+  assert (_boolfunction_ref '(false) as string = "false");
+  assert (_intfunction_ref '(true) as string = "int");
+  assert (_intfunction_ref '(false) as string = "int");
 ;;
diff --git a/Examples/test-suite/ocaml/primitive_ref_runme.ml b/Examples/test-suite/ocaml/primitive_ref_runme.ml
new file mode 100644
index 0000000..7c96caa
--- /dev/null
+++ b/Examples/test-suite/ocaml/primitive_ref_runme.ml
@@ -0,0 +1,20 @@
+open Swig
+open Primitive_ref
+
+let _ =
+  assert (_ref_int '(3) as int = 3);
+  assert (_ref_short '(3) as int = 3);
+  assert (_ref_ushort '(3) as int = 3);
+  assert (_ref_long '(3) as int = 3);
+  assert (_ref_ulong '(3) as int = 3);
+  assert (_ref_schar '(3) as int = 3);
+  assert (_ref_uchar '(3) as int = 3);
+  assert (_ref_float '(3.5) as float = 3.5);
+  assert (_ref_double '(3.5) as float = 3.5);
+  assert (_ref_bool '(true) as bool = true);
+  let arg = C_char 'x' in
+  assert (_ref_char '(arg) as char = 'x');
+  assert (_ref_over '(0) as int = 0);
+  let a = new_A '(12) in
+  assert (_ref_over '(a) as int = 12);
+;;
diff --git a/Examples/test-suite/ocaml/reference_global_vars_runme.ml b/Examples/test-suite/ocaml/reference_global_vars_runme.ml
new file mode 100644
index 0000000..aa17087
--- /dev/null
+++ b/Examples/test-suite/ocaml/reference_global_vars_runme.ml
@@ -0,0 +1,57 @@
+open Swig
+open Reference_global_vars
+
+let _ =
+  let tc = _getconstTC '() in
+  assert (tc -> "[num]" () as int = 33);
+
+  let _ = _var_bool (_createref_bool (C_bool false)) in
+  assert (_value_bool (_var_bool '()) as bool = false);
+
+  let _ = _var_bool (_createref_bool (C_bool true)) in
+  assert (_value_bool (_var_bool '()) as bool = true);
+
+  let _ = _var_char (_createref_char (C_char 'w')) in
+  assert (_value_char (_var_char '()) as char = 'w');
+
+  let _ = _var_unsigned_char (_createref_unsigned_char (C_uchar 'w')) in
+  assert (_value_unsigned_char (_var_unsigned_char '()) as char = 'w');
+
+  let _ = _var_signed_char (_createref_signed_char (C_uchar 'w')) in
+  assert (_value_signed_char (_var_signed_char '()) as char = 'w');
+
+  let _ = _var_short (_createref_short (C_short 10)) in
+  assert (_value_short (_var_short '()) as int = 10);
+  
+  let _ = _var_unsigned_short (_createref_unsigned_short (C_ushort 10)) in
+  assert (_value_unsigned_short (_var_unsigned_short '()) as int = 10);
+
+  let _ = _var_int (_createref_int (C_int 10)) in
+  assert (_value_int (_var_int '()) as int = 10);
+
+  let _ = _var_unsigned_int (_createref_unsigned_int (C_int 10)) in
+  assert (_value_unsigned_int (_var_unsigned_int '()) as int = 10);
+
+  let _ = _var_long (_createref_long (C_int64 10L)) in
+  assert (_value_long (_var_long '()) as int = 10);
+
+  let _ = _var_unsigned_long (_createref_unsigned_long (C_int64 10L)) in
+  assert (_value_unsigned_long (_var_unsigned_long '()) as int = 10);
+
+  let _ = _var_long_long (_createref_long_long (C_int64 0x6FFFFFFFFFFFFFF8L)) in
+  assert (_value_long_long (_var_long_long '()) = C_int64 0x6FFFFFFFFFFFFFF8L);
+
+  let _ = _var_unsigned_long_long (_createref_unsigned_long_long (C_int64 0x6FFFFFFFFFFFFFF8L)) in
+  assert (_value_unsigned_long_long (_var_unsigned_long_long '()) = C_int64 0x6FFFFFFFFFFFFFF8L);
+
+  let _ = _var_float (_createref_float (C_float 10.)) in
+  assert (_value_float (_var_float '()) as float = 10.);
+
+  let _ = _var_double (_createref_double (C_double 10.)) in
+  assert (_value_double (_var_double '()) as float = 10.);
+
+  let tc = new_TestClass '(20) in
+  let _ = _var_TestClass (_createref_TestClass (tc)) in
+  let tc = _value_TestClass (_var_TestClass '()) in
+  assert (tc -> "[num]" () as int = 20);
+;;
diff --git a/Examples/test-suite/ocaml/template_ref_type_runme.ml b/Examples/test-suite/ocaml/template_ref_type_runme.ml
new file mode 100644
index 0000000..2db2f9b
--- /dev/null
+++ b/Examples/test-suite/ocaml/template_ref_type_runme.ml
@@ -0,0 +1,6 @@
+open Swig
+open Template_ref_type
+
+let xr = new_XC '()
+let y = new_Y '()
+let _ = y -> find (xr)
diff --git a/Examples/test-suite/python/cpp17_hex_floating_literals_runme.py b/Examples/test-suite/python/cpp17_hex_floating_literals_runme.py
new file mode 100644
index 0000000..ed9f4d2
--- /dev/null
+++ b/Examples/test-suite/python/cpp17_hex_floating_literals_runme.py
@@ -0,0 +1,28 @@
+from cpp17_hex_floating_literals import *
+
+if cvar.f1 != 0.:
+    raise RuntimeError
+
+if cvar.f2 != 0.:
+    raise RuntimeError
+
+if cvar.f3 != 0.:
+    raise RuntimeError
+
+if cvar.f4 != 7.5:
+    raise RuntimeError
+
+if cvar.f5 != 20.:
+    raise RuntimeError
+
+if cvar.f6 != 64.:
+    raise RuntimeError
+
+if cvar.f7 != 11452.:
+    raise RuntimeError
+
+if cvar.f8 != 149140.:
+    raise RuntimeError
+
+if cvar.f9 != 18253638.:
+    raise RuntimeError
diff --git a/Lib/ocaml/ocaml.swg b/Lib/ocaml/ocaml.swg
index 192a181..2da3fb7 100644
--- a/Lib/ocaml/ocaml.swg
+++ b/Lib/ocaml/ocaml.swg
@@ -459,15 +459,6 @@
 	}
 	if( !Is_block(v) ) return -1;
 	switch( SWIG_Tag_val(v) ) {
-	case C_int:
-	    if( !caml_long_val( v ) ) {
-		*out = 0;
-		CAMLreturn_type(0);
-	    } else {
-		*out = 0;
-		CAMLreturn_type(1);
-	    }
-	    break;
 	case C_obj:
 	    if (!func_val) {
 	        func_val = caml_named_value("caml_obj_ptr");
diff --git a/Lib/ocaml/typemaps.i b/Lib/ocaml/typemaps.i
index 4475707..a6c7ef4 100644
--- a/Lib/ocaml/typemaps.i
+++ b/Lib/ocaml/typemaps.i
@@ -52,10 +52,14 @@
     $1 = *(($ltype) caml_ptr_val($input,$1_descriptor));
 }
 
-%typemap(out) SWIGTYPE &, SWIGTYPE && {
+%typemap(varout) SWIGTYPE &, SWIGTYPE && {
     $result = SWIG_Ocaml_ptr_to_val("create_$ntype_from_ptr", (void *)&$1, $1_descriptor);
 }
 
+%typemap(out) SWIGTYPE &, SWIGTYPE && {
+    $result = SWIG_Ocaml_ptr_to_val("create_$ntype_from_ptr", (void *)$1, $1_descriptor);
+}
+
 #if 0
 %typemap(argout) SWIGTYPE & {
     CAML_VALUE *fromval = caml_named_value("create_$ntype_from_ptr");
@@ -85,9 +89,6 @@
 }
 #endif
 
-%typemap(argout) const SWIGTYPE & { }
-%typemap(argout) const SWIGTYPE && { }
-
 %typemap(in) SWIGTYPE {
     $1 = *(($&1_ltype) caml_ptr_val($input,$&1_descriptor)) ;
 }
@@ -123,26 +124,26 @@
 /* The SIMPLE_MAP macro below defines the whole set of typemaps needed
    for simple types. */
 
-%define SIMPLE_MAP(C_NAME, C_TO_MZ, MZ_TO_C)
+%define SIMPLE_MAP(C_NAME, C_TO_OCAML, OCAML_TO_C)
 /* In */
 %typemap(in) C_NAME {
-    $1 = MZ_TO_C($input);
+    $1 = OCAML_TO_C($input);
 }
 %typemap(varin) C_NAME {
-    $1 = MZ_TO_C($input);
+    $1 = OCAML_TO_C($input);
 }
 %typemap(in) C_NAME & ($*1_ltype temp) {
-    temp = ($*1_ltype) MZ_TO_C($input);
+    temp = ($*1_ltype) OCAML_TO_C($input);
     $1 = &temp;
 }
 %typemap(varin) C_NAME & {
-    $1 = MZ_TO_C($input);
+    $1 = OCAML_TO_C($input);
 }
 %typemap(directorout) C_NAME {
-    $1 = MZ_TO_C($input);
+    $1 = OCAML_TO_C($input);
 }
 %typemap(in) C_NAME *INPUT ($*1_ltype temp) {
-    temp = ($*1_ltype) MZ_TO_C($input);
+    temp = ($*1_ltype) OCAML_TO_C($input);
     $1 = &temp;
 }
 %typemap(in,numinputs=0) C_NAME *OUTPUT ($*1_ltype temp) {
@@ -150,25 +151,22 @@
 }
 /* Out */
 %typemap(out) C_NAME {
-    $result = C_TO_MZ($1);
+    $result = C_TO_OCAML($1);
 }
 %typemap(varout) C_NAME {
-    $result = C_TO_MZ($1);
+    $result = C_TO_OCAML($1);
 }
 %typemap(varout) C_NAME & {
-    $result = C_TO_MZ($1);
+    $result = C_TO_OCAML($1);
 }
 %typemap(argout) C_NAME *OUTPUT {
-    swig_result = caml_list_append(swig_result,C_TO_MZ((long)*$1));
+    swig_result = caml_list_append(swig_result, C_TO_OCAML((long)*$1));
 }
 %typemap(out) C_NAME & {
-    $result = C_TO_MZ(*$1);
-}
-%typemap(argout) C_NAME & {
-    swig_result = caml_list_append(swig_result,C_TO_MZ((long)*$1));
+    $result = C_TO_OCAML(*$1);
 }
 %typemap(directorin) C_NAME {
-    args = caml_list_append(args,C_TO_MZ($1));
+    args = caml_list_append(args, C_TO_OCAML($1));
 }
 %enddef
 
@@ -307,6 +305,11 @@
     $2 = ($2_ltype) caml_string_len($input);
 }
 
+%typemap(out) SWIGTYPE *DYNAMIC, SWIGTYPE &DYNAMIC {
+    swig_type_info *ty = SWIG_TypeDynamicCast($1_descriptor, (void **)&$1);
+    $result = SWIG_Ocaml_ptr_to_val("create_$ntype_from_ptr", (void *)$1, ty);
+}
+
 /* Array reference typemaps */
 %apply SWIGTYPE & { SWIGTYPE ((&)[ANY]) }
 %apply SWIGTYPE && { SWIGTYPE ((&)[ANY]) }
diff --git a/Source/Swig/scanner.c b/Source/Swig/scanner.c
index 24a07e6..9643366 100644
--- a/Source/Swig/scanner.c
+++ b/Source/Swig/scanner.c
@@ -1196,6 +1196,10 @@
 	return SWIG_TOKEN_INT;
       if (isxdigit(c))
 	state = 85;
+      else if (c == '.') /* hexadecimal float */
+	state = 860;
+      else if ((c == 'p') || (c == 'P')) /* hexadecimal float */
+	state = 820;
       else if ((c == 'l') || (c == 'L')) {
 	state = 87;
       } else if ((c == 'u') || (c == 'U')) {
@@ -1220,7 +1224,22 @@
 	return SWIG_TOKEN_INT;
       }
       break;
-
+    case 860:
+      /* hexadecimal float */
+      if ((c = nextchar(s)) == 0) {
+	Swig_error(cparse_file, cparse_start_line, "Hexadecimal floating literals require an exponent\n");
+	return SWIG_TOKEN_ERROR;
+      }
+      if (isxdigit(c))
+	state = 860;
+      else if ((c == 'p') || (c == 'P'))
+	state = 820;
+      else {
+	retract(s, 2);
+	Swig_error(cparse_file, cparse_start_line, "Hexadecimal floating literals require an exponent\n");
+	return SWIG_TOKEN_ERROR;
+      }
+      break;
     case 86:
       /* Rest of floating point number */