diff options
author | Colin Walters <walters@verbum.org> | 2010-10-29 18:37:43 -0400 |
---|---|---|
committer | Colin Walters <walters@verbum.org> | 2010-12-02 09:14:06 -0500 |
commit | aa8b7d2d0f586976ea7399d95e1ccce3000b4734 (patch) | |
tree | c775426885ef784d29161c306096a30be21a3591 /giscanner | |
parent | 1113955bb6a5276c21771685dd30c51f9ef1661f (diff) | |
download | gobject-introspection-aa8b7d2d0f586976ea7399d95e1ccce3000b4734.tar.gz |
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
Diffstat (limited to 'giscanner')
-rw-r--r-- | giscanner/scannerparser.y | 83 |
1 files changed, 81 insertions, 2 deletions
diff --git a/giscanner/scannerparser.y b/giscanner/scannerparser.y index d32bbcc8..bac20980 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); |