Implement wide string literal concatenation (with normal string literals, too).
authorChristoph Mallon <christoph.mallon@gmx.de>
Thu, 20 Dec 2007 16:04:08 +0000 (16:04 +0000)
committerChristoph Mallon <christoph.mallon@gmx.de>
Thu, 20 Dec 2007 16:04:08 +0000 (16:04 +0000)
[r18814]

lexer.c
lexer.h
parser.c

diff --git a/lexer.c b/lexer.c
index 4956dfc..749db3d 100644 (file)
--- a/lexer.c
+++ b/lexer.c
@@ -685,6 +685,48 @@ string_t concat_strings(const string_t *const s1, const string_t *const s2)
 #endif
 }
 
+wide_string_t concat_string_wide_string(const string_t *const s1, const wide_string_t *const s2)
+{
+       const size_t len1 = s1->size - 1;
+       const size_t len2 = s2->size - 1;
+
+       wchar_rep_t *const concat = obstack_alloc(&symbol_obstack, (len1 + len2 + 1) * sizeof(*concat));
+       const char *const src = s1->begin;
+       for (size_t i = 0; i != len1; ++i) {
+               concat[i] = src[i];
+       }
+       memcpy(concat + len1, s2->begin, (len2 + 1) * sizeof(*concat));
+
+       return (wide_string_t){ concat, len1 + len2 + 1 };
+}
+
+wide_string_t concat_wide_strings(const wide_string_t *const s1, const wide_string_t *const s2)
+{
+       const size_t len1 = s1->size - 1;
+       const size_t len2 = s2->size - 1;
+
+       wchar_rep_t *const concat = obstack_alloc(&symbol_obstack, (len1 + len2 + 1) * sizeof(*concat));
+       memcpy(concat,        s1->begin, len1       * sizeof(*concat));
+       memcpy(concat + len1, s2->begin, (len2 + 1) * sizeof(*concat));
+
+       return (wide_string_t){ concat, len1 + len2 + 1 };
+}
+
+wide_string_t concat_wide_string_string(const wide_string_t *const s1, const string_t *const s2)
+{
+       const size_t len1 = s1->size - 1;
+       const size_t len2 = s2->size - 1;
+
+       wchar_rep_t *const concat = obstack_alloc(&symbol_obstack, (len1 + len2 + 1) * sizeof(*concat));
+       memcpy(concat, s1->begin, len1 * sizeof(*concat));
+       const char *const src = s2->begin;
+       for (size_t i = 0; i != len2 + 1; ++i) {
+               concat[i] = src[i];
+       }
+
+       return (wide_string_t){ concat, len1 + len2 + 1 };
+}
+
 static void parse_string_literal(void)
 {
        const unsigned start_linenr = lexer_token.source_position.linenr;
diff --git a/lexer.h b/lexer.h
index 35827e9..a1a5d76 100644 (file)
--- a/lexer.h
+++ b/lexer.h
@@ -16,6 +16,9 @@ void exit_lexer(void);
 
 void lexer_open_stream(FILE *stream, const char *input_name);
 
-string_t concat_strings(const string_t *s1, const string_t *s2);
+string_t      concat_strings(           const string_t      *s1, const string_t      *s2);
+wide_string_t concat_string_wide_string(const string_t      *s1, const wide_string_t *s2);
+wide_string_t concat_wide_strings(      const wide_string_t *s1, const wide_string_t *s2);
+wide_string_t concat_wide_string_string(const wide_string_t *s1, const string_t      *s2);
 
 #endif
index 6c97705..fe527a4 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -3121,23 +3121,46 @@ static expression_t *expected_expression_error(void)
  */
 static expression_t *parse_string_const(void)
 {
-       expression_t *cnst = allocate_expression_zero(EXPR_STRING_LITERAL);
-       cnst->base.type    = type_char_ptr;
-       cnst->string.value = parse_string_literals();
-
-       return cnst;
-}
+       wide_string_t wres;
+       if (token.type == T_STRING_LITERAL) {
+               string_t res = token.v.string;
+               next_token();
+               while (token.type == T_STRING_LITERAL) {
+                       res = concat_strings(&res, &token.v.string);
+                       next_token();
+               }
+               if (token.type != T_WIDE_STRING_LITERAL) {
+                       expression_t *const cnst = allocate_expression_zero(EXPR_STRING_LITERAL);
+                       cnst->base.type    = type_char_ptr;
+                       cnst->string.value = res;
+                       return cnst;
+               }
 
-/**
- * Parse a wide string constant.
- */
-static expression_t *parse_wide_string_const(void)
-{
-       expression_t *const cnst = allocate_expression_zero(EXPR_WIDE_STRING_LITERAL);
-       cnst->base.type         = type_wchar_t_ptr;
-       cnst->wide_string.value = token.v.wide_string; /* TODO concatenate */
+               wres = concat_string_wide_string(&res, &token.v.wide_string);
+       } else {
+               wres = token.v.wide_string;
+       }
        next_token();
-       return cnst;
+
+       for (;;) {
+               switch (token.type) {
+                       case T_WIDE_STRING_LITERAL:
+                               wres = concat_wide_strings(&wres, &token.v.wide_string);
+                               break;
+
+                       case T_STRING_LITERAL:
+                               wres = concat_wide_string_string(&wres, &token.v.string);
+                               break;
+
+                       default: {
+                               expression_t *const cnst = allocate_expression_zero(EXPR_WIDE_STRING_LITERAL);
+                               cnst->base.type         = type_wchar_t_ptr;
+                               cnst->wide_string.value = wres;
+                               return cnst;
+                       }
+               }
+               next_token();
+       }
 }
 
 /**
@@ -3739,9 +3762,8 @@ static expression_t *parse_primary_expression(void)
        case T_FLOATINGPOINT:
                return parse_float_const();
        case T_STRING_LITERAL:
-               return parse_string_const();
        case T_WIDE_STRING_LITERAL:
-               return parse_wide_string_const();
+               return parse_string_const();
        case T_IDENTIFIER:
                return parse_reference();
        case T___FUNCTION__: