This is the mail archive of the
newlib@sources.redhat.com
mailing list for the newlib project.
[RFA] Add hh and ll modifiers to scanf functions
- From: Corinna Vinschen <vinschen at redhat dot com>
- To: newlib at sources dot redhat dot com
- Date: Mon, 31 Mar 2003 12:00:08 +0200
- Subject: [RFA] Add hh and ll modifiers to scanf functions
- Reply-to: newlib at sources dot redhat dot com
Hi,
the below patch adds size modifiers 'hh' and 'll' to the scanf routines.
These modifiers are defined by SUSv3, see e. g.
http://www.opengroup.org/onlinepubs/007904975/toc.htm
I also updated the description in stdio/sscanf.c. However, I don't
quite see a reason to keep this description in sscanf.c. It's not
the "natural" point for that, IMHO. Should that be moved to vfscanf.c?
Corinna
2003-03-31 Corinna Vinschen <corinna at vinschen dot de>
* libc/stdio/sscanf.c: Update flags description.
* libc/stdio/vfscanf.c: Add CHAR flag value to denote 8 bit target
type.
(__svfscanf_r): Add 'hh' and 'll' handling.
Index: libc/stdio/sscanf.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/sscanf.c,v
retrieving revision 1.3
diff -p -u -r1.3 sscanf.c
--- libc/stdio/sscanf.c 20 Apr 2001 22:50:51 -0000 1.3
+++ libc/stdio/sscanf.c 31 Mar 2003 09:49:19 -0000
@@ -152,22 +152,31 @@ DESCRIPTION
.Modifier Type(s)
-. h d, i, o, u, x convert input to short,
+. hh d, i, o, u, x, n convert input to char,
+. store in char object
+.
+. h d, i, o, u, x, n convert input to short,
. store in short object
.
. h D, I, O, U, X no effect
-. e, f, c, s, n, p
+. e, f, c, s, p
.
-. l d, i, o, u, x convert input to long,
+. l d, i, o, u, x, n convert input to long,
. store in long object
.
. l e, f, g convert input to double
. store in a double object
.
. l D, I, O, U, X no effect
-. c, s, n, p
+. c, s, p
+.
+. ll d, i, o, u, x, n convert to long long,
+. store in long long
+.
+. L d, i, o, u, x, n convert to long long,
+. store in long long
.
-. L d, i, o, u, x convert to long double,
+. L e, f, g, E, G convert to long double,
. store in long double
.
. L all others no effect
Index: libc/stdio/vfscanf.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/vfscanf.c,v
retrieving revision 1.13
diff -p -u -r1.13 vfscanf.c
--- libc/stdio/vfscanf.c 20 Mar 2003 17:23:57 -0000 1.13
+++ libc/stdio/vfscanf.c 31 Mar 2003 09:49:20 -0000
@@ -151,11 +151,12 @@ extern _LONG_DOUBLE _strtold _PARAMS((ch
*/
#define LONG 0x01 /* l: long or double */
-#define LONGDBL 0x02 /* L: long double or long long */
+#define LONGDBL 0x02 /* L/ll: long double or long long */
#define SHORT 0x04 /* h: short */
-#define SUPPRESS 0x08 /* suppress assignment */
-#define POINTER 0x10 /* weird %p pointer (`fake hex') */
-#define NOSKIP 0x20 /* do not skip blanks */
+#define CHAR 0x08 /* hh: 8 bit integer */
+#define SUPPRESS 0x10 /* suppress assignment */
+#define POINTER 0x20 /* weird %p pointer (`fake hex') */
+#define NOSKIP 0x40 /* do not skip blanks */
/*
* The following are used in numeric conversions only:
@@ -163,14 +164,14 @@ extern _LONG_DOUBLE _strtold _PARAMS((ch
* SIGNOK, NDIGITS, PFXOK, and NZDIGITS are for integral.
*/
-#define SIGNOK 0x40 /* +/- is (still) legal */
-#define NDIGITS 0x80 /* no digits detected */
+#define SIGNOK 0x80 /* +/- is (still) legal */
+#define NDIGITS 0x100 /* no digits detected */
-#define DPTOK 0x100 /* (float) decimal point is still legal */
-#define EXPOK 0x200 /* (float) exponent (e+3, etc) still legal */
+#define DPTOK 0x200 /* (float) decimal point is still legal */
+#define EXPOK 0x400 /* (float) exponent (e+3, etc) still legal */
-#define PFXOK 0x100 /* 0x prefix is (still) legal */
-#define NZDIGITS 0x200 /* no zero digits detected */
+#define PFXOK 0x200 /* 0x prefix is (still) legal */
+#define NZDIGITS 0x400 /* no zero digits detected */
/*
* Conversion types.
@@ -262,6 +263,7 @@ __svfscanf_r (rptr, fp, fmt0, ap)
mbstate_t state; /* value to keep track of multibyte state */
#endif
+ char *cp;
short *sp;
int *ip;
float *flp;
@@ -335,13 +337,25 @@ __svfscanf_r (rptr, fp, fmt0, ap)
flags |= SUPPRESS;
goto again;
case 'l':
- flags |= LONG;
+ if (*fmt == 'l') /* Check for 'll' = long long (SUSv3) */
+ {
+ ++fmt;
+ flags |= LONGDBL;
+ }
+ else
+ flags |= LONG;
goto again;
case 'L':
flags |= LONGDBL;
goto again;
case 'h':
- flags |= SHORT;
+ if (*fmt == 'h') /* Check for 'hh' = char int (SUSv3) */
+ {
+ ++fmt;
+ flags |= CHAR;
+ }
+ else
+ flags |= SHORT;
goto again;
case '0':
@@ -440,7 +454,12 @@ __svfscanf_r (rptr, fp, fmt0, ap)
case 'n':
if (flags & SUPPRESS) /* ??? */
continue;
- if (flags & SHORT)
+ if (flags & CHAR)
+ {
+ cp = va_arg (ap, char *);
+ *cp = nread;
+ }
+ else if (flags & SHORT)
{
sp = va_arg (ap, short *);
*sp = nread;
@@ -808,6 +827,11 @@ __svfscanf_r (rptr, fp, fmt0, ap)
res = (*ccfn) (rptr, buf, (char **) NULL, base);
if (flags & POINTER)
*(va_arg (ap, _PTR *)) = (_PTR) (unsigned _POINTER_INT) res;
+ else if (flags & CHAR)
+ {
+ cp = va_arg (ap, char *);
+ *cp = res;
+ }
else if (flags & SHORT)
{
sp = va_arg (ap, short *);
--
Corinna Vinschen
Cygwin Developer
Red Hat, Inc.
mailto:vinschen at redhat dot com