diff -ur ../gccorgrpm/gcc/c-common.c ./gcc/c-common.c
--- ../gccorgrpm/gcc/c-common.c	Fri May 16 18:21:04 2003
+++ ./gcc/c-common.c	Wed May 14 11:39:37 2003
@@ -564,7 +564,10 @@
   int length = 1;
   int wide_length = 0;
   int wide_flag = 0;
+/* UTF_CHAR: used wide bytes instead of wchar_bytes */
+#ifndef UTF_CHAR
   int wchar_bytes = TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT;
+#endif
   int nchars;
   const int nchars_max = flag_isoc99 ? 4095 : 509;
 
@@ -576,6 +579,35 @@
       /* Don't include the \0 at the end of each substring,
 	 except for the last one.
 	 Count wide strings and ordinary strings separately.  */
+/* UTF_CHAR: 
+   calculate length independent of string type
+   during adding all string length is counted in characters
+   at the end length is converted to bytes
+*/
+#ifdef UTF_CHAR
+      for (t = strings; t; t = TREE_CHAIN (t))
+	{
+          int current_wide_flag = TREE_ARRAY_TYPE_TO_WIDE_FLAG(TREE_TYPE(t));
+          /* add length in chars without terminating 0
+             because of terminating 0 for the whole string
+             length has been initialized with 1 */
+          length += TREE_STRING_LENGTH (t) / WIDE_BYTES( current_wide_flag ) - 1;
+
+          /* determine largest involved string type */
+          if( WIDE_BYTES(current_wide_flag)>WIDE_BYTES(wide_flag) ||
+	      (WIDE_BYTES(current_wide_flag)==WIDE_BYTES(wide_flag) && current_wide_flag>wide_flag)
+	  ) {
+            wide_flag = current_wide_flag;
+          }
+
+	  if( !wide_flag && C_ARTIFICIAL_STRING_P (t) && !in_system_header) {
+            warning ("concatenation of string literals with __FUNCTION__ is deprecated"); 
+	  }
+	}
+
+      /* convert length from characters to bytes */
+      length = length * WIDE_BYTES(wide_flag);
+#else /* UTF_CHAR */
       for (t = strings; t; t = TREE_CHAIN (t))
 	{
 	  if (TREE_TYPE (t) == wchar_array_type_node)
@@ -595,6 +627,7 @@
 	 which makes them take more space.  */
       if (wide_flag)
 	length = length * wchar_bytes + wide_length;
+#endif /* UTF_CHAR */
 
       p = xmalloc (length);
 
@@ -605,10 +638,29 @@
       q = p;
       for (t = strings; t; t = TREE_CHAIN (t))
 	{
+/* UTF_CHAR: expand if neccessary and concat strings */
+#ifdef UTF_CHAR	
+          int current_wide_flag = TREE_ARRAY_TYPE_TO_WIDE_FLAG (TREE_TYPE (t));
+          /* source character size in bytes */
+          int current_wide_bytes = WIDE_BYTES (current_wide_flag);
+          /* target character size in bytes */
+          int wide_bytes = WIDE_BYTES (wide_flag);
+	  /* expansion factor */
+	  int expansion = wide_bytes/current_wide_bytes;
+          /* string length in bytes without terminating 0 */
+          int len = TREE_STRING_LENGTH (t) - current_wide_bytes;
+#else
 	  int len = (TREE_STRING_LENGTH (t)
 		     - ((TREE_TYPE (t) == wchar_array_type_node)
 			? wchar_bytes : 1));
+#endif			
+
+/* UTF_CHAR: expansion neccessary? */
+#ifdef UTF_CHAR
+	  if ( expansion == 1 )
+#else
 	  if ((TREE_TYPE (t) == wchar_array_type_node) == wide_flag)
+#endif	  
 	    {
 	      memcpy (q, TREE_STRING_POINTER (t), len);
 	      q += len;
@@ -620,23 +672,39 @@
 		{
 		  if (BYTES_BIG_ENDIAN)
 		    {
+/* UTF_CHAR: expand by adding neccessary numbers of 0 */
+#ifdef UTF_CHAR
+		      for (j=0; j<expansion-1; j++)
+#else		    
 		      for (j=0; j<(WCHAR_TYPE_SIZE / BITS_PER_UNIT)-1; j++)
+#endif		      
 			*q++ = 0;
 		      *q++ = TREE_STRING_POINTER (t)[i];
 		    }
 		  else
 		    {
 		      *q++ = TREE_STRING_POINTER (t)[i];
+/* UTF_CHAR: expand by adding neccessary number of 0 bytes */
+#ifdef UTF_CHAR
+		      for (j=0; j<expansion-1; j++)
+#else		    
 		      for (j=0; j<(WCHAR_TYPE_SIZE / BITS_PER_UNIT)-1; j++)
+#endif		      
 			*q++ = 0;
 		    }
 		}
 	    }
 	}
+
       if (wide_flag)
 	{
 	  int i;
+/* UTF_CHAR: add neccessary number of terminating 0 bytes  */
+#ifdef UTF_CHAR	  
+	  for (i = 0; i < WIDE_BYTES(wide_flag); i++)
+#else	  
 	  for (i = 0; i < wchar_bytes; i++)
+#endif	  
 	    *q++ = 0;
 	}
       else
@@ -649,12 +717,21 @@
     {
       value = strings;
       length = TREE_STRING_LENGTH (value);
+/* UTF_CHAR: determine wide_flag for single strings */
+#ifdef UTF_CHAR
+      wide_flag = TREE_ARRAY_TYPE_TO_WIDE_FLAG( TREE_TYPE(value) );
+#else
       if (TREE_TYPE (value) == wchar_array_type_node)
 	wide_flag = 1;
+#endif
     }
 
   /* Compute the number of elements, for the array type.  */
+#ifdef UTF_CHAR
+  nchars = length / WIDE_BYTES(wide_flag);
+#else
   nchars = wide_flag ? length / wchar_bytes : length;
+#endif
 
   if (pedantic && nchars - 1 > nchars_max && c_language == clk_c)
     pedwarn ("string length `%d' is greater than the length `%d' ISO C%d compilers are required to support",
@@ -667,17 +744,32 @@
   if (flag_const_strings
       && (! flag_traditional  && ! flag_writable_strings))
     {
+/* UTF_CHAR: type node for literal */
+#ifdef UTF_CHAR
+      tree elements
+	= build_type_variant (WIDE_FLAG_TO_TYPE(wide_flag),
+			      1, 0);
+#else
       tree elements
 	= build_type_variant (wide_flag ? wchar_type_node : char_type_node,
 			      1, 0);
+#endif
+
       TREE_TYPE (value)
 	= build_array_type (elements,
 			    build_index_type (build_int_2 (nchars - 1, 0)));
     }
   else
+/* UTF_CHAR: type node for literal */
+#ifdef UTF_CHAR
+    TREE_TYPE (value)
+      = build_array_type (WIDE_FLAG_TO_TYPE(wide_flag),
+			  build_index_type (build_int_2 (nchars - 1, 0)));
+#else
     TREE_TYPE (value)
       = build_array_type (wide_flag ? wchar_type_node : char_type_node,
 			  build_index_type (build_int_2 (nchars - 1, 0)));
+#endif
 
   TREE_CONSTANT (value) = 1;
   TREE_READONLY (value) = ! flag_writable_strings;
@@ -2489,6 +2581,18 @@
   { NULL,                     0, 0, false, false, false, NULL }
 };
 
+
+/* UTF_CHAR: selection arrays for wide string literals */
+#ifdef UTF_CHAR
+
+int wide_type_size[WIDE_FLAG_LAST] = { 0 };
+
+tree wide_type_nodes[WIDE_FLAG_LAST] = { 0 };
+tree wide_array_type_nodes[WIDE_FLAG_LAST] = { 0 };
+
+#endif 
+
+
 /* Build tree nodes and builtin functions common to both C and C++ language
    frontends.  */
 
@@ -2684,6 +2788,32 @@
   /* This is for wide string constants.  */
   wchar_array_type_node
     = build_array_type (wchar_type_node, array_domain_type);
+
+/* UTF_CHAR: unicode literal types */
+#ifdef UTF_CHAR
+  u16char_type_node = short_unsigned_type_node;
+  u32char_type_node = unsigned_type_node;
+
+  u16char_array_type_node
+    = build_array_type (u16char_type_node, array_domain_type);
+  u32char_array_type_node
+    = build_array_type (u32char_type_node, array_domain_type);
+
+  wide_type_nodes[WIDE_FLAG_CHAR]  = char_type_node;
+  wide_type_nodes[WIDE_FLAG_WCHAR] = wchar_type_node;
+  wide_type_nodes[WIDE_FLAG_U16CHAR] = u16char_type_node;
+  wide_type_nodes[WIDE_FLAG_U32CHAR] = u32char_type_node;
+
+  wide_array_type_nodes[WIDE_FLAG_CHAR]  = char_array_type_node;
+  wide_array_type_nodes[WIDE_FLAG_WCHAR] = wchar_array_type_node;
+  wide_array_type_nodes[WIDE_FLAG_U16CHAR] = u16char_array_type_node;
+  wide_array_type_nodes[WIDE_FLAG_U32CHAR] = u32char_array_type_node;
+
+  wide_type_size[WIDE_FLAG_CHAR]  = CHAR_TYPE_SIZE;
+  wide_type_size[WIDE_FLAG_WCHAR] = WCHAR_TYPE_SIZE;
+  wide_type_size[WIDE_FLAG_U16CHAR] = TYPE_PRECISION(u16char_type_node);
+  wide_type_size[WIDE_FLAG_U32CHAR] = TYPE_PRECISION(u32char_type_node);
+#endif /* UTF_CHAR */
 
   wint_type_node =
     TREE_TYPE (identifier_global_value (get_identifier (WINT_TYPE)));
diff -ur ../gccorgrpm/gcc/c-common.h ./gcc/c-common.h
--- ../gccorgrpm/gcc/c-common.h	Fri May 16 18:21:04 2003
+++ ./gcc/c-common.h	Wed May 14 09:25:25 2003
@@ -153,6 +153,14 @@
     CTI_STRING_TYPE,
     CTI_CONST_STRING_TYPE,
 
+/* UTF_CHAR: unicode literal types */
+#ifdef UTF_CHAR
+    CTI_U16_CHAR_TYPE,
+    CTI_U32_CHAR_TYPE,
+    CTI_U16_ARRAY_TYPE,
+    CTI_U32_ARRAY_TYPE,
+#endif
+
     /* Type for boolean expressions (bool in C++, int in C).  */
     CTI_BOOLEAN_TYPE,
     CTI_BOOLEAN_TRUE,
@@ -214,6 +222,14 @@
 #define int_array_type_node		c_global_trees[CTI_INT_ARRAY_TYPE]
 #define string_type_node		c_global_trees[CTI_STRING_TYPE]
 #define const_string_type_node		c_global_trees[CTI_CONST_STRING_TYPE]
+
+/* UTF_CHAR: unicode literal types */
+#ifdef UTF_CHAR
+#define u16char_type_node               c_global_trees[CTI_U16_CHAR_TYPE]
+#define u32char_type_node               c_global_trees[CTI_U32_CHAR_TYPE]
+#define u16char_array_type_node		c_global_trees[CTI_U16_ARRAY_TYPE]
+#define u32char_array_type_node		c_global_trees[CTI_U32_ARRAY_TYPE]
+#endif
 
 #define default_function_type		c_global_trees[CTI_DEFAULT_FUNCTION_TYPE]
 
diff -ur ../gccorgrpm/gcc/c-lex.c ./gcc/c-lex.c
--- ../gccorgrpm/gcc/c-lex.c	Fri May 16 18:21:04 2003
+++ ./gcc/c-lex.c	Wed May 21 08:51:18 2003
@@ -119,6 +119,20 @@
       toplevel->time = body_time;
     }
   
+/* UTF_CHAR: support locale dependent unicode strings. Evaluate $(UGCC_LANG) */
+#ifdef UTF_CHAR
+  {
+    const char* ugcc_lang_env = NULL;
+    GET_ENVIRONMENT (ugcc_lang_env, "UGCC_LANG");
+    if( ugcc_lang_env!=NULL ) {
+      const char* setlocale_return = setlocale( LC_CTYPE, ugcc_lang_env );
+      if( setlocale_return==NULL || strcmp( ugcc_lang_env, setlocale_return) != 0 ) {
+         warning("setlocale $(UGCC_LANG) failed");
+      }
+    }
+  }
+#endif
+
 #ifdef MULTIBYTE_CHARS
   /* Change to the native locale for multibyte conversions.  */
   setlocale (LC_CTYPE, "");
@@ -240,7 +254,12 @@
   if (! flag_no_ident)
     {
       /* Convert escapes in the string.  */
+/* UTF_CHAR: lex_string - pass token type instead of boolean flag wide/not wide */
+#ifdef UTF_CHAR
+      tree value = lex_string (str->text, str->len, CPP_STRING);
+#else
       tree value = lex_string (str->text, str->len, 0);
+#endif
       ASM_OUTPUT_IDENT (asm_out_file, TREE_STRING_POINTER (value));
     }
 #endif
