Commit 70fd20e67ee79a198237f6a640d57424c2e00bc9

Alexei Podtelezhnikov 2021-02-12T19:28:05

Decorate qsort callbacks with cdecl. * include/freetype/internal/compiler-macros.h (FT_COMPARE_DEF): Add new macro. * src/base/ftrfork.c, src/bdf/bdflib.c, src/gxvalid/gxvcommn.c, src/psaux/afmparse.c, src/psnames/psmodule.c, src/type1/t1afm.c, src/sfnt/sfwoff.c, src/sfnt/sfwoff2.c: Update qsort callbacks. Fixes #1026 when compiling FreeType with an unusual calling convention while the C library qsort still expects cdecl.

diff --git a/ChangeLog b/ChangeLog
index 62400f4..664d51a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2021-02-12  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	Decorate qsort callbacks with cdecl.
+
+	* include/freetype/internal/compiler-macros.h (FT_COMPARE_DEF):
+	Add new macro.
+	* src/base/ftrfork.c, src/bdf/bdflib.c, src/gxvalid/gxvcommn.c,
+        src/psaux/afmparse.c, src/psnames/psmodule.c, src/type1/t1afm.c,
+        src/sfnt/sfwoff.c, src/sfnt/sfwoff2.c: Update qsort callbacks.
+
+	Fixes #1026 when compiling FreeType with an unusual calling convention
+	while the C library qsort still expects cdecl.
+
 2021-02-10  Dominik Röttsches  <drott@chromium.org>
 
 	[sfnt] Implement 'COLR' v1 sweep gradients.
diff --git a/include/freetype/internal/compiler-macros.h b/include/freetype/internal/compiler-macros.h
index 570949a..869d1d1 100644
--- a/include/freetype/internal/compiler-macros.h
+++ b/include/freetype/internal/compiler-macros.h
@@ -267,7 +267,8 @@ FT_BEGIN_HEADER
   /*                                                                 */
   /* FT_CALLBACK_DEF is used to _define_ a callback function,        */
   /* located in the same source code file as the structure that uses */
-  /* it.                                                             */
+  /* it.  FT_COMPARE_DEF, in addition, ensures the cdecl calling     */
+  /* convention on x86, required by the C library qsort.             */
   /*                                                                 */
   /* FT_BASE_CALLBACK and FT_BASE_CALLBACK_DEF are used to declare   */
   /* and define a callback function, respectively, in a similar way  */
@@ -289,6 +290,14 @@ FT_BEGIN_HEADER
 #define FT_CALLBACK_DEF( x )  static  x
 #endif
 
+#if defined( __i386__ )
+#define FT_COMPARE_DEF( x )  FT_CALLBACK_DEF( x ) __attribute__(( cdecl ))
+#elif defined( _M_IX86 )
+#define FT_COMPARE_DEF( x )  FT_CALLBACK_DEF( x ) __cdecl
+#else
+#define FT_COMPARE_DEF( x )  FT_CALLBACK_DEF( x )
+#endif
+
 #define FT_BASE_CALLBACK( x )      FT_FUNCTION_DECLARATION( x )
 #define FT_BASE_CALLBACK_DEF( x )  FT_FUNCTION_DEFINITION( x )
 
diff --git a/src/base/ftrfork.c b/src/base/ftrfork.c
index 0748172..b558437 100644
--- a/src/base/ftrfork.c
+++ b/src/base/ftrfork.c
@@ -167,16 +167,11 @@
   }
 
 
-  static int
-  ft_raccess_sort_ref_by_id( FT_RFork_Ref*  a,
-                             FT_RFork_Ref*  b )
+  FT_COMPARE_DEF( int )
+  ft_raccess_sort_ref_by_id( const void*  a,
+                             const void*  b )
   {
-    if ( a->res_id < b->res_id )
-      return -1;
-    else if ( a->res_id > b->res_id )
-      return 1;
-    else
-      return 0;
+    return  ( (FT_RFork_Ref*)a )->res_id - ( (FT_RFork_Ref*)b )->res_id;
   }
 
 
@@ -294,8 +289,7 @@
           ft_qsort( ref,
                     (size_t)*count,
                     sizeof ( FT_RFork_Ref ),
-                    ( int(*)(const void*,
-                             const void*) )ft_raccess_sort_ref_by_id );
+                    ft_raccess_sort_ref_by_id );
 
           FT_TRACE3(( "             -- sort resources by their ids --\n" ));
 
diff --git a/src/bdf/bdflib.c b/src/bdf/bdflib.c
index b494a09..e62f09a 100644
--- a/src/bdf/bdflib.c
+++ b/src/bdf/bdflib.c
@@ -807,7 +807,7 @@
 
 
   /* Routine to compare two glyphs by encoding so they can be sorted. */
