This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: add "%J" for diagnostics (Redux. Positional format specifierfor diagnostic)


Gabriel Dos Reis wrote:
Richard Henderson <rth@redhat.com> writes:

| On Tue, Sep 23, 2003 at 06:58:33PM +0200, Gabriel Dos Reis wrote:
| > %H can appear anywhere in the text. If it is at the begining then it
| > indicates the prefix, otherwise it is handled as I inidicated, just
| > like any regular format specifier.
| | Then why do we do this?
| | /* Skip any leading text. */
| for (p = text->format_spec; *p && *p != '%'; ++p)
| ;


we should not have it. It mush have been a copy-n-paste error. Thanks,


I am attaching the diff for positional parameter support including "%J" hopefully.


As the preceding disucssion has revealed,
the handling of "%H" was a little  fishy BEFORE
my patch, too. We can try a format  string "... %H ..." that contains %H
in the middle of it, and the output looks a little out of place although
I kept the output format as is. (No one uses %H in the middle of a format
string anyway.)
In the presence of the positional format specifiers,
the first %H must be written as %$1H and
so the handling needs to take care of it.

Patch attached.


-- int main(void){int j=2003;/*(c)2003 cishikawa. */ char t[] ="<CI> @abcdefghijklmnopqrstuvwxyz.,\n\""; char *i ="g>qtCIuqivb,gCwe\np@.ietCIuqi\"tqkvv is>dnamz"; while(*i)((j+=strchr(t,*i++)-(int)t),(j%=sizeof t-1), (putchar(t[j])));return 0;}/* under GPL */
ChangeLog

2003-09-23    <ishikawa@yk.rim.or.jp>

	Positional format specifier support for 
	pp_format_text().	
	
	* pretty-print.h (struct): struct argtype_t, enum
	  arg_decode_action, struct text_info.
	  printer_fn takes extra argument of type  arg_decode_action.
	
	* pretty-print.c (pp_helper_abort): print the problematic format string
	  and abort.
	  (pp_type_width): returns the argument width based
	  on format specifier type.
	  (pp_compatible_and_has_same_width): check if the double use of
	  an argument uses the same type and width.
	  (set_argument_type_with_precision): store the argument type in 
	  a static array.
	  (set_argument_type): store the argument type without precision.
	  (pp_integer_with_precision_NEW): Macro based on the
	  original pp_integer_with_precision. Uses the created argument
	  array to fetch the value.
	  (pp_build_argument_array): build an array of argument to support
	  positional format specifier.
	  (pp_format_text): modified to work with the positional format
	  specifier support. %H no longer prints output.
	
	* c-objc-common.c (c_tree_printer): takes extra argument of type
	  arg_decode_action. Modified to support four actions.

	* toplev.c (default_tree_printer): ditto.
	
	* cp/error.c (cp_printer) : ditto
	
	* diagnostic.c (text_specifies_location): 
	  check for "%1$H" as well as for "%H". Restores the pointer.
	  '%H' is now retained by text_specifies_location. 
	  Similar handling for the newly introduced '%J'.
	  diagnostic_J_tree2locus() added.	

cp/ChangeLog
2003-09-18    <ishikawa@yk.rim.or.jp>

	Positional format specifier support for 
	pp_format_text().	
	
        * error.c (cp_printer):  takes extra argument of type
	  arg_decode_action. Modified to support four actions.




Index: gcc/c-objc-common.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/c-objc-common.c,v
retrieving revision 1.35
diff -c -3 -p -r1.35 c-objc-common.c
*** gcc/c-objc-common.c	21 Sep 2003 05:07:09 -0000	1.35
--- gcc/c-objc-common.c	23 Sep 2003 18:11:27 -0000
*************** Software Foundation, 59 Temple Place - S
*** 39,45 ****
  #include "target.h"
  #include "cgraph.h"
  
! static bool c_tree_printer (pretty_printer *, text_info *);
  static tree start_cdtor (int);
  static void finish_cdtor (tree);
  
--- 39,45 ----
  #include "target.h"
  #include "cgraph.h"
  
! static bool c_tree_printer (pretty_printer *, text_info *, arg_decode_action);
  static tree start_cdtor (int);
  static void finish_cdtor (tree);
  
*************** c_objc_common_finish_file (void)
*** 288,321 ****
     These format specifiers form a subset of the format specifiers set used
     by the C++ front-end.
     Please notice when called, the `%' part was already skipped by the
!    diagnostic machinery.  */
  static bool
! c_tree_printer (pretty_printer *pp, text_info *text)
  {
!   tree t = va_arg (*text->args_ptr, tree);
  
!   switch (*text->format_spec)
      {
-     case 'D':
-     case 'F':
-     case 'T':
-       {
-         const char *n = DECL_NAME (t)
-           ? (*lang_hooks.decl_printable_name) (t, 2)
-           : "({anonymous})";
-         pp_string (pp, n);
-       }
-       return true;
  
!     case 'E':
!        if (TREE_CODE (t) == IDENTIFIER_NODE)
!          {
!            pp_string (pp, IDENTIFIER_POINTER (t));
!            return true;
!          }
!        return false;
  
!     default:
!       return false;
      }
  }
--- 288,396 ----
     These format specifiers form a subset of the format specifiers set used
     by the C++ front-end.
     Please notice when called, the `%' part was already skipped by the
!    diagnostic machinery.  
! 
! 
!    Additional comment about support for positional parameters.
! 
!    Modifying c_tree_printer to support positional parameters was
!    relatively easy.
!    Reasons why.
! 
!    (1) Only a single format character is used as opposed to 
!        multi-character sequence.
! 
!    (2) Value fetched from the argument list is of only ONE type, namely
!        "tree".
! 
!    Below, I play fast and loose in handling of 'E' format.
!    I don't return "false" to indicate error until
!    PRINT_ARG_VALUE is requested, and the TREE value is not
!    found to be IDENTIFIER_NODE.
!    This is because I know for certain that the any error is
!    eventually caught during the processing of PRINT_ARG_VALUE.
!    No need to complicate processing during
!      - GET_ARG_TYPE, and 
!      - COPY_ARG_VALUE. */
  static bool
! c_tree_printer (pretty_printer *pp, text_info *text, arg_decode_action a)
  {
!   tree t;
! 
  
!   if (a == PRINT_ARG_VALUE_AS_BEFORE 
!      || a == PRINT_ARG_VALUE)	
!     {
!       if (a == PRINT_ARG_VALUE)
! 	t = (tree) text->arg_array[text->index_num].v.ptr;
!       else
! 	t = va_arg (*text->args_ptr, tree);
! 
!       switch (*text->format_spec)
! 	{
! 	case 'D':
! 	case 'F':
! 	case 'T':
! 	  {
! 	    const char *n = DECL_NAME (t)
! 	      ? (*lang_hooks.decl_printable_name) (t, 2)
! 	      : "({anonymous})";
! 	    pp_string (pp, n);
! 	  }
! 	  return true;
! 
! 	case 'E':
! 	  if (TREE_CODE (t) == IDENTIFIER_NODE)
! 	    {
! 	      pp_string (pp, IDENTIFIER_POINTER (t));
! 	      return true;
! 	    }
! 	  return false;
! 
! 	default:
! 	  return false;
! 	}
!     }
!   else if (a == GET_ARG_TYPE)
      {
  
!       text->bump_format = 0;
!       switch (*text->format_after_percent_or_dollar)
! 	{
! 	case 'D':
! 	case 'F':
! 	case 'T':
! 	case 'E':
! 	  text->bump_format = 1;
! 	  text->arg_array[text->index_num].custom_format[0]
! 	    = *text->format_after_percent_or_dollar;
! 	  return true;
! 	default:
! 	  return false;
! 	}
!     }
!   else if (a == COPY_ARG_VALUE)
!     {
! 
!       text->arg_array[text->index_num].v.ptr 
! 	= (void *) va_arg (*text->args_ptr, tree);
  
!       text->bump_format = 1;	/* we know it is 1 at most. */
!       switch (*text->format_after_percent_or_dollar)
! 	{
! 	case 'D':
! 	case 'F':
! 	case 'T':
! 	  return true;
! 
! 	case 'E':
! 	  return true;
! 	default:
! 	  return false;
! 	}
      }
+   else 
+     abort ();
+ 
+   return false;
  }
Index: gcc/diagnostic.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/diagnostic.c,v
retrieving revision 1.133
diff -c -3 -p -r1.133 diagnostic.c
*** gcc/diagnostic.c	22 Sep 2003 05:09:12 -0000	1.133
--- gcc/diagnostic.c	23 Sep 2003 18:11:28 -0000
*************** diagnostic_initialize (diagnostic_contex
*** 118,126 ****
    context->x_data = NULL;
  }
  
  /* Returns true if the next format specifier in TEXT is a format specifier
     for a location_t.  If so, update the object pointed by LOCUS to reflect
!    the specified location in *TEXT->args_ptr.  */
  static bool
  text_specifies_location (text_info *text, location_t *locus)
  {
--- 118,144 ----
    context->x_data = NULL;
  }
  
+ /* Returns location_t struct from a tree node for a
+    declaration. Called from within pretty-print.c.
+    This function is here so that pretty-print.c itself is
+    free of tree-related typedefs, etc. necessary for DECL_SOURCE_LOCATION. */
+ location_t 
+ diagnostic_J_tree2locus (tree t)
+ {
+   return DECL_SOURCE_LOCATION (t);
+ }
+ 
  /* Returns true if the next format specifier in TEXT is a format specifier
     for a location_t.  If so, update the object pointed by LOCUS to reflect
!    the specified location in *TEXT->args_ptr.  
! 
!    To bring consistency to positional format specifier support,
!    we restore the original args_ptr before returning
!    so that the subsequent call to pp_text_format() can access %H (or %1$H).
!    and  we don't remove the %H reference.
! 
!    pp_format_text() doesn't formats/prints the first %H reference.
!    It merely bumps the arg pointer. */
  static bool
  text_specifies_location (text_info *text, location_t *locus)
  {
*************** text_specifies_location (text_info *text
*** 129,152 ****
    for (p = text->format_spec; *p && *p != '%'; ++p)
      ;
  
!   /* Extract the location information if any.  */
!   if (p[0] == '%' && p[1] == 'H')
      {
        *locus = *va_arg (*text->args_ptr, location_t *);
!       text->format_spec = p + 2;
        return true;
      }
!   else if (p[0] == '%' && p[1] == 'J')
      {
        tree t = va_arg (*text->args_ptr, tree);
        *locus = DECL_SOURCE_LOCATION (t);
!       text->format_spec = p + 2;
        return true;
      }
  
    return false;
  }
  
  void
  diagnostic_set_info (diagnostic_info *diagnostic, const char *msgid,
  		     va_list *args, location_t location,
--- 147,181 ----
    for (p = text->format_spec; *p && *p != '%'; ++p)
      ;
  
!   /* assert *p == NUL 
!      || *p == '%' */
! 
!   /* Extract the location information if any.  
!      We now match either %H or %1$H, and
!      don't skip in the format_spec either. */
! 
!   if (strncmp (p, "%H", 2) == 0
!       || strncmp (p, "%1$H", 4) == 0)
      {
+       va_list saved_ptr =  *text->args_ptr; /* save */
        *locus = *va_arg (*text->args_ptr, location_t *);
!       *text->args_ptr = saved_ptr; /* restore */
        return true;
      }
!   else if (    strncmp (p, "%J",   2)   == 0
! 	    || strncmp (p, "%1$J", 4) == 0 )
      {
+       va_list saved_ptr =  *text->args_ptr; /* save */
        tree t = va_arg (*text->args_ptr, tree);
        *locus = DECL_SOURCE_LOCATION (t);
!       *text->args_ptr = saved_ptr; /* restore */
        return true;
      }
  
    return false;
  }
  
+ 
  void
  diagnostic_set_info (diagnostic_info *diagnostic, const char *msgid,
  		     va_list *args, location_t location,
*************** fnotice (FILE *file, const char *msgid, 
*** 562,568 ****
     so give up now.  But do try to flush out the previous error.
     This mustn't use internal_error, that will cause infinite recursion.  */
  
! static void
  error_recursion (diagnostic_context *context)
  {
    if (context->lock < 3)
--- 591,597 ----
     so give up now.  But do try to flush out the previous error.
     This mustn't use internal_error, that will cause infinite recursion.  */
  
! void
  error_recursion (diagnostic_context *context)
  {
    if (context->lock < 3)
Index: gcc/diagnostic.h
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/diagnostic.h,v
retrieving revision 1.66
diff -c -3 -p -r1.66 diagnostic.h
*** gcc/diagnostic.h	22 Aug 2003 06:25:08 -0000	1.66
--- gcc/diagnostic.h	23 Sep 2003 18:11:28 -0000
*************** extern char *diagnostic_build_prefix (di
*** 182,185 ****
--- 182,189 ----
  extern void verbatim (const char *, ...);
  extern char *file_name_as_prefix (const char *);
  
+ extern location_t diagnostic_J_tree2locus (tree t);
+ 
+ 
+ 
  #endif /* ! GCC_DIAGNOSTIC_H */
Index: gcc/pretty-print.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/pretty-print.c,v
retrieving revision 2.6
diff -c -3 -p -r2.6 pretty-print.c
*** gcc/pretty-print.c	12 Sep 2003 23:47:01 -0000	2.6
--- gcc/pretty-print.c	23 Sep 2003 18:11:30 -0000
*************** Software Foundation, 59 Temple Place - S
*** 26,31 ****
--- 26,33 ----
  #include "coretypes.h"
  #include "pretty-print.h"
  
+ #include <ctype.h>
+ 
  #define obstack_chunk_alloc xmalloc
  #define obstack_chunk_free  free
  
*************** Software Foundation, 59 Temple Place - S
*** 58,63 ****
--- 60,67 ----
    while (0)
  
  
+ 
+ 
  /* Subroutine of pp_set_maximum_length.  Set up PRETTY-PRINTER's
     internal maximum characters per line.  */
  static void
*************** pp_base_indent (pretty_printer *pp)
*** 164,169 ****
--- 168,787 ----
      pp_space (pp);
  }
  
+ 
+ /*  ========================================
+     Supporting positional format specifiers a la 
+     %2$d, %1$d, %3$c, etc..
+     ======================================== */
+ #define UNDEFINED_FORMAT 0
+ #define LOCATION_T_TYPE 1001
+ #define LOCATION_D_TYPE 1002	/* for DECL_SOURCE_LOCATION,  %J */
+ 
+ /* Aborting with error message and the format string that caused it. */
+ static void pp_helper_abort (const char *a, text_info *text)
+ {
+   fprintf (stderr, "Problem with output formatting: %s\n", a);
+   fprintf (stderr, "format=<<%s>>\n", text->original_format_spec);
+ #ifdef ENABLE_CHECKING
+   abort ();
+ #endif
+ }
+ 
+ /*   type compatibility info for %d$c processing.
+    Check is based only on the width, i.e., sizeof (t).
+ 
+    The whole scheme does not feel quit right in that 
+    it is not quite clear whether %lld, %ld, and/or %d  should
+    be compatible with HOST_WIDE_INT. 
+    But it works. */
+ static int pp_type_width (int t)
+ {
+   switch (t)
+     {
+     default:
+       fprintf (stderr, "pp_type_width: unknown type spec. %d\n", t);
+       abort ();
+       break;
+ 
+     case 's': return sizeof (char *); 
+ 
+     case 'c': return sizeof (int);
+ 
+     case 'i':
+     case 'd': return sizeof (int);
+ 
+       /* HOST_WIDE_INT may be blank "" on some systems such as x86 
+          So we use 'W' to stand for it. */
+     case 'W' /* for HOST_WIDE_INT */ : return  sizeof (long); 
+ 
+     case 'U' /* UNSIGNED_HOST_WIDE_INT */ : return sizeof (unsigned long int);
+ 
+     case 'x':
+     case 'u': 
+     case 'o': return sizeof (unsigned int) ;
+ 
+     case 'p': return sizeof (void *);
+ 
+     case LOCATION_D_TYPE: return sizeof (void *);
+ 
+     case LOCATION_T_TYPE: return sizeof (void *);
+     }
+ 
+   /* NOTREACHED */
+   abort ();
+ }
+ 
+ /* if an argument is referenced twice, we
+   say, the references are compatible if the type (width)
+  is the same, and its precisions are the same.
+ 
+  E.g. %1$d and %1$lld is not considered compatible. */
+ static int
+ pp_compatible_and_has_same_width (int t, int prec1, int u, int prec2)
+ {
+   return pp_type_width (t) == pp_type_width (u)
+     && prec1 == prec2 ;
+ }
+ 
+ 
+ /* store argument tye with precision. */
+ static void 
+ set_argument_type_with_precision (int i, int type, 
+ 				  int precision, text_info *text)
+ {
+   if (i <= 0 || i >= 10)
+     abort ();
+ 
+   if (precision < 0 || precision > 2)
+     abort ();
+ 
+   if (type == UNDEFINED_FORMAT)
+     abort ();
+ 
+   /* First definition/reference is OK. */
+   if (text->arg_array[i].typespec == UNDEFINED_FORMAT)
+     {
+       text->arg_array[i].typespec = type;
+       text->arg_array[i].precision = precision;
+ 
+       switch (precision)
+ 	{
+ 	default: abort ();
+ 
+ 	case 0:
+ 	  text->arg_array[i].format[0] = '%';
+ 	  text->arg_array[i].format[1] = type;
+ 	  break;
+ 
+ 	case 1:
+ 	  text->arg_array[i].format[0] = '%';
+ 	  text->arg_array[i].format[1] = 'l';
+ 	  text->arg_array[i].format[2] = type;
+ 	  break;
+ 
+ 	case 2:
+ 	  text->arg_array[i].format[0] = '%';
+ 	  text->arg_array[i].format[1] = 'l';
+ 	  text->arg_array[i].format[2] = 'l';
+ 	  text->arg_array[i].format[3] = type;
+ 	  break;
+ 	}
+ 
+       return;
+     }
+ 
+   /* Check the double definition */
+   if (pp_compatible_and_has_same_width
+        (text->arg_array[i].typespec, text->arg_array[i].precision, 
+ 	 type, precision))
+     return;
+   else
+     {
+       fprintf (stderr, "pretty-print.c: Specifying incompatible types for argument (at %d) twice\n", i);
+       fprintf (stderr, "format : <<%s>>\n", text->arg_array[0].v.cptr);
+ #ifdef ENABLE_CHECKING
+       abort ();      	
+ #endif
+     }
+ } 
+ 
+ /* store argument type (without precision.) */
+ static void 
+ set_argument_type (int i, int type, text_info *text)
+ {
+   /* precision is 0 */
+   set_argument_type_with_precision (i, type, 0, text);
+ }
+ 
+ 
+ /* we define the format string to be used
+    at the time of first scan (for types) 
+    by calling set_argument_type_with_precision, 
+    and do away with the dynamic construction of "%" F, "%l", F, "%ll", F
+    in pp_integer_with_precision. 
+ 
+    Assumption. This is used ONLY for
+    'd', 'i', 'x', 'o', 'u', that is for value meant to be numbers.
+    So I use i, li, and lli fields.
+    CAVEAT: I am making an assumption that
+    long long int, and long long unsigned uses a same size
+    memory cell. This seems reasonable.
+ 
+    arg_array[ind] holds the value, format, and precision. */ 
+ 
+ 
+ #define pp_integer_with_precision_NEW(PP, ind, text)  		\
+   do                                                            \
+     switch (text->arg_array[ind].precision)                     \
+       {                                                         \
+       case 0:                                                   \
+         pp_scalar                                 		\
+           (PP, text->arg_array[ind].format, text->arg_array[ind].v.i);  \
+         break;                                                  \
+                                                                 \
+       case 1:                                                   \
+         pp_scalar                                 		\
+           (PP, text->arg_array[ind].format, text->arg_array[ind].v.l);  \
+         break;                                                  \
+                                                                 \
+       case 2:                                                   \
+         pp_scalar                                 		\
+           (PP, text->arg_array[ind].format, text->arg_array[ind].v.ll); \
+         break;                                                  \
+                                                                 \
+       default:                                                  \
+         abort (); break;                                         \
+       }                                                         \
+   while (0)
+ 
+ 
+ /* Build argument array to support format specifiers in the form 
+  of %1$s, %2$d %3$d, etc. */
+ static void 
+ pp_build_argument_array (const char * format, 
+ 			 pretty_printer *pp, text_info *text)
+ {
+   int arg_index = 0;
+   int i;
+   int has_seen_number = 0;	/* have we seen "n$" in %n$d? */
+   
+   text->arg_max = 0;
+ 
+   memset (text->arg_array, 
+ 	 0, sizeof (text->arg_array)); /* fill in zero. UNDEFINED_FORMAT. */
+ 
+   text->arg_array[0].v.cptr = (char *) format; /* record for error message. */
+ 
+   /* loop through the string just looking for the type
+      Note that the variable, format, changes its value in this loop. */
+   for (; *format; ++format)
+     {
+       int precision = 0;
+       bool wide = false;
+ 
+       has_seen_number = 0;
+ 
+       /*  "Ignore text." while we build the array.  */
+       {
+ 	const char *p = format;
+ 	while (*p && *p != '%')
+ 	  ++p;
+         format = p;
+       }
+ 
+       /* assert:    format == '\0'
+ 	 || format == '%'
+       */
+ 
+       if (*format == '\0') /* we are at the end. Finish */
+ 	break;
+ 
+       /* We got a '%'.  Parse precision modifiers, if any.  
+          We also need to handle [0-9] as in %1$d */
+ 
+       /* assert:    
+ 	 we have  % [non-digit]
+ 	 || we have  % [digit] $    */
+ 
+       if (isdigit (format[1]))
+ 	{
+ 	  /* %1$ ... */
+ 	  if (format[2] == '$')
+ 	    {
+ 	      char tmp[2];
+ 
+ 	      tmp[1] = '\0';
+ 	      tmp[0] = format[1];
+ 	      arg_index = atoi (tmp);
+ 
+ 	      if (arg_index == 0)
+ 		{
+ 		  pp_helper_abort ("The digit that comes after % must be non-zero.",  text);
+ 		}
+ 
+ 	      if (text->arg_max < arg_index)
+ 		text->arg_max = arg_index;
+ 
+ 	      has_seen_number = 1;
+ 
+ 	      format += 2;
+ 	    }
+ 	  else  /* We expected '$' after "%1" */
+ 	    {
+ 	      if (isdigit (format[2]))
+ 		pp_helper_abort ("we handle only 1-9 in %%d$ as of now.\n", text);
+ 	      else
+ 		pp_helper_abort ("We expected '$' after %% and digit as in '%%1$'", text);
+ 	    }
+ 	}
+ 
+       /* assert:    
+ 	 format points at the % in   % [non-digit]
+ 	 || format points at the $ in   % [digit] $    */
+ 
+       switch (*++format)
+         {
+         case 'w':
+           wide = true;
+           ++format;
+           break;
+ 
+         case 'l':
+           do
+             ++precision;
+           while (*++format == 'l');
+           break;
+ 
+ 
+         default:
+           break;
+         }
+ 
+       /* We don't support precision behond that of "long long".  */
+       if (precision > 2)
+ 	pp_helper_abort ("We don't support precision behond that of \"long long\" ", text);
+ 
+       if (arg_index >= 10 || arg_index < 0)
+ 	abort ();
+ 
+       if (!has_seen_number && ! (*format == '%' || *format == 'm'))
+ 	{
+ 	  pp_helper_abort ("Use %n$c form specifier in ALL places except for % (percent sign) and %m.", text);
+ 	}
+ 
+       switch (*format)
+ 	{
+ 	case 'c':
+ 	  set_argument_type (arg_index, 'c', text);
+ 	  break;
+ 
+ 	case 'd':
+ 	case 'i':
+           if (wide)
+ 	    set_argument_type (arg_index, 'W' /* HOST_WIDE_INT*/, text);
+           else
+ 	    set_argument_type_with_precision (arg_index, 'd',  precision, text);
+ 	  break;
+ 
+ 	  /* TODO/FIXME long 'U', and long long 'U' can be
+ 	     used as in %lw %llw ?  */
+ 	case 'o':
+           if (wide)
+ 	    set_argument_type (arg_index, 'U' /*UNSIGNED_HOST_WIDE_INT*/, text) ;
+           else
+ 	    set_argument_type_with_precision (arg_index, 'o', precision, text);
+ 	  break;
+ 
+ 	case 's':
+ 	  set_argument_type (arg_index, 's', text); /* char *ptr */
+ 	  break;
+ 
+         case 'p':
+ 	  set_argument_type (arg_index, 'p', text); /* void *p */
+           break;
+ 
+ 	case 'u': /* now we must split this from 'x' to handle
+                      precision string processing. */
+           if (wide)
+ 	    set_argument_type (arg_index, 'U' /*UNSIGNED_HOST_WIDE_INT*/, text);
+           else
+ 	    set_argument_type_with_precision (arg_index,  'u', precision, text);
+ 	  break;
+ 
+ 
+ 	case 'x':
+           if (wide)
+ 	    set_argument_type (arg_index, 'U' /*UNSIGNED_HOST_WIDE_INT*/, text);
+           else
+ 	    set_argument_type_with_precision (arg_index,  'x', precision, text);
+ 	  break;
+ 
+ 	case 'm': /* error code: handles separately. */
+ 	  break;
+ 
+ 	case '%': /* % character */
+ 
+ 	  if (format[-1] != '%')
+ 	    {
+ 	      /* Before we catch this, we saw subtle Error as in:
+ 		argument at 1 not specified in format string. <<pointer=%3$p, char=%1$%c, integer=%4$d
+ 		
+ 		%1$%c is handled as if it were %%c and thus 
+ 		no information about argument was recorded. */
+ 
+ 	      fprintf (stderr, "cf. char=%%1$%%c is handled as if it were char %%%%c\n");
+ 	      fprintf (stderr, "That is, 1$ is ignored when the second %% is seen.\n");
+ 
+ 	      pp_helper_abort ("We should have a consecutive % s ", text);
+ 
+ 	    }
+ 
+ 	  break;
+ 
+ 	case 'J': 
+ 	  set_argument_type (arg_index, LOCATION_D_TYPE, text);
+ 	  break;
+ 
+         case 'H':
+ 	  set_argument_type (arg_index, LOCATION_T_TYPE, text);
+           break;
+ 
+ 	case '.':  /* Either  %.*s, orpositional paraeter as in
+ 		      %1$.*3$s ... 1st argument with the
+ 	              width given by the third argument. */
+ 	  {
+ 	    /* From SUS.
+ 	    The precision takes the form of a period ( '.' ) followed
+ 	    either by an asterisk ( '*' ), described below, or an
+ 	    optional decimal digit string, where a null digit string is
+ 	    treated as zero.  
+ 
+ 	    [...]  
+ 
+ 	    In format strings containing the "%n$" form of a
+ 	    conversion specification, a field width or precision may
+ 	    be indicated by the sequence "*m$", where m is a decimal
+ 	    integer in the range [1,{NL_ARGMAX}] giving the position
+ 	    in the argument list (after the format argument) of an
+ 	    integer argument containing the field width or
+ 	    precision,  */
+ 
+ 
+ 	    /* We handle no precision specifier except for string type
+ 	       as in `%.*s'.  
+ 	       pp_build_argument_array () is called when positional
+ 	       specifier of the form %n$ is used and 
+ 	       so the width also needs to be specified as *m$ ! */
+ 	    
+ 	    if (*++format != '*')
+ 	      pp_helper_abort ("We expected '*' after '.'", text);
+ 	    else 
+ 	      { /* we handle only %d$.*m$s : we have seen "*". */ 
+ 		int a;
+ 		char tmp[2];
+ 		int c;
+ 		c = *++format;
+ 		if (!isdigit (c))
+  		  pp_helper_abort ("We expected a digit after '*'", text);
+ 		tmp[0] = c; 
+ 		tmp[1] = '\0';
+ 		a = atoi (tmp);
+ 		if (a == 0)
+ 		  pp_helper_abort ("The digit that comes after % must be non-zero.\n",  text);
+ 		if (text->arg_max < a) 
+ 		  text->arg_max = a;
+ 		if (text->arg_max < arg_index)
+ 		  text->arg_max = arg_index;
+ 
+ 		set_argument_type (a, 'd', text); /* host int */
+ 		set_argument_type (arg_index, 's', text);
+ 	      }
+ 	  }
+ 	  break;
+ 
+ 	default:
+ 
+ 	  /* Let us see if custom decoder installed can understand the
+ 	   format character. Custom format_decoder examples are as
+ 	   follows.  
+ 	   c_tree_printer in c-objc-common.c 
+ 	   cp_print in  cp/error.c 
+ 	   default_tree_printer in toplev.c */
+ 
+ 
+ 	  /* Set up for calling custom format decoder 
+ 	   with GET_ARG_TYPE action. */
+ 
+ 	  text->index_num = arg_index;
+ 	  text->format_after_percent_or_dollar = format;
+ 
+ 	  /* Save previously seen format, if any, for checking
+ 	     incompatible double references later. */
+ 	  memcpy (text->arg_array[0].custom_format,
+ 		 text->arg_array[arg_index].custom_format,
+ 		 sizeof (text->arg_array[0].custom_format));
+ 
+ 	  if (arg_index <= 0 || arg_index > 9)
+ 	    pp_helper_abort ("arg_index out of range.", text);
+ 
+ 	  if (!pp_format_decoder (pp)
+               || !(*pp_format_decoder (pp)) (pp, text, GET_ARG_TYPE))
+ 	    {
+ 	      /* Ugh. Error. */
+ 
+ 	      /* Hmmm.  The front-end failed to install a format translator
+                  but called us with an unrecognized format.  Or, maybe, the
+                  translated string just contains an invalid format, or
+                  has formats in the wrong order.  Sorry.  */
+ 	      pp_helper_abort ("Unrecognized format.", text);
+ 	    }
+ 
+ 	  /* Check for double definition for custom-extended format
+ 	     argument */
+ 	  
+ 	  if (text->arg_array[0].custom_format[0] == '\0')
+ 	    ; 			/* OK. It was the first reference. */
+ 	  else 
+ 	    {
+ 	      /* If the previously used type information `matches' with
+ 		 the latest type information, then the double usage is OK.
+  		 Otherwise, it is an error.
+ 
+ 		 Now the semantics of `match' is a little tricky to get right.
+ 		 We probably need to ask the format decoder to decide
+ 		 the compatibility of two different format strings.
+ 		
+ 		 As an initial implementation, we simply use the strncmp ()
+ 		 against the two format strings. */
+ 
+ 	      if (strncmp (text->arg_array[0].custom_format, 
+ 			 text->arg_array[arg_index].custom_format, 
+ 			 sizeof (text->arg_array[0].custom_format)) == 0)
+ 		;		/* OK */
+ 	      else 
+ 		{
+ 		  fprintf (stderr, "Specifying incompatible types for argument (at %d)\n", arg_index);
+ 		  fprintf (stderr, "format:<<%s>>\n", text->arg_array[0].v.cptr);
+ 		  abort ();      	
+ 		}
+ 
+ 	    }
+ 
+ 	  /* adjust the format pointer by the number of
+ 	     bytes understood by the custom decoder. */
+ 	  if (text->bump_format > 1)
+ 	    format += (text->bump_format - 1);
+ 		 
+ 	}
+ 	  
+     }
+ 
+ 
+   /* Now let us scan the argumet and fetch the value as specified by the type. 
+     NOTE: we start at position 1. */
+ 
+   for (i = 1; i <= text->arg_max; i++)
+     {
+       switch (text->arg_array[i].typespec)
+ 	{
+ 	case UNDEFINED_FORMAT:
+ 	  if (text->arg_array[i].custom_format[0] == '\0')
+ 	    {
+ 	      fprintf (stderr, "argument at %d not specified in format string. <<%s>>\n", i, text->arg_array[0].v.cptr);
+ 	      abort ();
+ 	    }
+ 	  else 	  /* handling custom extended format character */
+ 	    {
+ 	      /* setup for COPY_ARG_VALUE. */
+ 	      text->index_num = i;
+ 	      text->format_after_percent_or_dollar 
+ 		= text->arg_array[i].custom_format;
+ 
+ 	      if (!pp_format_decoder (pp) 
+ 		  || !(*pp_format_decoder (pp)) (pp, text,
+ 						 COPY_ARG_VALUE))
+ 		{
+ 		  pp_helper_abort ("Unrecognized format.", text);
+ 		}
+ 	    }
+ 
+ 	  break;
+ 
+ 	case 's': text->arg_array[i].v.cptr = (char *) va_arg (*text->args_ptr, const char *);
+ 	  break;
+ 
+ 	case 'i':
+ 	case 'd': 
+ 	  switch (text->arg_array[i].precision)
+ 	    {
+ 	    case 0:
+ 	      text->arg_array[i].v.i = va_arg (*text->args_ptr, int);
+ 	      break;
+ 	    case 1:	    
+ 	      text->arg_array[i].v.l = va_arg (*text->args_ptr, long int);
+ 	      break;
+ 	    case 2:
+ 	      text->arg_array[i].v.ll = va_arg (*text->args_ptr, long  long int);
+ 	      break;
+ 		    
+ 	    default: abort ();
+ 	    }
+ 	  break;
+ 
+ 	case 'c': text->arg_array[i].v.i = va_arg (*text->args_ptr, int);
+ 	  break;
+ 
+ 
+ 	case 'W'   /* We use 'W' for HOST_WIDE_INT */ : 
+ 	  text->arg_array[i].v.hwi = va_arg (*text->args_ptr, HOST_WIDE_INT);
+ 	  break;
+ 
+ 	case 'U' : /* We use 'U' for UNSIGNED_HOST_WIDE_INT*/
+ 	  text->arg_array[i].v.uhwi = va_arg (*text->args_ptr, unsigned HOST_WIDE_INT);
+ 	  break;
+ 
+ 	case 'x':
+ 	case 'u': 
+ 	case 'o': 
+ 	  switch (text->arg_array[i].precision)
+ 	    {
+ 	    case 0:	
+ 	      text->arg_array[i].v.ui = va_arg (*text->args_ptr, unsigned);
+ 	      break;
+ 	    case 1:	    
+ 	      text->arg_array[i].v.ul = va_arg (*text->args_ptr, long unsigned);
+ 	      break;
+ 	    case 2:
+ 	      text->arg_array[i].v.ull = va_arg (*text->args_ptr, long  long unsigned);
+ 	      break;
+ 	    default: abort ();
+ 
+ 	    }
+ 	  break;
+ 
+ 	case 'p': 
+ 	  text->arg_array[i].v.ptr = va_arg (*text->args_ptr, void *);
+ 	  break;
+ 
+ 	case LOCATION_D_TYPE: 
+ 	  text->arg_array[i].v.ptr = va_arg (*text->args_ptr, tree);
+ 	  break;
+ 
+ 	case LOCATION_T_TYPE: 
+ 	  text->arg_array[i].v.ptr = va_arg (*text->args_ptr, location_t *);
+ 	  break;
+ 
+ 	default:
+ 	  pp_helper_abort ("Unknown output specifier during value copy.", text);
+ 	}
+ 
+     }
+ 
+   /* We have established the type/value of arguments when we return. */
+   
+   return;
+ }
+ 
  /* Format a message pointed to by TEXT.  The following format specifiers are
     recognized as being client independent:
     %d, %i: (signed) integer in base ten.
*************** pp_base_indent (pretty_printer *pp)
*** 176,194 ****
     %c: character.
     %s: string.
     %p: pointer.
!    %m: strerror(text->err_no) - does not consume a value from args_ptr.
     %%: `%'.
     %*.s: a substring the length of which is specified by an integer.
!    %H: location_t.  */
! void
  pp_base_format_text (pretty_printer *pp, text_info *text)
  {
    for (; *text->format_spec; ++text->format_spec)
      {
        int precision = 0;
        bool wide = false;
  
!       /* Ignore text.  */
        {
  	const char *p = text->format_spec;
  	while (*p && *p != '%')
--- 794,823 ----
     %c: character.
     %s: string.
     %p: pointer.
!    %m: strerror (text->err_no) - does not consume a value from args_ptr.
     %%: `%'.
     %*.s: a substring the length of which is specified by an integer.
!    %H: location_t.  
! 
!    Addition: positional parameter.
!    %[0-9]${d,i,u,o,x,...,H}  */
! 
! void 
  pp_base_format_text (pretty_printer *pp, text_info *text)
  {
+   int arg_index = -1; 		/* for positional format specifier. */
+   int has_processed_one = 0;	/* has processed specifiers. (counter) */
+   int use_pos_specifier = 0;	/* %d$c form positional specifier was found. */
+ 
+   text->original_format_spec = text->format_spec; /* save the original. */
+ 
    for (; *text->format_spec; ++text->format_spec)
      {
        int precision = 0;
        bool wide = false;
  
!       /* Misleading old comment "Ignore text."  */
!       /* Rather We output text as is (!) */
        {
  	const char *p = text->format_spec;
  	while (*p && *p != '%')
*************** pp_base_format_text (pretty_printer *pp,
*** 197,206 ****
          text->format_spec = p;
        }
  
        if (*text->format_spec == '\0')
  	break;
  
!       /* We got a '%'.  Parse precision modifiers, if any.  */
        switch (*++text->format_spec)
          {
          case 'w':
--- 826,883 ----
          text->format_spec = p;
        }
  
+       /* assert:    text->format_spec == '\0'
+ 	 || text->format_spec == '%' */
+ 
        if (*text->format_spec == '\0')
  	break;
  
!       /* We got a '%'.  Parse precision modifiers, if any.  
! 	 We also need to handle [0-9] as in %1$d */
! 
!       if (isdigit (text->format_spec[1]))
! 	{
! 	  if (text->format_spec[2] == '$')
! 	    {
! 	      char tmp[2];
! 
! 	      tmp[1] = '\0';
! 	      tmp[0] = (text->format_spec)[1];
! 	      arg_index = atoi (tmp);
! 
! 	      if (arg_index == 0)
! 		pp_helper_abort ("The digit that comes after % must be non-zero.\n", text);
! 
! 	      if (!use_pos_specifier)
! 		{
! 		  if (has_processed_one > 1)
! 		    pp_helper_abort ("We can't mix %d and %n$d form\n", text);
! 		  pp_build_argument_array (text->original_format_spec, pp, text);
! 		}
! 	      use_pos_specifier = 1;
! 
! 	      /* after the above call to pp_build_argument_array (),
! 		 we know the value (and type) for each argument. */
! 
! 	      text->format_spec += 2;
! 
! 	    }
! 	  else 
! 	    {
! 	      /* we have seen % and digit as in '%1', 
! 		 but it is not followed by '$' */
! 
! 	      if (isdigit ((text->format_spec)[2]))
! 		pp_helper_abort ("we handle only 1-9 in %d$ style positional parameter.\n", text);
! 	      else 
! 		pp_helper_abort ("we have seen a percent sign followed by a digit, but it is not followed by '$'\n", text);
! 	    }
! 	}
! 
!       /* assert:
! 	 text->format_spec points at % as in % [non-digit]
! 	 || text->format_spec points at $ as in % [digit] $    */
! 
        switch (*++text->format_spec)
          {
          case 'w':
*************** pp_base_format_text (pretty_printer *pp,
*** 219,325 ****
          }
        /* We don't support precision beyond that of "long long".  */
        if (precision > 2)
!         abort();
  
        switch (*text->format_spec)
  	{
  	case 'c':
! 	  pp_character (pp, va_arg (*text->args_ptr, int));
  	  break;
  
  	case 'd':
  	case 'i':
            if (wide)
!             pp_wide_integer (pp, va_arg (*text->args_ptr, HOST_WIDE_INT));
            else
!             pp_integer_with_precision
!               (pp, *text->args_ptr, precision, int, "d");
  	  break;
  
  	case 'o':
!           if (wide)
!             pp_scalar (pp, "%" HOST_WIDE_INT_PRINT "o",
!                        va_arg (*text->args_ptr, unsigned HOST_WIDE_INT));
!           else
!             pp_integer_with_precision
!               (pp, *text->args_ptr, precision, unsigned, "u");
  	  break;
  
  	case 's':
! 	  pp_string (pp, va_arg (*text->args_ptr, const char *));
  	  break;
  
          case 'p':
!           pp_pointer (pp, va_arg (*text->args_ptr, void *));
            break;
  
  	case 'u':
            if (wide)
!             pp_scalar (pp, HOST_WIDE_INT_PRINT_UNSIGNED,
!                        va_arg (*text->args_ptr, unsigned HOST_WIDE_INT));
            else
!             pp_integer_with_precision
!               (pp, *text->args_ptr, precision, unsigned, "u");
  	  break;
  
  	case 'x':
            if (wide)
!             pp_scalar (pp, HOST_WIDE_INT_PRINT_HEX,
!                        va_arg (*text->args_ptr, unsigned HOST_WIDE_INT));
            else
!             pp_integer_with_precision
!               (pp, *text->args_ptr, precision, unsigned, "x");
  	  break;
  
  	case 'm':
  	  pp_string (pp, xstrerror (text->err_no));
  	  break;
  
  	case '%':
  	  pp_character (pp, '%');
  	  break;
  
          case 'H':
            {
!             const location_t *locus = va_arg (*text->args_ptr, location_t *);
!             pp_string (pp, "file '");
!             pp_string (pp, locus->file);
!             pp_string (pp, "', line ");
!             pp_decimal_int (pp, locus->line);
            }
            break;
  
  	case '.':
! 	  {
! 	    int n;
! 	    const char *s;
! 	    /* We handle no precision specifier but `%.*s'.  */
! 	    if (*++text->format_spec != '*')
! 	      abort ();
! 	    else if (*++text->format_spec != 's')
! 	      abort ();
! 	    n = va_arg (*text->args_ptr, int);
! 	    s = va_arg (*text->args_ptr, const char *);
! 	    pp_append_text (pp, s, s + n);
! 	  }
  	  break;
  
  	default:
!           if (!pp_format_decoder (pp) || !(*pp_format_decoder (pp)) (pp, text))
  	    {
  	      /* Hmmm.  The client failed to install a format translator
                   but called us with an unrecognized format.  Or, maybe, the
                   translated string just contains an invalid format, or
                   has formats in the wrong order.  Sorry.  */
! 	      abort ();
  	    }
  	}
      }
  }
  
  /* Helper subroutine of output_verbatim and verbatim. Do the appropriate
     settings needed by BUFFER for a verbatim formatting.  */
! void
  pp_base_format_verbatim (pretty_printer *pp, text_info *text)
  {
    diagnostic_prefixing_rule_t rule = pp_prefixing_rule (pp);
--- 896,1170 ----
          }
        /* We don't support precision beyond that of "long long".  */
        if (precision > 2)
!         pp_helper_abort ("Too many precision 'l' specfied.", text);
! 
!       if (use_pos_specifier
! 	  && (arg_index <= 0 || arg_index > 9))
! 	pp_helper_abort ("Argument index out of range.\n", text);
! 
  
        switch (*text->format_spec)
  	{
  	case 'c':
! 	  if (!use_pos_specifier) 
! 	    pp_character (pp, va_arg (*text->args_ptr, int)) ;
! 	  else
! 	    pp_character (pp, text->arg_array[arg_index].v.i);
  	  break;
  
  	case 'd':
  	case 'i':
            if (wide)
! 	    {
! 	      if (!use_pos_specifier)
! 		pp_wide_integer (pp, va_arg (*text->args_ptr, HOST_WIDE_INT)); 
! 	      else
! 		pp_wide_integer (pp, text->arg_array[arg_index].v.hwi);
! 	    }
            else
! 	    {
! 	      if (use_pos_specifier)
! 		pp_integer_with_precision_NEW (pp, arg_index, text);
! 	      else
! 		pp_integer_with_precision
! 		  (pp, *text->args_ptr, precision, int, "d");
! 	    }
  	  break;
  
  	case 'o':
! 	  if (!use_pos_specifier)
! 	    {
! 	      if (wide)
! 		pp_scalar (pp, "%" HOST_WIDE_INT_PRINT "o",
! 			   va_arg (*text->args_ptr, unsigned HOST_WIDE_INT));
! 	      else
! 		pp_integer_with_precision
! 		  (pp, *text->args_ptr, precision, unsigned, "u");
! 	    }
! 	  else 
! 	    {
! 	      if (wide)
! 		pp_scalar (pp, "%" HOST_WIDE_INT_PRINT "o",
! 			   text->arg_array[arg_index].v.uhwi);
! 	      else
! 		pp_integer_with_precision_NEW
! 		  (pp, arg_index, text);
! 
! 	    }
  	  break;
  
  	case 's':
! 	  if (!use_pos_specifier)
! 	    pp_string (pp, va_arg (*text->args_ptr, const char *));
! 	  else
! 	    pp_string (pp, text->arg_array[arg_index].v.cptr);
  	  break;
  
          case 'p':
! 	  if (!use_pos_specifier)
! 	    pp_pointer (pp, va_arg (*text->args_ptr, void *));
! 	  else
! 	    pp_pointer (pp, text->arg_array[arg_index].v.ptr);
            break;
  
  	case 'u':
            if (wide)
! 	    {
! 	      if (!use_pos_specifier) 
! 		pp_scalar (pp, HOST_WIDE_INT_PRINT_UNSIGNED,
! 			   va_arg (*text->args_ptr, unsigned HOST_WIDE_INT));
! 	      else
! 		pp_scalar (pp, HOST_WIDE_INT_PRINT_UNSIGNED,
! 			   text->arg_array[arg_index].v.uhwi);
! 	    }
            else
! 	    {
! 	      if (!use_pos_specifier)
! 		pp_integer_with_precision
! 		  (pp, *text->args_ptr, precision, unsigned, "u");
! 	      else
! 		pp_integer_with_precision_NEW
! 		  (pp, arg_index, text);
! 	    }
  	  break;
  
  	case 'x':
            if (wide)
! 	    {
! 	      if (!use_pos_specifier) 
! 		pp_scalar (pp, HOST_WIDE_INT_PRINT_HEX,
! 			   va_arg (*text->args_ptr, unsigned HOST_WIDE_INT));
! 	      else
! 		pp_scalar (pp, HOST_WIDE_INT_PRINT_HEX,
! 			   text->arg_array[arg_index].v.uhwi);
! 	    }
            else
! 	    {
! 	      if (!use_pos_specifier)
! 		pp_integer_with_precision
! 		  (pp, *text->args_ptr, precision, unsigned, "x");
! 	      else
! 		pp_integer_with_precision_NEW
! 		  (pp, arg_index, text);
! 	    }
  	  break;
  
  	case 'm':
  	  pp_string (pp, xstrerror (text->err_no));
+ 	  has_processed_one --;	/* Adjust. we don't want to count this.   */
  	  break;
  
  	case '%':
  	  pp_character (pp, '%');
+ 	  has_processed_one --;	/* Adjust. we don't want to count this.   */
  	  break;
  
+ 	  /* In the following, the reference to %H should be taken to
+ 	     include the reference to "%J" as well. */
+ 	case 'J':
          case 'H':
            {
!             const location_t *locus;
! 	    static location_t l_locus;
! 
! 	    if (*text->format_spec == 'H')
! 	      {
! 		if (!use_pos_specifier)
! 		  locus = va_arg (*text->args_ptr, location_t *);
! 		else
! 		  locus = (location_t *) text->arg_array[arg_index].v.ptr;
! 	      }
! 	    else if (*text->format_spec == 'J')
! 	      {
! 		tree np;
! 		if (!use_pos_specifier)
! 		  {
! 		    np =  va_arg (*text->args_ptr, tree);
! 		    l_locus = diagnostic_J_tree2locus (np);
! 		    locus = &l_locus;
! 		  }
! 		else
! 		  {
! 		    np = (tree) text->arg_array[arg_index].v.ptr;
! 		    l_locus = diagnostic_J_tree2locus (np);
! 		    locus = &l_locus;
! 		  }
! 	      }
! 	    else
! 	      abort ();
! 	    /* We dont format %H if it is the first specifier. 
! 	       This is necessary to work with text_specifies_location ()
! 	       in diagnostic.c */
! 	    if (has_processed_one <= 0)
! 	      ; 
! 	    else
! 	      {
! 		pp_string (pp, "file '");
! 		pp_string (pp, locus->file);
! 		pp_string (pp, "', line ");
! 		pp_decimal_int (pp, locus->line);
! 	      }
            }
            break;
  
  	case '.':
! 
! 	  if (!use_pos_specifier)
! 	    {
! 	      int n;
! 	      const char *s;
! 	      /* We handle no precision specifier except for string type
! 		 as in `%.*s'.  
! 	         E.g.,  warning ("String = %.*s, extra=%d\n", 10, str, i);  */
! 
! 	      if (*++text->format_spec != '*')
! 		pp_helper_abort ("We expected '*' after '.'", text);
! 	      else if (*++text->format_spec != 's')
! 		pp_helper_abort ("We expected 's' after '*'", text);
! 	      n = va_arg (*text->args_ptr, int);
! 	      if (n <= 0)	/* we may want to check this. */
! 		{
! 		  fprintf (stderr, "diagnostic: string width %d given is not positive.\n", n);
! 		  n = 0;
! 		}
! 	      s = va_arg (*text->args_ptr, const char *);
! 	      pp_append_text (pp, s, s + n);
! 	    }
! 	  else
! 	    {
! 	      /* we handle %d$.*m$s : we have seen "period". */ 
! 
! 	      int a;
! 	      char tmp[2];
! 	      int c;
! 	      int n;
! 	      char *s;
! 
! 	      if (*++text->format_spec != '*')
! 		pp_helper_abort ("We expected '*' afer '.'", text);
! 
! 	      c = *++text->format_spec;
! 	      if (!isdigit (c))
! 		pp_helper_abort ("We expected a digit after '*'", text);
! 	      tmp[0] = c; tmp[1] = '\0';
! 	      a = atoi (tmp);
! 	      c = *++text->format_spec;
! 	      if (c != '$')
! 		pp_helper_abort ("We expected a '$' after a digit", text);
! 	      c = *++text->format_spec;
! 	      if (c != 's')
! 		pp_helper_abort ("We expected an 's' after '$'", text);
! 	      n = text->arg_array[a].v.i;
! 	      if (n <= 0)
! 		{
! 		  fprintf (stderr, "diagnostic: string width %d at %d is not positive.\n", n, a);
! 		  n = 0;
! 		}
! 	      s = text->arg_array[arg_index].v.cptr;
! 	      pp_append_text (pp, s, s + n);
! 
! 	    }
  	  break;
  
  	default:
! 
! 	  text->index_num = arg_index;
! 
! 	  /* We decided to use text->format_spec even
! 	     in the case of PRINT_ARG_VALUE case (positional
! 	     parameter support), but still set this just in case. */
! 	  text->format_after_percent_or_dollar = text->format_spec;
! 	  text->bump_format = 0;
! 
! 	  if (use_pos_specifier 
! 	      && (arg_index <= 0 || arg_index > 9))
! 	    pp_helper_abort ("arg_index out of range.", text);
! 
!           if (!pp_format_decoder (pp) 
! 	      || !(*pp_format_decoder (pp)) (pp, text,
! 					     use_pos_specifier ?
! 					     PRINT_ARG_VALUE :
! 					     PRINT_ARG_VALUE_AS_BEFORE))
  	    {
  	      /* Hmmm.  The client failed to install a format translator
                   but called us with an unrecognized format.  Or, maybe, the
                   translated string just contains an invalid format, or
                   has formats in the wrong order.  Sorry.  */
! 	      pp_helper_abort ("unrecognized format.", text);
  	    }
+ 
+ 	  /* adjust the pointer by the bytes understood by the
+ 	     custom format decoder. */
+ 	  if (use_pos_specifier && text->bump_format > 1)
+ 	    text->format_spec += (text->bump_format - 1);
  	}
+       has_processed_one ++;
      }
  }
  
  /* Helper subroutine of output_verbatim and verbatim. Do the appropriate
     settings needed by BUFFER for a verbatim formatting.  */
! void 
  pp_base_format_verbatim (pretty_printer *pp, text_info *text)
  {
    diagnostic_prefixing_rule_t rule = pp_prefixing_rule (pp);
Index: gcc/pretty-print.h
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/pretty-print.h,v
retrieving revision 1.10
diff -c -3 -p -r1.10 pretty-print.h
*** gcc/pretty-print.h	25 Aug 2003 19:10:48 -0000	1.10
--- gcc/pretty-print.h	23 Sep 2003 18:11:30 -0000
*************** Software Foundation, 59 Temple Place - S
*** 25,30 ****
--- 25,78 ----
  #include "obstack.h"
  #include "input.h"
  
+ /*  The type of variable argument arg_array[] (part of
+  text_info)  to store type and the value.
+  This is to support positional format specifiers 
+  in the form of %1$s, %2$d %3$d, etc.
+ 
+  Note that we use the arg_array[0].v.cptr to store the format string. 
+  The whole array is set to zero before each construction. */
+ typedef struct 
+ {
+   int typespec ;		/* type 'd', etc. */
+   int precision ;		/* to handle %d, %ld, %lld */
+   char format [5];		/* %lld at the longest. */
+   char custom_format[4]; /* CUSTOM decoder format. May contain #+, etc. */
+   union {			/* holding the value of argument */
+     int i;
+     unsigned int ui;
+     short s;
+     unsigned short us;
+     char c;
+     unsigned char uc;
+     long l;
+     unsigned long ul;
+     long long ll;
+     unsigned long long ull;
+     HOST_WIDE_INT hwi;
+     unsigned HOST_WIDE_INT uhwi;
+     void *ptr;			
+     char *cptr;
+     int  *iptr;
+     long *lptr;
+     long long *llptr;
+     location_t l_ptr;
+   } v;
+ }  argtype_t;
+ 
+ 
+ /* The type of an action to custom defined format decoder:
+    to return information or perform copy/print action 
+    for positional parameter processing. */
+ typedef enum 
+ {
+   GET_ARG_TYPE = 2,
+   COPY_ARG_VALUE = 3,
+   PRINT_ARG_VALUE = 4,
+   PRINT_ARG_VALUE_AS_BEFORE = 5 /* as before: no positional support */
+ } arg_decode_action;
+ 
+ 
  /* The type of a text to be formatted according a format specification
     along with a list of things.  */
  typedef struct
*************** typedef struct
*** 32,37 ****
--- 80,98 ----
    const char *format_spec;
    va_list *args_ptr;
    int err_no;  /* for %m */
+ 
+   /* Below is for positional argument support */
+ 
+   const char *original_format_spec; /* this remains unchanged.  */
+   argtype_t arg_array[10 + 1];	/* arg_array[0].v.cptr holds 
+ 				   the original format pointer. 
+                                    Argument is counted from postion no. 1. */
+   int arg_max;
+   const char *format_after_percent_or_dollar;   /* for GET_ARG_TYPE, COPY_ARG_VALUE */
+   int index_num;		/* argument index for custom decoder. */
+   int bump_format ;		/* GET_ARG_TYPE: returns
+ 				   how many bytes of format chars will 
+ 				   be eaten by  custom decoder. */
  } text_info;
  
  /* How often diagnostics are prefixed by their locations:
*************** typedef enum
*** 76,82 ****
     A client-supplied formatter returns true if everything goes well,
     otherwise it returns false.  */
  typedef struct pretty_print_info pretty_printer;
! typedef bool (*printer_fn) (pretty_printer *, text_info *);
  
  /* Client supplied function used to decode formats.  */
  #define pp_format_decoder(PP) pp_base (PP)->format_decoder
--- 137,143 ----
     A client-supplied formatter returns true if everything goes well,
     otherwise it returns false.  */
  typedef struct pretty_print_info pretty_printer;
! typedef bool (*printer_fn) (pretty_printer *, text_info *, arg_decode_action);
  
  /* Client supplied function used to decode formats.  */
  #define pp_format_decoder(PP) pp_base (PP)->format_decoder
*************** extern void pp_base_indent (pretty_print
*** 257,261 ****
--- 318,326 ----
  extern void pp_base_newline (pretty_printer *);
  extern void pp_base_character (pretty_printer *, int);
  extern void pp_base_string (pretty_printer *, const char *);
+ 
+ /* in diagnostic.c */
+ extern location_t diagnostic_J_tree2locus (tree t);
+ 
  
  #endif /* GCC_PRETTY_PRINT_H */
Index: gcc/toplev.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/toplev.c,v
retrieving revision 1.829
diff -c -3 -p -r1.829 toplev.c
*** gcc/toplev.c	22 Sep 2003 05:09:12 -0000	1.829
--- gcc/toplev.c	23 Sep 2003 18:11:35 -0000
*************** crash_signal (int signo)
*** 1331,1337 ****
  }
  
  /* Arrange to dump core on error.  (The regular error message is still
!    printed first, except in the case of abort().)  */
  
  static void
  setup_core_dumping (void)
--- 1331,1337 ----
  }
  
  /* Arrange to dump core on error.  (The regular error message is still
!    printed first, except in the case of abort ().)  */
  
  static void
  setup_core_dumping (void)
*************** init_asm_output (const char *name)
*** 4011,4035 ****
  
  /* Default tree printer.   Handles declarations only.  */
  static bool
! default_tree_printer (pretty_printer * pp, text_info *text)
  {
!   switch (*text->format_spec)
      {
!     case 'D':
!     case 'F':
!     case 'T':
!       {
!         tree t = va_arg (*text->args_ptr, tree);
!         const char *n = DECL_NAME (t)
!           ? (*lang_hooks.decl_printable_name) (t, 2)
!           : "<anonymous>";
!         pp_string (pp, n);
!       }
!       return true;
  
-     default:
-       return false;
      }
  }
  
  /* Initialization of the front end environment, before command line
--- 4011,4091 ----
  
  /* Default tree printer.   Handles declarations only.  */
  static bool
! default_tree_printer (pretty_printer * pp, text_info *text, arg_decode_action a)
  {
! 
!   /* We share the code for printing between
!      positional and non-positional specifier cases */
! 
!   if (a == PRINT_ARG_VALUE_AS_BEFORE  
!      || a == PRINT_ARG_VALUE)	
      {
!       tree t;
!       if (a == PRINT_ARG_VALUE)
! 	t = (tree) text->arg_array[text->index_num].v.ptr ;
!       else
! 	t = va_arg (*text->args_ptr, tree);
! 
!       switch (*text->format_spec)
! 	{
! 	case 'D':
! 	case 'F':
! 	case 'T':
! 	  {
! 	    const char *n = DECL_NAME (t)
! 	      ? (*lang_hooks.decl_printable_name) (t, 2)
! 	      : "<anonymous>";
! 	    pp_string (pp, n);
! 	  }
! 	  return true;
! 
! 	default:
! 	  return false;
! 	}
!     }
!   else if (a == GET_ARG_TYPE)
!     {
!       text->bump_format = 0;
!       
!       switch (*text->format_after_percent_or_dollar)
! 	{
! 	case 'D':
! 	case 'F':
! 	case 'T':
! 	  {
! 	    text->bump_format = 1;
! 	    text->arg_array[text->index_num].custom_format[0]
! 	      = *text->format_after_percent_or_dollar;
! 	  }
! 	  return true;
! 	default:
! 	  return false;
! 	}
!     }
!   else if (a == COPY_ARG_VALUE)
!     {
!       text->bump_format = 0;
!       
!       switch (*text->format_after_percent_or_dollar)
! 	{
! 	case 'D':
! 	case 'F':
! 	case 'T':
! 	  {
! 	    text->bump_format = 1;
! 	    text->arg_array[text->index_num].v.ptr 
! 	      = (void *) va_arg (*text->args_ptr, tree);
! 	  }
! 	  return true;
! 	default:
! 	  return false;
! 	}
! 
  
      }
+   else
+     abort ();
+ 
  }
  
  /* Initialization of the front end environment, before command line
*************** toplev_main (unsigned int argc, const ch
*** 4507,4512 ****
--- 4563,4719 ----
  
    /* Initialization of GCC's environment, and diagnostics.  */
    general_init (argv[0]);
+ 
+ #if 0
+  {
+    /* This is a test code for checking the
+       positional parameter support in diagnostic routines. 
+       I wonder where we should keep this code. 
+       As I explained in my post to gcc-patches , there is no easy way to
+       test the positional parameter support without
+       using an existing program and inserting this test code
+       somewhere. */
+ 
+ #include <errno.h>
+    int i;
+    long t;
+    long long ill;
+    long long xll;
+    extern void warning (const char *msgid, ...);
+ 
+    static char str [] = "123456789A123456789A123456789A";
+ 
+    i = 1234;
+    t = 0x0FFFFFFl;
+    ill = (long long) t * t;
+    xll = 0x0123456789ABCDEFull;
+ 
+ 
+    warning ("Test diagnostic.\n");
+ 
+    warning ("integer=%d, pointer=%p, char=%c", i, &t, 'c');
+ 
+    warning ("\nPointer value print\n");
+ 
+    fprintf (stderr, "pointer=%p\n",  (void *) &t);
+    warning ("1st: pointer=%2$p, char=%3$c, integer=%1$d", i, &t, 'c');
+    warning ("2nd: pointer=%2$p, char=%3$c, integer=%1$d", i, &t, 'c');
+    warning ("3rd: pointer=%1$p, char=%3$c, integer=%2$d", &t, i, 'c');
+    warning ("pointer=%2$p, char=%3$c, integer=%1$d", i, &t, 'c');
+ 
+ 
+    warning ("\nOne argument");
+    warning ("integer=%1$d", i);
+    warning ("char   =%1$c", 'c');
+    warning ("pointer=%1$p", &t);
+    warning ("long=%1$ld", t);
+    warning ("long=%1$lx", t);
+ 
+ 
+    /* long */
+    warning ("long=(x) %1$lx", t);
+    fprintf (stderr, " ordinary printf: %lx\n", t);
+    warning ("long=(o) %1$lo", t);
+    fprintf (stderr, " ordinary printf: %lo\n", t);
+    warning ("long=(d) %1$ld", t);
+    fprintf (stderr, " ordinary printf: %ld\n", t);
+ 
+ 
+    /* long long */
+ 
+    warning ("long long=(d) %1$lld", ill);
+    fprintf (stderr, "ordinary fprintf(): %lld\n", ill);
+ 
+ 
+    warning ("long long=(x) %1$llx", xll);
+    fprintf (stderr, " ordinary printf: %llx\n", xll);
+ 
+ 
+    warning ("long long=(o) %1$llo", xll);
+    fprintf (stderr, " ordinary printf: %llo\n", xll);
+ 
+ 
+    warning ("long long=(d) %1$lld", xll);
+    fprintf (stderr, " ordinary printf: %lld\n", xll);
+ 
+    /* wide ? */
+ 
+    warning ("Wide\n");
+    warning ("wide=(wd) %1$wd", t);
+    warning ("wide=(wx) %1$wx", t);
+    warning ("wide=(wo) %1$wo", t);
+ 
+    warning ("\nTwo arguments");
+    warning ("integer=%1$d, char=%2$c", i, 'c');
+    warning ("char   =%2$c, integer=%1$d", i, 'c');
+ 
+    warning ("\nThree Arguments\n");
+    warning ("char=%3$c, integer=%1$d, pointer=%2$p", i, &t, 'c');
+ 
+    warning ("char=%c, integer=%d, pointer=%p", 'c', i, &t);
+    warning ("pointer=%3$p, char=%1$c, integer=%2$d", 'c', i, &t);
+    warning ("char=%1$c, integer=%2$d, pointer=%3$p", 'c', i, &t);
+ 
+    warning ("integer=%d, long=%ld, long long=%lld", i, t, ill);
+    warning ("long=%2$ld, long long=%3$lld, int=%1$d", i, t, ill);
+    warning ("long long=%3$lld, int=%1$d, long=%2$ld", i, t, ill);
+ 
+    warning ("pointer=%2$p, char=%3$c, integer=%1$d", i, &t, 'c');
+ 
+    warning ("long long=%lld, long=%ld, int=%d", ill, t, i);
+    warning ("long=%2$ld, int=%3$d, long long=%1$lld", ill, t, i);
+    warning ("int=%3$d, long long=%1$lld, long=%2$ld", ill, t, i);
+ 
+ 
+    /* String and its width*/
+    warning ("\nString");
+ 
+    warning ("String =%s", str);
+    warning ("String =%1$s", str);  
+    fprintf (stderr, "ordinary fprintf(): %s\n", str);
+ 
+    warning ("String = %.*s, extra=%d",           10, str, i);
+    warning ("String = %3$.*1$s, extra=%2$d",     10, i, str);
+    warning ("String = %2$.*1$s, extra=%3$d",     10, str, i);
+    fprintf (stderr, "ordinary fprintf(): %.*s\n", 10, str);
+ 
+    /* modified test from a post by Jonathan Lennox */
+    {
+      const char *str = "Hello!";
+      warning ("String = %2$.*1$s, extra=%3$d",     10, str, i);
+      warning ("\n%.*s\n%.*s\n%.*s\n%.*s\n%.*s\n%.*s",
+ 	     1, str, 2, str,  3, str, 4, str, 5, str, 6, str);
+      warning ("\n%1$.*2$s\n%1$.*3$s\n%1$.*4$s\n%1$.*5$s\n%1$.*6$s\n%1$.*7$s",
+ 	     str, 1, 2, 3, 4, 5, 6);
+    }
+ 
+ 
+    /* %% and %m */
+ 
+    warning ("This is one %% (percent sign)  and error code message: could be random <<%m>>");
+ 
+ 
+    errno = EPIPE;
+    warning ("int=%1$d, long long=%2$lld,  %% (percent sign) and error message should be for EPIPE <<%m>>", i, ill);
+ 
+ 
+    /* should abort: we can't mix two forms. */
+    warning ("Should abort: integer=%d, pointer=%p, char=%3$c\n", i, &t, 'c');
+ 
+    /* should abort because %3$whatever is missing. */
+    warning ("Should abort: char=%4$p, integer=%1$d, pointer=%2$p\n", i, &t, 'c');
+ 
+    /* should abort: we can't mix two forms */
+    warning ("Should abort: integer=%1$d, pointer=%2$p, char=%c\n", i, &t, 'c');
+ 
+    /* should abort: 0 after %. */
+    warning ("Should abort: integer=%0$d, pointer=%2$p, char=%3c\n", i, &t, 'c'); 
+ 
+  }
+ 
+ #endif 
+ 
+ 
  
    /* Parse the options and do minimal processing; basically just
       enough to default flags appropriately.  */
Index: gcc/cp/error.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/cp/error.c,v
retrieving revision 1.238
diff -c -3 -p -r1.238 error.c
*** gcc/cp/error.c	22 Sep 2003 05:09:23 -0000	1.238
--- gcc/cp/error.c	23 Sep 2003 18:11:40 -0000
*************** static void print_instantiation_partial_
*** 96,103 ****
  static void cp_diagnostic_starter (diagnostic_context *, diagnostic_info *);
  static void cp_diagnostic_finalizer (diagnostic_context *, diagnostic_info *);
  static void cp_print_error_function (diagnostic_context *, diagnostic_info *);
! 
! static bool cp_printer (pretty_printer *, text_info *);
  static void pp_non_consecutive_character (cxx_pretty_printer *, int);
  static tree locate_error (const char *, va_list);
  static location_t location_of (tree);
--- 96,102 ----
  static void cp_diagnostic_starter (diagnostic_context *, diagnostic_info *);
  static void cp_diagnostic_finalizer (diagnostic_context *, diagnostic_info *);
  static void cp_print_error_function (diagnostic_context *, diagnostic_info *);
! static bool cp_printer (pretty_printer *, text_info *, arg_decode_action);
  static void pp_non_consecutive_character (cxx_pretty_printer *, int);
  static tree locate_error (const char *, va_list);
  static location_t location_of (tree);
*************** dump_expr (tree t, int flags)
*** 1550,1556 ****
  	}
        else
  	{
! 	  if (TREE_OPERAND (t,0) != NULL_TREE
  	      && TREE_TYPE (TREE_OPERAND (t, 0))
  	      && NEXT_CODE (TREE_OPERAND (t, 0)) == REFERENCE_TYPE)
  	    dump_expr (TREE_OPERAND (t, 0), flags);
--- 1549,1555 ----
  	}
        else
  	{
! 	  if (TREE_OPERAND (t, 0) != NULL_TREE
  	      && TREE_TYPE (TREE_OPERAND (t, 0))
  	      && NEXT_CODE (TREE_OPERAND (t, 0)) == REFERENCE_TYPE)
  	    dump_expr (TREE_OPERAND (t, 0), flags);
*************** print_instantiation_context (void)
*** 2268,2276 ****
     %P   function parameter whose position is indicated by an integer.
     %Q	assignment operator.
     %T   type.
!    %V   cv-qualifier.  */
  static bool
! cp_printer (pretty_printer *pp, text_info *text)
  {
    int verbose = 0;
    const char *result;
--- 2267,2277 ----
     %P   function parameter whose position is indicated by an integer.
     %Q	assignment operator.
     %T   type.
!    %V   cv-qualifier.  
! 
!    Modified to support postional format parameter. */
  static bool
! cp_printer (pretty_printer *pp, text_info *text, arg_decode_action a)
  {
    int verbose = 0;
    const char *result;
*************** cp_printer (pretty_printer *pp, text_inf
*** 2279,2316 ****
  #define next_lang    va_arg (*text->args_ptr, enum languages)
  #define next_int     va_arg (*text->args_ptr, int)
  
!   if (*text->format_spec == '+')
!     ++text->format_spec;
!   if (*text->format_spec == '#')
!     {
!       verbose = 1;
!       ++text->format_spec;
!     }
! 
!   switch (*text->format_spec)
!     {
!     case 'A': result = args_to_string (next_tree, verbose);	break;
!     case 'C': result = code_to_string (next_tcode);	        break;
!     case 'D': result = decl_to_string (next_tree, verbose);	break;
!     case 'E': result = expr_to_string (next_tree);      	break;
!     case 'F': result = fndecl_to_string (next_tree, verbose);	break;
!     case 'L': result = language_to_string (next_lang);          break;
!     case 'O': result = op_to_string (next_tcode);       	break;
!     case 'P': result = parm_to_string (next_int);	        break;
!     case 'Q': result = assop_to_string (next_tcode);	        break;
!     case 'T': result = type_to_string (next_tree, verbose);	break;
!     case 'V': result = cv_to_string (next_tree, verbose);	break;
   
!     default:
!       return false;
      }
  
-   pp_base_string (pp, result);
-   return true;
  #undef next_tree
  #undef next_tcode
  #undef next_lang
  #undef next_int
  }
  
  static void
--- 2280,2423 ----
  #define next_lang    va_arg (*text->args_ptr, enum languages)
  #define next_int     va_arg (*text->args_ptr, int)
  
! #define pos_next_tree    ((tree) text->arg_array[i].v.ptr)
! #define pos_next_tcode   ((enum tree_code) text->arg_array[i].v.i)
! #define pos_next_lang    ((enum languages) text->arg_array[i].v.i)
! #define pos_next_int     (text->arg_array[i].v.i)
! 
! 
! #define x_next_tree    ((a == PRINT_ARG_VALUE) ? pos_next_tree  : next_tree)
! #define x_next_tcode   ((a == PRINT_ARG_VALUE) ? pos_next_tcode : next_tcode)
! #define x_next_lang    ((a == PRINT_ARG_VALUE) ? pos_next_lang  : next_lang)
! #define x_next_int     ((a == PRINT_ARG_VALUE) ? pos_next_int   : next_int)
! 
! 
!   /* We share the code for printing between
!      positional and non-positional specifier cases */
! 
!   if (a == PRINT_ARG_VALUE_AS_BEFORE 
!      || a == PRINT_ARG_VALUE)
!     {
!       int i = text->index_num;
! 
!       text->bump_format = 0;
!       
!       if (*text->format_spec == '+')
! 	++text->format_spec;
!       if (*text->format_spec == '#')
! 	{
! 	  verbose = 1;
! 	  ++text->format_spec;
! 	}
! 
!       switch (*text->format_spec)
! 	{
! 	case 'A': result = args_to_string (x_next_tree, verbose);	break;
! 	case 'C': result = code_to_string (x_next_tcode);	        break;
! 	case 'D': result = decl_to_string (x_next_tree, verbose);	break;
! 	case 'E': result = expr_to_string (x_next_tree);      	break;
! 	case 'F': result = fndecl_to_string (x_next_tree, verbose);	break;
! 	case 'L': result = language_to_string (x_next_lang);          break;
! 	case 'O': result = op_to_string (x_next_tcode);       	break;
! 	case 'P': result = parm_to_string (x_next_int);	        break;
! 	case 'Q': result = assop_to_string (x_next_tcode);	        break;
! 	case 'T': result = type_to_string (x_next_tree, verbose);	break;
! 	case 'V': result = cv_to_string (x_next_tree, verbose);	break;
   
! 	default:
! 	  return false;
! 	}
! 
!       pp_base_string (pp, result);
!       return true;
      }
+   else if (a == GET_ARG_TYPE)
+     {
+       text->bump_format = 0;
+       if (*text->format_after_percent_or_dollar == '+')
+ 	text->arg_array[text->index_num].custom_format[text->bump_format++] =
+ 	  *text->format_after_percent_or_dollar++;
+       if (*text->format_spec == '#')
+ 	{
+ 	  verbose = 1;
+ 	  text->arg_array[text->index_num].custom_format[text->bump_format++] =
+ 	    *text->format_after_percent_or_dollar++;
+ 	}
+ 
+       switch (*text->format_after_percent_or_dollar)
+ 	{
+ 	case 'A': 
+ 	case 'C': 
+ 	case 'D': 
+ 	case 'E': 
+ 	case 'F': 
+ 	case 'L': 
+ 	case 'O': 
+ 	case 'P': 
+ 	case 'Q': 
+ 	case 'T': 
+ 	case 'V': 
+ 	  text->arg_array[text->index_num].custom_format[text->bump_format++] =
+ 	    *text->format_after_percent_or_dollar;
+ 	  break;
+ 
+ 	default:
+ 	  return false;
+ 	}
+       return true;
+     }
+   else if (a == COPY_ARG_VALUE)
+     {
+       int i = text->index_num;
+ 
+       text->bump_format = 0;
+ 
+       if (*text->format_after_percent_or_dollar == '+')
+ 	++text->format_after_percent_or_dollar,  ++text->bump_format;
+       if (*text->format_spec == '#')
+ 	{
+ 	  verbose = 1;
+ 	  ++text->format_after_percent_or_dollar;
+ 	  ++text->bump_format;
+ 	}
+ 
+       switch (*text->format_after_percent_or_dollar)
+ 	{
+ 	case 'A': text->arg_array[i].v.ptr = (void *) next_tree ; break;
+ 	case 'C': text->arg_array[i].v.ptr = (void *) next_tcode;        break;
+ 	case 'D': text->arg_array[i].v.ptr = (void *) next_tree;	break;
+ 	case 'E': text->arg_array[i].v.ptr = (void *) next_tree;      	break;
+ 	case 'F': text->arg_array[i].v.ptr = (void *) next_tree;	break;
+ 	case 'L': text->arg_array[i].v.i = next_lang;          break;
+ 	case 'O': text->arg_array[i].v.i = next_tcode;       	break;
+ 	case 'P': text->arg_array[i].v.i = next_int;	        break;
+ 	case 'Q': text->arg_array[i].v.i = next_tcode;	        break;
+ 	case 'T': text->arg_array[i].v.ptr = next_tree; 	break;
+ 	case 'V': text->arg_array[i].v.ptr = next_tree;	break;
+  
+ 	default:
+ 	  return false;
+ 	}
+       return true;
+     }
+   else
+     abort ();
  
  #undef next_tree
  #undef next_tcode
  #undef next_lang
  #undef next_int
+ 
+ #undef pos_next_tree
+ #undef pos_next_tcode
+ #undef pos_next_lang
+ #undef pos_next_int
+ 
+ #undef x_next_tree
+ #undef x_next_tcode
+ #undef x_next_lang
+ #undef x_next_int
+ 
  }
  
  static void
*************** pp_non_consecutive_character (cxx_pretty
*** 2324,2330 ****
  }
  
  /* These are temporary wrapper functions which handle the historic
!    behavior of cp_*_at.  */
  
  static tree
  locate_error (const char *msgid, va_list ap)
--- 2431,2441 ----
  }
  
  /* These are temporary wrapper functions which handle the historic
!    behavior of cp_*_at.  
! 
!   We don't have to worry about positional format specifier
!   in this function since this receives msgid, i.e., the original format string
!   before translation that should NOT contain such postional specifier. */
  
  static tree
  locate_error (const char *msgid, va_list ap)



While we are at it,
someone might want to answer the question below.
Now, another question:

While creating the patch, I noticed that a call to pp_string () in
cp_printer() in cp/error.c is now modified to pp_base_string ().

I suppose this is intentional.

However, if so, should we not modify the call to pp_string() in

 - default_printer () in toplev.c,
 - c_tree_printer () in c-objc-common.c 

to pp_base_string() as well?

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]