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: Special handling of "%H" (Re: Support for %d$c format specifierin diagnostics.c)


"Joseph S. Myers" wrote:
>
> I agree that since %H is a format that does consume an argument, it should
> become %1$H when operand numbers are used (with special handling for %1$H
> at the start, if necessary) and the subsequent operands should be counted
> from 2 as usual.

(Sorry for my earlier posts in the last few days where my PC's clock
was off by 9 hours forward or something like that.  I am afraid that
the mail archive got confused by the skewed time of my post.)

This is the fifth cut for the patch to support positional format
specifiers.

Tested on i686-pc-linux-gnu.

In this patch:
  (new)
      Modified text_specifies_location() and pp_format_text() as 
      explained in my previous post to handle
      all strings including the ones with %H (or %1$H) at the
      beginning in a uniform manner.

So, now the code (near line 5570) in function.c,

warning ("%H'%D' might be used uninitialized in this function",
                 &DECL_SOURCE_LOCATION (decl), decl);

and the modified 

warning ("%1$H'%2$D' might be used uninitialized in this function",
                 &DECL_SOURCE_LOCATION (decl), decl);
   
produce the same output (!).

>/tmp/test.c:4: warning: 'i' might be used uninitialized in this function

We no longer have to tell the PO translators irregular counting rule.
(But %H must stay at the beginning, but this is much easier rule to
explain.) Good thing as we retain the uniformity of counting, and
an advanced format string checker might be capable of
working over such uniformly numberered format strings less
special counting rules for "%H" at the beginning of the format string.

Also in this patch:
     (modification of the patch)
      Argument index range check is done now within pretty-print.c
      immediately before the call to custom decoder and so the check
      is taken out from the custom decoders.
      This checking is valid only when  (use_pos_paramter && ...)

      PRINT_ARG_VALUE action for custom format decoder now
      uses text->format_spec instead of
	   text->format_after_percent_or_dollar
      and so the action for PRINT_ARG_VALUE (positional parameter)
      and PRINT_ARG_AS_BEFORE (old behavior) code can be shared very much.
      The decoder functions in cp/error.c, toplev.c c-objc-common.c
      are somewhat simplified.

      An array index bug was also fixed during the
      processing of custom decoder (found during local testing.).

Status of the patch.

I am certain that this works now.

Please note that my patch tried to preserve the behavior of the code
when there is no positional parameter and I believe that they work for
English-only language environment without any ill-effect.  Also, after
testing on local PC (with a small test program
and also by make -k check), I am fairly certain that
the mechanism works without problems for current PO file
disregarding the potential errors in PO files themselves.
[the Japanese PO file that is installed in my Debian GNU/Linux, that is.
I have not yet gotten around to install the current GCC CVS po files
under the system directory where running GCC would pick it up.]

So I would like to see others in different locale to test this out if
they are brave, er, forward-looking types.
But do not be afraid. If there is a problem, my patch is quite
likely to print the problematic format string to stderr, and
so we will see immediately what format string caused a problem. 

We now probably need to move on to clean up external  PO files once
the support code is in the mainline.
(It is a chicken and egg situtation: PO file translators, I am sure,
will use positional parameters, but unless the support is in
the code, it will be useless. Worse, it might stop the compilation.
I think it does. Without my patch a digit following a '%' as in "%2$d"
will result in abort(). )

One problem of testing the patch is that most of the error/warning
messages that use extended format characters are for printing
semantical problems in the source code
and not with syntactic errors. So, in order to
invoke the error/warning processing with interesting format strings,
we need source files that exhibit such semantical problems.

I won't be able to write exhaustive list of test files alone. So the
separate check of PO files, and the format argument check proposed
(and implemented?)  in this mailing list is in order.

