Phase 3 is in pp_output_formatted_text, which pops the pp_formatted_chunks
instance. */
+static void
+format_phase_1 (const text_info &text,
+ obstack &chunk_obstack,
+ pp_token_list **args,
+ pp_token_list ***formatters);
+
+static void
+format_phase_2 (pretty_printer *pp,
+ text_info &text,
+ obstack &chunk_obstack,
+ pp_token_list ***formatters);
+
void
-pretty_printer::format (text_info *text)
+pretty_printer::format (text_info &text)
{
- output_buffer * const buffer = m_buffer;
+ pp_formatted_chunks *new_chunk_array = m_buffer->push_formatted_chunks ();
+ pp_token_list **args = new_chunk_array->m_args;
- unsigned int chunk = 0, argno;
pp_token_list **formatters[PP_NL_ARGMAX];
-
- pp_formatted_chunks *new_chunk_array = buffer->push_formatted_chunks ();
- pp_token_list **args = new_chunk_array->m_args;
+ memset (formatters, 0, sizeof formatters);
/* Formatting phase 1: split up TEXT->format_spec into chunks in
pp_buffer (PP)->args[]. Even-numbered chunks are to be output
verbatim, odd-numbered chunks are format specifiers.
%m, %%, %<, %>, %} and %' are replaced with the appropriate text at
this point. */
+ format_phase_1 (text, m_buffer->m_chunk_obstack, args, formatters);
- memset (formatters, 0, sizeof formatters);
+ /* Note that you can debug the state of the chunk arrays here using
+ (gdb) call m_buffer->cur_chunk_array->dump()
+ which, given e.g. "foo: %s bar: %s" might print:
+ 0: [TEXT("foo: ")]
+ 1: [TEXT("s")]
+ 2: [TEXT(" bar: ")]
+ 3: [TEXT("s")]
+ */
+
+ /* Set output to the argument obstack, and switch line-wrapping and
+ prefixing off. */
+ m_buffer->m_obstack = &m_buffer->m_chunk_obstack;
+ const int old_line_length = m_buffer->m_line_length;
+ const pp_wrapping_mode_t old_wrapping_mode = pp_set_verbatim_wrapping (this);
+
+ format_phase_2 (this, text, m_buffer->m_chunk_obstack, formatters);
+
+ /* If the client supplied a postprocessing object, call its "handle"
+ hook here. */
+ if (m_format_postprocessor)
+ m_format_postprocessor->handle (this);
+
+ /* Revert to normal obstack and wrapping mode. */
+ m_buffer->m_obstack = &m_buffer->m_formatted_obstack;
+ m_buffer->m_line_length = old_line_length;
+ pp_wrapping_mode (this) = old_wrapping_mode;
+ clear_state ();
+}
+static void
+format_phase_1 (const text_info &text,
+ obstack &chunk_obstack,
+ pp_token_list **args,
+ pp_token_list ***formatters)
+{
+ unsigned chunk = 0;
unsigned int curarg = 0;
bool any_unnumbered = false, any_numbered = false;
pp_token_list *cur_token_list;
- args[chunk++] = cur_token_list
- = pp_token_list::make (buffer->m_chunk_obstack);
- for (const char *p = text->m_format_spec; *p; )
+ args[chunk++] = cur_token_list = pp_token_list::make (chunk_obstack);
+ for (const char *p = text.m_format_spec; *p; )
{
while (*p != '\0' && *p != '%')
{
- obstack_1grow (&buffer->m_chunk_obstack, *p);
+ obstack_1grow (&chunk_obstack, *p);
p++;
}
gcc_unreachable ();
case '%':
- obstack_1grow (&buffer->m_chunk_obstack, '%');
+ obstack_1grow (&chunk_obstack, '%');
p++;
continue;
case '<':
{
- push_back_any_text (cur_token_list, &buffer->m_chunk_obstack);
+ push_back_any_text (cur_token_list, &chunk_obstack);
cur_token_list->push_back<pp_token_begin_quote> ();
p++;
continue;
case '>':
{
- push_back_any_text (cur_token_list, &buffer->m_chunk_obstack);
+ push_back_any_text (cur_token_list, &chunk_obstack);
cur_token_list->push_back<pp_token_end_quote> ();
p++;
continue;
}
case '\'':
{
- push_back_any_text (cur_token_list, &buffer->m_chunk_obstack);
+ push_back_any_text (cur_token_list, &chunk_obstack);
cur_token_list->push_back<pp_token_end_quote> ();
p++;
}
case '}':
{
- push_back_any_text (cur_token_list, &buffer->m_chunk_obstack);
+ push_back_any_text (cur_token_list, &chunk_obstack);
cur_token_list->push_back<pp_token_end_url> ();
p++;
}
case 'R':
{
- push_back_any_text (cur_token_list, &buffer->m_chunk_obstack);
+ push_back_any_text (cur_token_list, &chunk_obstack);
cur_token_list->push_back<pp_token_end_color> ();
p++;
continue;
case 'm':
{
- const char *errstr = xstrerror (text->m_err_no);
- obstack_grow (&buffer->m_chunk_obstack, errstr, strlen (errstr));
+ const char *errstr = xstrerror (text.m_err_no);
+ obstack_grow (&chunk_obstack, errstr, strlen (errstr));
}
p++;
continue;
default:
/* Handled in phase 2. Terminate the plain chunk here. */
- push_back_any_text (cur_token_list, &buffer->m_chunk_obstack);
+ push_back_any_text (cur_token_list, &chunk_obstack);
break;
}
/* Start a new token list for the formatting args. */
- args[chunk] = cur_token_list
- = pp_token_list::make (buffer->m_chunk_obstack);
+ args[chunk] = cur_token_list = pp_token_list::make (chunk_obstack);
+ unsigned argno;
if (ISDIGIT (*p))
{
char *end;
formatters[argno] = &args[chunk++];
do
{
- obstack_1grow (&buffer->m_chunk_obstack, *p);
+ obstack_1grow (&chunk_obstack, *p);
p++;
}
while (strchr ("qwlzt+#", p[-1]));
{
do
{
- obstack_1grow (&buffer->m_chunk_obstack, *p);
+ obstack_1grow (&chunk_obstack, *p);
p++;
}
while (ISDIGIT (p[-1]));
else
{
gcc_assert (*p == '*');
- obstack_1grow (&buffer->m_chunk_obstack, '*');
+ obstack_1grow (&chunk_obstack, '*');
p++;
if (ISDIGIT (*p))
curarg++;
}
gcc_assert (*p == 's');
- obstack_1grow (&buffer->m_chunk_obstack, 's');
+ obstack_1grow (&chunk_obstack, 's');
p++;
}
}
if (*p == '\0')
{
- push_back_any_text (cur_token_list, &buffer->m_chunk_obstack);
+ push_back_any_text (cur_token_list, &chunk_obstack);
break;
}
- obstack_1grow (&buffer->m_chunk_obstack, '\0');
- push_back_any_text (cur_token_list, &buffer->m_chunk_obstack);
+ obstack_1grow (&chunk_obstack, '\0');
+ push_back_any_text (cur_token_list, &chunk_obstack);
/* Start a new token list for the next (non-formatted) text. */
gcc_assert (chunk < PP_NL_ARGMAX * 2);
- args[chunk++] = cur_token_list
- = pp_token_list::make (buffer->m_chunk_obstack);
+ args[chunk++] = cur_token_list = pp_token_list::make (chunk_obstack);
}
- obstack_1grow (&buffer->m_chunk_obstack, '\0');
- push_back_any_text (cur_token_list, &buffer->m_chunk_obstack);
+ obstack_1grow (&chunk_obstack, '\0');
+ push_back_any_text (cur_token_list, &chunk_obstack);
gcc_assert (chunk < PP_NL_ARGMAX * 2);
args[chunk] = nullptr;
+}
- /* Set output to the argument obstack, and switch line-wrapping and
- prefixing off. */
- buffer->m_obstack = &buffer->m_chunk_obstack;
- const int old_line_length = buffer->m_line_length;
- const pp_wrapping_mode_t old_wrapping_mode = pp_set_verbatim_wrapping (this);
-
- /* Note that you can debug the state of the chunk arrays here using
- (gdb) call buffer->cur_chunk_array->dump()
- which, given e.g. "foo: %s bar: %s" might print:
- 0: [TEXT("foo: ")]
- 1: [TEXT("s")]
- 2: [TEXT(" bar: ")]
- 3: [TEXT("s")]
- */
-
- /* Second phase. Replace each formatter with the formatted text it
- corresponds to. */
+/* Second phase. Replace each formatter with pp_tokens for the formatted
+ text it corresponds to, consuming va_args from TEXT->m_args_ptr. */
+static void
+format_phase_2 (pretty_printer *pp,
+ text_info &text,
+ obstack &chunk_obstack,
+ pp_token_list ***formatters)
+{
+ unsigned argno;
for (argno = 0; formatters[argno]; argno++)
{
int precision = 0;
bool hash = false;
bool quote = false;
- const char *p;
-
/* We expect a single text token containing the formatter. */
pp_token_list *tok_list = *(formatters[argno]);
gcc_assert (tok_list);
/* Accumulate the value of the formatted text into here. */
pp_token_list *formatted_tok_list
- = pp_token_list::make (buffer->m_chunk_obstack);
+ = pp_token_list::make (chunk_obstack);
/* We do not attempt to enforce any ordering on the modifier
characters. */
+ const char *p;
for (p = as_a <pp_token_text *> (tok_list->m_first)->m_value.get ();; p++)
{
switch (*p)
if (quote)
{
- push_back_any_text (formatted_tok_list, &buffer->m_chunk_obstack);
+ push_back_any_text (formatted_tok_list, &chunk_obstack);
formatted_tok_list->push_back<pp_token_begin_quote> ();
}
{
case 'r':
{
- const char *color = va_arg (*text->m_args_ptr, const char *);
+ const char *color = va_arg (*text.m_args_ptr, const char *);
formatted_tok_list->push_back<pp_token_begin_color>
(label_text::borrow (color));
}
/* When quoting, print alphanumeric, punctuation, and the space
character unchanged, and all others in hexadecimal with the
"\x" prefix. Otherwise print them all unchanged. */
- int chr = va_arg (*text->m_args_ptr, int);
+ int chr = va_arg (*text.m_args_ptr, int);
if (ISPRINT (chr) || !quote)
- pp_character (this, chr);
+ pp_character (pp, chr);
else
{
const char str [2] = { chr, '\0' };
- pp_quoted_string (this, str, 1);
+ pp_quoted_string (pp, str, 1);
}
break;
}
case 'd':
case 'i':
if (wide)
- pp_wide_integer (this, va_arg (*text->m_args_ptr, HOST_WIDE_INT));
+ pp_wide_integer (pp, va_arg (*text.m_args_ptr, HOST_WIDE_INT));
else
- pp_integer_with_precision (this, *text->m_args_ptr, precision,
+ pp_integer_with_precision (pp, *text.m_args_ptr, precision,
int, "d");
break;
case 'o':
if (wide)
- pp_scalar (this, "%" HOST_WIDE_INT_PRINT "o",
- va_arg (*text->m_args_ptr, unsigned HOST_WIDE_INT));
+ pp_scalar (pp, "%" HOST_WIDE_INT_PRINT "o",
+ va_arg (*text.m_args_ptr, unsigned HOST_WIDE_INT));
else
- pp_integer_with_precision (this, *text->m_args_ptr, precision,
+ pp_integer_with_precision (pp, *text.m_args_ptr, precision,
unsigned, "o");
break;
case 's':
if (quote)
- pp_quoted_string (this, va_arg (*text->m_args_ptr, const char *));
+ pp_quoted_string (pp, va_arg (*text.m_args_ptr, const char *));
else
- pp_string (this, va_arg (*text->m_args_ptr, const char *));
+ pp_string (pp, va_arg (*text.m_args_ptr, const char *));
break;
case 'p':
- pp_pointer (this, va_arg (*text->m_args_ptr, void *));
+ pp_pointer (pp, va_arg (*text.m_args_ptr, void *));
break;
case 'u':
if (wide)
- pp_scalar (this, HOST_WIDE_INT_PRINT_UNSIGNED,
- va_arg (*text->m_args_ptr, unsigned HOST_WIDE_INT));
+ pp_scalar (pp, HOST_WIDE_INT_PRINT_UNSIGNED,
+ va_arg (*text.m_args_ptr, unsigned HOST_WIDE_INT));
else
- pp_integer_with_precision (this, *text->m_args_ptr, precision,
+ pp_integer_with_precision (pp, *text.m_args_ptr, precision,
unsigned, "u");
break;
case 'f':
- pp_double (this, va_arg (*text->m_args_ptr, double));
+ pp_double (pp, va_arg (*text.m_args_ptr, double));
break;
case 'Z':
{
- int *v = va_arg (*text->m_args_ptr, int *);
- unsigned len = va_arg (*text->m_args_ptr, unsigned);
+ int *v = va_arg (*text.m_args_ptr, int *);
+ unsigned len = va_arg (*text.m_args_ptr, unsigned);
for (unsigned i = 0; i < len; ++i)
{
- pp_scalar (this, "%i", v[i]);
+ pp_scalar (pp, "%i", v[i]);
if (i < len - 1)
{
- pp_comma (this);
- pp_space (this);
+ pp_comma (pp);
+ pp_space (pp);
}
}
break;
case 'x':
if (wide)
- pp_scalar (this, HOST_WIDE_INT_PRINT_HEX,
- va_arg (*text->m_args_ptr, unsigned HOST_WIDE_INT));
+ pp_scalar (pp, HOST_WIDE_INT_PRINT_HEX,
+ va_arg (*text.m_args_ptr, unsigned HOST_WIDE_INT));
else
- pp_integer_with_precision (this, *text->m_args_ptr, precision,
+ pp_integer_with_precision (pp, *text.m_args_ptr, precision,
unsigned, "x");
break;
gcc_assert (*p == '*');
p++;
gcc_assert (*p == 's');
- n = va_arg (*text->m_args_ptr, int);
+ n = va_arg (*text.m_args_ptr, int);
/* This consumes a second entry in the formatters array. */
gcc_assert (formatters[argno] == formatters[argno+1]);
argno++;
}
- s = va_arg (*text->m_args_ptr, const char *);
+ s = va_arg (*text.m_args_ptr, const char *);
/* Append the lesser of precision and strlen (s) characters
from the array (which need not be a nul-terminated string).
Negative precision is treated as if it were omitted. */
size_t len = n < 0 ? strlen (s) : strnlen (s, n);
- pp_append_text (this, s, s + len);
+ pp_append_text (pp, s, s + len);
}
break;
{
/* diagnostic_event_id_t *. */
diagnostic_event_id_ptr event_id
- = va_arg (*text->m_args_ptr, diagnostic_event_id_ptr);
+ = va_arg (*text.m_args_ptr, diagnostic_event_id_ptr);
gcc_assert (event_id->known_p ());
formatted_tok_list->push_back<pp_token_event_id> (*event_id);
}
case '{':
{
- const char *url = va_arg (*text->m_args_ptr, const char *);
+ const char *url = va_arg (*text.m_args_ptr, const char *);
formatted_tok_list->push_back<pp_token_begin_url>
(label_text::borrow (url));
}
case 'e':
{
- pp_element *element
- = va_arg (*text->m_args_ptr, pp_element *);
- pp_markup::context ctxt (*this, *buffer, chunk,
+ pp_element *element = va_arg (*text.m_args_ptr, pp_element *);
+ pp_markup::context ctxt (*pp,
quote, /* by reference */
formatted_tok_list);
element->add_to_phase_2 (ctxt);
default:
{
- bool ok;
-
/* Call the format decoder.
Pass the address of "quote" so that format decoders can
potentially disable printing of the closing quote
(e.g. when printing "'TYPEDEF' aka 'TYPE'" in the C family
of frontends). */
- gcc_assert (pp_format_decoder (this));
+ printer_fn format_decoder = pp_format_decoder (pp);
+ gcc_assert (format_decoder);
gcc_assert (formatted_tok_list);
- ok = m_format_decoder (this, text, p,
- precision, wide, plus, hash, "e,
- *formatted_tok_list);
+ bool ok = format_decoder (pp, &text, p,
+ precision, wide, plus, hash, "e,
+ *formatted_tok_list);
gcc_assert (ok);
}
}
if (quote)
{
- push_back_any_text (formatted_tok_list, &buffer->m_chunk_obstack);
+ push_back_any_text (formatted_tok_list, &chunk_obstack);
formatted_tok_list->push_back<pp_token_end_quote> ();
}
- push_back_any_text (formatted_tok_list, &buffer->m_chunk_obstack);
+ push_back_any_text (formatted_tok_list, &chunk_obstack);
delete *formatters[argno];
*formatters[argno] = formatted_tok_list;
}
if (CHECKING_P)
for (; argno < PP_NL_ARGMAX; argno++)
gcc_assert (!formatters[argno]);
-
- /* If the client supplied a postprocessing object, call its "handle"
- hook here. */
- if (m_format_postprocessor)
- m_format_postprocessor->handle (this);
-
- /* Revert to normal obstack and wrapping mode. */
- buffer->m_obstack = &buffer->m_formatted_obstack;
- buffer->m_line_length = old_line_length;
- pp_wrapping_mode (this) = old_wrapping_mode;
- clear_state ();
}
struct auto_obstack