1*e4b17023SJohn Marino /* Various declarations for language-independent pretty-print subroutines.
2*e4b17023SJohn Marino Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2010
3*e4b17023SJohn Marino Free Software Foundation, Inc.
4*e4b17023SJohn Marino Contributed by Gabriel Dos Reis <gdr@integrable-solutions.net>
5*e4b17023SJohn Marino
6*e4b17023SJohn Marino This file is part of GCC.
7*e4b17023SJohn Marino
8*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under
9*e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free
10*e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later
11*e4b17023SJohn Marino version.
12*e4b17023SJohn Marino
13*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14*e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or
15*e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16*e4b17023SJohn Marino for more details.
17*e4b17023SJohn Marino
18*e4b17023SJohn Marino You should have received a copy of the GNU General Public License
19*e4b17023SJohn Marino along with GCC; see the file COPYING3. If not see
20*e4b17023SJohn Marino <http://www.gnu.org/licenses/>. */
21*e4b17023SJohn Marino
22*e4b17023SJohn Marino #include "config.h"
23*e4b17023SJohn Marino #include "system.h"
24*e4b17023SJohn Marino #include "coretypes.h"
25*e4b17023SJohn Marino #include "intl.h"
26*e4b17023SJohn Marino #include "pretty-print.h"
27*e4b17023SJohn Marino
28*e4b17023SJohn Marino #if HAVE_ICONV
29*e4b17023SJohn Marino #include <iconv.h>
30*e4b17023SJohn Marino #endif
31*e4b17023SJohn Marino
32*e4b17023SJohn Marino /* A pointer to the formatted diagnostic message. */
33*e4b17023SJohn Marino #define pp_formatted_text_data(PP) \
34*e4b17023SJohn Marino ((const char *) obstack_base (pp_base (PP)->buffer->obstack))
35*e4b17023SJohn Marino
36*e4b17023SJohn Marino /* Format an integer given by va_arg (ARG, type-specifier T) where
37*e4b17023SJohn Marino type-specifier is a precision modifier as indicated by PREC. F is
38*e4b17023SJohn Marino a string used to construct the appropriate format-specifier. */
39*e4b17023SJohn Marino #define pp_integer_with_precision(PP, ARG, PREC, T, F) \
40*e4b17023SJohn Marino do \
41*e4b17023SJohn Marino switch (PREC) \
42*e4b17023SJohn Marino { \
43*e4b17023SJohn Marino case 0: \
44*e4b17023SJohn Marino pp_scalar (PP, "%" F, va_arg (ARG, T)); \
45*e4b17023SJohn Marino break; \
46*e4b17023SJohn Marino \
47*e4b17023SJohn Marino case 1: \
48*e4b17023SJohn Marino pp_scalar (PP, "%l" F, va_arg (ARG, long T)); \
49*e4b17023SJohn Marino break; \
50*e4b17023SJohn Marino \
51*e4b17023SJohn Marino case 2: \
52*e4b17023SJohn Marino pp_scalar (PP, "%" HOST_LONG_LONG_FORMAT F, va_arg (ARG, long long T)); \
53*e4b17023SJohn Marino break; \
54*e4b17023SJohn Marino \
55*e4b17023SJohn Marino default: \
56*e4b17023SJohn Marino break; \
57*e4b17023SJohn Marino } \
58*e4b17023SJohn Marino while (0)
59*e4b17023SJohn Marino
60*e4b17023SJohn Marino
61*e4b17023SJohn Marino /* Subroutine of pp_set_maximum_length. Set up PRETTY-PRINTER's
62*e4b17023SJohn Marino internal maximum characters per line. */
63*e4b17023SJohn Marino static void
pp_set_real_maximum_length(pretty_printer * pp)64*e4b17023SJohn Marino pp_set_real_maximum_length (pretty_printer *pp)
65*e4b17023SJohn Marino {
66*e4b17023SJohn Marino /* If we're told not to wrap lines then do the obvious thing. In case
67*e4b17023SJohn Marino we'll emit prefix only once per message, it is appropriate
68*e4b17023SJohn Marino not to increase unnecessarily the line-length cut-off. */
69*e4b17023SJohn Marino if (!pp_is_wrapping_line (pp)
70*e4b17023SJohn Marino || pp_prefixing_rule (pp) == DIAGNOSTICS_SHOW_PREFIX_ONCE
71*e4b17023SJohn Marino || pp_prefixing_rule (pp) == DIAGNOSTICS_SHOW_PREFIX_NEVER)
72*e4b17023SJohn Marino pp->maximum_length = pp_line_cutoff (pp);
73*e4b17023SJohn Marino else
74*e4b17023SJohn Marino {
75*e4b17023SJohn Marino int prefix_length = pp->prefix ? strlen (pp->prefix) : 0;
76*e4b17023SJohn Marino /* If the prefix is ridiculously too long, output at least
77*e4b17023SJohn Marino 32 characters. */
78*e4b17023SJohn Marino if (pp_line_cutoff (pp) - prefix_length < 32)
79*e4b17023SJohn Marino pp->maximum_length = pp_line_cutoff (pp) + 32;
80*e4b17023SJohn Marino else
81*e4b17023SJohn Marino pp->maximum_length = pp_line_cutoff (pp);
82*e4b17023SJohn Marino }
83*e4b17023SJohn Marino }
84*e4b17023SJohn Marino
85*e4b17023SJohn Marino /* Clear PRETTY-PRINTER's output state. */
86*e4b17023SJohn Marino static inline void
pp_clear_state(pretty_printer * pp)87*e4b17023SJohn Marino pp_clear_state (pretty_printer *pp)
88*e4b17023SJohn Marino {
89*e4b17023SJohn Marino pp->emitted_prefix = false;
90*e4b17023SJohn Marino pp_indentation (pp) = 0;
91*e4b17023SJohn Marino }
92*e4b17023SJohn Marino
93*e4b17023SJohn Marino /* Flush the formatted text of PRETTY-PRINTER onto the attached stream. */
94*e4b17023SJohn Marino void
pp_write_text_to_stream(pretty_printer * pp)95*e4b17023SJohn Marino pp_write_text_to_stream (pretty_printer *pp)
96*e4b17023SJohn Marino {
97*e4b17023SJohn Marino const char *text = pp_formatted_text (pp);
98*e4b17023SJohn Marino fputs (text, pp->buffer->stream);
99*e4b17023SJohn Marino pp_clear_output_area (pp);
100*e4b17023SJohn Marino }
101*e4b17023SJohn Marino
102*e4b17023SJohn Marino /* Wrap a text delimited by START and END into PRETTY-PRINTER. */
103*e4b17023SJohn Marino static void
pp_wrap_text(pretty_printer * pp,const char * start,const char * end)104*e4b17023SJohn Marino pp_wrap_text (pretty_printer *pp, const char *start, const char *end)
105*e4b17023SJohn Marino {
106*e4b17023SJohn Marino bool wrapping_line = pp_is_wrapping_line (pp);
107*e4b17023SJohn Marino
108*e4b17023SJohn Marino while (start != end)
109*e4b17023SJohn Marino {
110*e4b17023SJohn Marino /* Dump anything bordered by whitespaces. */
111*e4b17023SJohn Marino {
112*e4b17023SJohn Marino const char *p = start;
113*e4b17023SJohn Marino while (p != end && !ISBLANK (*p) && *p != '\n')
114*e4b17023SJohn Marino ++p;
115*e4b17023SJohn Marino if (wrapping_line
116*e4b17023SJohn Marino && p - start >= pp_remaining_character_count_for_line (pp))
117*e4b17023SJohn Marino pp_newline (pp);
118*e4b17023SJohn Marino pp_append_text (pp, start, p);
119*e4b17023SJohn Marino start = p;
120*e4b17023SJohn Marino }
121*e4b17023SJohn Marino
122*e4b17023SJohn Marino if (start != end && ISBLANK (*start))
123*e4b17023SJohn Marino {
124*e4b17023SJohn Marino pp_space (pp);
125*e4b17023SJohn Marino ++start;
126*e4b17023SJohn Marino }
127*e4b17023SJohn Marino if (start != end && *start == '\n')
128*e4b17023SJohn Marino {
129*e4b17023SJohn Marino pp_newline (pp);
130*e4b17023SJohn Marino ++start;
131*e4b17023SJohn Marino }
132*e4b17023SJohn Marino }
133*e4b17023SJohn Marino }
134*e4b17023SJohn Marino
135*e4b17023SJohn Marino /* Same as pp_wrap_text but wrap text only when in line-wrapping mode. */
136*e4b17023SJohn Marino static inline void
pp_maybe_wrap_text(pretty_printer * pp,const char * start,const char * end)137*e4b17023SJohn Marino pp_maybe_wrap_text (pretty_printer *pp, const char *start, const char *end)
138*e4b17023SJohn Marino {
139*e4b17023SJohn Marino if (pp_is_wrapping_line (pp))
140*e4b17023SJohn Marino pp_wrap_text (pp, start, end);
141*e4b17023SJohn Marino else
142*e4b17023SJohn Marino pp_append_text (pp, start, end);
143*e4b17023SJohn Marino }
144*e4b17023SJohn Marino
145*e4b17023SJohn Marino /* Append to the output area of PRETTY-PRINTER a string specified by its
146*e4b17023SJohn Marino STARTing character and LENGTH. */
147*e4b17023SJohn Marino static inline void
pp_append_r(pretty_printer * pp,const char * start,int length)148*e4b17023SJohn Marino pp_append_r (pretty_printer *pp, const char *start, int length)
149*e4b17023SJohn Marino {
150*e4b17023SJohn Marino obstack_grow (pp->buffer->obstack, start, length);
151*e4b17023SJohn Marino pp->buffer->line_length += length;
152*e4b17023SJohn Marino }
153*e4b17023SJohn Marino
154*e4b17023SJohn Marino /* Insert enough spaces into the output area of PRETTY-PRINTER to bring
155*e4b17023SJohn Marino the column position to the current indentation level, assuming that a
156*e4b17023SJohn Marino newline has just been written to the buffer. */
157*e4b17023SJohn Marino void
pp_base_indent(pretty_printer * pp)158*e4b17023SJohn Marino pp_base_indent (pretty_printer *pp)
159*e4b17023SJohn Marino {
160*e4b17023SJohn Marino int n = pp_indentation (pp);
161*e4b17023SJohn Marino int i;
162*e4b17023SJohn Marino
163*e4b17023SJohn Marino for (i = 0; i < n; ++i)
164*e4b17023SJohn Marino pp_space (pp);
165*e4b17023SJohn Marino }
166*e4b17023SJohn Marino
167*e4b17023SJohn Marino /* The following format specifiers are recognized as being client independent:
168*e4b17023SJohn Marino %d, %i: (signed) integer in base ten.
169*e4b17023SJohn Marino %u: unsigned integer in base ten.
170*e4b17023SJohn Marino %o: unsigned integer in base eight.
171*e4b17023SJohn Marino %x: unsigned integer in base sixteen.
172*e4b17023SJohn Marino %ld, %li, %lo, %lu, %lx: long versions of the above.
173*e4b17023SJohn Marino %lld, %lli, %llo, %llu, %llx: long long versions.
174*e4b17023SJohn Marino %wd, %wi, %wo, %wu, %wx: HOST_WIDE_INT versions.
175*e4b17023SJohn Marino %c: character.
176*e4b17023SJohn Marino %s: string.
177*e4b17023SJohn Marino %p: pointer.
178*e4b17023SJohn Marino %m: strerror(text->err_no) - does not consume a value from args_ptr.
179*e4b17023SJohn Marino %%: '%'.
180*e4b17023SJohn Marino %<: opening quote.
181*e4b17023SJohn Marino %>: closing quote.
182*e4b17023SJohn Marino %': apostrophe (should only be used in untranslated messages;
183*e4b17023SJohn Marino translations should use appropriate punctuation directly).
184*e4b17023SJohn Marino %.*s: a substring the length of which is specified by an argument
185*e4b17023SJohn Marino integer.
186*e4b17023SJohn Marino %Ns: likewise, but length specified as constant in the format string.
187*e4b17023SJohn Marino Flag 'q': quote formatted text (must come immediately after '%').
188*e4b17023SJohn Marino
189*e4b17023SJohn Marino Arguments can be used sequentially, or through %N$ resp. *N$
190*e4b17023SJohn Marino notation Nth argument after the format string. If %N$ / *N$
191*e4b17023SJohn Marino notation is used, it must be used for all arguments, except %m, %%,
192*e4b17023SJohn Marino %<, %> and %', which may not have a number, as they do not consume
193*e4b17023SJohn Marino an argument. When %M$.*N$s is used, M must be N + 1. (This may
194*e4b17023SJohn Marino also be written %M$.*s, provided N is not otherwise used.) The
195*e4b17023SJohn Marino format string must have conversion specifiers with argument numbers
196*e4b17023SJohn Marino 1 up to highest argument; each argument may only be used once.
197*e4b17023SJohn Marino A format string can have at most 30 arguments. */
198*e4b17023SJohn Marino
199*e4b17023SJohn Marino /* Formatting phases 1 and 2: render TEXT->format_spec plus
200*e4b17023SJohn Marino TEXT->args_ptr into a series of chunks in PP->buffer->args[].
201*e4b17023SJohn Marino Phase 3 is in pp_base_format_text. */
202*e4b17023SJohn Marino
203*e4b17023SJohn Marino void
pp_base_format(pretty_printer * pp,text_info * text)204*e4b17023SJohn Marino pp_base_format (pretty_printer *pp, text_info *text)
205*e4b17023SJohn Marino {
206*e4b17023SJohn Marino output_buffer *buffer = pp->buffer;
207*e4b17023SJohn Marino const char *p;
208*e4b17023SJohn Marino const char **args;
209*e4b17023SJohn Marino struct chunk_info *new_chunk_array;
210*e4b17023SJohn Marino
211*e4b17023SJohn Marino unsigned int curarg = 0, chunk = 0, argno;
212*e4b17023SJohn Marino pp_wrapping_mode_t old_wrapping_mode;
213*e4b17023SJohn Marino bool any_unnumbered = false, any_numbered = false;
214*e4b17023SJohn Marino const char **formatters[PP_NL_ARGMAX];
215*e4b17023SJohn Marino
216*e4b17023SJohn Marino /* Allocate a new chunk structure. */
217*e4b17023SJohn Marino new_chunk_array = XOBNEW (&buffer->chunk_obstack, struct chunk_info);
218*e4b17023SJohn Marino new_chunk_array->prev = buffer->cur_chunk_array;
219*e4b17023SJohn Marino buffer->cur_chunk_array = new_chunk_array;
220*e4b17023SJohn Marino args = new_chunk_array->args;
221*e4b17023SJohn Marino
222*e4b17023SJohn Marino /* Formatting phase 1: split up TEXT->format_spec into chunks in
223*e4b17023SJohn Marino PP->buffer->args[]. Even-numbered chunks are to be output
224*e4b17023SJohn Marino verbatim, odd-numbered chunks are format specifiers.
225*e4b17023SJohn Marino %m, %%, %<, %>, and %' are replaced with the appropriate text at
226*e4b17023SJohn Marino this point. */
227*e4b17023SJohn Marino
228*e4b17023SJohn Marino memset (formatters, 0, sizeof formatters);
229*e4b17023SJohn Marino
230*e4b17023SJohn Marino for (p = text->format_spec; *p; )
231*e4b17023SJohn Marino {
232*e4b17023SJohn Marino while (*p != '\0' && *p != '%')
233*e4b17023SJohn Marino {
234*e4b17023SJohn Marino obstack_1grow (&buffer->chunk_obstack, *p);
235*e4b17023SJohn Marino p++;
236*e4b17023SJohn Marino }
237*e4b17023SJohn Marino
238*e4b17023SJohn Marino if (*p == '\0')
239*e4b17023SJohn Marino break;
240*e4b17023SJohn Marino
241*e4b17023SJohn Marino switch (*++p)
242*e4b17023SJohn Marino {
243*e4b17023SJohn Marino case '\0':
244*e4b17023SJohn Marino gcc_unreachable ();
245*e4b17023SJohn Marino
246*e4b17023SJohn Marino case '%':
247*e4b17023SJohn Marino obstack_1grow (&buffer->chunk_obstack, '%');
248*e4b17023SJohn Marino p++;
249*e4b17023SJohn Marino continue;
250*e4b17023SJohn Marino
251*e4b17023SJohn Marino case '<':
252*e4b17023SJohn Marino obstack_grow (&buffer->chunk_obstack,
253*e4b17023SJohn Marino open_quote, strlen (open_quote));
254*e4b17023SJohn Marino p++;
255*e4b17023SJohn Marino continue;
256*e4b17023SJohn Marino
257*e4b17023SJohn Marino case '>':
258*e4b17023SJohn Marino case '\'':
259*e4b17023SJohn Marino obstack_grow (&buffer->chunk_obstack,
260*e4b17023SJohn Marino close_quote, strlen (close_quote));
261*e4b17023SJohn Marino p++;
262*e4b17023SJohn Marino continue;
263*e4b17023SJohn Marino
264*e4b17023SJohn Marino case 'm':
265*e4b17023SJohn Marino {
266*e4b17023SJohn Marino const char *errstr = xstrerror (text->err_no);
267*e4b17023SJohn Marino obstack_grow (&buffer->chunk_obstack, errstr, strlen (errstr));
268*e4b17023SJohn Marino }
269*e4b17023SJohn Marino p++;
270*e4b17023SJohn Marino continue;
271*e4b17023SJohn Marino
272*e4b17023SJohn Marino default:
273*e4b17023SJohn Marino /* Handled in phase 2. Terminate the plain chunk here. */
274*e4b17023SJohn Marino obstack_1grow (&buffer->chunk_obstack, '\0');
275*e4b17023SJohn Marino gcc_assert (chunk < PP_NL_ARGMAX * 2);
276*e4b17023SJohn Marino args[chunk++] = XOBFINISH (&buffer->chunk_obstack, const char *);
277*e4b17023SJohn Marino break;
278*e4b17023SJohn Marino }
279*e4b17023SJohn Marino
280*e4b17023SJohn Marino if (ISDIGIT (*p))
281*e4b17023SJohn Marino {
282*e4b17023SJohn Marino char *end;
283*e4b17023SJohn Marino argno = strtoul (p, &end, 10) - 1;
284*e4b17023SJohn Marino p = end;
285*e4b17023SJohn Marino gcc_assert (*p == '$');
286*e4b17023SJohn Marino p++;
287*e4b17023SJohn Marino
288*e4b17023SJohn Marino any_numbered = true;
289*e4b17023SJohn Marino gcc_assert (!any_unnumbered);
290*e4b17023SJohn Marino }
291*e4b17023SJohn Marino else
292*e4b17023SJohn Marino {
293*e4b17023SJohn Marino argno = curarg++;
294*e4b17023SJohn Marino any_unnumbered = true;
295*e4b17023SJohn Marino gcc_assert (!any_numbered);
296*e4b17023SJohn Marino }
297*e4b17023SJohn Marino gcc_assert (argno < PP_NL_ARGMAX);
298*e4b17023SJohn Marino gcc_assert (!formatters[argno]);
299*e4b17023SJohn Marino formatters[argno] = &args[chunk];
300*e4b17023SJohn Marino do
301*e4b17023SJohn Marino {
302*e4b17023SJohn Marino obstack_1grow (&buffer->chunk_obstack, *p);
303*e4b17023SJohn Marino p++;
304*e4b17023SJohn Marino }
305*e4b17023SJohn Marino while (strchr ("qwl+#", p[-1]));
306*e4b17023SJohn Marino
307*e4b17023SJohn Marino if (p[-1] == '.')
308*e4b17023SJohn Marino {
309*e4b17023SJohn Marino /* We handle '%.Ns' and '%.*s' or '%M$.*N$s'
310*e4b17023SJohn Marino (where M == N + 1). */
311*e4b17023SJohn Marino if (ISDIGIT (*p))
312*e4b17023SJohn Marino {
313*e4b17023SJohn Marino do
314*e4b17023SJohn Marino {
315*e4b17023SJohn Marino obstack_1grow (&buffer->chunk_obstack, *p);
316*e4b17023SJohn Marino p++;
317*e4b17023SJohn Marino }
318*e4b17023SJohn Marino while (ISDIGIT (p[-1]));
319*e4b17023SJohn Marino gcc_assert (p[-1] == 's');
320*e4b17023SJohn Marino }
321*e4b17023SJohn Marino else
322*e4b17023SJohn Marino {
323*e4b17023SJohn Marino gcc_assert (*p == '*');
324*e4b17023SJohn Marino obstack_1grow (&buffer->chunk_obstack, '*');
325*e4b17023SJohn Marino p++;
326*e4b17023SJohn Marino
327*e4b17023SJohn Marino if (ISDIGIT (*p))
328*e4b17023SJohn Marino {
329*e4b17023SJohn Marino char *end;
330*e4b17023SJohn Marino unsigned int argno2 = strtoul (p, &end, 10) - 1;
331*e4b17023SJohn Marino p = end;
332*e4b17023SJohn Marino gcc_assert (argno2 == argno - 1);
333*e4b17023SJohn Marino gcc_assert (!any_unnumbered);
334*e4b17023SJohn Marino gcc_assert (*p == '$');
335*e4b17023SJohn Marino
336*e4b17023SJohn Marino p++;
337*e4b17023SJohn Marino formatters[argno2] = formatters[argno];
338*e4b17023SJohn Marino }
339*e4b17023SJohn Marino else
340*e4b17023SJohn Marino {
341*e4b17023SJohn Marino gcc_assert (!any_numbered);
342*e4b17023SJohn Marino formatters[argno+1] = formatters[argno];
343*e4b17023SJohn Marino curarg++;
344*e4b17023SJohn Marino }
345*e4b17023SJohn Marino gcc_assert (*p == 's');
346*e4b17023SJohn Marino obstack_1grow (&buffer->chunk_obstack, 's');
347*e4b17023SJohn Marino p++;
348*e4b17023SJohn Marino }
349*e4b17023SJohn Marino }
350*e4b17023SJohn Marino if (*p == '\0')
351*e4b17023SJohn Marino break;
352*e4b17023SJohn Marino
353*e4b17023SJohn Marino obstack_1grow (&buffer->chunk_obstack, '\0');
354*e4b17023SJohn Marino gcc_assert (chunk < PP_NL_ARGMAX * 2);
355*e4b17023SJohn Marino args[chunk++] = XOBFINISH (&buffer->chunk_obstack, const char *);
356*e4b17023SJohn Marino }
357*e4b17023SJohn Marino
358*e4b17023SJohn Marino obstack_1grow (&buffer->chunk_obstack, '\0');
359*e4b17023SJohn Marino gcc_assert (chunk < PP_NL_ARGMAX * 2);
360*e4b17023SJohn Marino args[chunk++] = XOBFINISH (&buffer->chunk_obstack, const char *);
361*e4b17023SJohn Marino args[chunk] = 0;
362*e4b17023SJohn Marino
363*e4b17023SJohn Marino /* Set output to the argument obstack, and switch line-wrapping and
364*e4b17023SJohn Marino prefixing off. */
365*e4b17023SJohn Marino buffer->obstack = &buffer->chunk_obstack;
366*e4b17023SJohn Marino old_wrapping_mode = pp_set_verbatim_wrapping (pp);
367*e4b17023SJohn Marino
368*e4b17023SJohn Marino /* Second phase. Replace each formatter with the formatted text it
369*e4b17023SJohn Marino corresponds to. */
370*e4b17023SJohn Marino
371*e4b17023SJohn Marino for (argno = 0; formatters[argno]; argno++)
372*e4b17023SJohn Marino {
373*e4b17023SJohn Marino int precision = 0;
374*e4b17023SJohn Marino bool wide = false;
375*e4b17023SJohn Marino bool plus = false;
376*e4b17023SJohn Marino bool hash = false;
377*e4b17023SJohn Marino bool quote = false;
378*e4b17023SJohn Marino
379*e4b17023SJohn Marino /* We do not attempt to enforce any ordering on the modifier
380*e4b17023SJohn Marino characters. */
381*e4b17023SJohn Marino
382*e4b17023SJohn Marino for (p = *formatters[argno];; p++)
383*e4b17023SJohn Marino {
384*e4b17023SJohn Marino switch (*p)
385*e4b17023SJohn Marino {
386*e4b17023SJohn Marino case 'q':
387*e4b17023SJohn Marino gcc_assert (!quote);
388*e4b17023SJohn Marino quote = true;
389*e4b17023SJohn Marino continue;
390*e4b17023SJohn Marino
391*e4b17023SJohn Marino case '+':
392*e4b17023SJohn Marino gcc_assert (!plus);
393*e4b17023SJohn Marino plus = true;
394*e4b17023SJohn Marino continue;
395*e4b17023SJohn Marino
396*e4b17023SJohn Marino case '#':
397*e4b17023SJohn Marino gcc_assert (!hash);
398*e4b17023SJohn Marino hash = true;
399*e4b17023SJohn Marino continue;
400*e4b17023SJohn Marino
401*e4b17023SJohn Marino case 'w':
402*e4b17023SJohn Marino gcc_assert (!wide);
403*e4b17023SJohn Marino wide = true;
404*e4b17023SJohn Marino continue;
405*e4b17023SJohn Marino
406*e4b17023SJohn Marino case 'l':
407*e4b17023SJohn Marino /* We don't support precision beyond that of "long long". */
408*e4b17023SJohn Marino gcc_assert (precision < 2);
409*e4b17023SJohn Marino precision++;
410*e4b17023SJohn Marino continue;
411*e4b17023SJohn Marino }
412*e4b17023SJohn Marino break;
413*e4b17023SJohn Marino }
414*e4b17023SJohn Marino
415*e4b17023SJohn Marino gcc_assert (!wide || precision == 0);
416*e4b17023SJohn Marino
417*e4b17023SJohn Marino if (quote)
418*e4b17023SJohn Marino pp_string (pp, open_quote);
419*e4b17023SJohn Marino
420*e4b17023SJohn Marino switch (*p)
421*e4b17023SJohn Marino {
422*e4b17023SJohn Marino case 'c':
423*e4b17023SJohn Marino pp_character (pp, va_arg (*text->args_ptr, int));
424*e4b17023SJohn Marino break;
425*e4b17023SJohn Marino
426*e4b17023SJohn Marino case 'd':
427*e4b17023SJohn Marino case 'i':
428*e4b17023SJohn Marino if (wide)
429*e4b17023SJohn Marino pp_wide_integer (pp, va_arg (*text->args_ptr, HOST_WIDE_INT));
430*e4b17023SJohn Marino else
431*e4b17023SJohn Marino pp_integer_with_precision
432*e4b17023SJohn Marino (pp, *text->args_ptr, precision, int, "d");
433*e4b17023SJohn Marino break;
434*e4b17023SJohn Marino
435*e4b17023SJohn Marino case 'o':
436*e4b17023SJohn Marino if (wide)
437*e4b17023SJohn Marino pp_scalar (pp, "%" HOST_WIDE_INT_PRINT "o",
438*e4b17023SJohn Marino va_arg (*text->args_ptr, unsigned HOST_WIDE_INT));
439*e4b17023SJohn Marino else
440*e4b17023SJohn Marino pp_integer_with_precision
441*e4b17023SJohn Marino (pp, *text->args_ptr, precision, unsigned, "o");
442*e4b17023SJohn Marino break;
443*e4b17023SJohn Marino
444*e4b17023SJohn Marino case 's':
445*e4b17023SJohn Marino pp_string (pp, va_arg (*text->args_ptr, const char *));
446*e4b17023SJohn Marino break;
447*e4b17023SJohn Marino
448*e4b17023SJohn Marino case 'p':
449*e4b17023SJohn Marino pp_pointer (pp, va_arg (*text->args_ptr, void *));
450*e4b17023SJohn Marino break;
451*e4b17023SJohn Marino
452*e4b17023SJohn Marino case 'u':
453*e4b17023SJohn Marino if (wide)
454*e4b17023SJohn Marino pp_scalar (pp, HOST_WIDE_INT_PRINT_UNSIGNED,
455*e4b17023SJohn Marino va_arg (*text->args_ptr, unsigned HOST_WIDE_INT));
456*e4b17023SJohn Marino else
457*e4b17023SJohn Marino pp_integer_with_precision
458*e4b17023SJohn Marino (pp, *text->args_ptr, precision, unsigned, "u");
459*e4b17023SJohn Marino break;
460*e4b17023SJohn Marino
461*e4b17023SJohn Marino case 'x':
462*e4b17023SJohn Marino if (wide)
463*e4b17023SJohn Marino pp_scalar (pp, HOST_WIDE_INT_PRINT_HEX,
464*e4b17023SJohn Marino va_arg (*text->args_ptr, unsigned HOST_WIDE_INT));
465*e4b17023SJohn Marino else
466*e4b17023SJohn Marino pp_integer_with_precision
467*e4b17023SJohn Marino (pp, *text->args_ptr, precision, unsigned, "x");
468*e4b17023SJohn Marino break;
469*e4b17023SJohn Marino
470*e4b17023SJohn Marino case '.':
471*e4b17023SJohn Marino {
472*e4b17023SJohn Marino int n;
473*e4b17023SJohn Marino const char *s;
474*e4b17023SJohn Marino
475*e4b17023SJohn Marino /* We handle '%.Ns' and '%.*s' or '%M$.*N$s'
476*e4b17023SJohn Marino (where M == N + 1). The format string should be verified
477*e4b17023SJohn Marino already from the first phase. */
478*e4b17023SJohn Marino p++;
479*e4b17023SJohn Marino if (ISDIGIT (*p))
480*e4b17023SJohn Marino {
481*e4b17023SJohn Marino char *end;
482*e4b17023SJohn Marino n = strtoul (p, &end, 10);
483*e4b17023SJohn Marino p = end;
484*e4b17023SJohn Marino gcc_assert (*p == 's');
485*e4b17023SJohn Marino }
486*e4b17023SJohn Marino else
487*e4b17023SJohn Marino {
488*e4b17023SJohn Marino gcc_assert (*p == '*');
489*e4b17023SJohn Marino p++;
490*e4b17023SJohn Marino gcc_assert (*p == 's');
491*e4b17023SJohn Marino n = va_arg (*text->args_ptr, int);
492*e4b17023SJohn Marino
493*e4b17023SJohn Marino /* This consumes a second entry in the formatters array. */
494*e4b17023SJohn Marino gcc_assert (formatters[argno] == formatters[argno+1]);
495*e4b17023SJohn Marino argno++;
496*e4b17023SJohn Marino }
497*e4b17023SJohn Marino
498*e4b17023SJohn Marino s = va_arg (*text->args_ptr, const char *);
499*e4b17023SJohn Marino pp_append_text (pp, s, s + n);
500*e4b17023SJohn Marino }
501*e4b17023SJohn Marino break;
502*e4b17023SJohn Marino
503*e4b17023SJohn Marino default:
504*e4b17023SJohn Marino {
505*e4b17023SJohn Marino bool ok;
506*e4b17023SJohn Marino
507*e4b17023SJohn Marino gcc_assert (pp_format_decoder (pp));
508*e4b17023SJohn Marino ok = pp_format_decoder (pp) (pp, text, p,
509*e4b17023SJohn Marino precision, wide, plus, hash);
510*e4b17023SJohn Marino gcc_assert (ok);
511*e4b17023SJohn Marino }
512*e4b17023SJohn Marino }
513*e4b17023SJohn Marino
514*e4b17023SJohn Marino if (quote)
515*e4b17023SJohn Marino pp_string (pp, close_quote);
516*e4b17023SJohn Marino
517*e4b17023SJohn Marino obstack_1grow (&buffer->chunk_obstack, '\0');
518*e4b17023SJohn Marino *formatters[argno] = XOBFINISH (&buffer->chunk_obstack, const char *);
519*e4b17023SJohn Marino }
520*e4b17023SJohn Marino
521*e4b17023SJohn Marino #ifdef ENABLE_CHECKING
522*e4b17023SJohn Marino for (; argno < PP_NL_ARGMAX; argno++)
523*e4b17023SJohn Marino gcc_assert (!formatters[argno]);
524*e4b17023SJohn Marino #endif
525*e4b17023SJohn Marino
526*e4b17023SJohn Marino /* Revert to normal obstack and wrapping mode. */
527*e4b17023SJohn Marino buffer->obstack = &buffer->formatted_obstack;
528*e4b17023SJohn Marino buffer->line_length = 0;
529*e4b17023SJohn Marino pp_wrapping_mode (pp) = old_wrapping_mode;
530*e4b17023SJohn Marino pp_clear_state (pp);
531*e4b17023SJohn Marino }
532*e4b17023SJohn Marino
533*e4b17023SJohn Marino /* Format of a message pointed to by TEXT. */
534*e4b17023SJohn Marino void
pp_base_output_formatted_text(pretty_printer * pp)535*e4b17023SJohn Marino pp_base_output_formatted_text (pretty_printer *pp)
536*e4b17023SJohn Marino {
537*e4b17023SJohn Marino unsigned int chunk;
538*e4b17023SJohn Marino output_buffer *buffer = pp_buffer (pp);
539*e4b17023SJohn Marino struct chunk_info *chunk_array = buffer->cur_chunk_array;
540*e4b17023SJohn Marino const char **args = chunk_array->args;
541*e4b17023SJohn Marino
542*e4b17023SJohn Marino gcc_assert (buffer->obstack == &buffer->formatted_obstack);
543*e4b17023SJohn Marino gcc_assert (buffer->line_length == 0);
544*e4b17023SJohn Marino
545*e4b17023SJohn Marino /* This is a third phase, first 2 phases done in pp_base_format_args.
546*e4b17023SJohn Marino Now we actually print it. */
547*e4b17023SJohn Marino for (chunk = 0; args[chunk]; chunk++)
548*e4b17023SJohn Marino pp_string (pp, args[chunk]);
549*e4b17023SJohn Marino
550*e4b17023SJohn Marino /* Deallocate the chunk structure and everything after it (i.e. the
551*e4b17023SJohn Marino associated series of formatted strings). */
552*e4b17023SJohn Marino buffer->cur_chunk_array = chunk_array->prev;
553*e4b17023SJohn Marino obstack_free (&buffer->chunk_obstack, chunk_array);
554*e4b17023SJohn Marino }
555*e4b17023SJohn Marino
556*e4b17023SJohn Marino /* Helper subroutine of output_verbatim and verbatim. Do the appropriate
557*e4b17023SJohn Marino settings needed by BUFFER for a verbatim formatting. */
558*e4b17023SJohn Marino void
pp_base_format_verbatim(pretty_printer * pp,text_info * text)559*e4b17023SJohn Marino pp_base_format_verbatim (pretty_printer *pp, text_info *text)
560*e4b17023SJohn Marino {
561*e4b17023SJohn Marino /* Set verbatim mode. */
562*e4b17023SJohn Marino pp_wrapping_mode_t oldmode = pp_set_verbatim_wrapping (pp);
563*e4b17023SJohn Marino
564*e4b17023SJohn Marino /* Do the actual formatting. */
565*e4b17023SJohn Marino pp_format (pp, text);
566*e4b17023SJohn Marino pp_output_formatted_text (pp);
567*e4b17023SJohn Marino
568*e4b17023SJohn Marino /* Restore previous settings. */
569*e4b17023SJohn Marino pp_wrapping_mode (pp) = oldmode;
570*e4b17023SJohn Marino }
571*e4b17023SJohn Marino
572*e4b17023SJohn Marino /* Flush the content of BUFFER onto the attached stream. */
573*e4b17023SJohn Marino void
pp_base_flush(pretty_printer * pp)574*e4b17023SJohn Marino pp_base_flush (pretty_printer *pp)
575*e4b17023SJohn Marino {
576*e4b17023SJohn Marino pp_write_text_to_stream (pp);
577*e4b17023SJohn Marino pp_clear_state (pp);
578*e4b17023SJohn Marino fputc ('\n', pp->buffer->stream);
579*e4b17023SJohn Marino fflush (pp->buffer->stream);
580*e4b17023SJohn Marino pp_needs_newline (pp) = false;
581*e4b17023SJohn Marino }
582*e4b17023SJohn Marino
583*e4b17023SJohn Marino /* Sets the number of maximum characters per line PRETTY-PRINTER can
584*e4b17023SJohn Marino output in line-wrapping mode. A LENGTH value 0 suppresses
585*e4b17023SJohn Marino line-wrapping. */
586*e4b17023SJohn Marino void
pp_base_set_line_maximum_length(pretty_printer * pp,int length)587*e4b17023SJohn Marino pp_base_set_line_maximum_length (pretty_printer *pp, int length)
588*e4b17023SJohn Marino {
589*e4b17023SJohn Marino pp_line_cutoff (pp) = length;
590*e4b17023SJohn Marino pp_set_real_maximum_length (pp);
591*e4b17023SJohn Marino }
592*e4b17023SJohn Marino
593*e4b17023SJohn Marino /* Clear PRETTY-PRINTER output area text info. */
594*e4b17023SJohn Marino void
pp_base_clear_output_area(pretty_printer * pp)595*e4b17023SJohn Marino pp_base_clear_output_area (pretty_printer *pp)
596*e4b17023SJohn Marino {
597*e4b17023SJohn Marino obstack_free (pp->buffer->obstack, obstack_base (pp->buffer->obstack));
598*e4b17023SJohn Marino pp->buffer->line_length = 0;
599*e4b17023SJohn Marino }
600*e4b17023SJohn Marino
601*e4b17023SJohn Marino /* Set PREFIX for PRETTY-PRINTER. */
602*e4b17023SJohn Marino void
pp_base_set_prefix(pretty_printer * pp,const char * prefix)603*e4b17023SJohn Marino pp_base_set_prefix (pretty_printer *pp, const char *prefix)
604*e4b17023SJohn Marino {
605*e4b17023SJohn Marino pp->prefix = prefix;
606*e4b17023SJohn Marino pp_set_real_maximum_length (pp);
607*e4b17023SJohn Marino pp->emitted_prefix = false;
608*e4b17023SJohn Marino pp_indentation (pp) = 0;
609*e4b17023SJohn Marino }
610*e4b17023SJohn Marino
611*e4b17023SJohn Marino /* Free PRETTY-PRINTER's prefix, a previously malloc()'d string. */
612*e4b17023SJohn Marino void
pp_base_destroy_prefix(pretty_printer * pp)613*e4b17023SJohn Marino pp_base_destroy_prefix (pretty_printer *pp)
614*e4b17023SJohn Marino {
615*e4b17023SJohn Marino if (pp->prefix != NULL)
616*e4b17023SJohn Marino {
617*e4b17023SJohn Marino free (CONST_CAST (char *, pp->prefix));
618*e4b17023SJohn Marino pp->prefix = NULL;
619*e4b17023SJohn Marino }
620*e4b17023SJohn Marino }
621*e4b17023SJohn Marino
622*e4b17023SJohn Marino /* Write out PRETTY-PRINTER's prefix. */
623*e4b17023SJohn Marino void
pp_base_emit_prefix(pretty_printer * pp)624*e4b17023SJohn Marino pp_base_emit_prefix (pretty_printer *pp)
625*e4b17023SJohn Marino {
626*e4b17023SJohn Marino if (pp->prefix != NULL)
627*e4b17023SJohn Marino {
628*e4b17023SJohn Marino switch (pp_prefixing_rule (pp))
629*e4b17023SJohn Marino {
630*e4b17023SJohn Marino default:
631*e4b17023SJohn Marino case DIAGNOSTICS_SHOW_PREFIX_NEVER:
632*e4b17023SJohn Marino break;
633*e4b17023SJohn Marino
634*e4b17023SJohn Marino case DIAGNOSTICS_SHOW_PREFIX_ONCE:
635*e4b17023SJohn Marino if (pp->emitted_prefix)
636*e4b17023SJohn Marino {
637*e4b17023SJohn Marino pp_base_indent (pp);
638*e4b17023SJohn Marino break;
639*e4b17023SJohn Marino }
640*e4b17023SJohn Marino pp_indentation (pp) += 3;
641*e4b17023SJohn Marino /* Fall through. */
642*e4b17023SJohn Marino
643*e4b17023SJohn Marino case DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE:
644*e4b17023SJohn Marino {
645*e4b17023SJohn Marino int prefix_length = strlen (pp->prefix);
646*e4b17023SJohn Marino pp_append_r (pp, pp->prefix, prefix_length);
647*e4b17023SJohn Marino pp->emitted_prefix = true;
648*e4b17023SJohn Marino }
649*e4b17023SJohn Marino break;
650*e4b17023SJohn Marino }
651*e4b17023SJohn Marino }
652*e4b17023SJohn Marino }
653*e4b17023SJohn Marino
654*e4b17023SJohn Marino /* Construct a PRETTY-PRINTER with PREFIX and of MAXIMUM_LENGTH
655*e4b17023SJohn Marino characters per line. */
656*e4b17023SJohn Marino void
pp_construct(pretty_printer * pp,const char * prefix,int maximum_length)657*e4b17023SJohn Marino pp_construct (pretty_printer *pp, const char *prefix, int maximum_length)
658*e4b17023SJohn Marino {
659*e4b17023SJohn Marino memset (pp, 0, sizeof (pretty_printer));
660*e4b17023SJohn Marino pp->buffer = XCNEW (output_buffer);
661*e4b17023SJohn Marino obstack_init (&pp->buffer->chunk_obstack);
662*e4b17023SJohn Marino obstack_init (&pp->buffer->formatted_obstack);
663*e4b17023SJohn Marino pp->buffer->obstack = &pp->buffer->formatted_obstack;
664*e4b17023SJohn Marino pp->buffer->stream = stderr;
665*e4b17023SJohn Marino pp_line_cutoff (pp) = maximum_length;
666*e4b17023SJohn Marino pp_prefixing_rule (pp) = DIAGNOSTICS_SHOW_PREFIX_ONCE;
667*e4b17023SJohn Marino pp_set_prefix (pp, prefix);
668*e4b17023SJohn Marino pp_translate_identifiers (pp) = true;
669*e4b17023SJohn Marino }
670*e4b17023SJohn Marino
671*e4b17023SJohn Marino /* Append a string delimited by START and END to the output area of
672*e4b17023SJohn Marino PRETTY-PRINTER. No line wrapping is done. However, if beginning a
673*e4b17023SJohn Marino new line then emit PRETTY-PRINTER's prefix and skip any leading
674*e4b17023SJohn Marino whitespace if appropriate. The caller must ensure that it is
675*e4b17023SJohn Marino safe to do so. */
676*e4b17023SJohn Marino void
pp_base_append_text(pretty_printer * pp,const char * start,const char * end)677*e4b17023SJohn Marino pp_base_append_text (pretty_printer *pp, const char *start, const char *end)
678*e4b17023SJohn Marino {
679*e4b17023SJohn Marino /* Emit prefix and skip whitespace if we're starting a new line. */
680*e4b17023SJohn Marino if (pp->buffer->line_length == 0)
681*e4b17023SJohn Marino {
682*e4b17023SJohn Marino pp_emit_prefix (pp);
683*e4b17023SJohn Marino if (pp_is_wrapping_line (pp))
684*e4b17023SJohn Marino while (start != end && *start == ' ')
685*e4b17023SJohn Marino ++start;
686*e4b17023SJohn Marino }
687*e4b17023SJohn Marino pp_append_r (pp, start, end - start);
688*e4b17023SJohn Marino }
689*e4b17023SJohn Marino
690*e4b17023SJohn Marino /* Finishes constructing a NULL-terminated character string representing
691*e4b17023SJohn Marino the PRETTY-PRINTED text. */
692*e4b17023SJohn Marino const char *
pp_base_formatted_text(pretty_printer * pp)693*e4b17023SJohn Marino pp_base_formatted_text (pretty_printer *pp)
694*e4b17023SJohn Marino {
695*e4b17023SJohn Marino obstack_1grow (pp->buffer->obstack, '\0');
696*e4b17023SJohn Marino return pp_formatted_text_data (pp);
697*e4b17023SJohn Marino }
698*e4b17023SJohn Marino
699*e4b17023SJohn Marino /* Return a pointer to the last character emitted in PRETTY-PRINTER's
700*e4b17023SJohn Marino output area. A NULL pointer means no character available. */
701*e4b17023SJohn Marino const char *
pp_base_last_position_in_text(const pretty_printer * pp)702*e4b17023SJohn Marino pp_base_last_position_in_text (const pretty_printer *pp)
703*e4b17023SJohn Marino {
704*e4b17023SJohn Marino const char *p = NULL;
705*e4b17023SJohn Marino struct obstack *text = pp->buffer->obstack;
706*e4b17023SJohn Marino
707*e4b17023SJohn Marino if (obstack_base (text) != obstack_next_free (text))
708*e4b17023SJohn Marino p = ((const char *) obstack_next_free (text)) - 1;
709*e4b17023SJohn Marino return p;
710*e4b17023SJohn Marino }
711*e4b17023SJohn Marino
712*e4b17023SJohn Marino /* Return the amount of characters PRETTY-PRINTER can accept to
713*e4b17023SJohn Marino make a full line. Meaningful only in line-wrapping mode. */
714*e4b17023SJohn Marino int
pp_base_remaining_character_count_for_line(pretty_printer * pp)715*e4b17023SJohn Marino pp_base_remaining_character_count_for_line (pretty_printer *pp)
716*e4b17023SJohn Marino {
717*e4b17023SJohn Marino return pp->maximum_length - pp->buffer->line_length;
718*e4b17023SJohn Marino }
719*e4b17023SJohn Marino
720*e4b17023SJohn Marino
721*e4b17023SJohn Marino /* Format a message into BUFFER a la printf. */
722*e4b17023SJohn Marino void
pp_printf(pretty_printer * pp,const char * msg,...)723*e4b17023SJohn Marino pp_printf (pretty_printer *pp, const char *msg, ...)
724*e4b17023SJohn Marino {
725*e4b17023SJohn Marino text_info text;
726*e4b17023SJohn Marino va_list ap;
727*e4b17023SJohn Marino
728*e4b17023SJohn Marino va_start (ap, msg);
729*e4b17023SJohn Marino text.err_no = errno;
730*e4b17023SJohn Marino text.args_ptr = ≈
731*e4b17023SJohn Marino text.format_spec = msg;
732*e4b17023SJohn Marino text.locus = NULL;
733*e4b17023SJohn Marino pp_format (pp, &text);
734*e4b17023SJohn Marino pp_output_formatted_text (pp);
735*e4b17023SJohn Marino va_end (ap);
736*e4b17023SJohn Marino }
737*e4b17023SJohn Marino
738*e4b17023SJohn Marino
739*e4b17023SJohn Marino /* Output MESSAGE verbatim into BUFFER. */
740*e4b17023SJohn Marino void
pp_verbatim(pretty_printer * pp,const char * msg,...)741*e4b17023SJohn Marino pp_verbatim (pretty_printer *pp, const char *msg, ...)
742*e4b17023SJohn Marino {
743*e4b17023SJohn Marino text_info text;
744*e4b17023SJohn Marino va_list ap;
745*e4b17023SJohn Marino
746*e4b17023SJohn Marino va_start (ap, msg);
747*e4b17023SJohn Marino text.err_no = errno;
748*e4b17023SJohn Marino text.args_ptr = ≈
749*e4b17023SJohn Marino text.format_spec = msg;
750*e4b17023SJohn Marino text.locus = NULL;
751*e4b17023SJohn Marino pp_format_verbatim (pp, &text);
752*e4b17023SJohn Marino va_end (ap);
753*e4b17023SJohn Marino }
754*e4b17023SJohn Marino
755*e4b17023SJohn Marino
756*e4b17023SJohn Marino
757*e4b17023SJohn Marino /* Have PRETTY-PRINTER start a new line. */
758*e4b17023SJohn Marino void
pp_base_newline(pretty_printer * pp)759*e4b17023SJohn Marino pp_base_newline (pretty_printer *pp)
760*e4b17023SJohn Marino {
761*e4b17023SJohn Marino obstack_1grow (pp->buffer->obstack, '\n');
762*e4b17023SJohn Marino pp->buffer->line_length = 0;
763*e4b17023SJohn Marino }
764*e4b17023SJohn Marino
765*e4b17023SJohn Marino /* Have PRETTY-PRINTER add a CHARACTER. */
766*e4b17023SJohn Marino void
pp_base_character(pretty_printer * pp,int c)767*e4b17023SJohn Marino pp_base_character (pretty_printer *pp, int c)
768*e4b17023SJohn Marino {
769*e4b17023SJohn Marino if (pp_is_wrapping_line (pp)
770*e4b17023SJohn Marino && pp_remaining_character_count_for_line (pp) <= 0)
771*e4b17023SJohn Marino {
772*e4b17023SJohn Marino pp_newline (pp);
773*e4b17023SJohn Marino if (ISSPACE (c))
774*e4b17023SJohn Marino return;
775*e4b17023SJohn Marino }
776*e4b17023SJohn Marino obstack_1grow (pp->buffer->obstack, c);
777*e4b17023SJohn Marino ++pp->buffer->line_length;
778*e4b17023SJohn Marino }
779*e4b17023SJohn Marino
780*e4b17023SJohn Marino /* Append a STRING to the output area of PRETTY-PRINTER; the STRING may
781*e4b17023SJohn Marino be line-wrapped if in appropriate mode. */
782*e4b17023SJohn Marino void
pp_base_string(pretty_printer * pp,const char * str)783*e4b17023SJohn Marino pp_base_string (pretty_printer *pp, const char *str)
784*e4b17023SJohn Marino {
785*e4b17023SJohn Marino pp_maybe_wrap_text (pp, str, str + (str ? strlen (str) : 0));
786*e4b17023SJohn Marino }
787*e4b17023SJohn Marino
788*e4b17023SJohn Marino /* Maybe print out a whitespace if needed. */
789*e4b17023SJohn Marino
790*e4b17023SJohn Marino void
pp_base_maybe_space(pretty_printer * pp)791*e4b17023SJohn Marino pp_base_maybe_space (pretty_printer *pp)
792*e4b17023SJohn Marino {
793*e4b17023SJohn Marino if (pp_base (pp)->padding != pp_none)
794*e4b17023SJohn Marino {
795*e4b17023SJohn Marino pp_space (pp);
796*e4b17023SJohn Marino pp_base (pp)->padding = pp_none;
797*e4b17023SJohn Marino }
798*e4b17023SJohn Marino }
799*e4b17023SJohn Marino
800*e4b17023SJohn Marino /* The string starting at P has LEN (at least 1) bytes left; if they
801*e4b17023SJohn Marino start with a valid UTF-8 sequence, return the length of that
802*e4b17023SJohn Marino sequence and set *VALUE to the value of that sequence, and
803*e4b17023SJohn Marino otherwise return 0 and set *VALUE to (unsigned int) -1. */
804*e4b17023SJohn Marino
805*e4b17023SJohn Marino static int
decode_utf8_char(const unsigned char * p,size_t len,unsigned int * value)806*e4b17023SJohn Marino decode_utf8_char (const unsigned char *p, size_t len, unsigned int *value)
807*e4b17023SJohn Marino {
808*e4b17023SJohn Marino unsigned int t = *p;
809*e4b17023SJohn Marino
810*e4b17023SJohn Marino if (len == 0)
811*e4b17023SJohn Marino abort ();
812*e4b17023SJohn Marino if (t & 0x80)
813*e4b17023SJohn Marino {
814*e4b17023SJohn Marino size_t utf8_len = 0;
815*e4b17023SJohn Marino unsigned int ch;
816*e4b17023SJohn Marino size_t i;
817*e4b17023SJohn Marino for (t = *p; t & 0x80; t <<= 1)
818*e4b17023SJohn Marino utf8_len++;
819*e4b17023SJohn Marino
820*e4b17023SJohn Marino if (utf8_len > len || utf8_len < 2 || utf8_len > 6)
821*e4b17023SJohn Marino {
822*e4b17023SJohn Marino *value = (unsigned int) -1;
823*e4b17023SJohn Marino return 0;
824*e4b17023SJohn Marino }
825*e4b17023SJohn Marino ch = *p & ((1 << (7 - utf8_len)) - 1);
826*e4b17023SJohn Marino for (i = 1; i < utf8_len; i++)
827*e4b17023SJohn Marino {
828*e4b17023SJohn Marino unsigned int u = p[i];
829*e4b17023SJohn Marino if ((u & 0xC0) != 0x80)
830*e4b17023SJohn Marino {
831*e4b17023SJohn Marino *value = (unsigned int) -1;
832*e4b17023SJohn Marino return 0;
833*e4b17023SJohn Marino }
834*e4b17023SJohn Marino ch = (ch << 6) | (u & 0x3F);
835*e4b17023SJohn Marino }
836*e4b17023SJohn Marino if ( (ch <= 0x7F && utf8_len > 1)
837*e4b17023SJohn Marino || (ch <= 0x7FF && utf8_len > 2)
838*e4b17023SJohn Marino || (ch <= 0xFFFF && utf8_len > 3)
839*e4b17023SJohn Marino || (ch <= 0x1FFFFF && utf8_len > 4)
840*e4b17023SJohn Marino || (ch <= 0x3FFFFFF && utf8_len > 5)
841*e4b17023SJohn Marino || (ch >= 0xD800 && ch <= 0xDFFF))
842*e4b17023SJohn Marino {
843*e4b17023SJohn Marino *value = (unsigned int) -1;
844*e4b17023SJohn Marino return 0;
845*e4b17023SJohn Marino }
846*e4b17023SJohn Marino *value = ch;
847*e4b17023SJohn Marino return utf8_len;
848*e4b17023SJohn Marino }
849*e4b17023SJohn Marino else
850*e4b17023SJohn Marino {
851*e4b17023SJohn Marino *value = t;
852*e4b17023SJohn Marino return 1;
853*e4b17023SJohn Marino }
854*e4b17023SJohn Marino }
855*e4b17023SJohn Marino
856*e4b17023SJohn Marino /* Allocator for identifier_to_locale and corresponding function to
857*e4b17023SJohn Marino free memory. */
858*e4b17023SJohn Marino
859*e4b17023SJohn Marino void *(*identifier_to_locale_alloc) (size_t) = xmalloc;
860*e4b17023SJohn Marino void (*identifier_to_locale_free) (void *) = free;
861*e4b17023SJohn Marino
862*e4b17023SJohn Marino /* Given IDENT, an identifier in the internal encoding, return a
863*e4b17023SJohn Marino version of IDENT suitable for diagnostics in the locale character
864*e4b17023SJohn Marino set: either IDENT itself, or a string, allocated using
865*e4b17023SJohn Marino identifier_to_locale_alloc, converted to the locale character set
866*e4b17023SJohn Marino and using escape sequences if not representable in the locale
867*e4b17023SJohn Marino character set or containing control characters or invalid byte
868*e4b17023SJohn Marino sequences. Existing backslashes in IDENT are not doubled, so the
869*e4b17023SJohn Marino result may not uniquely specify the contents of an arbitrary byte
870*e4b17023SJohn Marino sequence identifier. */
871*e4b17023SJohn Marino
872*e4b17023SJohn Marino const char *
identifier_to_locale(const char * ident)873*e4b17023SJohn Marino identifier_to_locale (const char *ident)
874*e4b17023SJohn Marino {
875*e4b17023SJohn Marino const unsigned char *uid = (const unsigned char *) ident;
876*e4b17023SJohn Marino size_t idlen = strlen (ident);
877*e4b17023SJohn Marino bool valid_printable_utf8 = true;
878*e4b17023SJohn Marino bool all_ascii = true;
879*e4b17023SJohn Marino size_t i;
880*e4b17023SJohn Marino
881*e4b17023SJohn Marino for (i = 0; i < idlen;)
882*e4b17023SJohn Marino {
883*e4b17023SJohn Marino unsigned int c;
884*e4b17023SJohn Marino size_t utf8_len = decode_utf8_char (&uid[i], idlen - i, &c);
885*e4b17023SJohn Marino if (utf8_len == 0 || c <= 0x1F || (c >= 0x7F && c <= 0x9F))
886*e4b17023SJohn Marino {
887*e4b17023SJohn Marino valid_printable_utf8 = false;
888*e4b17023SJohn Marino break;
889*e4b17023SJohn Marino }
890*e4b17023SJohn Marino if (utf8_len > 1)
891*e4b17023SJohn Marino all_ascii = false;
892*e4b17023SJohn Marino i += utf8_len;
893*e4b17023SJohn Marino }
894*e4b17023SJohn Marino
895*e4b17023SJohn Marino /* If IDENT contains invalid UTF-8 sequences (which may occur with
896*e4b17023SJohn Marino attributes putting arbitrary byte sequences in identifiers), or
897*e4b17023SJohn Marino control characters, we use octal escape sequences for all bytes
898*e4b17023SJohn Marino outside printable ASCII. */
899*e4b17023SJohn Marino if (!valid_printable_utf8)
900*e4b17023SJohn Marino {
901*e4b17023SJohn Marino char *ret = (char *) identifier_to_locale_alloc (4 * idlen + 1);
902*e4b17023SJohn Marino char *p = ret;
903*e4b17023SJohn Marino for (i = 0; i < idlen; i++)
904*e4b17023SJohn Marino {
905*e4b17023SJohn Marino if (uid[i] > 0x1F && uid[i] < 0x7F)
906*e4b17023SJohn Marino *p++ = uid[i];
907*e4b17023SJohn Marino else
908*e4b17023SJohn Marino {
909*e4b17023SJohn Marino sprintf (p, "\\%03o", uid[i]);
910*e4b17023SJohn Marino p += 4;
911*e4b17023SJohn Marino }
912*e4b17023SJohn Marino }
913*e4b17023SJohn Marino *p = 0;
914*e4b17023SJohn Marino return ret;
915*e4b17023SJohn Marino }
916*e4b17023SJohn Marino
917*e4b17023SJohn Marino /* Otherwise, if it is valid printable ASCII, or printable UTF-8
918*e4b17023SJohn Marino with the locale character set being UTF-8, IDENT is used. */
919*e4b17023SJohn Marino if (all_ascii || locale_utf8)
920*e4b17023SJohn Marino return ident;
921*e4b17023SJohn Marino
922*e4b17023SJohn Marino /* Otherwise IDENT is converted to the locale character set if
923*e4b17023SJohn Marino possible. */
924*e4b17023SJohn Marino #if defined ENABLE_NLS && defined HAVE_LANGINFO_CODESET && HAVE_ICONV
925*e4b17023SJohn Marino if (locale_encoding != NULL)
926*e4b17023SJohn Marino {
927*e4b17023SJohn Marino iconv_t cd = iconv_open (locale_encoding, "UTF-8");
928*e4b17023SJohn Marino bool conversion_ok = true;
929*e4b17023SJohn Marino char *ret = NULL;
930*e4b17023SJohn Marino if (cd != (iconv_t) -1)
931*e4b17023SJohn Marino {
932*e4b17023SJohn Marino size_t ret_alloc = 4 * idlen + 1;
933*e4b17023SJohn Marino for (;;)
934*e4b17023SJohn Marino {
935*e4b17023SJohn Marino /* Repeat the whole conversion process as needed with
936*e4b17023SJohn Marino larger buffers so non-reversible transformations can
937*e4b17023SJohn Marino always be detected. */
938*e4b17023SJohn Marino ICONV_CONST char *inbuf = CONST_CAST (char *, ident);
939*e4b17023SJohn Marino char *outbuf;
940*e4b17023SJohn Marino size_t inbytesleft = idlen;
941*e4b17023SJohn Marino size_t outbytesleft = ret_alloc - 1;
942*e4b17023SJohn Marino size_t iconv_ret;
943*e4b17023SJohn Marino
944*e4b17023SJohn Marino ret = (char *) identifier_to_locale_alloc (ret_alloc);
945*e4b17023SJohn Marino outbuf = ret;
946*e4b17023SJohn Marino
947*e4b17023SJohn Marino if (iconv (cd, 0, 0, 0, 0) == (size_t) -1)
948*e4b17023SJohn Marino {
949*e4b17023SJohn Marino conversion_ok = false;
950*e4b17023SJohn Marino break;
951*e4b17023SJohn Marino }
952*e4b17023SJohn Marino
953*e4b17023SJohn Marino iconv_ret = iconv (cd, &inbuf, &inbytesleft,
954*e4b17023SJohn Marino &outbuf, &outbytesleft);
955*e4b17023SJohn Marino if (iconv_ret == (size_t) -1 || inbytesleft != 0)
956*e4b17023SJohn Marino {
957*e4b17023SJohn Marino if (errno == E2BIG)
958*e4b17023SJohn Marino {
959*e4b17023SJohn Marino ret_alloc *= 2;
960*e4b17023SJohn Marino identifier_to_locale_free (ret);
961*e4b17023SJohn Marino ret = NULL;
962*e4b17023SJohn Marino continue;
963*e4b17023SJohn Marino }
964*e4b17023SJohn Marino else
965*e4b17023SJohn Marino {
966*e4b17023SJohn Marino conversion_ok = false;
967*e4b17023SJohn Marino break;
968*e4b17023SJohn Marino }
969*e4b17023SJohn Marino }
970*e4b17023SJohn Marino else if (iconv_ret != 0)
971*e4b17023SJohn Marino {
972*e4b17023SJohn Marino conversion_ok = false;
973*e4b17023SJohn Marino break;
974*e4b17023SJohn Marino }
975*e4b17023SJohn Marino /* Return to initial shift state. */
976*e4b17023SJohn Marino if (iconv (cd, 0, 0, &outbuf, &outbytesleft) == (size_t) -1)
977*e4b17023SJohn Marino {
978*e4b17023SJohn Marino if (errno == E2BIG)
979*e4b17023SJohn Marino {
980*e4b17023SJohn Marino ret_alloc *= 2;
981*e4b17023SJohn Marino identifier_to_locale_free (ret);
982*e4b17023SJohn Marino ret = NULL;
983*e4b17023SJohn Marino continue;
984*e4b17023SJohn Marino }
985*e4b17023SJohn Marino else
986*e4b17023SJohn Marino {
987*e4b17023SJohn Marino conversion_ok = false;
988*e4b17023SJohn Marino break;
989*e4b17023SJohn Marino }
990*e4b17023SJohn Marino }
991*e4b17023SJohn Marino *outbuf = 0;
992*e4b17023SJohn Marino break;
993*e4b17023SJohn Marino }
994*e4b17023SJohn Marino iconv_close (cd);
995*e4b17023SJohn Marino if (conversion_ok)
996*e4b17023SJohn Marino return ret;
997*e4b17023SJohn Marino }
998*e4b17023SJohn Marino }
999*e4b17023SJohn Marino #endif
1000*e4b17023SJohn Marino
1001*e4b17023SJohn Marino /* Otherwise, convert non-ASCII characters in IDENT to UCNs. */
1002*e4b17023SJohn Marino {
1003*e4b17023SJohn Marino char *ret = (char *) identifier_to_locale_alloc (10 * idlen + 1);
1004*e4b17023SJohn Marino char *p = ret;
1005*e4b17023SJohn Marino for (i = 0; i < idlen;)
1006*e4b17023SJohn Marino {
1007*e4b17023SJohn Marino unsigned int c;
1008*e4b17023SJohn Marino size_t utf8_len = decode_utf8_char (&uid[i], idlen - i, &c);
1009*e4b17023SJohn Marino if (utf8_len == 1)
1010*e4b17023SJohn Marino *p++ = uid[i];
1011*e4b17023SJohn Marino else
1012*e4b17023SJohn Marino {
1013*e4b17023SJohn Marino sprintf (p, "\\U%08x", c);
1014*e4b17023SJohn Marino p += 10;
1015*e4b17023SJohn Marino }
1016*e4b17023SJohn Marino i += utf8_len;
1017*e4b17023SJohn Marino }
1018*e4b17023SJohn Marino *p = 0;
1019*e4b17023SJohn Marino return ret;
1020*e4b17023SJohn Marino }
1021*e4b17023SJohn Marino }
1022