@@ -806,13 +825,27 @@
 
     case CPP_CHAR:
     case CPP_WCHAR:
+/* UTF_CHAR: lex unicode literals */
+#ifdef UTF_CHAR
+    case CPP_U16CHAR:
+    case CPP_U32CHAR:
+#endif
       *value = lex_charconst (tok);
       break;
 
     case CPP_STRING:
     case CPP_WSTRING:
+/* UTF_CHAR: lex strings also for U strings 
+   pass token type instead of boolean value to lex_string */
+#ifdef UTF_CHAR
+    case CPP_U16STRING:
+    case CPP_U32STRING:
+      *value = lex_string (tok->val.str.text, tok->val.str.len,
+			   tok->type);
+#else
       *value = lex_string (tok->val.str.text, tok->val.str.len,
 			   tok->type == CPP_WSTRING);
+#endif 
       break;
 
       /* These tokens should not be visible outside cpplib.  */
@@ -1299,32 +1332,71 @@
   return integer_zero_node;
 }
 
+/* UTF_CHAR: pass token type */
+#ifdef UTF_CHAR
+static tree
+lex_string (str, len, token_type)
+     const unsigned char *str;
+     unsigned int len;
+     int token_type;
+#else
 static tree
 lex_string (str, len, wide)
      const unsigned char *str;
      unsigned int len;
      int wide;
+#endif
+
 {
   tree value;
+/* UTF_CHAR: determine char type and width */
+#ifdef UTF_CHAR
+  enum wide_flag_type wide_flag = STRING_TOKEN_TYPE_TO_WIDE_FLAG( token_type );
+  int wide = wide_flag!=WIDE_FLAG_CHAR;
+  unsigned wide_bytes = WIDE_BYTES(wide_flag);
+  char *buf = alloca ((len + 1) * wide_bytes);
+#else
   char *buf = alloca ((len + 1) * (wide ? WCHAR_BYTES : 1));
+#endif
   char *q = buf;
   const unsigned char *p = str, *limit = str + len;
   unsigned int c;
+/* UTF_CHAR: determine char type and width */
+#ifdef UTF_CHAR
+  unsigned width = WIDE_WIDTH( wide_flag );
+#else
   unsigned width = wide ? WCHAR_TYPE_SIZE
 			: TYPE_PRECISION (char_type_node);
+#endif 
+
+/* UTF_CHAR: support locale dependent string conversion */
+#ifdef UTF_CHAR
+  #ifdef MULTIBYTE_CHARS
+    #define MULTIBYTE_CHARS_DEFINED
+  #endif
+  #define MULTIBYTE_CHARS
+#endif
 
 #ifdef MULTIBYTE_CHARS
   /* Reset multibyte conversion state.  */
-  (void) local_mbtowc (NULL, NULL, 0);
+  #ifdef UTF_CHAR
+    (void) mbtowc (NULL, NULL, 0);
+  #else
+    (void) local_mbtowc (NULL, NULL, 0);
+  #endif
 #endif
 
   while (p < limit)
-    {
+  {
 #ifdef MULTIBYTE_CHARS
       wchar_t wc;
       int char_len;
 
+#ifdef UTF_CHAR
+      char_len = mbtowc (&wc, (const char *) p, limit - p);
+#else
       char_len = local_mbtowc (&wc, (const char *) p, limit - p);
+#endif
       if (char_len == -1)
 	{
 	  warning ("ignoring invalid multibyte character");
@@ -1336,10 +1408,17 @@
 	  p += char_len;
 	  c = wc;
 	}
+
 #else
       c = *p++;
 #endif
 
+#ifdef UTF_CHAR
+  #ifndef MULTIBYTE_CHARS_DEFINED
+    #undef MULTIBYTE_CHARS
+  #endif
+#endif
+
       if (c == '\\' && !ignore_escape_flag)
 	{
 	  unsigned int mask;
@@ -1360,7 +1439,12 @@
 	  unsigned bytemask = (1 << charwidth) - 1;
 	  int byte;
 
+/* UTF_CHAR: use wide_bytes instead of WCHAR_BYTES */
+#ifdef UTF_CHAR
+	  for (byte = 0; byte < wide_bytes; ++byte)
+#else
 	  for (byte = 0; byte < WCHAR_BYTES; ++byte)
+#endif
 	    {
 	      int n;
 	      if (byte >= (int) sizeof (c))
@@ -1368,11 +1452,19 @@
 	      else
 		n = (c >> (byte * charwidth)) & bytemask;
 	      if (BYTES_BIG_ENDIAN)
+#ifdef UTF_CHAR
+		q[wide_bytes - byte - 1] = n;
+#else		
 		q[WCHAR_BYTES - byte - 1] = n;
+#endif		
 	      else
 		q[byte] = n;
 	    }
+#ifdef UTF_CHAR
+	  q += wide_bytes;
+#else	  
 	  q += WCHAR_BYTES;
+#endif	  
 	}
       else
 	{
@@ -1385,8 +1477,14 @@
 
   if (wide)
     {
+/* UTF_CHAR: use wide_bytes instead of WCHAR_BYTES */
+#ifdef UTF_CHAR
+      memset (q, 0, wide_bytes);
+      q += wide_bytes;
+#else
       memset (q, 0, WCHAR_BYTES);
       q += WCHAR_BYTES;
+#endif
     }
   else
     {
@@ -1395,10 +1493,15 @@
 
   value = build_string (q - buf, buf);
 
+/* UTF_CHAR: type for string literal */
+#ifdef UTF_CHAR
+  TREE_TYPE (value) = WIDE_FLAG_TO_ARRAY_TYPE( wide_flag );
+#else
   if (wide)
     TREE_TYPE (value) = wchar_array_type_node;
   else
     TREE_TYPE (value) = char_array_type_node;
+#endif 
   return value;
 }
 
@@ -1418,6 +1521,19 @@
       value = build_int_2 (result, 0);
       type = wchar_type_node;
     }
+/* UTF_CHAR: lex unicode character constants */
+#ifdef UTF_CHAR
+  else if (token->type == CPP_U16CHAR)
+    {
+      value = build_int_2 (result, 0);
+      type = u16char_type_node;
+    }
+  else if (token->type == CPP_U32CHAR)
+    {
+      value = build_int_2 (result, 0);
+      type = u32char_type_node;
+    }
+#endif
   else
     {
       if (result < 0)
diff -ur ../gccorgrpm/gcc/c-parse.in ./gcc/c-parse.in
--- ../gccorgrpm/gcc/c-parse.in	Fri May 16 18:23:29 2003
+++ ./gcc/c-parse.in	Fri May 16 17:39:39 2003
@@ -3582,7 +3582,12 @@
 
   if (last_token == CPP_EOF)
     error ("%s at end of input", string);
+#ifdef UTF_CHAR
+  else if (last_token == CPP_CHAR || last_token == CPP_WCHAR 
+           || last_token == CPP_U16CHAR || last_token == CPP_U32CHAR)
+#else
   else if (last_token == CPP_CHAR || last_token == CPP_WCHAR)
+#endif
     {
       unsigned int val = TREE_INT_CST_LOW (yylval.ttype);
       const char *const ell = (last_token == CPP_CHAR) ? "" : "L";
@@ -3592,7 +3597,12 @@
 	error ("%s before %s'\\x%x'", string, ell, val);
     }
   else if (last_token == CPP_STRING
-	   || last_token == CPP_WSTRING)
+	   || last_token == CPP_WSTRING
+#ifdef UTF_CHAR
+	   || last_token == CPP_U16STRING
+	   || last_token == CPP_U32STRING
+#endif
+          )	   
     error ("%s before string constant", string);
   else if (last_token == CPP_NUMBER)
     error ("%s before numeric constant", string);
@@ -3745,10 +3755,18 @@
     case CPP_NUMBER:
     case CPP_CHAR:
     case CPP_WCHAR:
+#ifdef UTF_CHAR
+    case CPP_U16CHAR:
+    case CPP_U32CHAR:
+#endif    
       return CONSTANT;
 
     case CPP_STRING:
     case CPP_WSTRING:
+#ifdef UTF_CHAR
+    case CPP_U16STRING:
+    case CPP_U32STRING:
+#endif    
       return STRING;
       
       /* This token is Objective-C specific.  It gives the next token
diff -ur ../gccorgrpm/gcc/c-typeck.c ./gcc/c-typeck.c
--- ../gccorgrpm/gcc/c-typeck.c	Fri May 16 18:21:04 2003
+++ ./gcc/c-typeck.c	Wed May 14 10:24:54 2003
@@ -4691,7 +4691,12 @@
 	   || typ1 == signed_char_type_node
 	   || typ1 == unsigned_char_type_node
 	   || typ1 == unsigned_wchar_type_node
-	   || typ1 == signed_wchar_type_node)
+	   || typ1 == signed_wchar_type_node
+#ifdef UTF_CHAR
+	   || typ1 == u16char_type_node
+	   || typ1 == u32char_type_node
+#endif
+	   )
 	  && ((inside_init && TREE_CODE (inside_init) == STRING_CST)))
 	{
 	  if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)),
@@ -4720,6 +4725,12 @@
 	      /* Subtract 1 (or sizeof (wchar_t))
 		 because it's ok to ignore the terminating null char
 		 that is counted in the length of the constant.  */
+/* UTF_CHAR: adapt subtract 1 for unicode literals */
+#ifdef UTF_CHAR
+	      && 0 > compare_tree_int (TYPE_SIZE_UNIT (type),
+				       TREE_STRING_LENGTH (inside_init)
+				       - TYPE_PRECISION(typ1)/BITS_PER_UNIT))
+#else
 	      && 0 > compare_tree_int (TYPE_SIZE_UNIT (type),
 				       TREE_STRING_LENGTH (inside_init)
 				       - ((TYPE_PRECISION (typ1)
@@ -4727,6 +4738,7 @@
 					  ? (TYPE_PRECISION (wchar_type_node)
 					     / BITS_PER_UNIT)
 					  : 1)))
+#endif
 	    pedwarn_init ("initializer-string for array of chars is too long");
 
 	  return inside_init;
@@ -6087,6 +6099,10 @@
   if (TREE_CODE (constructor_type) != ARRAY_TYPE)
     abort ();
 
+/* UTF_CHAR */
+#ifdef UTF_CHAR
+  wchar_bytes = TYPE_PRECISION (TREE_TYPE (TREE_TYPE (str))) / BITS_PER_UNIT;
+#else
   if (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (str)))
       == TYPE_PRECISION (char_type_node))
     wchar_bytes = 1;
@@ -6095,6 +6111,7 @@
     wchar_bytes = TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT;
   else
     abort ();
+#endif
 
   charwidth = TYPE_PRECISION (char_type_node);
   type = TREE_TYPE (constructor_type);
diff -ur ../gccorgrpm/gcc/cp/spew.c ./gcc/cp/spew.c
--- ../gccorgrpm/gcc/cp/spew.c	Fri May 16 18:21:38 2003
+++ ./gcc/cp/spew.c	Wed May 14 10:33:39 2003
@@ -331,11 +331,19 @@
     case CPP_NUMBER:
     case CPP_CHAR:
     case CPP_WCHAR:
+#ifdef UTF_CHAR
+    case CPP_U16CHAR:
+    case CPP_U32CHAR:
+#endif
       t->yychar = CONSTANT;
       break;
 
     case CPP_STRING:
     case CPP_WSTRING:
+#ifdef UTF_CHAR
+    case CPP_U16STRING:
+    case CPP_U32STRING:
+#endif
       t->yychar = STRING;
       break;
 
@@ -1475,7 +1483,11 @@
 
   if (last_token == CPP_EOF)
     error ("%s at end of input", string);
+#ifdef UTF_CHAR
+  else if (last_token == CPP_CHAR || last_token == CPP_WCHAR || last_token == CPP_U16CHAR || last_token == CPP_U32CHAR)
+#else
   else if (last_token == CPP_CHAR || last_token == CPP_WCHAR)
+#endif
     {
       unsigned int val = TREE_INT_CST_LOW (yylval.ttype);
       const char *const ell = (last_token == CPP_CHAR) ? "" : "L";
@@ -1485,7 +1497,12 @@
 	error ("%s before %s'\\x%x'", string, ell, val);
     }
   else if (last_token == CPP_STRING
-	   || last_token == CPP_WSTRING)
+	   || last_token == CPP_WSTRING
+#ifdef UTF_CHAR
+	   || last_token == CPP_U16STRING
+	   || last_token == CPP_U32STRING
+#endif
+	  )
     error ("%s before string constant", string);
   else if (last_token == CPP_NUMBER)
     error ("%s before numeric constant", string);
