summaryrefslogtreecommitdiff
path: root/printf/doprnt.c
diff options
context:
space:
mode:
authorKevin Ryde <user42@zip.com.au>2001-10-16 02:19:37 +0200
committerKevin Ryde <user42@zip.com.au>2001-10-16 02:19:37 +0200
commita0da410936fb2172e4f87f545848a1658bdd6ffa (patch)
tree0b50d3507bd552f1db3aeedc5c89830405ae8fb3 /printf/doprnt.c
parentae6293286159c273657b67461e2e09c5d315898f (diff)
downloadgmp-a0da410936fb2172e4f87f545848a1658bdd6ffa.tar.gz
* printf/doprnt.c: Support %lln and %hhn.
Diffstat (limited to 'printf/doprnt.c')
-rw-r--r--printf/doprnt.c41
1 files changed, 29 insertions, 12 deletions
diff --git a/printf/doprnt.c b/printf/doprnt.c
index 123d60d9c..6b110068b 100644
--- a/printf/doprnt.c
+++ b/printf/doprnt.c
@@ -152,7 +152,9 @@ __gmp_doprnt (const struct doprnt_funs_t *funs, void *data,
/* The format string is chopped up into pieces to be passed to
funs->format. Unfortunately that means it has to be copied so each
- piece can be null-terminated. */
+ piece can be null-terminated. We're not going to be very fast here, so
+ use __gmp_allocate_func rather than TMP_ALLOC, to avoid overflowing the
+ stack if a long output string is given. */
alloc_fmt_size = strlen (orig_fmt) + 1;
alloc_fmt = (*__gmp_allocate_func) (alloc_fmt_size);
fmt = alloc_fmt;
@@ -351,13 +353,13 @@ __gmp_doprnt (const struct doprnt_funs_t *funs, void *data,
goto floating;
case 'F':
- case 'h':
case 'j':
case 'L':
case 'q':
case 'Q':
case 't':
case 'Z':
+ set_type:
type = fchar;
break;
@@ -370,23 +372,38 @@ __gmp_doprnt (const struct doprnt_funs_t *funs, void *data,
param.showtrailing = 0;
goto floating;
- case 'l':
- if (type == 'l')
- type = 'L'; /* "ll" means "L" */
- else
- type = 'l';
+ case 'h':
+ if (type != 'h')
+ goto set_type;
+ type = 'H'; /* internal code for "hh" */
break;
+ case 'l':
+ if (type != 'l')
+ goto set_type;
+ type = 'L'; /* "ll" means "L" */
+ break;
+
case 'm':
/* glibc strerror(errno), no argument */
goto next;
case 'n':
- FLUSH ();
- switch (type) {
- case 'h': { short *p = va_arg (ap, short *); *p = retval; } break;
- case 'l': { long *p = va_arg (ap, long *); *p = retval; } break;
- default: { int *p = va_arg (ap, int *); *p = retval; } break;
+ {
+ void *p;
+ FLUSH ();
+ p = va_arg (ap, void *);
+ switch (type) {
+ case 'H': * (char *) p = retval; break;
+ case 'h': * (short *) p = retval; break;
+ case 'l': * (long *) p = retval; break;
+ default: * (int *) p = retval; break;
+#if HAVE_LONG_LONG
+ case 'L': * (long long *) p = retval; break;
+#else
+ case 'L': ASSERT_FAIL (long long not available); break;
+#endif
+ }
}
va_copy (last_ap, ap);
last_fmt = fmt;