about summary refs log tree commit diff
path: root/stdio-common/vfscanf.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2000-02-11 18:50:36 +0000
committerUlrich Drepper <drepper@redhat.com>2000-02-11 18:50:36 +0000
commita1d84548c8aa7023cd039c85f81b831eef6d4a4c (patch)
treed4f80547dd8c427aebbf0b43051d01206ea972ae /stdio-common/vfscanf.c
parentf296f567c3f69fd2a61983f464d5c52174e3bab8 (diff)
downloadglibc-a1d84548c8aa7023cd039c85f81b831eef6d4a4c.tar.gz
glibc-a1d84548c8aa7023cd039c85f81b831eef6d4a4c.tar.xz
glibc-a1d84548c8aa7023cd039c85f81b831eef6d4a4c.zip
Update.
2000-02-11  Ulrich Drepper  <drepper@redhat.com>

	* stdio-common/printf-parse.h (parse_one_spec): Set wide elements.

	* stdio-common/printf_fp.c: Truely support wide characater output.
	Finally handle decimal points and thousands separator characters
	correctly for multibyte output.
	* stdio-common/printf_size.c: Likewise.
	* sysdeps/generic/printf_fphex.c: Likewise.
	* sysdeps/ieee754/ldbl-96/printf_fphex.c: Likewise.

	* stdio-common/vfscanf.c: Implement I modifier for numbers to read
	locale dependent digits.

	* locale/C-monetary.c (_nl_C_LC_MONETARY): Change wide character
	decimal point and thousands separator values to wide characters from
	wide character strings.
	* locale/C-numeric.c (_nl_C_LC_NUMERIC): Likewise.

	* locale/indigitswc.h: Dereference wcdigits array elements.

2000-02-03  Jakub Jelinek  <jakub@redhat.com>

	* stdlib/canonicalize.c (canonicalize): Zero terminate
	path to copy on error.

2000-02-01  Cristian Gafton  <gafton@redhat.com>

	* misc/syslog.c (closelog): Reset LogType to SOCK_DGRAM.

2000-01-31  Philip Blundell  <philb@gnu.org>

	* sysdeps/arm/fpu/fpu_control.h (_FPU_DEFAULT): Set the AC bit.

2000-01-31  Andreas Jaeger  <aj@suse.de>

	* intl/Makefile (generated): msgs.h is generated.

	* localedata/Makefile (generated-dirs): Add de_DE.437.

2000-01-31  Jakub Jelinek  <jakub@redhat.com>

	* config.make.in: Allow default localedir to come from configure.
	* configure.in: Export libc_cv_localedir.
	* sysdeps/unix/sysv/linux/configure.in: For sparc64, put locale
	stuff into $exec_prefix/lib/locale because it can be shared between
	32bit and 64bit libraries.
	* configure: Rebuilt.
	* sysdeps/unix/sysv/linux/configure: Rebuilt.

2000-01-31  Andreas Jaeger  <aj@suse.de>

	* inet/tst-network.c: New file.
	* inet/Makefile (tests): Add tst-network.

	* inet/inet_net.c (inet_network): Don't overwrite memory or allow
	to great last digits.
Diffstat (limited to 'stdio-common/vfscanf.c')
-rw-r--r--stdio-common/vfscanf.c150
1 files changed, 135 insertions, 15 deletions
diff --git a/stdio-common/vfscanf.c b/stdio-common/vfscanf.c
index b50e7b8323..6b95352971 100644
--- a/stdio-common/vfscanf.c
+++ b/stdio-common/vfscanf.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991,92,93,94,95,96,97,98,99 Free Software Foundation, Inc.
+/* Copyright (C) 1991-1999, 2000 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -62,6 +62,7 @@
 #define GROUP		0x080	/* ': group numbers */
 #define MALLOC		0x100	/* a: malloc strings */
 #define CHAR		0x200	/* hh: char */
+#define I18N		0x400	/* I: use locale's digits */
 
 
 #ifdef USE_IN_LIBIO
@@ -479,8 +480,9 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
 	    }
 	}
 
-      /* Check for the assignment-suppressing and the number grouping flag.  */
-      while (*f == L_('*') || *f == L_('\''))
+      /* Check for the assignment-suppressing, the number grouping flag,
+	 and the signal to use the locale's digit representation.  */
+      while (*f == L_('*') || *f == L_('\'') || *f == L_('I'))
 	switch (*f++)
 	  {
 	  case L_('*'):
@@ -489,6 +491,9 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
 	  case L_('\''):
 	    flags |= GROUP;
 	    break;
+	  case L_('I'):
+	    flags |= I18N;
+	    break;
 	  }
 
       /* We have seen width. */