diff -ur ../gccorgrpm/gcc/cp/tree.c ./gcc/cp/tree.c
--- ../gccorgrpm/gcc/cp/tree.c	Fri May 16 18:21:38 2003
+++ ./gcc/cp/tree.c	Wed May 14 10:25:09 2003
@@ -2483,7 +2483,12 @@
   return (same_type_p (type, char_type_node)
 	  || same_type_p (type, unsigned_char_type_node)
 	  || same_type_p (type, signed_char_type_node)
-	  || same_type_p (type, wchar_type_node));
+	  || same_type_p (type, wchar_type_node)
+#ifdef UTF_CHAR
+	  || same_type_p (type, u16char_type_node)
+	  || same_type_p (type, u32char_type_node)
+#endif
+	 );
 }
 
 /* Returns the kind of linkage associated with the indicated DECL.  Th
diff -ur ../gccorgrpm/gcc/cp/typeck.c ./gcc/cp/typeck.c
--- ../gccorgrpm/gcc/cp/typeck.c	Fri May 16 18:21:38 2003
+++ ./gcc/cp/typeck.c	Wed May 14 10:27:23 2003
@@ -1793,7 +1793,12 @@
 
   t = TREE_TYPE (totype);
   if (!same_type_p (t, char_type_node)
-      && !same_type_p (t, wchar_type_node))
+      && !same_type_p (t, wchar_type_node)
+#ifdef UTF_CHAR
+      && !same_type_p (t, u16char_type_node)
+      && !same_type_p (t, u32char_type_node)
+#endif      
+     )
     return 0;
 
   if (TREE_CODE (exp) == STRING_CST)
diff -ur ../gccorgrpm/gcc/cppexp.c ./gcc/cppexp.c
--- ../gccorgrpm/gcc/cppexp.c	Fri May 16 18:21:05 2003
+++ ./gcc/cppexp.c	Wed May 14 10:04:58 2003
@@ -290,6 +290,10 @@
 
     case CPP_CHAR:
     case CPP_WCHAR:
+#ifdef UTF_CHAR
+    case CPP_U16CHAR:
+    case CPP_U32CHAR:
+#endif
       {
 	unsigned int chars_seen;
 
@@ -304,6 +308,10 @@
 
     case CPP_STRING:
     case CPP_WSTRING:
+#ifdef UTF_CHAR
+    case CPP_U16STRING:
+    case CPP_U32STRING:
+#endif
       SYNTAX_ERROR ("string constants are not valid in #if");
 
     case CPP_OTHER:
diff -ur ../gccorgrpm/gcc/cpplex.c ./gcc/cpplex.c
--- ../gccorgrpm/gcc/cpplex.c	Fri May 16 18:21:05 2003
+++ ./gcc/cpplex.c	Wed May 21 10:23:47 2003
@@ -25,6 +25,13 @@
 #include "cpplib.h"
 #include "cpphash.h"
 
+/* UTF_CHAR selection arrays for wide string literals */
+#ifdef UTF_CHAR
+enum cpp_ttype wide_char_token_type[WIDE_FLAG_LAST] = { CPP_CHAR, CPP_WCHAR, CPP_U16CHAR, CPP_U32CHAR };
+enum cpp_ttype wide_string_token_type[WIDE_FLAG_LAST] = { CPP_STRING, CPP_WSTRING, CPP_U16STRING, CPP_U32STRING };
+#endif 
+
+
 /* MULTIBYTE_CHARS support only works for native compilers.
    ??? Ideally what we want is to model widechar support after
    the current floating point support.  */
@@ -980,13 +987,33 @@
 
     case 'L':
       /* 'L' may introduce wide characters or strings.  */
