#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;
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
*/
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();
+ }
}
/**
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__: