Tell `libgc' that we're using POSIX threads. This fixes Guile on PPC.
[bpt/guile.git] / libguile / convert.i.c
dissimilarity index 91%
index 7ab0eae..4e73bf9 100644 (file)
-/* this file is #include'd (x times) by convert.c */
-
-/* FIXME: Should we use exported wrappers for malloc (and free), which
- * allow windows DLLs to call the correct freeing function? */
-
-
-/* Convert a vector, weak vector, (if possible string, substring), list
-   or uniform vector into an C array.  If result array in argument 2 is 
-   NULL, malloc() a new one.  If out of memory, return NULL.  */
-#define FUNC_NAME SCM2CTYPES_FN
-CTYPE *
-SCM2CTYPES (SCM obj, CTYPE *data)
-{
-  long i, n;
-  SCM val;
-
-  SCM_ASSERT (SCM_NIMP (obj) || SCM_NFALSEP (scm_list_p (obj)), 
-             obj, SCM_ARG1, FUNC_NAME);
-
-  if (SCM_NFALSEP (scm_list_p (obj)))
-    {
-      SCM list = obj;
-      for (n = 0; SCM_NFALSEP (scm_pair_p (list)); list = SCM_CDR (list), n++)
-       {
-         val = SCM_CAR (list);
-#if defined (CTYPEMIN) && defined (CTYPEMAX)
-          if (SCM_INUMP (val))
-            {
-              long v = SCM_INUM (val);
-             SCM_ASSERT_RANGE (SCM_ARG1, obj, v >= CTYPEMIN && v <= CTYPEMAX);
-            }
-          else
-#elif defined (FLOATTYPE1)
-          if (!SCM_INUMP (val) && !(SCM_BIGP (val) || SCM_REALP (val)))
-#else
-         if (!SCM_INUMP (val) && !SCM_BIGP (val))
-#endif
-            SCM_WRONG_TYPE_ARG (SCM_ARG1, obj);
-        }
-      if (data == NULL)
-        data = (CTYPE *) malloc (n * sizeof (CTYPE));
-      if (data == NULL)
-        return NULL;
-
-      list = obj;
-      for (i = 0; SCM_NFALSEP (scm_pair_p (list)); list = SCM_CDR (list), i++)
-       {
-          val = SCM_CAR (list);
-         if (SCM_INUMP (val))
-            data[i] = SCM_INUM (val);
-          else if (SCM_BIGP (val))
-           data[i] = (CTYPE) scm_num2long (val, SCM_ARG1, FUNC_NAME);
-#ifdef FLOATTYPE1
-          else
-            data[i] = (CTYPE) SCM_REAL_VALUE (val);
-#endif
-       }
-      return data;
-    }
-
-  switch (SCM_TYP7 (obj))
-    {
-    case scm_tc7_vector:
-    case scm_tc7_wvect:
-      n = SCM_VECTOR_LENGTH (obj);
-      for (i = 0; i < n; i++)
-        {
-          val = SCM_VELTS (obj)[i];
-
-#if defined (CTYPEMIN) && defined (CTYPEMAX)
-          if (SCM_INUMP (val))
-            {
-              long v = SCM_INUM (val);
-             SCM_ASSERT_RANGE (SCM_ARG1, obj, v >= CTYPEMIN && v <= CTYPEMAX);
-            }
-          else
-#elif defined (FLOATTYPE1)
-          if (!SCM_INUMP (val) && !(SCM_BIGP (val) || SCM_REALP (val)))
-#else
-         if (!SCM_INUMP (val) && !SCM_BIGP (val))
-#endif
-            SCM_WRONG_TYPE_ARG (SCM_ARG1, obj);
-        }
-      if (data == NULL)
-        data = (CTYPE *) malloc (n * sizeof (CTYPE));
-      if (data == NULL)
-        return NULL;
-      for (i = 0; i < n; i++)
-       {
-          val = SCM_VELTS (obj)[i];
-         if (SCM_INUMP (val))
-            data[i] = (CTYPE) SCM_INUM (val);
-          else if (SCM_BIGP (val))
-           data[i] = (CTYPE) scm_num2long (val, SCM_ARG1, FUNC_NAME);
-#ifdef FLOATTYPE1
-          else
-            data[i] = (CTYPE) SCM_REAL_VALUE (val);
-#endif
-       }
-      break;
-
-#ifdef HAVE_ARRAYS
-    case ARRAYTYPE1:
-#ifdef ARRAYTYPE2
-    case ARRAYTYPE2:
-#endif
-      n = SCM_UVECTOR_LENGTH (obj);
-      if (data == NULL)
-        data = (CTYPE *) malloc (n * sizeof (CTYPE));
-      if (data == NULL)
-        return NULL;
-#ifdef FLOATTYPE2
-      if (SCM_TYP7 (obj) == ARRAYTYPE2)
-       {
-         for (i = 0; i < n; i++)
-           data[i] = ((FLOATTYPE2 *) SCM_UVECTOR_BASE (obj))[i];
-       }
-      else
-#endif
-      memcpy (data, (CTYPE *) SCM_UVECTOR_BASE (obj), n * sizeof (CTYPE));
-      break;
-#endif /* HAVE_ARRAYS */
-
-#ifdef STRINGTYPE
-    case scm_tc7_string:
-      n = SCM_STRING_LENGTH (obj);
-      if (data == NULL)
-        data = (CTYPE *) malloc (n * sizeof (CTYPE));
-      if (data == NULL)
-        return NULL;
-      memcpy (data, SCM_STRING_CHARS (obj), n * sizeof (CTYPE));
-      break;
-#endif /* STRINGTYPE */
-
-    default:
-      SCM_WRONG_TYPE_ARG (SCM_ARG1, obj);
-    }
-  return data;
-}
-#undef FUNC_NAME
-
-
-#if HAVE_ARRAYS
-
-/* Converts a C array into a uniform vector, returns SCM_UNDEFINED if out
-   of memory. */
-#define FUNC_NAME CTYPES2UVECT_FN
-SCM
-CTYPES2UVECT (const CTYPE *data, long n)
-{
-  char *v;
-
-  SCM_ASSERT_RANGE (SCM_ARG2, scm_long2num (n), 
-                   n > 0 && n <= SCM_UVECTOR_MAX_LENGTH);
-  v = scm_gc_malloc (sizeof (CTYPE) * n, "vector");
-  memcpy (v, data, n * sizeof (CTYPE));
-  return scm_alloc_cell (SCM_MAKE_UVECTOR_TAG (n, UVECTTYPE), (scm_t_bits) v);
-}
-#undef FUNC_NAME
-
-#ifdef UVECTTYPE2
-#define FUNC_NAME CTYPES2UVECT_FN2
-SCM
-CTYPES2UVECT2 (const unsigned CTYPE *data, long n)
-{
-  char *v;
-
-  SCM_ASSERT_RANGE (SCM_ARG2, scm_long2num (n), 
-                   n > 0 && n <= SCM_UVECTOR_MAX_LENGTH);
-  v = scm_gc_malloc (sizeof (unsigned CTYPE) * n, "vector");
-  memcpy (v, data, n * sizeof (unsigned CTYPE));
-  return scm_alloc_cell (SCM_MAKE_UVECTOR_TAG (n, UVECTTYPE2), (scm_t_bits) v);
-}
-#undef FUNC_NAME
-#endif /* UVECTTYPE2 */
-
-#endif /* HAVE_ARRAYS */
-
-/* Converts a C array into a vector. */
-#define FUNC_NAME CTYPES2SCM_FN
-SCM
-CTYPES2SCM (const CTYPE *data, long n)
-{
-  long i;
-  SCM v, *velts;
-
-  SCM_ASSERT_RANGE (SCM_ARG2, scm_long2num (n), 
-                   n > 0 && n <= SCM_VECTOR_MAX_LENGTH);
-  v = scm_c_make_vector (n, SCM_UNSPECIFIED);
-  velts = SCM_VELTS (v);
-  for (i = 0; i < n; i++)
-#ifdef FLOATTYPE1
-    velts[i] = scm_make_real ((double) data[i]);
-#elif defined (CTYPEFIXABLE)
-    velts[i] = SCM_MAKINUM (data[i]);
-#else
-    velts[i] = (SCM_FIXABLE (data[i]) ? SCM_MAKINUM (data[i]) : 
-               scm_i_long2big (data[i]));
-#endif
-  return v;
-}
-#undef FUNC_NAME
-
-/* cleanup of conditionals */
-#undef SCM2CTYPES
-#undef SCM2CTYPES_FN
-#undef CTYPES2SCM
-#undef CTYPES2SCM_FN
-#undef CTYPE
-#undef CTYPES2UVECT
-#undef CTYPES2UVECT_FN
-#ifdef CTYPEFIXABLE
-#undef CTYPEFIXABLE
-#endif
-#undef UVECTTYPE
-#ifdef UVECTTYPE2
-#undef CTYPES2UVECT2
-#undef CTYPES2UVECT_FN2
-#undef UVECTTYPE2
-#endif
-#ifdef CTYPEMIN
-#undef CTYPEMIN
-#endif
-#ifdef CTYPEMAX
-#undef CTYPEMAX
-#endif
-#undef ARRAYTYPE1
-#ifdef ARRAYTYPE2
-#undef ARRAYTYPE2
-#endif
-#ifdef FLOATTYPE1
-#undef FLOATTYPE1
-#endif
-#ifdef FLOATTYPE2
-#undef FLOATTYPE2
-#endif
-#ifdef STRINGTYPE
-#undef STRINGTYPE
-#endif
-
-/*
-  Local Variables:
-  c-file-style: "gnu"
-  End:
-*/
+/* this file is #include'd (x times) by convert.c */
+
+/* You need to define the following macros before including this
+   template.  They are undefined at the end of this file to give a
+   clean slate for the next inclusion.
+
+   - CTYPE
+
+   The type of an element of the C array, for example 'char'.
+
+   - FROM_CTYPE
+
+   The function that converts a CTYPE to a SCM, for example
+   scm_from_char.
+
+   - UVEC_TAG
+
+   The tag of a suitable uniform vector that can hold the CTYPE, for
+   example 's8'.
+
+   - UVEC_CTYPE
+
+   The C type of an element of the uniform vector, for example
+   scm_t_int8.
+
+   - SCM2CTYPES
+
+   The name of the 'SCM-to-C' function, for example scm_c_scm2chars.
+
+   - CTYPES2SCM
+
+   The name of the 'C-to-SCM' function, for example, scm_c_chars2scm.
+
+   - CTYPES2UVECT
+
+   The name of the 'C-to-uniform-vector' function, for example
+   scm_c_chars2byvect.  It will create a uniform vector of kind
+   UVEC_TAG.
+
+   - CTYPES2UVECT_2
+
+   The name of a second 'C-to-uniform-vector' function.  Leave
+   undefined if you want only one such function.
+
+   - CTYPE_2
+   - UVEC_TAG_2
+   - UVEC_CTYPE_2
+
+   The tag and C type of the second kind of uniform vector, for use
+   with the function described above.
+
+*/
+
+/* The first level does not expand macros in the arguments. */
+#define paste(a1,a2,a3)   a1##a2##a3
+#define stringify(a)      #a
+
+/* But the second level does. */
+#define F(pre,T,suf)   paste(pre,T,suf)
+#define S(T)           stringify(T)
+
+/* Convert a vector, list or uniform vector into a C array.  If the
+   result array in argument 2 is NULL, malloc() a new one.
+*/
+
+CTYPE *
+SCM2CTYPES (SCM obj, CTYPE *data)
+{
+  scm_t_array_handle handle;
+  size_t i, len;
+  ssize_t inc;
+  const UVEC_CTYPE *uvec_elements;
+
+  obj = F(scm_any_to_,UVEC_TAG,vector) (obj);
+  uvec_elements = F(scm_,UVEC_TAG,vector_elements) (obj, &handle, &len, &inc);
+
+  if (data == NULL)
+    data = scm_malloc (len * sizeof (CTYPE));
+  for (i = 0; i < len; i++, uvec_elements += inc)
+    data[i] = uvec_elements[i];
+
+  scm_array_handle_release (&handle);
+
+  return data;
+}
+
+/* Converts a C array into a vector. */
+
+SCM
+CTYPES2SCM (const CTYPE *data, long n)
+{
+  long i;
+  SCM v;
+  
+  v = scm_c_make_vector (n, SCM_UNSPECIFIED);
+
+  for (i = 0; i < n; i++)
+    SCM_SIMPLE_VECTOR_SET (v, i, FROM_CTYPE (data[i]));
+
+  return v;
+}
+
+/* Converts a C array into a uniform vector. */
+
+SCM
+CTYPES2UVECT (const CTYPE *data, long n)
+{
+  scm_t_array_handle handle;
+  long i;
+  SCM uvec;
+  UVEC_CTYPE *uvec_elements;
+  
+  uvec = F(scm_make_,UVEC_TAG,vector) (scm_from_long (n), SCM_UNDEFINED);
+  uvec_elements = F(scm_,UVEC_TAG,vector_writable_elements) (uvec, &handle,
+                                                            NULL, NULL);
+  for (i = 0; i < n; i++)
+    uvec_elements[i] = data[i];
+
+  scm_array_handle_release (&handle);
+
+  return uvec;
+}
+
+#ifdef CTYPE2UVECT_2
+
+SCM
+CTYPES2UVECT_2 (const CTYPE_2 *data, long n)
+{
+  scm_t_array_handle handle;
+  long i;
+  SCM uvec;
+  UVEC_CTYPE_2 *uvec_elements;
+  
+  uvec = F(scm_make_,UVEC_TAG_2,vector) (scm_from_long (n), SCM_UNDEFINED);
+  uvec_elements = F(scm_,UVEC_TAG_2,vector_writable_elements) (uvec, &handle,
+                                                              NULL, NULL);
+
+  for (i = 0; i < n; i++)
+    uvec_elements[i] = data[i];
+
+  scm_array_handle_release (&handle);
+
+  return uvec;
+}
+
+#endif
+
+#undef paste
+#undef stringify
+#undef F
+#undef S
+
+#undef CTYPE
+#undef FROM_CTYPE
+#undef UVEC_TAG
+#undef UVEC_CTYPE
+#undef SCM2CTYPES
+#undef CTYPES2SCM
+#undef CTYPES2UVECT
+#ifdef CTYPES2UVECT_2
+#undef CTYPES2UVECT_2
+#undef CTYPE_2
+#undef UVEC_TAG_2
+#undef UVEC_CTYPE_2
+#endif
+
+/*
+  Local Variables:
+  c-file-style: "gnu"
+  End:
+*/