[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