-  static int
+  FT_COMPARE_DEF( int )
   by_encoding( const void*  a,
                const void*  b )
   {
diff --git a/src/gxvalid/gxvcommn.c b/src/gxvalid/gxvcommn.c
index 57b8845..f96d57b 100644
--- a/src/gxvalid/gxvcommn.c
+++ b/src/gxvalid/gxvcommn.c
@@ -46,16 +46,11 @@
   /*************************************************************************/
   /*************************************************************************/
 
-  static int
-  gxv_compare_ushort_offset( FT_UShort*  a,
-                             FT_UShort*  b )
+  FT_COMPARE_DEF( int )
+  gxv_compare_ushort_offset( const void*  a,
+                             const void*  b )
   {
-    if ( *a < *b )
-      return -1;
-    else if ( *a > *b )
-      return 1;
-    else
-      return 0;
+    return  *(FT_UShort*)a - *(FT_UShort*)b;
   }
 
 
@@ -78,7 +73,7 @@
     buff[nmemb] = limit;
 
     ft_qsort( buff, ( nmemb + 1 ), sizeof ( FT_UShort ),
-              ( int(*)(const void*, const void*) )gxv_compare_ushort_offset );
+              gxv_compare_ushort_offset );
 
     if ( buff[nmemb] > limit )
       FT_INVALID_OFFSET;
@@ -111,13 +106,17 @@
   /*************************************************************************/
   /*************************************************************************/
 
-  static int
-  gxv_compare_ulong_offset( FT_ULong*  a,
-                            FT_ULong*  b )
+  FT_COMPARE_DEF( int )
+  gxv_compare_ulong_offset( const void*  a,
+                            const void*  b )
   {
-    if ( *a < *b )
+    FT_ULong  a_ = *(FT_ULong*)a;
+    FT_ULong  b_ = *(FT_ULong*)b;
+
+
+    if ( a_ < b_ )
       return -1;
-    else if ( *a > *b )
+    else if ( a_ > b_ )
       return 1;
     else
       return 0;
@@ -143,7 +142,7 @@
     buff[nmemb] = limit;
 
     ft_qsort( buff, ( nmemb + 1 ), sizeof ( FT_ULong ),
-              ( int(*)(const void*, const void*) )gxv_compare_ulong_offset );
+              gxv_compare_ulong_offset );
 
     if ( buff[nmemb] > limit )
       FT_INVALID_OFFSET;
diff --git a/src/psaux/afmparse.c b/src/psaux/afmparse.c
index 79587e1..a778cde 100644
--- a/src/psaux/afmparse.c
+++ b/src/psaux/afmparse.c
@@ -667,7 +667,7 @@
 
 
   /* compare two kerning pairs */
-  FT_CALLBACK_DEF( int )
+  FT_COMPARE_DEF( int )
   afm_compare_kern_pairs( const void*  a,
                           const void*  b )
   {
diff --git a/src/psnames/psmodule.c b/src/psnames/psmodule.c
index 89dd253..913ca98 100644
--- a/src/psnames/psmodule.c
+++ b/src/psnames/psmodule.c
@@ -179,7 +179,7 @@
 
 
   /* ft_qsort callback to sort the unicode map */
-  FT_CALLBACK_DEF( int )
+  FT_COMPARE_DEF( int )
   compare_uni_maps( const void*  a,
                     const void*  b )
   {
diff --git a/src/sfnt/sfwoff.c b/src/sfnt/sfwoff.c
index be102aa..481179c 100644
--- a/src/sfnt/sfwoff.c
+++ b/src/sfnt/sfwoff.c
@@ -66,7 +66,7 @@
   }
 
 
-  FT_CALLBACK_DEF( int )
+  FT_COMPARE_DEF( int )
   compare_offsets( const void*  a,
                    const void*  b )
   {
diff --git a/src/sfnt/sfwoff2.c b/src/sfnt/sfwoff2.c
index 8809ec5..2fe7f47 100644
--- a/src/sfnt/sfwoff2.c
+++ b/src/sfnt/sfwoff2.c
@@ -101,7 +101,7 @@
   }
 
 
-  FT_CALLBACK_DEF( int )
+  FT_COMPARE_DEF( int )
   compare_tags( const void*  a,
                 const void*  b )
   {
diff --git a/src/type1/t1afm.c b/src/type1/t1afm.c
index f39068d..4c18ed1 100644
--- a/src/type1/t1afm.c
+++ b/src/type1/t1afm.c
@@ -83,7 +83,7 @@
 
 
   /* compare two kerning pairs */
-  FT_CALLBACK_DEF( int )
+  FT_COMPARE_DEF( int )
   compare_kern_pairs( const void*  a,
                       const void*  b )
   {