diff options
author | Jeff Johnston <jjohnstn@redhat.com> | 2006-09-07 00:03:27 +0400 |
---|---|---|
committer | Jeff Johnston <jjohnstn@redhat.com> | 2006-09-07 00:03:27 +0400 |
commit | d39002f9ca0725bbc4eed86bb5b98ae59b7296e8 (patch) | |
tree | d022116ca216389c49b443502b8b4517e577a8e0 /newlib/libc | |
parent | a046f426ed7e3b4a89b85f8e5795ef49702fcbf0 (diff) |
2006-09-06 Eric Blake <ebb9@byu.net>
* libc/stdio/vfprintf.c (_vfprintf_r, get_arg): Add 'hh', 'j',
't', and 'z' modifiers.
Diffstat (limited to 'newlib/libc')
-rw-r--r-- | newlib/libc/stdio/vfprintf.c | 107 |
1 files changed, 102 insertions, 5 deletions
diff --git a/newlib/libc/stdio/vfprintf.c b/newlib/libc/stdio/vfprintf.c index 370ffe0e5..9e5477aa6 100644 --- a/newlib/libc/stdio/vfprintf.c +++ b/newlib/libc/stdio/vfprintf.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1990 The Regents of the University of California. + * Copyright (c) 1990, 2006 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by @@ -182,6 +182,7 @@ static char *rcsid = "$Id$"; #include <stdlib.h> #include <string.h> #include <limits.h> +#include <stdint.h> #include <wchar.h> #include <string.h> #include <sys/lock.h> @@ -372,6 +373,7 @@ _EXFUN(get_arg, (struct _reent *data, int n, char *fmt, #define SHORTINT 0x040 /* short integer */ #define ZEROPAD 0x080 /* zero (as opposed to blank) pad */ #define FPT 0x100 /* Floating point number */ +#define CHARINT 0x200 /* char as integer */ int _EXFUN(_VFPRINTF_R, (struct _reent *, FILE *, _CONST char *, va_list)); @@ -427,7 +429,7 @@ _DEFUN(_VFPRINTF_R, (data, fp, fmt0, ap), #endif int expt; /* integer value of exponent */ int expsize = 0; /* character count for expstr */ - int ndig; /* actual number of digits returned by cvt */ + int ndig = 0; /* actual number of digits returned by cvt */ char expstr[7]; /* buffer for exponent string */ #endif u_quad_t _uquad; /* integer arguments %[diouxX] */ @@ -517,20 +519,24 @@ _DEFUN(_VFPRINTF_R, (data, fp, fmt0, ap), (flags&QUADINT ? GET_ARG (N, ap, quad_t) : \ flags&LONGINT ? GET_ARG (N, ap, long) : \ flags&SHORTINT ? (long)(short)GET_ARG (N, ap, int) : \ + flags&CHARINT ? (long)(signed char)GET_ARG (N, ap, int) : \ (long)GET_ARG (N, ap, int)) #define UARG() \ (flags&QUADINT ? GET_ARG (N, ap, u_quad_t) : \ flags&LONGINT ? GET_ARG (N, ap, u_long) : \ flags&SHORTINT ? (u_long)(u_short)GET_ARG (N, ap, int) : \ + flags&CHARINT ? (u_long)(unsigned char)GET_ARG (N, ap, int) : \ (u_long)GET_ARG (N, ap, u_int)) #else #define SARG() \ (flags&LONGINT ? GET_ARG (N, ap, long) : \ flags&SHORTINT ? (long)(short)GET_ARG (N, ap, int) : \ + flags&CHARINT ? (long)(signed char)GET_ARG (N, ap, int) : \ (long)GET_ARG (N, ap, int)) #define UARG() \ (flags&LONGINT ? GET_ARG (N, ap, u_long) : \ flags&SHORTINT ? (u_long)(u_short)GET_ARG (N, ap, int) : \ + flags&CHARINT ? (u_long)(unsigned char)GET_ARG (N, ap, int) : \ (u_long)GET_ARG (N, ap, u_int)) #endif @@ -747,7 +753,12 @@ reswitch: switch (ch) { goto rflag; #endif case 'h': - flags |= SHORTINT; + if (*fmt == 'h') { + fmt++; + flags |= CHARINT; + } else { + flags |= SHORTINT; + } goto rflag; case 'l': if (*fmt == 'l') { @@ -760,6 +771,43 @@ reswitch: switch (ch) { case 'q': flags |= QUADINT; goto rflag; + case 'j': + if (sizeof (intmax_t) == sizeof (long)) + flags |= LONGINT; + else + flags |= QUADINT; + goto rflag; + case 'z': + if (sizeof (size_t) < sizeof (int)) + /* POSIX states size_t is 16 or more bits, as is short. */ + flags |= SHORTINT; + else if (sizeof (size_t) == sizeof (int)) + /* no flag needed */; + else if (sizeof (size_t) <= sizeof (long)) + flags |= LONGINT; + 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 |= QUADINT; + goto rflag; + case 't': + if (sizeof (ptrdiff_t) < sizeof (int)) + /* POSIX states ptrdiff_t is 16 or more bits, as + is short. */ + flags |= SHORTINT; + else if (sizeof (ptrdiff_t) == sizeof (int)) + /* no flag needed */; + else if (sizeof (ptrdiff_t) <= sizeof (long)) + flags |= LONGINT; + 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 |= QUADINT; + goto rflag; case 'c': case 'C': cp = buf; @@ -916,6 +964,8 @@ reswitch: switch (ch) { *GET_ARG (N, ap, long_ptr_t) = ret; else if (flags & SHORTINT) *GET_ARG (N, ap, short_ptr_t) = ret; + else if (flags & CHARINT) + *GET_ARG (N, ap, char_ptr_t) = ret; else *GET_ARG (N, ap, int_ptr_t) = ret; continue; /* no output */ @@ -1526,7 +1576,7 @@ _DEFUN(get_arg, (data, n, fmt, ap, numargs_p, args, arg_type, last_fmt), ACTION action; int pos, last_arg; int max_pos_arg = n; - enum types { INT, LONG_INT, SHORT_INT, QUAD_INT, CHAR, CHAR_PTR, DOUBLE, LONG_DOUBLE, WIDE_CHAR }; + enum types { INT, LONG_INT, SHORT_INT, CHAR_INT, QUAD_INT, CHAR, CHAR_PTR, DOUBLE, LONG_DOUBLE, WIDE_CHAR }; #ifdef _MB_CAPABLE wchar_t wc; mbstate_t wc_state; @@ -1585,7 +1635,13 @@ _DEFUN(get_arg, (data, n, fmt, ap, numargs_p, args, arg_type, last_fmt), switch (ch) { case 'h': - flags |= SHORTINT; + if (*fmt == 'h') + { + flags |= CHARINT; + ++fmt; + } + else + flags |= SHORTINT; break; case 'L': flags |= LONGDBL; @@ -1593,6 +1649,43 @@ _DEFUN(get_arg, (data, n, fmt, ap, numargs_p, args, arg_type, last_fmt), case 'q': flags |= QUADINT; break; + case 'j': + if (sizeof (intmax_t) == sizeof (long)) + flags |= LONGINT; + else + flags |= QUADINT; + break; + case 'z': + if (sizeof (size_t) < sizeof (int)) + /* POSIX states size_t is 16 or more bits, as is short. */ + flags |= SHORTINT; + else if (sizeof (size_t) == sizeof (int)) + /* no flag needed */; + else if (sizeof (size_t) <= sizeof (long)) + flags |= LONGINT; + 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 |= QUADINT; + break; + case 't': + if (sizeof (ptrdiff_t) < sizeof (int)) + /* POSIX states ptrdiff_t is 16 or more bits, as + is short. */ + flags |= SHORTINT; + else if (sizeof (ptrdiff_t) == sizeof (int)) + /* no flag needed */; + else if (sizeof (ptrdiff_t) <= sizeof (long)) + flags |= LONGINT; + 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 |= QUADINT; + break; case 'l': default: if (*fmt == 'l') @@ -1621,6 +1714,8 @@ _DEFUN(get_arg, (data, n, fmt, ap, numargs_p, args, arg_type, last_fmt), spec_type = LONG_INT; else if (flags & SHORTINT) spec_type = SHORT_INT; + else if (flags & CHARINT) + spec_type = CHAR_INT; #ifndef _NO_LONGLONG else if (flags & QUADINT) spec_type = QUAD_INT; @@ -1676,6 +1771,7 @@ _DEFUN(get_arg, (data, n, fmt, ap, numargs_p, args, arg_type, last_fmt), args[numargs++].val_wint_t = va_arg (*ap, wint_t); break; case CHAR: + case CHAR_INT: case SHORT_INT: case INT: args[numargs++].val_int = va_arg (*ap, int); @@ -1761,6 +1857,7 @@ _DEFUN(get_arg, (data, n, fmt, ap, numargs_p, args, arg_type, last_fmt), args[numargs++].val_wint_t = va_arg (*ap, wint_t); break; case INT: + case CHAR_INT: case SHORT_INT: case CHAR: default: |