diff options
author | ghazi <ghazi@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-06-16 16:34:04 +0000 |
---|---|---|
committer | ghazi <ghazi@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-06-16 16:34:04 +0000 |
commit | 3dc4d00f310d78cae8ca02e5fff6af3b9ac75532 (patch) | |
tree | c94e2380668c248fde903fae2d669a32e731a58b /gcc/c-format.c | |
parent | af2c132425a08b3ff05cc6c914154b224daf3b31 (diff) | |
download | gcc-3dc4d00f310d78cae8ca02e5fff6af3b9ac75532.tar.gz |
* c-format.c (dynamic_format_types): New pointer for dynamic data.
(find_length_info_modifier_index, init_dynamic_asm_fprintf_info):
New functions split out of...
(handle_format_attribute): ...here.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@68023 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/c-format.c')
-rw-r--r-- | gcc/c-format.c | 109 |
1 files changed, 71 insertions, 38 deletions
diff --git a/gcc/c-format.c b/gcc/c-format.c index 01814e15467..c72a803aff8 100644 --- a/gcc/c-format.c +++ b/gcc/c-format.c @@ -855,6 +855,8 @@ static const format_kind_info format_types_orig[] = new data if necessary, while still allowing the original data to be const. */ static const format_kind_info *format_types = format_types_orig; +/* We can modify this one. */ +static format_kind_info *dynamic_format_types; /* Structure detailing the results of checking a format function call where the format expression may be a conditional expression with @@ -2367,6 +2369,67 @@ check_format_types (status, types) } } +/* Given a format_length_info array FLI, and a character C, this + function returns the index into the conversion_specs where that + modifier's data is located. If the character isn't found it + aborts. */ +static unsigned int +find_length_info_modifier_index (const format_length_info *fli, int c) +{ + unsigned int i = 0; + + while (fli->name) + { + if (strchr (fli->name, c)) + return i; + i++; fli++; + } + + /* We shouldn't be looking for a non-existent modifier. */ + abort (); +} + +/* Determine the type of HOST_WIDE_INT in the code being compiled for + use in GCC's __asm_fprintf__ custom format attribute. You must + have set dynamic_format_types before calling this function. */ +static void +init_dynamic_asm_fprintf_info (void) +{ + static tree hwi; + + if (!hwi) + { + format_length_info *new_asm_fprintf_length_specs; + unsigned int i; + + /* Find the underlying type for HOST_WIDE_INT. For the %w + length modifier to work, one must have issued: "typedef + HOST_WIDE_INT __gcc_host_wide_int__;" in one's source code + prior to using that modifier. */ + if (!(hwi = maybe_get_identifier ("__gcc_host_wide_int__")) + || !(hwi = DECL_ORIGINAL_TYPE (identifier_global_value (hwi)))) + abort (); + + /* Create a new (writable) copy of asm_fprintf_length_specs. */ + new_asm_fprintf_length_specs = xmemdup (asm_fprintf_length_specs, + sizeof (asm_fprintf_length_specs), + sizeof (asm_fprintf_length_specs)); + + /* HOST_WIDE_INT must be one of 'long' or 'long long'. */ + i = find_length_info_modifier_index (new_asm_fprintf_length_specs, 'w'); + if (hwi == long_integer_type_node) + new_asm_fprintf_length_specs[i].index = FMT_LEN_l; + else if (hwi == long_long_integer_type_node) + new_asm_fprintf_length_specs[i].index = FMT_LEN_ll; + else + abort (); + + /* Assign the new data for use. */ + dynamic_format_types[asm_fprintf_format_type].length_char_specs = + new_asm_fprintf_length_specs; + } +} + /* Handle a "format" attribute; arguments as in struct attribute_spec.handler. */ tree @@ -2424,44 +2487,14 @@ handle_format_attribute (node, name, args, flags, no_add_attrs) GCC's notion of HOST_WIDE_INT for checking %wd. */ if (info.format_type == asm_fprintf_format_type) { - static tree hwi; - tree orig; - - /* For this custom check to work, one must have issued: - "typedef HOST_WIDE_INT __gcc_host_wide_int__;" - in your source code prior to using this attribute. */ - if (!hwi) - { - format_kind_info *new_format_types; - format_length_info *new_asm_fprintf_length_specs; - - if (!(hwi = maybe_get_identifier ("__gcc_host_wide_int__"))) - abort (); - - /* Create a new (writable) copy of asm_fprintf_length_specs. */ - new_asm_fprintf_length_specs = - xmalloc (sizeof (asm_fprintf_length_specs)); - memcpy (new_asm_fprintf_length_specs, asm_fprintf_length_specs, - sizeof (asm_fprintf_length_specs)); - - /* Create a new (writable) copy of format_types. */ - new_format_types = xmalloc (sizeof (format_types_orig)); - memcpy (new_format_types, format_types_orig, sizeof (format_types_orig)); - - /* Find the underlying type for HOST_WIDE_INT. */ - orig = DECL_ORIGINAL_TYPE (identifier_global_value (hwi)); - if (orig == long_integer_type_node) - new_asm_fprintf_length_specs[1].index = FMT_LEN_l; - else if (orig == long_long_integer_type_node) - new_asm_fprintf_length_specs[1].index = FMT_LEN_ll; - else - abort (); - - /* Assign the new data for use. */ - new_format_types[asm_fprintf_format_type].length_char_specs = - new_asm_fprintf_length_specs; - format_types = new_format_types; - } + /* Our first time through, we have to make sure that our + format_type data is allocated dynamically and is modifiable. */ + if (!dynamic_format_types) + format_types = dynamic_format_types = + xmemdup (format_types_orig, sizeof (format_types_orig), + sizeof (format_types_orig)); + + init_dynamic_asm_fprintf_info(); } return NULL_TREE; |