aboutsummaryrefslogtreecommitdiff
path: root/gcc/c-common.c
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2002-04-26 00:40:12 -0700
committerRichard Henderson <rth@gcc.gnu.org>2002-04-26 00:40:12 -0700
commitb84a3874349ccc870c3d278b874d43763efbc9bb (patch)
treef89357e36b49124025bfcd5e54bb2778e043f4e6 /gcc/c-common.c
parent4d7ea4fc78df072028a41875a967d49f9b4c9dea (diff)
downloadgcc-b84a3874349ccc870c3d278b874d43763efbc9bb.zip
gcc-b84a3874349ccc870c3d278b874d43763efbc9bb.tar.gz
gcc-b84a3874349ccc870c3d278b874d43763efbc9bb.tar.bz2
c-common.c (fix_string_type): Split out of ...
* c-common.c (fix_string_type): Split out of ... (combine_strings): ... here. Take a varray, not a tree list. (c_expand_builtin_printf): Use fix_string_type. * c-common.h: Update decls. * c-parse.in (string): Remove. Update all uses to use STRING instead, and not call combine_strings. (yylexstring): New. (_yylex): Use it. * c-typeck.c (simple_asm_stmt): Don't call combine_strings. (build_asm_stmt): Likewise. * objc/objc-act.c (my_build_string): Use fix_string_type. (build_objc_string_object): Build varray for combine_strings. * parse.y (string): Remove. Update all uses to use STRING instead, and not call combine_strings. * rtti.c (tinfo_name): Use fix_string_type. * semantics.c (finish_asm_stmt): Don't call combine_strings. * spew.c (yylexstring): New. (read_token): Use it. * g++.dg/parse/concat1.C: New. * gcc.dg/concat2.c: New. From-SVN: r52790
Diffstat (limited to 'gcc/c-common.c')
-rw-r--r--gcc/c-common.c209
1 files changed, 113 insertions, 96 deletions
diff --git a/gcc/c-common.c b/gcc/c-common.c
index f9337df..86fc7593 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -683,105 +683,17 @@ fname_decl (rid, id)
return decl;
}
-/* Given a chain of STRING_CST nodes,
- concatenate them into one STRING_CST
- and give it a suitable array-of-chars data type. */
+/* Given a STRING_CST, give it a suitable array-of-chars data type. */
tree
-combine_strings (strings)
- tree strings;
+fix_string_type (value)
+ tree value;
{
- tree value, t;
- int length = 1;
- int wide_length = 0;
- int wide_flag = 0;
- int wchar_bytes = TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT;
- int nchars;
+ const int wchar_bytes = TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT;
+ const int wide_flag = TREE_TYPE (value) == wchar_array_type_node;
const int nchars_max = flag_isoc99 ? 4095 : 509;
-
- if (TREE_CHAIN (strings))
- {
- /* More than one in the chain, so concatenate. */
- char *p, *q;
-
- /* Don't include the \0 at the end of each substring,
- except for the last one.
- Count wide strings and ordinary strings separately. */
- for (t = strings; t; t = TREE_CHAIN (t))
- {
- if (TREE_TYPE (t) == wchar_array_type_node)
- {
- wide_length += (TREE_STRING_LENGTH (t) - wchar_bytes);
- wide_flag = 1;
- }
- else
- {
- length += (TREE_STRING_LENGTH (t) - 1);
- if (C_ARTIFICIAL_STRING_P (t) && !in_system_header)
- warning ("concatenation of string literals with __FUNCTION__ is deprecated. This feature will be removed in future");
- }
- }
-
- /* If anything is wide, the non-wides will be converted,
- which makes them take more space. */
- if (wide_flag)
- length = length * wchar_bytes + wide_length;
-
- p = alloca (length);
-
- /* Copy the individual strings into the new combined string.
- If the combined string is wide, convert the chars to ints
- for any individual strings that are not wide. */
-
- q = p;
- for (t = strings; t; t = TREE_CHAIN (t))
- {
- int len = (TREE_STRING_LENGTH (t)
- - ((TREE_TYPE (t) == wchar_array_type_node)
- ? wchar_bytes : 1));
- if ((TREE_TYPE (t) == wchar_array_type_node) == wide_flag)
- {
- memcpy (q, TREE_STRING_POINTER (t), len);
- q += len;
- }
- else
- {
- int i, j;
- for (i = 0; i < len; i++)
- {
- if (BYTES_BIG_ENDIAN)
- {
- for (j=0; j<(WCHAR_TYPE_SIZE / BITS_PER_UNIT)-1; j++)
- *q++ = 0;
- *q++ = TREE_STRING_POINTER (t)[i];
- }
- else
- {
- *q++ = TREE_STRING_POINTER (t)[i];
- for (j=0; j<(WCHAR_TYPE_SIZE / BITS_PER_UNIT)-1; j++)
- *q++ = 0;
- }
- }
- }
- }
- if (wide_flag)
- {
- int i;
- for (i = 0; i < wchar_bytes; i++)
- *q++ = 0;
- }
- else
- *q = 0;
-
- value = build_string (length, p);
- }
- else
- {
- value = strings;
- length = TREE_STRING_LENGTH (value);
- if (TREE_TYPE (value) == wchar_array_type_node)
- wide_flag = 1;
- }
+ int length = TREE_STRING_LENGTH (value);
+ int nchars;
/* Compute the number of elements, for the array type. */
nchars = wide_flag ? length / wchar_bytes : length;
@@ -813,6 +725,111 @@ combine_strings (strings)
TREE_STATIC (value) = 1;
return value;
}
+
+/* Given a VARRAY of STRING_CST nodes, concatenate them into one
+ STRING_CST. */
+
+tree
+combine_strings (strings)
+ varray_type strings;
+{
+ const int wchar_bytes = TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT;
+ const int nstrings = VARRAY_ACTIVE_SIZE (strings);
+ tree value, t;
+ int length = 1;
+ int wide_length = 0;
+ int wide_flag = 0;
+ int i;
+ char *p, *q;
+
+ /* Don't include the \0 at the end of each substring. Count wide
+ strings and ordinary strings separately. */
+ for (i = 0; i < nstrings; ++i)
+ {
+ t = VARRAY_TREE (strings, i);
+
+ if (TREE_TYPE (t) == wchar_array_type_node)
+ {
+ wide_length += TREE_STRING_LENGTH (t) - wchar_bytes;
+ wide_flag = 1;
+ }
+ else
+ {
+ length += (TREE_STRING_LENGTH (t) - 1);
+ if (C_ARTIFICIAL_STRING_P (t) && !in_system_header)
+ warning ("concatenation of string literals with __FUNCTION__ is deprecated");
+ }
+ }
+
+ /* If anything is wide, the non-wides will be converted,
+ which makes them take more space. */
+ if (wide_flag)
+ length = length * wchar_bytes + wide_length;
+
+ p = xmalloc (length);
+
+ /* Copy the individual strings into the new combined string.
+ If the combined string is wide, convert the chars to ints
+ for any individual strings that are not wide. */
+
+ q = p;
+ for (i = 0; i < nstrings; ++i)
+ {
+ int len, this_wide;
+
+ t = VARRAY_TREE (strings, i);
+ this_wide = TREE_TYPE (t) == wchar_array_type_node;
+ len = TREE_STRING_LENGTH (t) - (this_wide ? wchar_bytes : 1);
+ if (this_wide == wide_flag)
+ {
+ memcpy (q, TREE_STRING_POINTER (t), len);
+ q += len;
+ }
+ else
+ {
+ const int nzeros = (WCHAR_TYPE_SIZE / BITS_PER_UNIT) - 1;
+ int j, k;
+
+ if (BYTES_BIG_ENDIAN)
+ {
+ for (k = 0; k < len; k++)
+ {
+ for (j = 0; j < nzeros; j++)
+ *q++ = 0;
+ *q++ = TREE_STRING_POINTER (t)[k];
+ }
+ }
+ else
+ {
+ for (k = 0; k < len; k++)
+ {
+ *q++ = TREE_STRING_POINTER (t)[k];
+ for (j = 0; j < nzeros; j++)
+ *q++ = 0;
+ }
+ }
+ }
+ }
+
+ /* Nul terminate the string. */
+ if (wide_flag)
+ {
+ for (i = 0; i < wchar_bytes; i++)
+ *q++ = 0;
+ }
+ else
+ *q = 0;
+
+ value = build_string (length, p);
+ free (p);
+
+ if (wide_flag)
+ TREE_TYPE (value) = wchar_array_type_node;
+ else
+ TREE_TYPE (value) = char_array_type_node;
+
+ return value;
+}
static int is_valid_printf_arglist PARAMS ((tree));
static rtx c_expand_builtin PARAMS ((tree, rtx, enum machine_mode, enum expand_modifier));
@@ -4058,7 +4075,7 @@ c_expand_builtin_printf (arglist, target, tmode, modifier, ignore, unlocked)
memcpy (newstr, TREE_STRING_POINTER (stripped_string), newlen - 1);
newstr[newlen - 1] = 0;
- arglist = combine_strings (build_string (newlen, newstr));
+ arglist = fix_string_type (build_string (newlen, newstr));
arglist = build_tree_list (NULL_TREE, arglist);
fn = fn_puts;
}