[patch] handle C99 j, t, and z flags in sscanf

Jeff Johnston jjohnstn@redhat.com
Tue Apr 17 22:40:00 GMT 2007


Patch applied.  I needed to modify vfscanf.c to include stdint.h and the 
test case needed modification because the current newlib stdint.h 
doesn't define INTMAX_MIN nor INTMAX_MAX.  Test case did run 
successfully after that though.

-- Jeff J.

Brian Dessent wrote:
> This patch enables support for the sscanf modifiers j (intmax_t), t
> (ptrdiff_t), and z (size_t).  The support was already present in
> vfprintf.c, so this is really just a copy and paste of the logic into
> sscanf.c.
> 
> I updated the inline documentation comments to mention the flags.  The
> corresponding docs for sprintf should really be updated too since they
> don't mention them either, but I figured that could be done with another
> patch.
> 
> I'm also attaching the brief testcase that I came up with as a sanity
> check.  It simply round-trips %jd, %td, and %zu through sprintf/sscanf
> and verifies the result.
> 
> Brian
> 
> 
> ------------------------------------------------------------------------
> 
> 2007-04-17  Brian Dessent  <brian@dessent.net>
> 
> 	* libc/stdio/sscanf.c: Update documentation comments.
> 	(__SVFSCANF_R): Handle j, t, and z modifiers.
> 
> Index: libc/stdio/sscanf.c
> ===================================================================
> RCS file: /cvs/src/src/newlib/libc/stdio/sscanf.c,v
> retrieving revision 1.9
> diff -u -p -r1.9 sscanf.c
> --- libc/stdio/sscanf.c	28 Oct 2005 21:38:59 -0000	1.9
> +++ libc/stdio/sscanf.c	17 Apr 2007 18:48:19 -0000
> @@ -147,9 +147,9 @@ DESCRIPTION
>  		Then <<scanf>> proceeds to the next format specification.
>  
>          o size
> -		<<h>>, <<l>>, and <<L>> are optional size characters which
> -		override the default way that <<scanf>> interprets the
> -		data type of the corresponding argument.
> +		<<h>>, <<j>>, <<l>>, <<L>>, <<t>>, and <<z>> are optional size
> +		characters which override the default way that <<scanf>>
> +		interprets the data type of the corresponding argument.
>  
>  
>  .Modifier   Type(s)
> @@ -162,6 +162,11 @@ DESCRIPTION
>  .   h       D, I, O, U, X     no effect
>  .           e, f, c, s, p
>  .
> +.   j       d, i, o, u, x, n  convert input to intmax_t,
> +.                             store in intmax_t object
> +.
> +.   j       all others        no effect
> +.
>  .   l       d, i, o, u, x, n  convert input to long,
>  .                             store in long object
>  .
> @@ -180,7 +185,18 @@ DESCRIPTION
>  .   L       e, f, g, E, G     convert to long double,
>  .                             store in long double
>  .
> -.   L      all others         no effect
> +.   L       all others        no effect
> +.
> +.   t       d, i, o, u, x, n  convert input to ptrdiff_t,
> +.                             store in ptrdiff_t object
> +.
> +.   t       all others        no effect
> +.
> +.   z       d, i, o, u, x, n  convert input to size_t,
> +.                             store in size_t object
> +.
> +.   z       all others        no effect
> +.
>  
>  
>          o <[type]>
> Index: libc/stdio/vfscanf.c
> ===================================================================
> RCS file: /cvs/src/src/newlib/libc/stdio/vfscanf.c,v
> retrieving revision 1.33
> diff -u -p -r1.33 vfscanf.c
> --- libc/stdio/vfscanf.c	26 Sep 2006 21:22:19 -0000	1.33
> +++ libc/stdio/vfscanf.c	17 Apr 2007 18:48:19 -0000
> @@ -380,6 +380,43 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap
>  	  else
>  	    flags |= SHORT;
>  	  goto again;
> +        case 'j':               /* intmax_t */
> +	  if (sizeof (intmax_t) == sizeof (long))
> +	    flags |= LONG;
> +	  else
> +	    flags |= LONGDBL;
> +	  goto again;
> +        case 't':               /* ptrdiff_t */
> +	  if (sizeof (ptrdiff_t) < sizeof (int))
> +	    /* POSIX states ptrdiff_t is 16 or more bits, as
> +	       is short.  */
> +	    flags |= SHORT;
> +	  else if (sizeof (ptrdiff_t) == sizeof (int))
> +	    /* no flag needed */;
> +	  else if (sizeof (ptrdiff_t) <= sizeof (long))
> +	    flags |= LONG;
> +	  else
> +	    /* POSIX states that at least one programming
> +	       environment must support ptrdiff_t no wider than
> +	       long, but that means other environments can
> +	       have ptrdiff_t as wide as long long.  */
> +	    flags |= LONGDBL;
> +	  goto again;
> +        case 'z':               /* size_t */
> +	  if (sizeof (size_t) < sizeof (int))
> +	    /* POSIX states size_t is 16 or more bits, as is short.  */
> +	    flags |= SHORT;
> +	  else if (sizeof (size_t) == sizeof (int))
> +	    /* no flag needed */;
> +	  else if (sizeof (size_t) <= sizeof (long))
> +	    flags |= LONG;
> +	  else
> +	    /* POSIX states that at least one programming
> +	       environment must support size_t no wider than
> +	       long, but that means other environments can
> +	       have size_t as wide as long long.  */
> +	    flags |= LONGDBL;
> +	  goto again;
>  
>  	case '0':
>  	case '1':
> 
> 
> ------------------------------------------------------------------------
> 
> #include <stdio.h>
> #include <stdint.h>
> #include <stdlib.h>
> #include <stddef.h>
> 
>   
> int main ()
> {
>   int i;
>   float f;
>   char buf[1024];
> 
> #define IVAL 42
> #define FVAL 42.4242F
> 
> #define ERR(fmt, ...) printf ("Line %d: " fmt "\n", \
>                               __LINE__, ##__VA_ARGS__)
> 
> #define ROUNDTRIP(t, v, fmt) ({ \
>     t var = 0; i = f = 0; \
>     sprintf (buf, "%d " fmt " %f", IVAL, (t)v, FVAL); \
>     if (getenv ("DEBUG")) printf ("%s\n", buf); \
>     if (sscanf (buf, "%d " fmt " %f", &i, &var, &f) != 3) \
>       ERR ("sscanf didn't return 3"); \
>     else if (i != IVAL || var != (t)v || f != FVAL) \
>       ERR ("wrong values: i = %d [want %d], " \
>            "var = " fmt " [want " fmt "], " \
>            "f = %f [want %f]", i, IVAL, var, (t)v, f, FVAL); \
>   })
>   
>   ROUNDTRIP (intmax_t, 0, "%jd");
>   ROUNDTRIP (intmax_t, -1, "%jd");
>   ROUNDTRIP (intmax_t, INTMAX_MIN, "%jd");
>   ROUNDTRIP (intmax_t, INTMAX_MAX, "%jd");
> 
>   ROUNDTRIP (ptrdiff_t, 0, "%td");
>   ROUNDTRIP (ptrdiff_t, -1, "%td");
>   ROUNDTRIP (ptrdiff_t, PTRDIFF_MIN, "%td");
>   ROUNDTRIP (ptrdiff_t, PTRDIFF_MAX, "%td");
> 
>   ROUNDTRIP (size_t, 0, "%zu");
>   ROUNDTRIP (size_t, SIZE_MAX, "%zu");
> 
>   exit (0);
> }



More information about the Newlib mailing list