about summary refs log tree commit diff
path: root/stdio-common/vfscanf-internal.c
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2023-09-28 17:27:58 +0000
committerJoseph Myers <joseph@codesourcery.com>2023-09-28 17:28:15 +0000
commitcdbf8229bb1438998b211e4760a97d94a13674d4 (patch)
treec3253d92a5c54051f664dcee3c64372df858f741 /stdio-common/vfscanf-internal.c
parentaea4ddb87168d0475777e605f3bb576b0f62b3a2 (diff)
downloadglibc-cdbf8229bb1438998b211e4760a97d94a13674d4.tar.gz
glibc-cdbf8229bb1438998b211e4760a97d94a13674d4.tar.xz
glibc-cdbf8229bb1438998b211e4760a97d94a13674d4.zip
C2x scanf %wN, %wfN support
ISO C2x defines scanf length modifiers wN (for intN_t / int_leastN_t /
uintN_t / uint_leastN_t) and wfN (for int_fastN_t / uint_fastN_t).
Add support for those length modifiers, similar to the printf support
previously added.

Tested for x86_64 and x86.
Diffstat (limited to 'stdio-common/vfscanf-internal.c')
-rw-r--r--stdio-common/vfscanf-internal.c48
1 files changed, 48 insertions, 0 deletions
diff --git a/stdio-common/vfscanf-internal.c b/stdio-common/vfscanf-internal.c
index 9b1197d751..cacb9668ba 100644
--- a/stdio-common/vfscanf-internal.c
+++ b/stdio-common/vfscanf-internal.c
@@ -381,6 +381,7 @@ __vfscanf_internal (FILE *s, const char *format, va_list argptr,
   while (*f != '\0')
     {
       unsigned int argpos;
+      bool is_fast;
       /* Extract the next argument, which is of type TYPE.
 	 For a %N$... spec, this is the Nth argument from the beginning;
 	 otherwise it is the next argument after the state now in ARG.  */
@@ -602,6 +603,53 @@ __vfscanf_internal (FILE *s, const char *format, va_list argptr,
 	  else if (sizeof (ptrdiff_t) > sizeof (int))
 	    flags |= LONG;
 	  break;
+	case L_('w'):
+	  {
+	    is_fast = false;
+	    if (*f == L_('f'))
+	      {
+		++f;
+		is_fast = true;
+	      }
+	    int bitwidth = 0;
+	    if (ISDIGIT (*f))
+	      bitwidth = read_int (&f);
+	    if (is_fast)
+	      switch (bitwidth)
+		{
+		case 8:
+		  bitwidth = INT_FAST8_WIDTH;
+		  break;
+		case 16:
+		  bitwidth = INT_FAST16_WIDTH;
+		  break;
+		case 32:
+		  bitwidth = INT_FAST32_WIDTH;
+		  break;
+		case 64:
+		  bitwidth = INT_FAST64_WIDTH;
+		  break;
+		}
+	    switch (bitwidth)
+	      {
+	      case 8:
+		flags |= CHAR;
+		break;
+	      case 16:
+		flags |= SHORT;
+		break;
+	      case 32:
+		break;
+	      case 64:
+		flags |= LONGDBL | LONG;
+		break;
+	      default:
+		/* ISO C requires this error to be detected.  */
+		__set_errno (EINVAL);
+		goto errout;
+	      }
+	  }
+	  break;
 	default:
 	  /* Not a recognized modifier.  Backup.  */
 	  --f;