(make -k check invokes only a subset of such error/warning, it seems.

Incidently, is there a known result of "make -k check"?  That is, I am
wondering if my patch breaks the compiler front end in a subtle manner
or not, and resorted to reading the log record in gcc/testsuite
directory. But a `official' result number list would be very handy in
comparing the local result after a modification is made.
For about a week, I noticed a strange error in cfgrtl.c 
at runtime. I am not sure if I saw this before that, for example. But
this is not related to my patch obviously.)

I will be happy to work on an external PO file checker script, maybe a
very crude one initially, once the positional parameter support in
mainline CVS.

Again feedback/comments welcome.

Happy Hacking,

Ishikawa, Chiaki

2003-07-29    <ishikawa@duron.erephon>

	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 (_helper_abort): print the problematic format string
	  and abort.
	  (_type_width): returns the argument width based
	  on format specifier type.
	  (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.
	  (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. 
	



/u2/tools/gcc-mainline-cvs/gcc
? check-num-percent.awk
? check-num-percent.sh
? gcc/ChangeLog.ci
? gcc/diagnostic-post.txt
? gcc/diagnostic.c-tmp
? gcc/diagnostic.c.new
? gcc/diagnostic.c.saved
? gcc/diagnostic.h.saved
? gcc/e.diff
? gcc/gmon.out
? gcc/t.err
? gcc/t.problem
? gcc/po/messages
? gcc/testsuite/gcc.dg/gmon.out
Index: gcc/c-objc-common.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/c-objc-common.c,v
retrieving revision 1.30
diff -c -3 -p -r1.30 c-objc-common.c
*** gcc/c-objc-common.c	25 Jul 2003 09:52:23 -0000	1.30
--- gcc/c-objc-common.c	28 Jul 2003 17:48:14 -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 inline_forbidden_p (tree *, int *, void *);
  static void expand_deferred_fns (void);
  static tree start_cdtor (int);
--- 39,45 ----
  #include "target.h"
  #include "cgraph.h"
  
! static bool c_tree_printer (pretty_printer *, text_info *, arg_decode_action);
  static tree inline_forbidden_p (tree *, int *, void *);
  static void expand_deferred_fns (void);
  static tree start_cdtor (int);
*************** c_objc_common_finish_file (void)
*** 414,449 ****
     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;
      }
  }
  
  #include "gt-c-objc-common.h"
--- 414,558 ----
     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.  
! 
! 
!    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;
! 
!   /* fprintf(stderr,"c_tree_printer: a =%d\n", a);*/
  
!   if(a == PRINT_ARG_VALUE_AS_BEFORE /* good old printing as before. */
!      || a == PRINT_ARG_VALUE )	/* positional parameter support. */
      {
!       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)
+     {
+ 
+       /* fprintf(stderr,"c_tree_printer: a =%d, c=%c\n", a,
+        *text->format_after_percent_or_dollar); */
+ 
+       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;
+ 	}
+     }
+ #if 0
+   else if (a == PRINT_ARG_VALUE )
+     {
+ 
+       t = (tree) text->arg_array[text->index_num].v.ptr;
+       text->bump_format = 1;	/* we know it is 1 at most. */
+       switch (*text->format_after_percent_or_dollar)
+ 	{
+ 	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;
+ 	}
+     }
+ #endif
+   else 
+     abort();
+ 
+   return false;
  }
  
  #include "gt-c-objc-common.h"
Index: gcc/diagnostic.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/diagnostic.c,v
retrieving revision 1.127
diff -c -3 -p -r1.127 diagnostic.c
*** gcc/diagnostic.c	25 Jul 2003 09:52:24 -0000	1.127
--- gcc/diagnostic.c	28 Jul 2003 17:48:14 -0000
*************** diagnostic_initialize (diagnostic_contex
*** 120,126 ****
  
  /* 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)
  {
--- 120,134 ----
  
  /* 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 so that the subsequent call
!    to pp_text_format() can access %H (or %1$H).
!    and  we no longer remove the %H reference.
!    Now pp_format_text() no longer 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,139 ****
    for (p = text->format_spec; *p && *p != '%'; ++p)
      ;
  
!   /* Extract the location information if any.  */
!   if (*p == '%' && *++p == 'H')
      {
        *locus = *va_arg (*text->args_ptr, location_t *);
!       text->format_spec = p + 1;
        return true;
      }
  
--- 137,162 ----
    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.
!   */
! 
!   /*fprintf(stderr,"text_specifies_location p=<<%s>>\n", p);*/
! 
!   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 *);
!       /*DONT SKIP: text->format_spec = p + 1;*/
!       /* fprintf(stderr,"saved_ptr =%p, *text->args_ptr=%p\n",
! 	 saved_ptr, *text->args_ptr); 
!       */
!       *text->args_ptr = saved_ptr;
        return true;
      }
  
Index: gcc/pretty-print.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/pretty-print.c,v
retrieving revision 2.1
diff -c -3 -p -r2.1 pretty-print.c
*** gcc/pretty-print.c	25 Jul 2003 09:52:25 -0000	2.1
--- gcc/pretty-print.c	28 Jul 2003 17:48:25 -0000
*************** Software Foundation, 59 Temple Place - S
*** 26,31 ****
--- 26,34 ----
  #include "coretypes.h"
  #include "pretty-print.h"
  
+ /* for isdigit */
+ #include <ctype.h>
+ 
  #define obstack_chunk_alloc xmalloc
  #define obstack_chunk_free  free
  
*************** pp_append_r (pretty_printer *pp, const c
*** 164,169 ****
--- 167,809 ----
    pp->buffer->line_length += length;
  }
  
+ /* 
+  ========================================
+   Supporting positional format specifiers a la 
+   %2$d, %1$d, %3$c, etc..
+  ========================================
+ */
+ #define UNDEFINED_FORMAT 0
+ #define LOCATION_T_TYPE 1001
+ /*
+  * Aborting with error message and the format string that caused it.
+  */
+ static
+ void
+ _helper_abort(const char *a, text_info *text)
+ {
+   fprintf(stderr,"Aborting 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.
+ */
+ static
+ int
+ _type_width(int t)
+ {
+   switch(t)
+     {
+     default:
+       fprintf(stderr,"_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_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
+ compatible_and_has_same_width ( int t, int prec1, int u, int prec2)
+ {
+   return _type_width(t) == _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();
+ 
+   /*   fprintf(stderr,"set_argument_type_with_precision: %d, prec=%d\n",
+        i, precision); 
+   */
+ 
+   /* First definition/reference */
+   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 ( 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)
+ 
+ 
+ /*
+   Building argument array to 
+   support format specifiers in the form of %1$s, %2$d %3$d, etc.
+ */
+ static
+ void
+ 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. */
+ 
+   /* TODO/FIXME: this is somewhat redundant now that arg_array is made 
+      part of text_info. Or we can still use this value as the unmodified
+      format string. 
+    */
+   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.  */
+       /* CI mods. We now 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];
+ 
+ 	      /* We may be handling non-ASCII like EBCDIC where
+ 		 digit character codes are not consecutive.
+ 		 Let atoi() take care of that. */
+ 
+ 	      tmp[1] = '\0';
+ 	      tmp[0] = format[1];
+ 
+ 	      arg_index = atoi(tmp);
+ 
+ 	      if(arg_index == 0)
+ 		{
+ 		  _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]))
+ 	       _helper_abort("we handle only 1-9 in %%d$ as of now.\n", text);
+ 	     else
+ 	       _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)
+ 	_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'))
+ 	{
+ 	  _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 */
+ 	  /* arg_index --; */
+ 	  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");
+ 
+ 	      _helper_abort("We should have a consecutive % s ", text);
+ 
+ 	    }
+ 
+ 	  break;
+ 
+         case 'H':
+ 	  set_argument_type(arg_index, LOCATION_T_TYPE, text);
+           break;
+ 
+ 	case '.':  /* Original %.*s, 
+ 	              but could be %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 but `%.*s'.  */
+ 	    /* This build_argument_array() is called when %n$
+ 	       specifier is used and so the width also needs to
+ 	       be specified as *m$ ! */
+ 	    
+ 	    if (*++format != '*')
+ 	      _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))
+  		  _helper_abort("We expected a digit after '*'", text);
+ 		tmp[0] = c; tmp[1] = '\0';
+ 		a = atoi(tmp);
+ 		if(a == 0)
+ 		  _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:
+ 	  /*
+ 	   * This problem probably is not a big deal since
+ 	   * the usage of format_decoder 
+ 	   * is mainly fr the dumping of compiler internal data
+ 	   * for debugging. (?)
+ 	   *
+ 	   * One format_decoder is c_tree_printer in c-objc-common.c
+ 	   */
+ 
+ 	  /* set up for GET_ARG_TYPE */
+ 
+ 	  text->index_num = arg_index;
+ 	  text->format_after_percent_or_dollar = format;
+ 
+ 	  /* save previously seen format, if any, for checking
+ 	     incompatible double references. */
+ 	  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)
+ 	    _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.  */
+ 	      _helper_abort("Unrecognized format.", text);
+ 	    }
+ 
+ 	  /* Check for double definition for custom-extended format
+ 	     argument */
+ 	  
+ 	  if(text->arg_array[0].custom_format[0] == '\0')
+ 	    ; 			/* First reference. OK */
+ 	  else 
+ 	    {
+ 	      /*
+ 		If it `matches', 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 */
+ 	  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. */
+   /* fprintf(stderr, "arg_max=%d\n", arg_max); */
+ 
+   /* NOTE: we start at 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))
+ 		{
+ 		  _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' /* HOST_WIDE_INT */ : 
+ 	  text->arg_array[i].v.hwi = va_arg (*text->args_ptr, HOST_WIDE_INT);
+ 	  break;
+ 
+ 	case 'U' /*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_T_TYPE: 
+ 	  text->arg_array[i].v.ptr = va_arg (*text->args_ptr, location_t *);
+ 	  break;
+ 
+ 	default:
+ 	  _helper_abort("Unknown output specifier during value copy.", text);
+ 	}
+ 
+     }
+ 
+   /* Now we know the type/value of arguments */
+   
+   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_append_r (pretty_printer *pp, const c
*** 179,194 ****
     %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_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 != '%')
--- 819,850 ----
     %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.
!    %[0-9]${d,i,u,o,x,...,H}
! 
! */
  void
  pp_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. */
+ 
+   /* fprintf(stderr,"pp_format_text:text->format_spec=<<%s>>\n", 
+      text->format_spec);
+   */
+ 
    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_format_text (pretty_printer *pp, text
*** 197,206 ****
--- 853,913 ----
          text->format_spec = p;
        }
  
+       /* assert:    text->format_spec == '\0'
+ 	 || text->format_spec == '%'
+       */
        if (*text->format_spec == '\0')
  	break;
  
+       /*fprintf(stderr,"loop:<<%c>>\n", *text->format_spec);*/
+ 
        /* We got a '%'.  Parse precision modifiers, if any.  */
+       /* We now need to handle [0-9] as in %1$d */
+ 
+       if(isdigit(text->format_spec[1]))
+ 	{
+ 	  if(text->format_spec[2] == '$')
+ 	    {
+ 	      char tmp[2];
+ 
+ 	      /* How about EBCDIC? */
+ 	      /* Let atoi handle the digit positions in  character set. */
+ 
+ 	      tmp[1] = '\0';
+ 	      tmp[0] = (text->format_spec)[1];
+ 	      arg_index = atoi(tmp);
+ 
+ 	      if(arg_index == 0)
+ 		_helper_abort("The digit that comes after % must be non-zero.\n", text);
+ 
+ 	      if(!use_pos_specifier)
+ 		{
+ 		  if(has_processed_one > 1)
+ 		    _helper_abort("We can't mix %d and %n$d form\n", text);
+ 		  build_argument_array(text->original_format_spec, pp, text);
+ 		}
+ 	      use_pos_specifier = 1;
+ 
+ 	      /* after the above call to 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]))
+ 		_helper_abort("we handle only 1-9 in %d$ as of now.\n", text);
+ 	      else 
+ 		_helper_abort("we have seen %d, 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_format_text (pretty_printer *pp, text
*** 217,248 ****
          default:
            break;
          }
!       /* We don't support precision behond 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':
--- 924,988 ----
          default:
            break;
          }
!       /* We don't support precision beyond that of "long long".  */
        if (precision > 2)
!         _helper_abort("Too many precision 'l' specfied.", text);
! 
!       if(   use_pos_specifier
! 	    && ( arg_index <= 0 || arg_index > 9))
! 	_helper_abort("Argument index out of range.\n", text);
! 
! 
!       /*fprintf(stderr,"loop2:<<%c>>\n", *text->format_spec);*/
  
        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':
*************** pp_format_text (pretty_printer *pp, text
*** 255,319 ****
  
  	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 ();
  	    }
  	}
      }
  }
  
