Description: Fix GYOTO_PROPERTY_SIZE_T to work on 32bit arch
 GYOTO_PROPERTY_SIZE_T assumes that size_t is an typedef for unsigned long,
 which is only true on 64 bit platforms. This patch extends the Property interface
 for size_t, but only when it is distinct from unsigned long.
Author: Thibaut Paumard <thibaut@debian.org>
Origin: upstream
Bug-Debian: https://bugs.debian.org/787725
Applied-Upstream: d069bb5d5ab279608a5a646568c7200fe4330937
Last-Update: 2015-06-05
---
This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
--- a/configure.ac
+++ b/configure.ac
@@ -31,6 +31,45 @@
 AS_IF([test "x$enable_release" != "xyes"],
   [FEATURES+="-unreleased"])
 
+## IS SIZE_T EQUIVALENT TO UNSIGNED LONG?
+#
+AC_MSG_CHECKING(whether size_t is the same as unsigned long)
+
+AC_ARG_WITH([size_t],
+  [AS_HELP_STRING([--with-size_t=same|distinct|auto],
+     [consider size_t as the same as or distinct from unsigned long (auto). Should normally be specified only if cross-compiling.])],
+  [AS_IF([test "x$with_size__t" != xsame && test "x$with_size__t" != xdistinct && test "x$with_size__t" != xauto],
+     [AC_MSG_ERROR([with-size_t should be one of same, distinct or auto])])
+  ],
+  [with_size__t=auto]
+)
+
+AS_IF([test "x$with_size__t" = xauto],
+  [AC_TRY_RUN(
+     [
+      #include <sys/types.h>
+      typedef void (* set_size_t_t) (size_t val);
+      typedef void (* set_unsigned_long_t) (unsigned long);
+      size_t size_t_value;
+      void set_size_t (size_t v) {size_t_value = v;}
+        int main(int, char**) {
+        set_unsigned_long_t ulsetter = &set_size_t;
+        (*ulsetter)(25);
+        if (size_t_value != 25) return 1;
+        return 0;
+      }
+     ],
+     [with_size__t="same"],
+     [with_size__t="distinct"])
+  ]
+)
+
+AS_IF([test "x$with_size__t" = xsame],
+  [AC_DEFINE([GYOTO_SIZE__T_IS_UNSIGNED_LONG], [1], [Define to 1 if size_t and unsigned long are the same])]
+)
+
+AC_MSG_RESULT($with_size__t)
+
 # PYTHON STUFF
 AC_ARG_WITH([python],
 	[AC_HELP_STRING([--with-python], [force (or disable) python support])],
@@ -40,7 +79,7 @@
 PC_PROG_PYTHON([], [2.7], [4.0])
 PC_PYTHON_CHECK_HEADERS(,[PYTHON=""])
 AS_IF([test "x$with_python" = xno], [PYTHON=""])
-AS_IF([test "x$with_python" = xyes && test "x$PYTHON"=x],
+AS_IF([test "x$with_python" = xyes && test "x$PYTHON" = x],
   [AC_MSG_ERROR([Python requested but no supported version found (>=2.7, <4.0)])])
 
 AC_ARG_WITH([virtualenv],
--- a/include/GyotoConfig.h.in
+++ b/include/GyotoConfig.h.in
@@ -69,6 +69,15 @@
 # endif
 #endif
 
+/** \def GYOTO_SIZE__T_IS_UNSIGNED_LONG
+    \brief Define to 1 if size_t and unsigned long are the same */
+#undef GYOTO_SIZE__T_IS_UNSIGNED_LONG
+#ifdef DOXYGEN_RUN
+# ifndef GYOTO_SIZE__T_IS_UNSIGNED_LONG
+#  define GYOTO_SIZE__T_IS_UNSIGNED_LONG (undefined)
+# endif
+#endif
+
 /** \def GYOTO_SOVERS
     \brief Gyoto ABI version.
 
--- a/include/GyotoProperty.h
+++ b/include/GyotoProperty.h
@@ -117,7 +117,15 @@
    (Gyoto::Property::set_unsigned_long_t)&class::fname,		\
    (Gyoto::Property::get_unsigned_long_t)&class::fname),
 
-#define GYOTO_PROPERTY_SIZE_T GYOTO_PROPERTY_UNSIGNED_LONG
+#if defined(GYOTO_SIZE__T_IS_UNSIGNED_LONG)
+# define GYOTO_PROPERTY_SIZE_T GYOTO_PROPERTY_UNSIGNED_LONG
+#else
+#define GYOTO_PROPERTY_SIZE_T(class, name, fname)	\
+  Gyoto::Property						\
+  (#name,							\
+   (Gyoto::Property::set_size_t_t)&class::fname,		\
+   (Gyoto::Property::get_size_t_t)&class::fname),
+#endif
 
 /// Define a Property of type Double supporting unit
 #define GYOTO_PROPERTY_DOUBLE_UNIT(class, name, fname) \
@@ -318,6 +326,10 @@
     long_t,
     /// Type is unsigned long (a.k.a. size_t)
     unsigned_long_t,
+#if !defined(GYOTO_SIZE__T_IS_UNSIGNED_LONG)
+    /// Type is size_t (only if distinct from unsigned long)
+    size_t_t,
+#endif
     /// Type is bool
     bool_t,
     /// Type is std::string
@@ -381,6 +393,12 @@
   typedef void (Object::* set_unsigned_long_t)(unsigned long val);
   /// Prototype for an accessor to get an unsigned long
   typedef unsigned long (Object::* get_unsigned_long_t)() const;
+#if !defined(GYOTO_SIZE__T_IS_UNSIGNED_LONG)
+  /// Prototype for an accessor to set a size_t
+  typedef void (Object::* set_size_t_t)(size_t val);
+  /// Prototype for an accessor to get a size_t
+  typedef size_t (Object::* get_size_t_t)() const;
+#endif
   /// Prototype for an accessor to set a bool
   typedef void (Object::* set_bool_t)(bool val);
   /// Prototype for an accessor to get a bool
@@ -449,6 +467,9 @@
     set_double_t set_double;
     set_long_t set_long;
     set_unsigned_long_t set_unsigned_long;
+#if !defined(GYOTO_SIZE__T_IS_UNSIGNED_LONG)
+    set_size_t_t set_size_t;
+#endif
     set_bool_t set_bool;
     set_string_t set_string;
     set_vector_double_t set_vdouble;
@@ -467,6 +488,9 @@
     get_double_t get_double;
     get_long_t get_long;
     get_unsigned_long_t get_unsigned_long;
+#if !defined(GYOTO_SIZE__T_IS_UNSIGNED_LONG)
+    get_size_t_t get_size_t;
+#endif
     get_bool_t get_bool;
     get_string_t get_string;
     get_vector_double_t get_vdouble;
@@ -531,6 +555,13 @@
 	   set_unsigned_long_t set_unsigned_long,
 	   get_unsigned_long_t get_unsigned_long);
 
+#if !defined(GYOTO_SIZE__T_IS_UNSIGNED_LONG)
+  /// Constructor for #type==#size_t_t
+  Property(std::string name,
+	   set_size_t_t set_size_t,
+	   get_size_t_t get_size_t);
+#endif
+
   /// Constructor for #type==#double_t, without unit support
   Property(std::string name,
 	   set_double_t set_double,
--- a/include/GyotoValue.h
+++ b/include/GyotoValue.h
@@ -107,6 +107,17 @@
   /// Cast to unsigned long
   operator unsigned long() const;
 
+#if !defined(GYOTO_SIZE__T_IS_UNSIGNED_LONG)
+ private:
+  /// A size_t (only if distinct from unsigned long)
+  size_t SizeT;
+ public:
+  /// Construct/cast from unsigned long
+  Value(size_t);
+  /// Cast to unsigned long
+  operator size_t() const;
+#endif
+
  private:
   /// A string value
   std::string String;
--- a/lib/Object.C
+++ b/lib/Object.C
@@ -111,6 +111,9 @@
     ___local_case(bool);
     ___local_case(long);
     ___local_case(unsigned_long);
+#if !defined(GYOTO_SIZE__T_IS_UNSIGNED_LONG)
+    ___local_case(size_t);
+#endif
   case Property::filename_t:
     ___local_case(string);
   case Property::vector_double_t:
@@ -193,6 +196,9 @@
     ___local_case(double);
     ___local_case(long);
     ___local_case(unsigned_long);
+#if !defined(GYOTO_SIZE__T_IS_UNSIGNED_LONG)
+    ___local_case(size_t);
+#endif
   case Property::filename_t:
     ___local_case(string);
   case Property::vector_double_t:
@@ -269,6 +275,11 @@
   case Property::unsigned_long_t:
     fmp->setParameter(name, (unsigned long)(get(p)));
     break;
+#if !defined(GYOTO_SIZE__T_IS_UNSIGNED_LONG)
+  case Property::size_t_t:
+    fmp->setParameter(name, (unsigned long)(size_t(get(p))));
+    break;
+#endif
   case Property::double_t:
     fmp->setParameter(name, double(get(p)));
     break;
@@ -389,6 +400,11 @@
   case Property::unsigned_long_t:
     val = strtoul(content.c_str(), NULL, 0);
     break;
+#if !defined(GYOTO_SIZE__T_IS_UNSIGNED_LONG)
+  case Property::size_t_t:
+    val = size_t(strtoul(content.c_str(), NULL, 0));
+    break;
+#endif
   case Property::double_t:
     val = atof(content.c_str());
     set(p, val, unit);
--- a/lib/Property.C
+++ b/lib/Property.C
@@ -15,6 +15,9 @@
 
 GYOTO_LOCAL(long)
 GYOTO_LOCAL(unsigned_long)
+#if !defined(GYOTO_SIZE__T_IS_UNSIGNED_LONG)
+GYOTO_LOCAL(size_t)
+#endif
 GYOTO_LOCAL(metric)
 GYOTO_LOCAL(spectrum)
 GYOTO_LOCAL(astrobj)
--- a/lib/UniformSpectrometer.C
+++ b/lib/UniformSpectrometer.C
@@ -45,7 +45,13 @@
 
 void Uniform::fillProperty(Gyoto::FactoryMessenger *fmp,
 			   Property const &p) const {
-  if (p.type == Property::unsigned_long_t      && p.name == "NSamples")
+  if (p.type == 
+#if defined(GYOTO_SIZE__T_IS_UNSIGNED_LONG)
+      Property::unsigned_long_t
+#else
+      Property::size_t_t
+#endif
+      && p.name == "NSamples")
     fmp -> setSelfAttribute("nsamples", nsamples_);
   else if (p.type == Property::string_t        && p.name == "Kind")
     ; // do nothing
--- a/lib/Value.C
+++ b/lib/Value.C
@@ -42,6 +42,9 @@
 
 Value::Value(long val) : type(Property::long_t), Long(val){}
 Value::Value(unsigned long val) : type(Property::unsigned_long_t), ULong(val){}
+#if !defined(GYOTO_SIZE__T_IS_UNSIGNED_LONG)
+Value::Value(size_t val) : type(Property::size_t_t), SizeT(val){}
+#endif
 Value::Value(bool val) : type(Property::bool_t), Bool(val){}
 Value::operator long() const {
   switch (type) {
@@ -49,6 +52,10 @@
     return Long;
   case Property::unsigned_long_t:
     return long(ULong);
+#if !defined(GYOTO_SIZE__T_IS_UNSIGNED_LONG)
+  case Property::size_t_t:
+    return long(SizeT);
+#endif
   default:
     throwError("This Value does not hold a long (or unsigned long)");
   }
@@ -61,12 +68,32 @@
     return (unsigned long)(Long);
   case Property::unsigned_long_t:
     return ULong;
+#if !defined(GYOTO_SIZE__T_IS_UNSIGNED_LONG)
+  case Property::size_t_t:
+    return (unsigned long)(SizeT);
+#endif
   default:
     throwError("This Value does not hold a long (or unsigned long)");
   }
   return 0;
 }
 
+#if !defined(GYOTO_SIZE__T_IS_UNSIGNED_LONG)
+Value::operator size_t() const {
+  switch (type) {
+  case Property::long_t:
+    return size_t(Long);
+  case Property::unsigned_long_t:
+    return size_t(ULong);
+  case Property::size_t_t:
+    return SizeT;
+  default:
+    throwError("This Value does not hold a long (or unsigned long)");
+  }
+  return 0;
+}
+#endif
+
 Value::operator bool() const {
   switch (type) {
   case Property::bool_t:
@@ -75,6 +102,9 @@
     return bool(Long);
   case Property::unsigned_long_t:
     return bool(ULong);
+#if !defined(GYOTO_SIZE__T_IS_UNSIGNED_LONG)
+    return bool(SizeT);
+#endif
   default:
     throwError("This Value does not hold an integer");
   }
@@ -98,6 +128,9 @@
   ___local_case(Bool);
   ___local_case(Long);
   ___local_case(ULong);
+#if !defined(GYOTO_SIZE__T_IS_UNSIGNED_LONG)
+  ___local_case(SizeT);
+#endif
   ___local_case(String);
   ___local_case(VDouble);
   ___local_case(VULong);
--- a/yorick/check-kerrks.i
+++ b/yorick/check-kerrks.i
@@ -232,7 +232,7 @@
 pos=[0, 10., 12., 5.];
 dk1=dkfunc(gg, pos);
 dk3=dknum(gg, pos);
-if (max(abs(dk1-dk3))>1e-6)
+if (max(abs(dk1-dk3))>1e-5)
   error, "dk is wrong";
 done;
 
--- a/yorick/check-scenery.i
+++ b/yorick/check-scenery.i
@@ -34,6 +34,35 @@
 
 write, format="%s %i\n", "Pointer to this Scenery:", sc(get_pointer=1);
 
+// MaxIter is a property of type size_t. The implementation of such
+// properties rely on undefined behaviour. Check here that it works in
+// practice. If one of these test fail, we have to find a new
+// implementation of GYOTO_PROPERTY_SIZE_T.
+
+doing, "Using maxiter()";
+max1=sc.maxiter();
+done;
+
+doing, "Using MaxIter()";
+max2=sc.MaxIter();
+done;
+
+doing, "Comparing";
+if (max1!=max2) error, "maxiter() and MaxIter() do not yield the same value";
+done;
+
+doing, "Checking MaxIter(val)";
+if ((sc.MaxIter(25)).maxiter() != 25) error, "MaxIter and maxiter do not agree";
+done;
+
+doing, "Checking maxiter(val)";
+if ((sc.maxiter(40)).MaxIter() != 40) error, "MaxIter and maxiter do not agree";
+done;
+
+// Set back the original value. Phew, GYOTO_PROPERTY_SIZE_T works as
+// expected.
+sc, MaxIter=max1;
+
 write, format="%s", "New scenery, setting only \"time\"... ";
 sc2=gyoto_Scenery(screen=gyoto_Screen(time=1));
 write, format="%s\n", "done.";
--- a/yorick/gyoto_utils.C
+++ b/yorick/gyoto_utils.C
@@ -397,6 +397,11 @@
   case Gyoto::Property::unsigned_long_t:
     ypush_long(long((unsigned long)(val)));
     break;
+#if !defined(GYOTO_SIZE__T_IS_UNSIGNED_LONG)
+  case Gyoto::Property::size_t_t:
+    ypush_long(long(size_t(val)));
+    break;
+#endif
   case Gyoto::Property::double_t:
     ypush_double(val);
     break;
@@ -473,6 +478,11 @@
   case Gyoto::Property::unsigned_long_t:
     val = (unsigned long)(ygets_l(iarg));
     break;
+#if !defined(GYOTO_SIZE__T_IS_UNSIGNED_LONG)
+  case Gyoto::Property::size_t_t:
+    val = size_t(ygets_l(iarg));
+    break;
+#endif
   case Gyoto::Property::double_t:
     object->set(p, ygets_d(iarg), unit);
     return;
