This is the mail archive of the newlib@sourceware.org mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


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);
}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]