Mail Archives: djgpp-workers/2012/12/21/19:16:26
X-Authentication-Warning: | delorie.com: mail set sender to djgpp-workers-bounces using -f
|
X-Recipient: | djgpp-workers AT delorie DOT com
|
X-Authenticated: | #27081556
|
X-Provags-ID: | V01U2FsdGVkX18kCCJ6sYUkKMX3sx8IIRpUVK5roMV6Xi3l0Dr3DY
|
| xzj/nbLz/kIYNf
|
Message-ID: | <50D4FBCF.2060706@gmx.de>
|
Date: | Sat, 22 Dec 2012 01:16:15 +0100
|
From: | Juan Manuel Guerrero <juan DOT guerrero AT gmx DOT de>
|
User-Agent: | Mozilla/5.0 (X11; Linux x86_64; rv:16.0) Gecko/20121025 Thunderbird/16.0.2
|
MIME-Version: | 1.0
|
To: | djgpp-workers AT delorie DOT com
|
Subject: | Implementation of %n$ conversion specifier for scanf family of functions.
|
X-Y-GMX-Trusted: | 0
|
Reply-To: | djgpp-workers AT delorie DOT com
|
The patch below will implement the C99 numeric conversion specifier aka %n$ for
the scanf family of functions.
Regards,
Juan M. Guerrero
# cvs ci -m"Info about %n$ conversion specifier added." djgpp/src/docs/kb/wc204.txi
# cvs ci -m"Support for %n$ conversion specifier added." djgpp/src/libc/ansi/stdio/doscan.c
# cvs ci -m"Info about %n$ conversion specifier added." djgpp/src/libc/ansi/stdio/scanf.txh
# cvs ci -m"Added new test file tscanf2.c." djgpp/tests/libc/ansi/stdio/makefile
# cvs add djgpp/tests/libc/ansi/stdio/tscanf3.c
# cvs ci -m"Test for %n$ conversion specifier." djgpp/tests/libc/ansi/stdio/tscanf3.c
2012-12-21 Juan Manuel Guerrero <juan DOT guerrero AT gmx DOT de>
* djgpp/src/docs/kb/wc204.txi: Info about %n$ conversion specifier added.
* djgpp/src/libc/ansi/stdio/doscan.c: Support for %n$ conversion specifier added.
* djgpp/src/libc/ansi/stdio/scanf.txh: Info about %n$ conversion specifier added.
* djgpp/tests/libc/ansi/stdio/makefile: Added new test file tscanf3.c.
* djgpp/tests/libc/ansi/stdio/tscanf3.c: Test for %n$ conversion specifier.
diff -aprNU5 djgpp.orig/src/docs/kb/wc204.txi djgpp/src/docs/kb/wc204.txi
--- djgpp.orig/src/docs/kb/wc204.txi 2012-12-21 20:58:08 +0000
+++ djgpp/src/docs/kb/wc204.txi 2012-12-21 21:13:22 +0000
@@ -1261,5 +1261,10 @@ family of functions.
@findex scanf AT r{, and m modifier character}
The @code{m} modifier character is now supported by @code{_doscan}
and the @code{scanf} family of functions. This is a @acronym{GNU}
@code{glibc} extension and it is specified in the upcoming revision
of the @acronym{POSIX.1} standard.
+
+@findex _doscan AT r{, and @acronym{C99} numeric conversion specifiers}
+@findex scanf AT r{, and @acronym{C99} numeric conversion specifiers}
+The @code{%n$} numeric conversion specifiers are now supported
+by @code{_doscan} and the @code{scanf} family of functions.
diff -aprNU5 djgpp.orig/src/libc/ansi/stdio/doscan.c djgpp/src/libc/ansi/stdio/doscan.c
--- djgpp.orig/src/libc/ansi/stdio/doscan.c 2012-12-21 21:32:48 +0000
+++ djgpp/src/libc/ansi/stdio/doscan.c 2012-12-22 00:26:24 +0000
@@ -61,15 +61,17 @@ _doscan(FILE *iop, const char *fmt, va_l
int
_doscan_low(FILE *iop, int (*scan_getc)(FILE *), int (*scan_ungetc)(int, FILE *), const char *fmt, va_list argp)
{
register int ch;
- int nmatch, len, ch1;
+ int nmatch, n, len, ch1;
int *ptr, fileended, size;
int suppressed;
bool allocate_char_buffer;
int previous_errno = errno;
+ const va_list arg_list = argp;
+ bool retrieve_argp;
decimal_point = localeconv()->decimal_point[0];
nchars = 0;
nmatch = 0;
fileended = 0;
@@ -84,25 +86,37 @@ _doscan_low(FILE *iop, int (*scan_getc)(
return nmatch;
case '%':
if ((ch = *fmt++) == '%')
goto def;
+ retrieve_argp = true;
allocate_char_buffer = false;
ptr = NULL;
- if (ch != '*')
+repeat:
+ if (ch != '*' && retrieve_argp)
ptr = va_arg(argp, int *);
else
ch = *fmt++;
- len = 0;
+ n = len = 0;
size = REGULAR;
while (isdigit(ch & 0xff))
{
- len = len * 10 + ch - '0';
+ n = n * 10 + ch - '0';
ch = *fmt++;
}
- if (len == 0)
- len = DEFAULT_WIDTH;
+ if (ch == '$')
+ {
+ /* C99 */
+ /* for %n$ numeric conversion specifier */
+ int i;
+ for (argp = arg_list, i = 0; i < n; i++)
+ ptr = va_arg(argp, int *);
+ retrieve_argp = false;
+ goto repeat;
+ }
+ else
+ len = (n == 0) ? DEFAULT_WIDTH : n;
if (ch == 'l')
{
size = LONG;
ch = *fmt++;
diff -aprNU5 djgpp.orig/src/libc/ansi/stdio/scanf.txh djgpp/src/libc/ansi/stdio/scanf.txh
--- djgpp.orig/src/libc/ansi/stdio/scanf.txh 2012-12-21 20:58:08 +0000
+++ djgpp/src/libc/ansi/stdio/scanf.txh 2012-12-21 21:13:22 +0000
@@ -16,12 +16,27 @@ the variables pointed to by the argument
The format string contains regular characters which much match the input
exactly as well as a conversion specifiers, which begin with a percent
symbol. Any whitespace in the format string matches zero or more of any
whitespace characters in the input. Thus, a single space may match a
newline and two tabs in the input. All conversions except @samp{c} and
-@samp{[} also skip leading whitespace automatically. Each conversion
-specifier contains the following fields:
+@samp{[} also skip leading whitespace automatically.
+Conversions can be applied to the nth argument after the format in the
+argument list, rather than to the next unused argument. In this case,
+the conversion specifier character @code{%} is replaced by the sequence
+@code{%n$}, where @code{n} is a decimal integer in the range [@code{1}, @code{number of the last argument}].
+This feature provides for the definition of format strings that select
+arguments in an order appropriate to specific languages. In format strings
+containing the @code{%n$} form of conversion specifications, it is unspecified
+whether numbered arguments in the argument list can be referenced from
+the format string more than once. The format can contain either form of
+a conversion specification - that is, @code{%} or @code{%n$} - but the two
+forms cannot be mixed within a single format string. The only exception
+to this is that @code{%%} or @code{%*} can be mixed with the @code{%n$}
+form. When numbered argument specifications are used, specifying the
+Nth argument requires that all the leading arguments, from the first
+to the (N-1)th, are pointers.
+Each conversion specifier contains the following fields:
@itemize @bullet
@item An asterisk (@samp{*}) which indicates that the input should be
converted according to the conversion spec, but not stored anywhere.
diff -aprNU5 djgpp.orig/tests/libc/ansi/stdio/makefile djgpp/tests/libc/ansi/stdio/makefile
--- djgpp.orig/tests/libc/ansi/stdio/makefile 2012-12-21 20:58:08 +0000
+++ djgpp/tests/libc/ansi/stdio/makefile 2012-12-21 21:13:22 +0000
@@ -23,9 +23,10 @@ SRC += sscanf2.c
SRC += sscanf3.c
SRC += tmpnam.c
SRC += tremove.c
SRC += tscanf.c
SRC += tscanf2.c
+SRC += tscanf3.c
SRC += tsnprtf.c
SRC += tsnprtf2.c
include $(TOP)/../makefile.inc
diff -aprNU5 djgpp.orig/tests/libc/ansi/stdio/tscanf3.c djgpp/tests/libc/ansi/stdio/tscanf3.c
--- djgpp.orig/tests/libc/ansi/stdio/tscanf3.c 1970-01-01 00:00:00 +0000
+++ djgpp/tests/libc/ansi/stdio/tscanf3.c 2012-12-22 00:58:18 +0000
@@ -0,0 +1,43 @@
+/* Test the n$ numeric conversion specifier. */
+
+#include <stdio.h>
+
+int main(void)
+{
+ const char *buffer[3] = {
+ "Fecha y hora es: 21 de deciembre de 2012, 01:02:03",
+ "Datum und Uhrzeit ist: 21. Dezember 2012, 01:02:03",
+ "Date and hour is: december 21 2012, 01:02:03"
+ };
+ const char *format[3] = {
+ "%*[A-Za-z :] %3$d %*[a-z] %2$9c %*[a-z] %1$d %*[,] %4$d%*[:] %5$d%*[:] %6$d%*",
+ "%*[A-Za-z :] %3$d %*[.] %2$8c %1$d %*[,] %4$d%*[:] %5$d%*[:] %6$d%*",
+ "%*[A-Za-z ]%*[:] %2$8c %3$d %1$d %*[,] %4$d%*[:] %5$d%*[:] %6$d%*"
+ };
+ const char *language[3] = {
+ "spanish",
+ "german",
+ "english"
+ };
+ char month[10];
+ int year, day, hour, min, sec, i;
+
+
+ for (i = 0; i < (sizeof buffer / sizeof buffer[0]); i++)
+ {
+ sscanf(buffer[i], format[i], &year, month, &day, &hour, &min, &sec);
+ if (i == 0)
+ month[9] = '\0';
+ else
+ month[8] = '\0';
+ printf("Result of scanf using %s format\n\"%s\":\n"
+ " year: %d\n"
+ " month: %s\n"
+ " day: %d\n"
+ " hour: %d\n"
+ " min: %d\n"
+ " sec: %d\n", language[i], format[i], year, month, day, hour, min, sec);
+ }
+
+ return 0;
+}
- Raw text -