+/* UTF_CHAR: literals may also start with u,U */
+#ifdef UTF_CHAR
+    case 'U':
+    case 'u':
+#endif
 	{
+/* UTF_CHAR: keep literal introducer */
+#ifdef UTF_CHAR
+          int c_old = c;
+#endif
 	  const unsigned char *pos = buffer->cur;
 
 	  c = get_effective_char (pfile);
 	  if (c == '\'' || c == '"')
 	    {
+/* UTF_CHAR: new token types for u literals */
+#ifdef UTF_CHAR
+          enum wide_flag_type wide_flag = LITERAL_TO_WIDE_FLAG(c_old);
+          result->type = 
+            (c == '"' ? 
+              WIDE_FLAG_TO_STRING_TOKEN_TYPE(wide_flag) : 
+              WIDE_FLAG_TO_CHAR_TOKEN_TYPE(wide_flag) 
+            );
+#else
 	      result->type = (c == '"' ? CPP_WSTRING: CPP_WCHAR);
+#endif
+
 	      parse_string (pfile, result, c);
 	      break;
 	    }
@@ -999,12 +1026,22 @@
     case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
     case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
     case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
+/* UTF_CHAR: u can introduce literal */
+#ifdef UTF_CHAR
+    case 's': case 't':           case 'v': case 'w': case 'x':
+#else
     case 's': case 't': case 'u': case 'v': case 'w': case 'x':
+#endif
     case 'y': case 'z':
     case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
     case 'G': case 'H': case 'I': case 'J': case 'K':
     case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
+/* UTF_CHAR: U can introduce literal */
+#ifdef UTF_CHAR
+    case 'S': case 'T':           case 'V': case 'W': case 'X':
+#else
     case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
+#endif 
     case 'Y': case 'Z':
       result->type = CPP_NAME;
       result->val.node = parse_identifier (pfile);
@@ -1362,6 +1399,12 @@
 	  case CPP_WSTRING:	left = '"';  right = '"';  tag = 'L';  break;
 	  case CPP_CHAR:	left = '\''; right = '\''; tag = '\0'; break;
     	  case CPP_WCHAR:	left = '\''; right = '\''; tag = 'L';  break;
+#ifdef UTF_CHAR
+	  case CPP_U16STRING:	left = '"';  right = '"';  tag = 'u'; break;
+	  case CPP_U32STRING:	left = '"';  right = '"';  tag = 'U';  break;
+	  case CPP_U16CHAR:	left = '\''; right = '\''; tag = 'u'; break;
+    	  case CPP_U32CHAR:	left = '\''; right = '\''; tag = 'U';  break;
+#endif
 	  case CPP_HEADER_NAME:	left = '<';  right = '>';  tag = '\0'; break;
 	  default:
 	    cpp_ice (pfile, "unknown string token %s\n", TOKEN_NAME (token));
@@ -1460,6 +1503,12 @@
 	  case CPP_WSTRING:	left = '"';  right = '"';  tag = 'L';  break;
 	  case CPP_CHAR:	left = '\''; right = '\''; tag = '\0'; break;
     	  case CPP_WCHAR:	left = '\''; right = '\''; tag = 'L';  break;
+#ifdef UTF_CHAR
+	  case CPP_U16STRING:	left = '"';  right = '"';  tag = 'u'; break;
+	  case CPP_U32STRING:	left = '"';  right = '"';  tag = 'U';  break;
+	  case CPP_U16CHAR:	left = '\''; right = '\''; tag = 'u'; break;
+    	  case CPP_U32CHAR:	left = '\''; right = '\''; tag = 'U';  break;
+#endif
 	  case CPP_HEADER_NAME:	left = '<';  right = '>';  tag = '\0'; break;
 	  default:
 	    fprintf (stderr, "impossible STRING token %s\n", TOKEN_NAME (token));
@@ -1839,8 +1888,20 @@
   HOST_WIDE_INT result = 0;
   bool unsigned_p;
 
+/* UTF_CHAR: support locale dependent string conversion */
+#ifdef UTF_CHAR
+  #ifdef MULTIBYTE_CHARS
+    #define MULTIBYTE_CHARS_DEFINED
+  #endif
+  #define MULTIBYTE_CHARS
+#endif
+
 #ifdef MULTIBYTE_CHARS
-  (void) local_mbtowc (NULL, NULL, 0);
+  #ifdef UTF_CHAR
+    (void) mbtowc (NULL, NULL, 0);
+  #else
+    (void) local_mbtowc (NULL, NULL, 0);
+  #endif
 #endif
 
   /* Width in bits.  */
@@ -1867,7 +1928,11 @@
       wchar_t wc;
       int char_len;
 
+#ifdef UTF_CHAR
+      char_len = mbtowc (&wc, str, limit - str);
+#else
       char_len = local_mbtowc (&wc, str, limit - str);
+#endif
       if (char_len == -1)
 	{
 	  cpp_warning (pfile, "ignoring invalid multibyte character");
@@ -1880,6 +1945,12 @@
 	}
 #else
       c = *str++;
+#endif
+
+#ifdef UTF_CHAR
+  #ifndef MULTIBYTE_CHARS_DEFINED
+    #undef MULTIBYTE_CHARS
+  #endif
 #endif
 
       if (c == '\\')
diff -ur ../gccorgrpm/gcc/cpplib.h ./gcc/cpplib.h
--- ../gccorgrpm/gcc/cpplib.h	Fri May 16 18:21:05 2003
+++ ./gcc/cpplib.h	Wed May 14 10:31:41 2003
@@ -23,6 +23,9 @@
 #ifndef GCC_CPPLIB_H
 #define GCC_CPPLIB_H
 
+/* UTF_CHAR: activation */
+#define UTF_CHAR
+
 #include <sys/types.h>
 #include "hashtable.h"
 #include "line-map.h"
@@ -126,10 +129,18 @@
 \
   TK(CPP_CHAR,		SPELL_STRING)	/* 'char' */			\
   TK(CPP_WCHAR,		SPELL_STRING)	/* L'char' */			\
+  /* UTF_CHAR: token types begin */                                     \
+  TK(CPP_U16CHAR,	SPELL_STRING)	/* u'char' */			\
+  TK(CPP_U32CHAR,	SPELL_STRING)	/* U'char' */			\
+  /* UTF_CHAR: token types end */                                       \
   TK(CPP_OTHER,		SPELL_CHAR)	/* stray punctuation */		\
 \
   TK(CPP_STRING,	SPELL_STRING)	/* "string" */			\
   TK(CPP_WSTRING,	SPELL_STRING)	/* L"string" */			\
+  /* UTF_CHAR: token types begin */                                     \
+  TK(CPP_U16STRING,	SPELL_STRING)	/* u"string" */			\
+  TK(CPP_U32STRING,	SPELL_STRING)	/* U"string" */			\
+  /* UTF_CHAR: token types end */                                       \
   TK(CPP_HEADER_NAME,	SPELL_STRING)	/* <stdio.h> in #include */	\
 \
   TK(CPP_COMMENT,	SPELL_NUMBER)	/* Only if output comments.  */ \
@@ -599,6 +610,89 @@
 /* In cppfiles.c */
 extern int cpp_included	PARAMS ((cpp_reader *, const char *));
 extern void cpp_make_system_header PARAMS ((cpp_reader *, int, int));
+
+/* UTF_CHAR: enums and selection macros for wide string literals */
+#ifdef UTF_CHAR
+
+/* enum to distinguish between char, wchar and unicode char */
+enum wide_flag_type
+{
+  WIDE_FLAG_CHAR = 0,
+  WIDE_FLAG_WCHAR,
+  WIDE_FLAG_U16CHAR,
+  WIDE_FLAG_U32CHAR,
+  WIDE_FLAG_LAST
+};
+
+/* determine if wchar or unicode char from string literal prefix ('L' or 'U') */
+#define LITERAL_TO_WIDE_FLAG(PREFIX) \
+  ((PREFIX)=='L' ?                   \
+    WIDE_FLAG_WCHAR :                \
+  (PREFIX)=='u' ?                    \
+    WIDE_FLAG_U16CHAR :              \
+  (PREFIX)=='U' ?                    \
+    WIDE_FLAG_U32CHAR :              \
+    WIDE_FLAG_CHAR                   \
+  )
+
+/* determine wide flag from token type */
+#define STRING_TOKEN_TYPE_TO_WIDE_FLAG(TOKEN_TYPE)  \
+  ((TOKEN_TYPE)==CPP_STRING ?                       \
+    WIDE_FLAG_CHAR :                                \
+  (TOKEN_TYPE)==CPP_WSTRING ?                       \
+    WIDE_FLAG_WCHAR :                               \
+  (TOKEN_TYPE)==CPP_U16STRING ?                     \
+    WIDE_FLAG_U16CHAR :                             \
+  (TOKEN_TYPE)==CPP_U32STRING ?                     \
+    WIDE_FLAG_U32CHAR :                             \
+    WIDE_FLAG_CHAR                                  \
+  )
+
+/* determine wide flag from tree type */
+#define TREE_TYPE_TO_WIDE_FLAG(NODE) \
+ ((NODE)==char_type_node ?           \
+    WIDE_FLAG_CHAR :                 \
+ (NODE)==wchar_type_node ?           \
+   WIDE_FLAG_WCHAR :                 \
+ (NODE)==short_unsigned_type_node ?  \
+   WIDE_FLAG_U16CHAR :               \
+ (NODE)==unsigned_type_node ?        \
+   WIDE_FLAG_U32CHAR :               \
+   WIDE_FLAG_CHAR                    \
+ )
+
+#define TREE_ARRAY_TYPE_TO_WIDE_FLAG(NODE) \
+ ((NODE)==char_array_type_node ?           \
+  WIDE_FLAG_CHAR :                         \
+ (NODE)==wchar_array_type_node ?           \
+   WIDE_FLAG_WCHAR :                       \
+ (NODE)==u16char_array_type_node ?         \
+   WIDE_FLAG_U16CHAR :                     \
+ (NODE)==u32char_array_type_node ?         \
+   WIDE_FLAG_U32CHAR :                     \
+   WIDE_FLAG_CHAR                          \
+ )
+
+/* determine token type for wide literals */
+
+extern enum cpp_ttype wide_char_token_type[WIDE_FLAG_LAST];
+#define WIDE_FLAG_TO_CHAR_TOKEN_TYPE(WIDE_FLAG)  (wide_char_token_type[(WIDE_FLAG)])
+
+extern enum cpp_ttype wide_string_token_type[WIDE_FLAG_LAST];
+#define WIDE_FLAG_TO_STRING_TOKEN_TYPE(WIDE_FLAG)  (wide_string_token_type[(WIDE_FLAG)])
+
+/* type nodes for character types */
+extern tree wide_type_nodes[WIDE_FLAG_LAST];
+extern tree wide_array_type_nodes[WIDE_FLAG_LAST];
+#define WIDE_FLAG_TO_TYPE(WIDE_FLAG) (wide_type_nodes[(WIDE_FLAG)])
+#define WIDE_FLAG_TO_ARRAY_TYPE(WIDE_FLAG) (wide_array_type_nodes[(WIDE_FLAG)])
+
+/* type node size for character types */
+extern int wide_type_size[WIDE_FLAG_LAST];
+#define WIDE_WIDTH(WIDE_FLAG) (wide_type_size[(WIDE_FLAG)])
+#define WIDE_BYTES(WIDE_FLAG) (wide_type_size[(WIDE_FLAG)]/BITS_PER_UNIT)
+
+#endif /* UTF_CHAR */
 
 #ifdef __cplusplus
 }