--- 995,1162 ----
  
  	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;
  
          case 'H':
            {
!             const location_t *locus;
! 
! 	    if(!use_pos_specifier)
! 	      locus = va_arg (*text->args_ptr, location_t *);
! 	    else
! 	      locus = (location_t *) text->arg_array[arg_index].v.ptr;
! 
! 	    if(has_processed_one <= 0)
! 	      ; 		/* dont format.  */
! 	    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 but `%.*s'.  */
+ 	    /* Like this.  warning("String = %.*s, extra=%d\n", 10, str, i); */
+ 
  	    if (*++text->format_spec != '*')
! 	      _helper_abort("We expected '*' after '.'", text);
  	    else if (*++text->format_spec != 's')
! 	      _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 only %d$.*m$s : we have seen "period". */ 
+ 
+ 	      int a;
+ 	      char tmp[2];
+ 	      int c;
+ 	      int n;
+ 	      char *s;
+ 
+ 	      if (*++text->format_spec != '*')
+ 		_helper_abort ("We expected '*' afer '.'", text);
+ 
+ 	      c = *++text->format_spec;
+ 	      if(!isdigit(c))
+ 		_helper_abort ("We expected a digit after '*'", text);
+ 	      tmp[0] = c; tmp[1] = '\0';
+ 	      a = atoi(tmp);
+ 	      c = *++text->format_spec;
+ 	      if(c != '$')
+ 		_helper_abort ("We expected a '$' after a digit", text);
+ 	      c = *++text->format_spec;
+ 	      if(c != 's')
+ 		_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))
! 	    _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.  */
! 	      _helper_abort ("unrecognized format.", text);
  	    }
+ 	  /* adjust */
+ 	  /*fprintf(stderr,"text->bump_format=%d\n", text->bump_format);*/
+ 
+ 	  if(use_pos_specifier && text->bump_format > 1)
+ 	    text->format_spec += (text->bump_format - 1);
  	}
+       has_processed_one ++;
      }
  }
  
Index: gcc/pretty-print.h
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/pretty-print.h,v
retrieving revision 1.6
diff -c -3 -p -r1.6 pretty-print.h
*** gcc/pretty-print.h	25 Jul 2003 09:52:25 -0000	1.6
--- gcc/pretty-print.h	28 Jul 2003 17:48:25 -0000
*************** Software Foundation, 59 Temple Place - S
*** 25,30 ****
--- 25,79 ----
  #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 {
+     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;   /* assuming one pointer type */
+     char *cptr;
+     int  *iptr;
+     long *lptr;
+     long long *llptr;
+     location_t l_ptr;
+   } v;
+ }  argtype_t;
+ 
+ 
+ /* Instruct custom defined format decoder to
+    return information for 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 ****
--- 81,99 ----
    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*/
+   int arg_max;
+   /* arg_decode_action action; made into function argument */
+   const char *format_after_percent_or_dollar; /* input for GET_ARG_TYPE, COPY_ARG_VALUE */
+   int index_num; /* used input for arg_decode_action */
+   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
--- 138,144 ----
     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
Index: gcc/toplev.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/toplev.c,v
retrieving revision 1.814
diff -c -3 -p -r1.814 toplev.c
*** gcc/toplev.c	25 Jul 2003 09:52:26 -0000	1.814
--- gcc/toplev.c	28 Jul 2003 17:48:30 -0000
*************** init_asm_output (const char *name)
*** 4101,4125 ****
  
  /* 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
--- 4101,4210 ----
  
  /* Default tree printer.   Handles declarations only.  */
  static bool
! default_tree_printer (pretty_printer * pp, text_info *text, arg_decode_action a)
  {
! 
!   /* fprintf(stderr,"default_tree_printer: a = %d\n", a); */
! 
!   if(a == PRINT_ARG_VALUE_AS_BEFORE  /* good ole format printing. */
!      || a == PRINT_ARG_VALUE )	/* positional format specifier */
!     {
!       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 )
!     {
!       if(text->index_num > 9 || text->index_num <= 0)
! 	abort();
!       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 )
!     {
!       if(text->index_num > 9 || text->index_num <= 0)
! 	abort();
!       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;
! 	}
! 
! 
!     }
! #if 0
!   else if ( a == PRINT_ARG_VALUE )
      {
!       tree t;
! 
! 
!       t = (tree) text->arg_array[text->index_num].v.ptr ;
  
!       switch (*text->format_after_percent_or_dollar)
! 	{
! 	case 'D':
! 	case 'F':
! 	case 'T':
! 	  {
! 	    const char *n = DECL_NAME (t)
! 	      ? (*lang_hooks.decl_printable_name) (t, 2)
! 	      : "<anonymous>";
! 	    pp_string (pp, n);
! 	    text->bump_format = 1;
! 	  }
! 	  return true;
! 	default:
! 	  return false;
! 	}
      }
+ #endif
+   else
+     abort();
+ 
  }
  
  /* Initialization of the front end environment, before command line
*************** toplev_main (unsigned int argc, const ch
*** 4589,4594 ****
--- 4674,4812 ----
  
    /* Initialization of GCC's environment, and diagnostics.  */
    general_init (argv[0]);
+ 
+ #if 0
+ 
+ {
+ #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=0x%08x\n", (unsigned int) &t);*/
+   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);
+ 
+   /* %% 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.227
diff -c -3 -p -r1.227 error.c
*** gcc/cp/error.c	28 Jul 2003 11:06:28 -0000	1.227
--- gcc/cp/error.c	28 Jul 2003 17:48:35 -0000
*************** static void print_instantiation_partial_
*** 97,104 ****
  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 (pretty_printer *, int);
  static tree locate_error (const char *, va_list);
  static location_t location_of (tree);
--- 97,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 *, arg_decode_action );
  static void pp_non_consecutive_character (pretty_printer *, int);
  static tree locate_error (const char *, va_list);
  static location_t location_of (tree);
*************** print_instantiation_context (void)
*** 2424,2432 ****
     %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;
--- 2423,2434 ----
     %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
*** 2435,2472 ****
  #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_string (pp, result);
-   return true;
  #undef next_tree
  #undef next_tcode
  #undef next_lang
  #undef next_int
  }
  
  static void
--- 2437,2619 ----
  #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)
! 
! 
!   /* fprintf(stderr,"cp_printer: a =%d\n", a); */
! 
! 
!   if(a == PRINT_ARG_VALUE_AS_BEFORE /* good old printing unmodified. */
!      || 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 (next_tree, verbose);	break;
! 	case 'V': result = cv_to_string (next_tree, verbose);	break;
   
! 	default:
! 	  return false;
! 	}
! 
!       pp_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;
!     }
! #if 0
!   else if ( a == PRINT_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_after_percent_or_dollar == '#')
! 	{
! 	  verbose = 1;
! 	  ++text->format_after_percent_or_dollar;
! 	  ++text->bump_format;
! 	}
! 
!       switch (*text->format_after_percent_or_dollar)
! 	{
! 	case 'A': result = args_to_string (pos_next_tree, verbose);	break;
! 	case 'C': result = code_to_string (pos_next_tcode);	        break;
! 	case 'D': result = decl_to_string (pos_next_tree, verbose);	break;
! 	case 'E': result = expr_to_string (pos_next_tree);      	break;
! 	case 'F': result = fndecl_to_string (pos_next_tree, verbose);	break;
! 	case 'L': result = language_to_string (pos_next_lang);          break;
! 	case 'O': result = op_to_string (pos_next_tcode);       	break;
! 	case 'P': result = parm_to_string (pos_next_int);	        break;
! 	case 'Q': result = assop_to_string (pos_next_tcode);	        break;
! 	case 'T': result = type_to_string (pos_next_tree, verbose);	break;
! 	case 'V': result = cv_to_string (pos_next_tree, verbose);	break;
!  
! 	default:
! 	  return false;
! 	}
! 
!       pp_string (pp, result);
!       return true;
      }
+ #endif
+   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


-- 
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 */


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