@@ -1192,22 +1197,137 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
 	  if (base == 0)
 	    base = 10;
 
-	  /* Read the number into workspace.  */
-	  while (c != EOF && width != 0)
+	  if (base == 10 && (flags & I18N) != 0)
 	    {
-	      if (base == 16 ? !ISXDIGIT (c) :
-		  ((!ISDIGIT (c) || c - L_('0') >= base) &&
-		   !((flags & GROUP) && base == 10 && c == thousands)))
-		break;
-	      ADDW (c);
-	      if (width > 0)
-		--width;
+	      int from_level;
+	      int to_level;
+#ifdef COMPILE_WPRINTF
+	      const wchar_t *wcdigits;
+#else
+	      const char *mbdigits[10];
+#endif
+	      int n;
 
-	      c = inchar ();
+	      from_level = 0;
+#ifdef COMPILE_WPRINTF
+	      to_level = _NL_CURRENT_WORD (LC_CTYPE,
+					   _NL_CTYPE_INDIGITS_WC_LEN) - 1;
+#else
+	      to_level = _NL_CURRENT_WORD (LC_CTYPE,
+					   _NL_CTYPE_INDIGITS_MB_LEN) - 1;
+#endif
+
+	      /* In this round we get the pointer to the digit strings
+		 and also perform the first round of comparisons.  */
+	      for (n = 0; n < 10; ++n)
+		{
+		  size_t dlen;
+		  size_t dcnt;
+
+		  /* Get the string for the digits with value N.  */
+#ifdef COMPILE_WPRINTF
+		  wcdigits[n] = _NL_CURRENT (LC_CTYPE,
+					     _NL_CTYPE_INDIGITS0_WC + n);
+		  if (c == *wcdigit[n])
+		    break;
+
+		  /* Advance the pointer to the next string.  */
+		  ++wcdigits[n];
+#else
+		  mbdigits[n] = _NL_CURRENT (LC_CTYPE,
+					     _NL_CTYPE_INDIGITS0_MB + n);
+		  dlen = strlen (mbdigits[n]);
+
+		  dcnt = 0;
+		  do
+		    {
+		      if (c != mbdigits[n][dcnt])
+			break;
+		      c = inchar ();
+		    }
+		  while (--dcnt > 0);
+
+		  if (dcnt == 0)
+		    /* We found it.  */
+		    break;
+
+		  /* Advance the pointer to the next string.  */
+		  mbdigits[n] += dlen + 1;
+		}
+#endif
+
+	      if (n == 10)
+		{
+		  /*Have not yet found the digit.  */
+		  while (++from_level <= to_level)
+		    {
+		      /* Search all ten digits of this level.  */
+		      for (n = 0; n < 10; ++n)
+			{
+#ifdef COMPILE_WPRINTF
+			  if (c == *wcdigit[n])
+			    break;
+
+			  /* Advance the pointer to the next string.  */
+			  ++wcdigits[n];
+#else
+			  size_t dlen = strlen (mbdigits[n]);
+			  size_t dcnt;
+
+			  dcnt = 0;
+			  do
+			    {
+			      if (c != mbdigits[n][dcnt])
+				break;
+			      c = inchar ();
+			    }
+			  while (--dcnt > 0);
+
+			  if (dcnt == 0)
+			    /* We found it.  */
+			    break;
+
+			  /* Advance the pointer to the next string.  */
+			  mbdigits[n] += dlen + 1;
+#endif
+			}
+
+		      if (n < 10)
+			/* Found it.  */
+			break;
+
+		      /* Next level.  */
+		      ++from_level;
+		    }
+		}
+
+	      if (n == 10)
+		{
+		  /* Haven't found anything.  Push the last character back
+		     and return an error.  */
+		  ungetc (c, s);
+		  input_error ();
+		}
+
+	      ADDW (L_('0') + n);
 	    }
+	  else
+	    /* Read the number into workspace.  */
+	    while (c != EOF && width != 0)
+	      {
+		if (base == 16 ? !ISXDIGIT (c) :
+		    ((!ISDIGIT (c) || c - L_('0') >= base) &&
+		     !((flags & GROUP) && base == 10 && c == thousands)))
+		  break;
+		ADDW (c);
+		if (width > 0)
+		  --width;
+
+		c = inchar ();
+	      }
 
-	  if (wpsize == 0 ||
-	      (wpsize == 1 && (wp[0] == L_('+') || wp[0] == L_('-'))))
+	  if (wpsize == 0
+	      || (wpsize == 1 && (wp[0] == L_('+') || wp[0] == L_('-'))))
 	    {
 	      /* There was no number.  If we are supposed to read a pointer
 		 we must recognize "(nil)" as well.  */