diff -ur ../gccorgrpm/gcc/cppmacro.c ./gcc/cppmacro.c
--- ../gccorgrpm/gcc/cppmacro.c	Fri May 16 18:21:05 2003
+++ ./gcc/cppmacro.c	Wed May 14 10:11:10 2003
@@ -297,7 +297,12 @@
 	}
 
       escape_it = (token->type == CPP_STRING || token->type == CPP_WSTRING
-		   || token->type == CPP_CHAR || token->type == CPP_WCHAR);
+		   || token->type == CPP_CHAR || token->type == CPP_WCHAR
+#ifdef UTF_CHAR
+                   || token->type == CPP_U16STRING || token->type == CPP_U32STRING
+                   || token->type == CPP_U16CHAR || token->type == CPP_U32CHAR
+#endif		   
+		   );
 
       /* Room for each char being written in octal, initial space and
 	 final NUL.  */
diff -ur ../gccorgrpm/gcc/cppmain.c ./gcc/cppmain.c
--- ../gccorgrpm/gcc/cppmain.c	Fri May 16 18:21:06 2003
+++ ./gcc/cppmain.c	Wed May 14 10:13:23 2003
@@ -260,6 +260,9 @@
       cpp_output_token (token, print.outf);
 
       if (token->type == CPP_STRING || token->type == CPP_WSTRING
+#ifdef UTF_CHAR
+          || token->type == CPP_U16STRING || token->type == CPP_U32STRING
+#endif
 	  || token->type == CPP_COMMENT)
 	check_multiline_token (&token->val.str);
     }
