[gobject-introspection] Support hexadecimal escapes in constants



commit aa8b7d2d0f586976ea7399d95e1ccce3000b4734
Author: Colin Walters <walters verbum org>
Date:   Fri Oct 29 18:37:43 2010 -0400

    Support hexadecimal escapes in constants
    
    g_strcompress() only does some of what we need; fork it
    and add support for \x escapes too.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=595773

 giscanner/scannerparser.y              |   83 +++++++++++++++++++++++++++++++-
 tests/scanner/Regress-1.0-expected.gir |    3 +
 tests/scanner/regress.h                |    2 +
 3 files changed, 86 insertions(+), 2 deletions(-)
---
diff --git a/giscanner/scannerparser.y b/giscanner/scannerparser.y
index d32bbcc..bac2098 100644
--- a/giscanner/scannerparser.y
+++ b/giscanner/scannerparser.y
@@ -49,6 +49,85 @@ extern void ctype_free (GISourceType * type);
 static int last_enum_value = -1;
 static gboolean is_bitfield;
 static GHashTable *const_table = NULL;
+
+/**
+ * parse_c_string_literal:
+ * @str: A string containing a C string literal
+ *
+ * Based on g_strcompress(), but also handles
+ * hexadecimal escapes.
+ */
+static char *
+parse_c_string_literal (const char *str)
+{
+  const gchar *p = str, *num;
+  gchar *dest = g_malloc (strlen (str) + 1);
+  gchar *q = dest;
+
+  while (*p)
+    {
+      if (*p == '\\')
+        {
+          p++;
+          switch (*p)
+            {
+            case '\0':
+              g_warning ("parse_c_string_literal: trailing \\");
+              goto out;
+            case '0':  case '1':  case '2':  case '3':  case '4':
+            case '5':  case '6':  case '7':
+              *q = 0;
+              num = p;
+              while ((p < num + 3) && (*p >= '0') && (*p <= '7'))
+                {
+                  *q = (*q * 8) + (*p - '0');
+                  p++;
+                }
+              q++;
+              p--;
+              break;
+	    case 'x':
+	      *q = 0;
+	      p++;
+	      num = p;
+	      while ((p < num + 2) && (g_ascii_isxdigit(*p)))
+		{
+		  *q = (*q * 16) + g_ascii_xdigit_value(*p);
+		  p++;
+		}
+              q++;
+              p--;
+	      break;
+            case 'b':
+              *q++ = '\b';
+              break;
+            case 'f':
+              *q++ = '\f';
+              break;
+            case 'n':
+              *q++ = '\n';
+              break;
+            case 'r':
+              *q++ = '\r';
+              break;
+            case 't':
+              *q++ = '\t';
+              break;
+            default:            /* Also handles \" and \\ */
+              *q++ = *p;
+              break;
+            }
+        }
+      else
+        *q++ = *p;
+      p++;
+    }
+out:
+  *q = 0;
+
+  return dest;
+}
+
 %}
 
 %error-verbose
@@ -186,7 +265,7 @@ strings
 	  {
 		$$ = gi_source_symbol_new (CSYMBOL_TYPE_CONST, lineno);
 		yytext[strlen (yytext) - 1] = '\0';
-		$$->const_string = g_strcompress (yytext + 1);
+		$$->const_string = parse_c_string_literal (yytext + 1);
                 if (!g_utf8_validate ($$->const_string, -1, NULL))
                   {
 #if 0
@@ -202,7 +281,7 @@ strings
 		char *strings, *string2;
 		$$ = $1;
 		yytext[strlen (yytext) - 1] = '\0';
-		string2 = g_strcompress (yytext + 1);
+		string2 = parse_c_string_literal (yytext + 1);
 		strings = g_strconcat ($$->const_string, string2, NULL);
 		g_free ($$->const_string);
 		g_free (string2);
diff --git a/tests/scanner/Regress-1.0-expected.gir b/tests/scanner/Regress-1.0-expected.gir
index 15fba0d..c0590d7 100644
--- a/tests/scanner/Regress-1.0-expected.gir
+++ b/tests/scanner/Regress-1.0-expected.gir
@@ -943,6 +943,9 @@ TpAccount::status-changed</doc>
         <type name="GObject.ObjectClass" c:type="GObjectClass"/>
       </field>
     </record>
+    <constant name="UTF8_CONSTANT" value="const â?¥ utf8">
+      <type name="utf8" c:type="gchar*"/>
+    </constant>
     <record name="_TestStructC" c:type="_RegressTestStructC">
       <field name="another_int" writable="1">
         <type name="gint" c:type="gint"/>
diff --git a/tests/scanner/regress.h b/tests/scanner/regress.h
index 9daf179..a7342a9 100644
--- a/tests/scanner/regress.h
+++ b/tests/scanner/regress.h
@@ -579,4 +579,6 @@ typedef enum {
   REGRESS_TEST_PUBLIC_ENUM_AFTER  = 1 << 2,
 } RegressTestPrivateEnum;
 
+#define REGRESS_UTF8_CONSTANT "const \xe2\x99\xa5 utf8"
+
 #endif /* __GITESTTYPES_H__ */



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