[gobject-introspection] scanner: Correctly handle large 64 bit integer constants



commit 383b0bdcc8e295d06035768062389797d3ba9262
Author: Colin Walters <walters verbum org>
Date:   Fri Oct 26 16:46:05 2012 -0400

    scanner: Correctly handle large 64 bit integer constants
    
    In C, positive integer constants are by default unsigned.  This means
    an expression like 0x8000000000000000 will be "unsigned long long".
    
    In the actual scanner code, we were parsing them as "gint64", and
    storing them as gint64.  This was incorrect; we need to parse them
    as guint64, and store the bits we get from that.  This gives us
    an equivalent result to what the C compiler does.
    
    However, when we actually return the value as a Python "long"
    (arbitrary length integer), we need to treat the value as unsigned if
    the result indicated it was.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=685022

 giscanner/giscannermodule.c            |    5 ++++-
 giscanner/scannerparser.y              |   12 ++++++++----
 giscanner/sourcescanner.h              |    1 +
 tests/scanner/Regress-1.0-expected.gir |   15 +++++++++++++++
 tests/scanner/regress.h                |    5 +++++
 5 files changed, 33 insertions(+), 5 deletions(-)
---
diff --git a/giscanner/giscannermodule.c b/giscanner/giscannermodule.c
index 0f8d6cb..0ece7f7 100644
--- a/giscanner/giscannermodule.c
+++ b/giscanner/giscannermodule.c
@@ -162,7 +162,10 @@ symbol_get_const_int (PyGISourceSymbol *self,
       return Py_None;
     }
 
-  return PyLong_FromLongLong ((long long)self->symbol->const_int);
+  if (self->symbol->const_int_is_unsigned)
+    return PyLong_FromUnsignedLongLong ((unsigned long long)self->symbol->const_int);
+  else
+    return PyLong_FromLongLong ((long long)self->symbol->const_int);
 }
 
 static PyObject *
diff --git a/giscanner/scannerparser.y b/giscanner/scannerparser.y
index 81a9374..82ee1d7 100644
--- a/giscanner/scannerparser.y
+++ b/giscanner/scannerparser.y
@@ -1,4 +1,4 @@
-/* GObject introspection: C parser
+/* GObject introspection: C parser -*- indent-tabs-mode: t; tab-width: 8 -*-
  *
  * Copyright (c) 1997 Sandro Sigala  <ssigala globalnet it>
  * Copyright (c) 2007-2008 JÃrg Billeter  <j bitron ch>
@@ -232,15 +232,19 @@ primary_expression
 	  }
 	| INTEGER
 	  {
+		char *rest;
+		guint64 value;
 		$$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, scanner->current_filename, lineno);
 		$$->const_int_set = TRUE;
 		if (g_str_has_prefix (yytext, "0x") && strlen (yytext) > 2) {
-			$$->const_int = g_ascii_strtoll (yytext + 2, NULL, 16);
+			value = g_ascii_strtoull (yytext + 2, &rest, 16);
 		} else if (g_str_has_prefix (yytext, "0") && strlen (yytext) > 1) {
-			$$->const_int = g_ascii_strtoll (yytext + 1, NULL, 8);
+			value = g_ascii_strtoull (yytext + 1, &rest, 8);
 		} else {
-			$$->const_int = g_ascii_strtoll (yytext, NULL, 10);
+			value = g_ascii_strtoull (yytext, &rest, 10);
 		}
+		$$->const_int = value;
+		$$->const_int_is_unsigned = (rest && (rest[0] == 'U'));
 	  }
 	| CHARACTER
 	  {
diff --git a/giscanner/sourcescanner.h b/giscanner/sourcescanner.h
index df16cf6..a2834ca 100644
--- a/giscanner/sourcescanner.h
+++ b/giscanner/sourcescanner.h
@@ -126,6 +126,7 @@ struct _GISourceSymbol
   gboolean const_int_set;
   gboolean private;
   gint64 const_int; /* 64-bit we can handle signed and unsigned 32-bit values */
+  gboolean const_int_is_unsigned;
   char *const_string;
   gboolean const_double_set;
   double const_double;
diff --git a/tests/scanner/Regress-1.0-expected.gir b/tests/scanner/Regress-1.0-expected.gir
index 53b3adc..17d9d78 100644
--- a/tests/scanner/Regress-1.0-expected.gir
+++ b/tests/scanner/Regress-1.0-expected.gir
@@ -90,11 +90,26 @@ and/or use gtk-doc annotations.  -->
         <type name="gdouble" c:type="double"/>
       </field>
     </record>
+    <constant name="MAXUINT64"
+              value="18446744073709551615"
+              c:type="REGRESS_MAXUINT64">
+      <type name="gint64" c:type="gint64"/>
+    </constant>
+    <constant name="MININT64"
+              value="-9223372036854775808"
+              c:type="REGRESS_MININT64">
+      <type name="gint64" c:type="gint64"/>
+    </constant>
     <constant name="Mixed_Case_Constant"
               value="4423"
               c:type="REGRESS_Mixed_Case_Constant">
       <type name="gint" c:type="gint"/>
     </constant>
+    <constant name="NEGATIVE_INT_CONSTANT"
+              value="-42"
+              c:type="REGRESS_NEGATIVE_INT_CONSTANT">
+      <type name="gint" c:type="gint"/>
+    </constant>
     <constant name="STRING_CONSTANT"
               value="Some String"
               c:type="REGRESS_STRING_CONSTANT">
diff --git a/tests/scanner/regress.h b/tests/scanner/regress.h
index aba29df..137c4e0 100644
--- a/tests/scanner/regress.h
+++ b/tests/scanner/regress.h
@@ -262,6 +262,7 @@ GQuark regress_atest_error_quark (void);
 
 /* constants */
 
+#define REGRESS_NEGATIVE_INT_CONSTANT -42
 #define REGRESS_INT_CONSTANT 4422
 #define REGRESS_DOUBLE_CONSTANT 44.22
 #define REGRESS_STRING_CONSTANT "Some String"
@@ -912,4 +913,8 @@ typedef struct {
  */
 #define _DONTSCANTHIS 1
 
+/* https://bugzilla.gnome.org/show_bug.cgi?id=685022 */
+#define REGRESS_MININT64 ((gint64) G_GINT64_CONSTANT(0x8000000000000000))
+#define REGRESS_MAXUINT64 (G_GINT64_CONSTANT(0xffffffffffffffffU))
+
 #endif /* __GITESTTYPES_H__ */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]