2003-11-05 Jeff Johnston <jjohnstn@redhat.com>
Artem B. Bityuckiy <mail_lists@mail.ru> * libc/stdio/vfprintf.c (_VFPRINTF_R): Add support for %ls, %S, %lc, and %C format specifiers. (get_arg): Ditto. * libc/stdio/sprintf.c: Add documentation regarding new format specifiers added in vfprintf.c.
This commit is contained in:
parent
da2d12279b
commit
d2ffac097d
|
@ -1,3 +1,12 @@
|
||||||
|
2003-11-05 Jeff Johnston <jjohnstn@redhat.com>
|
||||||
|
Artem B. Bityuckiy <mail_lists@mail.ru>
|
||||||
|
|
||||||
|
* libc/stdio/vfprintf.c (_VFPRINTF_R): Add support for
|
||||||
|
%ls, %S, %lc, and %C format specifiers.
|
||||||
|
(get_arg): Ditto.
|
||||||
|
* libc/stdio/sprintf.c: Add documentation regarding new
|
||||||
|
format specifiers added in vfprintf.c.
|
||||||
|
|
||||||
2003-11-05 Jeff Johnston <jjohnstn@redhat.com>
|
2003-11-05 Jeff Johnston <jjohnstn@redhat.com>
|
||||||
|
|
||||||
* libc/stdlib/wcsrtombs.c (_wcsrtombs_r): Numerous fixes
|
* libc/stdlib/wcsrtombs.c (_wcsrtombs_r): Numerous fixes
|
||||||
|
|
|
@ -205,7 +205,8 @@ DESCRIPTION
|
||||||
<<l>> forces the following <<d>>, <<i>>, <<o>>, <<u>>,
|
<<l>> forces the following <<d>>, <<i>>, <<o>>, <<u>>,
|
||||||
<<x>> or <<X>> conversion <[type]> to apply to a <<long>> or
|
<<x>> or <<X>> conversion <[type]> to apply to a <<long>> or
|
||||||
<<unsigned long>>. <<l>> also forces a following <<n>> <[type]> to
|
<<unsigned long>>. <<l>> also forces a following <<n>> <[type]> to
|
||||||
apply to a pointer to a <<long>>. If an <<h>>
|
apply to a pointer to a <<long>>. <<l>> with <<c>>, <<s>> is
|
||||||
|
equivalent to <<C>>, <<S>> respectively. If an <<h>>
|
||||||
or an <<l>> appears with another conversion
|
or an <<l>> appears with another conversion
|
||||||
specifier, the behavior is undefined. <<L>> forces a
|
specifier, the behavior is undefined. <<L>> forces a
|
||||||
following <<e>>, <<E>>, <<f>>, <<g>> or <<G>> conversion <[type]> to
|
following <<e>>, <<E>>, <<f>>, <<g>> or <<G>> conversion <[type]> to
|
||||||
|
@ -224,10 +225,18 @@ DESCRIPTION
|
||||||
o c
|
o c
|
||||||
prints <[arg]> as single character
|
prints <[arg]> as single character
|
||||||
|
|
||||||
|
o C
|
||||||
|
prints wchar_t <[arg]> as single multibyte character
|
||||||
|
|
||||||
o s
|
o s
|
||||||
prints characters until precision is reached or a null terminator
|
prints characters until precision is reached or a null terminator
|
||||||
is encountered; takes a string pointer
|
is encountered; takes a string pointer
|
||||||
|
|
||||||
|
o S
|
||||||
|
converts wchar_t characters to multibyte output characters until
|
||||||
|
precision is reached or a null wchar_t terminator
|
||||||
|
is encountered; takes a wchar_t pointer
|
||||||
|
|
||||||
o d
|
o d
|
||||||
prints a signed decimal integer; takes an <<int>> (same as <<i>>)
|
prints a signed decimal integer; takes an <<int>> (same as <<i>>)
|
||||||
|
|
||||||
|
|
|
@ -183,6 +183,7 @@ static char *rcsid = "$Id$";
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <reent.h>
|
#include <reent.h>
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -267,7 +268,12 @@ __sbprintf(fp, fmt, ap)
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include "floatio.h"
|
#include "floatio.h"
|
||||||
|
|
||||||
#define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */
|
#if ((MAXEXP+MAXFRACT+1) > MB_LEN_MAX)
|
||||||
|
# define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */
|
||||||
|
#else
|
||||||
|
# define BUF MB_LEN_MAX
|
||||||
|
#endif
|
||||||
|
|
||||||
#define DEFPREC 6
|
#define DEFPREC 6
|
||||||
|
|
||||||
#ifdef _NO_LONGDBL
|
#ifdef _NO_LONGDBL
|
||||||
|
@ -320,6 +326,7 @@ union arg_val
|
||||||
void_ptr_t val_void_ptr_t;
|
void_ptr_t val_void_ptr_t;
|
||||||
quad_t val_quad_t;
|
quad_t val_quad_t;
|
||||||
u_quad_t val_u_quad_t;
|
u_quad_t val_u_quad_t;
|
||||||
|
wint_t val_wint_t;
|
||||||
};
|
};
|
||||||
|
|
||||||
static union arg_val *get_arg (struct _reent *data, int n, char *fmt,
|
static union arg_val *get_arg (struct _reent *data, int n, char *fmt,
|
||||||
|
@ -428,7 +435,8 @@ _DEFUN (_VFPRINTF_R, (data, fp, fmt0, ap),
|
||||||
struct __siov iov[NIOV];/* ... and individual io vectors */
|
struct __siov iov[NIOV];/* ... and individual io vectors */
|
||||||
char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */
|
char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */
|
||||||
char ox[2]; /* space for 0x hex-prefix */
|
char ox[2]; /* space for 0x hex-prefix */
|
||||||
mbstate_t state; /* mbtowc calls from library must not change state */
|
mbstate_t state; /* mbtowc calls from library must not change state */
|
||||||
|
char *malloc_buf = NULL;/* handy pointer for malloced buffers */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Choose PADSIZE to trade efficiency vs. size. If larger printf
|
* Choose PADSIZE to trade efficiency vs. size. If larger printf
|
||||||
|
@ -728,8 +736,21 @@ reswitch: switch (ch) {
|
||||||
flags |= QUADINT;
|
flags |= QUADINT;
|
||||||
goto rflag;
|
goto rflag;
|
||||||
case 'c':
|
case 'c':
|
||||||
*(cp = buf) = GET_ARG(N, ap, int);
|
case 'C':
|
||||||
size = 1;
|
cp = buf;
|
||||||
|
if (*fmt == 'C' || (flags & LONGINT)) {
|
||||||
|
mbstate_t ps;
|
||||||
|
|
||||||
|
memset((void *)&ps, '\0', sizeof(mbstate_t));
|
||||||
|
if ((size = (int)wcrtomb(cp,
|
||||||
|
(wchar_t)GET_ARG(N, ap, wint_t),
|
||||||
|
&ps)) == -1)
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*cp = GET_ARG(N, ap, int);
|
||||||
|
size = 1;
|
||||||
|
}
|
||||||
sign = '\0';
|
sign = '\0';
|
||||||
break;
|
break;
|
||||||
case 'D':
|
case 'D':
|
||||||
|
@ -881,9 +902,61 @@ reswitch: switch (ch) {
|
||||||
ch = 'x';
|
ch = 'x';
|
||||||
goto nosign;
|
goto nosign;
|
||||||
case 's':
|
case 's':
|
||||||
if ((cp = GET_ARG(N, ap, char_ptr_t)) == NULL)
|
case 'S':
|
||||||
|
sign = '\0';
|
||||||
|
if ((cp = GET_ARG(N, ap, char_ptr_t)) == NULL) {
|
||||||
cp = "(null)";
|
cp = "(null)";
|
||||||
if (prec >= 0) {
|
size = 6;
|
||||||
|
}
|
||||||
|
else if (ch == 'S' || (flags & LONGINT)) {
|
||||||
|
mbstate_t ps;
|
||||||
|
_CONST wchar_t *wcp;
|
||||||
|
|
||||||
|
wcp = (_CONST wchar_t *)cp;
|
||||||
|
size = m = 0;
|
||||||
|
memset((void *)&ps, '\0', sizeof(mbstate_t));
|
||||||
|
|
||||||
|
/* Count number of bytes needed for multibyte
|
||||||
|
string that will be produced from widechar
|
||||||
|
string. */
|
||||||
|
if (prec >= 0) {
|
||||||
|
while (1) {
|
||||||
|
if (wcp[m] == L'\0')
|
||||||
|
break;
|
||||||
|
if ((n = (int)wcrtomb(buf,
|
||||||
|
wcp[m], &ps)) == -1)
|
||||||
|
goto error;
|
||||||
|
if (n + size > prec)
|
||||||
|
break;
|
||||||
|
m += 1;
|
||||||
|
size += n;
|
||||||
|
if (size == prec)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ((size = (int)wcsrtombs(NULL, &wcp,
|
||||||
|
0, &ps)) == -1)
|
||||||
|
goto error;
|
||||||
|
wcp = (_CONST wchar_t *)cp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if ((malloc_buf =
|
||||||
|
(char *)malloc(size + 1)) == NULL)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
/* Convert widechar string to multibyte string. */
|
||||||
|
memset((void *)&ps, '\0', sizeof(mbstate_t));
|
||||||
|
if (wcsrtombs(malloc_buf, &wcp, size, &ps)
|
||||||
|
!= size)
|
||||||
|
goto error;
|
||||||
|
cp = malloc_buf;
|
||||||
|
cp[size] = '\0';
|
||||||
|
}
|
||||||
|
else if (prec >= 0) {
|
||||||
/*
|
/*
|
||||||
* can't use strlen; can only look for the
|
* can't use strlen; can only look for the
|
||||||
* NUL in the first `prec' characters, and
|
* NUL in the first `prec' characters, and
|
||||||
|
@ -899,7 +972,7 @@ reswitch: switch (ch) {
|
||||||
size = prec;
|
size = prec;
|
||||||
} else
|
} else
|
||||||
size = strlen(cp);
|
size = strlen(cp);
|
||||||
sign = '\0';
|
|
||||||
break;
|
break;
|
||||||
case 'U':
|
case 'U':
|
||||||
flags |= LONGINT;
|
flags |= LONGINT;
|
||||||
|
@ -1097,10 +1170,17 @@ number: if ((dprec = prec) >= 0)
|
||||||
ret += width > realsz ? width : realsz;
|
ret += width > realsz ? width : realsz;
|
||||||
|
|
||||||
FLUSH(); /* copy out the I/O vectors */
|
FLUSH(); /* copy out the I/O vectors */
|
||||||
|
|
||||||
|
if (malloc_buf != NULL) {
|
||||||
|
free(malloc_buf);
|
||||||
|
malloc_buf = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
done:
|
done:
|
||||||
FLUSH();
|
FLUSH();
|
||||||
error:
|
error:
|
||||||
|
if (malloc_buf != NULL)
|
||||||
|
free(malloc_buf);
|
||||||
return (__sferror(fp) ? EOF : ret);
|
return (__sferror(fp) ? EOF : ret);
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
|
@ -1302,9 +1382,9 @@ const static CH_CLASS chclass[256] = {
|
||||||
/* 28-2f */ OTHER, OTHER, STAR, FLAG, OTHER, FLAG, DOT, OTHER,
|
/* 28-2f */ OTHER, OTHER, STAR, FLAG, OTHER, FLAG, DOT, OTHER,
|
||||||
/* 30-37 */ ZERO, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT,
|
/* 30-37 */ ZERO, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT,
|
||||||
/* 38-3f */ DIGIT, DIGIT, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
|
/* 38-3f */ DIGIT, DIGIT, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
|
||||||
/* 40-47 */ OTHER, OTHER, OTHER, OTHER, SPEC, SPEC, OTHER, SPEC,
|
/* 40-47 */ OTHER, OTHER, OTHER, SPEC, SPEC, SPEC, OTHER, SPEC,
|
||||||
/* 48-4f */ OTHER, OTHER, OTHER, OTHER, MODFR, OTHER, OTHER, SPEC,
|
/* 48-4f */ OTHER, OTHER, OTHER, OTHER, MODFR, OTHER, OTHER, SPEC,
|
||||||
/* 50-57 */ OTHER, OTHER, OTHER, OTHER, OTHER, SPEC, OTHER, SPEC,
|
/* 50-57 */ OTHER, OTHER, OTHER, SPEC, OTHER, SPEC, OTHER, SPEC,
|
||||||
/* 58-5f */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
|
/* 58-5f */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
|
||||||
/* 60-67 */ OTHER, OTHER, OTHER, SPEC, SPEC, SPEC, SPEC, SPEC,
|
/* 60-67 */ OTHER, OTHER, OTHER, SPEC, SPEC, SPEC, SPEC, SPEC,
|
||||||
/* 68-6f */ MODFR, SPEC, OTHER, OTHER, MODFR, OTHER, OTHER, SPEC,
|
/* 68-6f */ MODFR, SPEC, OTHER, OTHER, MODFR, OTHER, OTHER, SPEC,
|
||||||
|
@ -1375,7 +1455,7 @@ get_arg (struct _reent *data, int n, char *fmt, va_list *ap,
|
||||||
int pos, last_arg;
|
int pos, last_arg;
|
||||||
mbstate_t wc_state;
|
mbstate_t wc_state;
|
||||||
int max_pos_arg = n;
|
int max_pos_arg = n;
|
||||||
enum types { INT, LONG_INT, SHORT_INT, QUAD_INT, CHAR, CHAR_PTR, DOUBLE, LONG_DOUBLE };
|
enum types { INT, LONG_INT, SHORT_INT, QUAD_INT, CHAR, CHAR_PTR, DOUBLE, LONG_DOUBLE, WIDE_CHAR };
|
||||||
|
|
||||||
/* if this isn't the first call, pick up where we left off last time */
|
/* if this isn't the first call, pick up where we left off last time */
|
||||||
if (*last_fmt != NULL)
|
if (*last_fmt != NULL)
|
||||||
|
@ -1481,12 +1561,16 @@ get_arg (struct _reent *data, int n, char *fmt, va_list *ap,
|
||||||
spec_type = DOUBLE;
|
spec_type = DOUBLE;
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
|
case 'S':
|
||||||
case 'p':
|
case 'p':
|
||||||
spec_type = CHAR_PTR;
|
spec_type = CHAR_PTR;
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
spec_type = CHAR;
|
spec_type = CHAR;
|
||||||
break;
|
break;
|
||||||
|
case 'C':
|
||||||
|
spec_type = WIDE_CHAR;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if we have a positional parameter, just store the type, otherwise
|
/* if we have a positional parameter, just store the type, otherwise
|
||||||
|
@ -1503,6 +1587,9 @@ get_arg (struct _reent *data, int n, char *fmt, va_list *ap,
|
||||||
case QUAD_INT:
|
case QUAD_INT:
|
||||||
args[numargs++].val_quad_t = va_arg(*ap, quad_t);
|
args[numargs++].val_quad_t = va_arg(*ap, quad_t);
|
||||||
break;
|
break;
|
||||||
|
case WIDE_CHAR:
|
||||||
|
args[numargs++].val_wint_t = va_arg(*ap, wint_t);
|
||||||
|
break;
|
||||||
case CHAR:
|
case CHAR:
|
||||||
case SHORT_INT:
|
case SHORT_INT:
|
||||||
case INT:
|
case INT:
|
||||||
|
@ -1585,6 +1672,9 @@ get_arg (struct _reent *data, int n, char *fmt, va_list *ap,
|
||||||
case LONG_DOUBLE:
|
case LONG_DOUBLE:
|
||||||
args[numargs++].val__LONG_DOUBLE = va_arg(*ap, _LONG_DOUBLE);
|
args[numargs++].val__LONG_DOUBLE = va_arg(*ap, _LONG_DOUBLE);
|
||||||
break;
|
break;
|
||||||
|
case WIDE_CHAR:
|
||||||
|
args[numargs++].val_wint_t = va_arg(*ap, wint_t);
|
||||||
|
break;
|
||||||
case INT:
|
case INT:
|
||||||
case SHORT_INT:
|
case SHORT_INT:
|
||||||
case CHAR:
|
case CHAR:
|
||||||
|
|
Loading…
Reference in New Issue