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>
|
||||
|
||||
* libc/stdlib/wcsrtombs.c (_wcsrtombs_r): Numerous fixes
|
||||
|
|
|
@ -205,7 +205,8 @@ DESCRIPTION
|
|||
<<l>> forces the following <<d>>, <<i>>, <<o>>, <<u>>,
|
||||
<<x>> or <<X>> conversion <[type]> to apply to a <<long>> or
|
||||
<<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
|
||||
specifier, the behavior is undefined. <<L>> forces a
|
||||
following <<e>>, <<E>>, <<f>>, <<g>> or <<G>> conversion <[type]> to
|
||||
|
@ -224,10 +225,18 @@ DESCRIPTION
|
|||
o c
|
||||
prints <[arg]> as single character
|
||||
|
||||
o C
|
||||
prints wchar_t <[arg]> as single multibyte character
|
||||
|
||||
o s
|
||||
prints characters until precision is reached or a null terminator
|
||||
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
|
||||
prints a signed decimal integer; takes an <<int>> (same as <<i>>)
|
||||
|
||||
|
|
|
@ -183,6 +183,7 @@ static char *rcsid = "$Id$";
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <reent.h>
|
||||
#include <wchar.h>
|
||||
#include <string.h>
|
||||
|
@ -267,7 +268,12 @@ __sbprintf(fp, fmt, ap)
|
|||
#include <math.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
|
||||
|
||||
#ifdef _NO_LONGDBL
|
||||
|
@ -320,6 +326,7 @@ union arg_val
|
|||
void_ptr_t val_void_ptr_t;
|
||||
quad_t val_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,
|
||||
|
@ -428,7 +435,8 @@ _DEFUN (_VFPRINTF_R, (data, fp, fmt0, ap),
|
|||
struct __siov iov[NIOV];/* ... and individual io vectors */
|
||||
char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */
|
||||
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
|
||||
|
@ -728,8 +736,21 @@ reswitch: switch (ch) {
|
|||
flags |= QUADINT;
|
||||
goto rflag;
|
||||
case 'c':
|
||||
*(cp = buf) = GET_ARG(N, ap, int);
|
||||
size = 1;
|
||||
case 'C':
|
||||
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';
|
||||
break;
|
||||
case 'D':
|
||||
|
@ -881,9 +902,61 @@ reswitch: switch (ch) {
|
|||
ch = 'x';
|
||||
goto nosign;
|
||||
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)";
|
||||
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
|
||||
* NUL in the first `prec' characters, and
|
||||
|
@ -899,7 +972,7 @@ reswitch: switch (ch) {
|
|||
size = prec;
|
||||
} else
|
||||
size = strlen(cp);
|
||||
sign = '\0';
|
||||
|
||||
break;
|
||||
case 'U':
|
||||
flags |= LONGINT;
|
||||
|
@ -1097,10 +1170,17 @@ number: if ((dprec = prec) >= 0)
|
|||
ret += width > realsz ? width : realsz;
|
||||
|
||||
FLUSH(); /* copy out the I/O vectors */
|
||||
|
||||
if (malloc_buf != NULL) {
|
||||
free(malloc_buf);
|
||||
malloc_buf = NULL;
|
||||
}
|
||||
}
|
||||
done:
|
||||
FLUSH();
|
||||
error:
|
||||
if (malloc_buf != NULL)
|
||||
free(malloc_buf);
|
||||
return (__sferror(fp) ? EOF : ret);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
@ -1302,9 +1382,9 @@ const static CH_CLASS chclass[256] = {
|
|||
/* 28-2f */ OTHER, OTHER, STAR, FLAG, OTHER, FLAG, DOT, OTHER,
|
||||
/* 30-37 */ ZERO, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT,
|
||||
/* 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,
|
||||
/* 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,
|
||||
/* 60-67 */ OTHER, OTHER, OTHER, SPEC, SPEC, SPEC, SPEC, 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;
|
||||
mbstate_t wc_state;
|
||||
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 (*last_fmt != NULL)
|
||||
|
@ -1481,12 +1561,16 @@ get_arg (struct _reent *data, int n, char *fmt, va_list *ap,
|
|||
spec_type = DOUBLE;
|
||||
break;
|
||||
case 's':
|
||||
case 'S':
|
||||
case 'p':
|
||||
spec_type = CHAR_PTR;
|
||||
break;
|
||||
case 'c':
|
||||
spec_type = CHAR;
|
||||
break;
|
||||
case 'C':
|
||||
spec_type = WIDE_CHAR;
|
||||
break;
|
||||
}
|
||||
|
||||
/* 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:
|
||||
args[numargs++].val_quad_t = va_arg(*ap, quad_t);
|
||||
break;
|
||||
case WIDE_CHAR:
|
||||
args[numargs++].val_wint_t = va_arg(*ap, wint_t);
|
||||
break;
|
||||
case CHAR:
|
||||
case SHORT_INT:
|
||||
case INT:
|
||||
|
@ -1585,6 +1672,9 @@ get_arg (struct _reent *data, int n, char *fmt, va_list *ap,
|
|||
case LONG_DOUBLE:
|
||||
args[numargs++].val__LONG_DOUBLE = va_arg(*ap, _LONG_DOUBLE);
|
||||
break;
|
||||
case WIDE_CHAR:
|
||||
args[numargs++].val_wint_t = va_arg(*ap, wint_t);
|
||||
break;
|
||||
case INT:
|
||||
case SHORT_INT:
|
||||
case CHAR:
|
||||
|
|
Loading…
Reference in New Issue