GCC Wikia
Advertisement

このページを編集する際は,編集に関する方針に従ってください.[]

概要[]

引数[]

実装[]

 203 /* Formatting phases 1 and 2: render TEXT->format_spec plus
 204    TEXT->args_ptr into a series of chunks in PP->buffer->args[].
 205    Phase 3 is in pp_base_format_text.  */
206 
207 void
208 pp_base_format (pretty_printer *pp, text_info *text)
209 {
210   output_buffer *buffer = pp->buffer;
211   const char *p;
212   const char **args;
213   struct chunk_info *new_chunk_array;
214 
215   unsigned int curarg = 0, chunk = 0, argno;
216   pp_wrapping_mode_t old_wrapping_mode;
217   bool any_unnumbered = false, any_numbered = false;
218   const char **formatters[[[PP_NL_ARGMAX]]];
219 
 220   /* Allocate a new chunk structure.  */
221   new_chunk_array = XOBNEW (&buffer->chunk_obstack, struct chunk_info);
222   new_chunk_array->prev = buffer->cur_chunk_array;
223   buffer->cur_chunk_array = new_chunk_array;
224   args = new_chunk_array->args;
225 
 226   /* Formatting phase 1: split up TEXT->format_spec into chunks in
 227      PP->buffer->args[].  Even-numbered chunks are to be output
 228      verbatim, odd-numbered chunks are format specifiers.
 229      %m, %%, %<, %>, and %' are replaced with the appropriate text at
 230      this point.  */
231 
232   memset (formatters, 0, sizeof formatters);
233   
234   for (p = text->format_spec; *p; )
235     {
236       while (*p != '\0' && *p != '%')
237         {
238           obstack_1grow (&buffer->chunk_obstack, *p);
239           p++;
240         }
241 
242       if (*p == '\0')
243         break;
244 
 %のときの処理
245       switch (*++p)
246         {
247         case '\0':
248           gcc_unreachable ();
249           
250         case '%':
251           obstack_1grow (&buffer->chunk_obstack, '%');
252           p++;
253           continue;
254 
255         case '<':
256           obstack_grow (&buffer->chunk_obstack,
257                         open_quote, strlen (open_quote));
258           p++;
259           continue;
260 
261         case '>':
262         case '\:
263           obstack_grow (&buffer->chunk_obstack,
264                         close_quote, strlen (close_quote));
265           p++;
266           continue;
267 
268         case 'm':
269           {
270             const char *errstr = xstrerror (text->err_no);
271             obstack_grow (&buffer->chunk_obstack, errstr, strlen (errstr));
272           }
273           p++;
274           continue;
275 
276         default:
 277           /* Handled in phase 2.  Terminate the plain chunk here.  */
278           obstack_1grow (&buffer->chunk_obstack, '\0');
279           gcc_assert (chunk < PP_NL_ARGMAX * 2);
280           args[chunk++] = XOBFINISH (&buffer->chunk_obstack, const char *);
281           break;
282         }
283 
284       if (ISDIGIT (*p))
285         {
286           char *end;
287           argno = strtoul (p, &end, 10) - 1;
288           p = end;
289           gcc_assert (*p == '$');
290           p++;
291 
292           any_numbered = true;
293           gcc_assert (!any_unnumbered);
294         }
295       else
296         {
297           argno = curarg++;
298           any_unnumbered = true;
299           gcc_assert (!any_numbered);
300         }
301       gcc_assert (argno < PP_NL_ARGMAX);
302       gcc_assert (!formatters[argno]);
303       formatters[argno] = &args[chunk];
304       do
305         {
306           obstack_1grow (&buffer->chunk_obstack, *p);
307           p++;
308         }
309       while (strchr ("qwl+#", p[-1]));
310 
311       if (p[-1] == '.')
312         {
 313           /* We handle '%.Ns' and '%.*s' or '%M$.*N$s'
 314              (where M == N + 1).  */
315           if (ISDIGIT (*p))
316             {
317               do
318                 {
319                   obstack_1grow (&buffer->chunk_obstack, *p);
320                   p++;
321                 }
322               while (ISDIGIT (p[-1]));
323               gcc_assert (p[-1] == 's');
324             }
325           else
326             {
327               gcc_assert (*p == '*');
328               obstack_1grow (&buffer->chunk_obstack, '*');
329               p++;
330 
331               if (ISDIGIT (*p))
332                 {
333                   char *end;
334                   unsigned int argno2 = strtoul (p, &end, 10) - 1;
335                   p = end;
336                   gcc_assert (argno2 == argno - 1);
337                   gcc_assert (!any_unnumbered);
338                   gcc_assert (*p == '$');
339 
340                   p++;
341                   formatters[argno2] = formatters[argno];
342                 }
343               else
344                 {
345                   gcc_assert (!any_numbered);
346                   formatters[argno+1] = formatters[argno];
347                   curarg++;
348                 }
349               gcc_assert (*p == 's');
350               obstack_1grow (&buffer->chunk_obstack, 's');
351               p++;
352             }
353         }
354       if (*p == '\0')
355         break;
356 
357       obstack_1grow (&buffer->chunk_obstack, '\0');
358       gcc_assert (chunk < PP_NL_ARGMAX * 2);
359       args[chunk++] = XOBFINISH (&buffer->chunk_obstack, const char *);
360     }
361 
362   obstack_1grow (&buffer->chunk_obstack, '\0');
363   gcc_assert (chunk < PP_NL_ARGMAX * 2);
364   args[chunk++] = XOBFINISH (&buffer->chunk_obstack, const char *);
365   args[chunk] = 0;
366                   
 367   /* Set output to the argument obstack, and switch line-wrapping and
 368      prefixing off.  */
369   buffer->obstack = &buffer->chunk_obstack;
370   old_wrapping_mode = pp_set_verbatim_wrapping (pp);
371 
 372   /* Second phase.  Replace each formatter with the formatted text it
 373      corresponds to.  */
374 
375   for (argno = 0; formatters[argno]; argno++)
376     {
377       int precision = 0;
378       bool wide = false;
379       bool plus = false;
380       bool hash = false;
381       bool quote = false;
382 
 383       /* We do not attempt to enforce any ordering on the modifier
 384          characters.  */
385 
386       for (p = *formatters[argno];; p++)
387         {
388           switch (*p)
389             {
390             case 'q':
391               gcc_assert (!quote);
392               quote = true;
393               continue;
394 
395             case '+':
396               gcc_assert (!plus);
397               plus = true;
398               continue;
399 
400             case '#':
401               gcc_assert (!hash);
402               hash = true;
403               continue;
404 
405             case 'w':
406               gcc_assert (!wide);
407               wide = true;
408               continue;
409 
410             case 'l':
 411               /* We don't support precision beyond that of "long long".  */
412               gcc_assert (precision < 2);
413               precision++;
414               continue;
415             }
416           break;
417         }
418 
419       gcc_assert (!wide || precision == 0);
420 
421       if (quote)
422         pp_string (pp, open_quote);
423 
424       switch (*p)
425         {
426         case 'c':
427           pp_character (pp, va_arg (*text->args_ptr, int));
428           break;
429 
430         case 'd':
431         case 'i':
432           if (wide)
433             pp_wide_integer (pp, va_arg (*text->args_ptr, HOST_WIDE_INT));
434           else
435             pp_integer_with_precision
436               (pp, *text->args_ptr, precision, int, "d");
437           break;
438 
439         case 'o':
440           if (wide)
441             pp_scalar (pp, "%" HOST_WIDE_INT_PRINT "o",
442                        va_arg (*text->args_ptr, unsigned HOST_WIDE_INT));
443           else
444             pp_integer_with_precision
445               (pp, *text->args_ptr, precision, unsigned, "o");
446           break;
447 
448         case 's':
449           pp_string (pp, va_arg (*text->args_ptr, const char *));
450           break;

451 
452         case 'p':
453           pp_pointer (pp, va_arg (*text->args_ptr, void *));
454           break;
455 
456         case 'u':
457           if (wide)
458             pp_scalar (pp, HOST_WIDE_INT_PRINT_UNSIGNED,
459                        va_arg (*text->args_ptr, unsigned HOST_WIDE_INT));
460           else
461             pp_integer_with_precision
462               (pp, *text->args_ptr, precision, unsigned, "u");
463           break;
464 
465         case 'x':
466           if (wide)
467             pp_scalar (pp, HOST_WIDE_INT_PRINT_HEX,
468                        va_arg (*text->args_ptr, unsigned HOST_WIDE_INT));
469           else
470             pp_integer_with_precision
471               (pp, *text->args_ptr, precision, unsigned, "x");
472           break;
473 
474         case 'H':
475           {
476             location_t *locus = va_arg (*text->args_ptr, location_t *);
477             gcc_assert (text->locus != NULL);
478             *text->locus = *locus;
479           }
480           break;
481 
482         case 'J':
483           {
484             tree t = va_arg (*text->args_ptr, tree);
485             gcc_assert (text->locus != NULL);
486             *text->locus = DECL_SOURCE_LOCATION (t);
487           }
488           break;
489 
490         case '.':
491           {
492             int n;
493             const char *s;
494 
 495             /* We handle '%.Ns' and '%.*s' or '%M$.*N$s'
 496                (where M == N + 1).  The format string should be verified
 497                already from the first phase.  */
498             p++;
499             if (ISDIGIT (*p))
500               {
501                 char *end;
502                 n = strtoul (p, &end, 10);
503                 p = end;
504                 gcc_assert (*p == 's');
505               }
506             else
507               {
508                 gcc_assert (*p == '*');
509                 p++;
510                 gcc_assert (*p == 's');
511                 n = va_arg (*text->args_ptr, int);
512 
 513                 /* This consumes a second entry in the formatters array.  */
514                 gcc_assert (formatters[argno] == formatters[argno+1]);
515                 argno++;
516               }
517 
518             s = va_arg (*text->args_ptr, const char *);
519             pp_append_text (pp, s, s + n);
520           }
521           break;
522 
523         default:
524           {
525             bool ok;
526 
527             gcc_assert (pp_format_decoder (pp));
528             ok = pp_format_decoder (pp) (pp, text, p,
529                                          precision, wide, plus, hash);
530             gcc_assert (ok);
531           }
532         }
533 
534       if (quote)
535         pp_string (pp, close_quote);
536 
537       obstack_1grow (&buffer->chunk_obstack, '\0');
538       *formatters[argno] = XOBFINISH (&buffer->chunk_obstack, const char *);
539     }
540 
541 #ifdef ENABLE_CHECKING
542   for (; argno < PP_NL_ARGMAX; argno++)
543     gcc_assert (!formatters[argno]);
544 #endif
545 
 546   /* Revert to normal obstack and wrapping mode.  */
547   buffer->obstack = &buffer->formatted_obstack;
548   buffer->line_length = 0;
549   pp_wrapping_mode (pp) = old_wrapping_mode;
550   pp_clear_state (pp);
551 }


リンク元

Advertisement