mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-03-03 07:29:23 +00:00
Support printf %n directive
This commit is contained in:
parent
c1a0b017e9
commit
01b09bc817
8 changed files with 21 additions and 8 deletions
|
@ -47,6 +47,6 @@
|
|||
|
||||
int __vcscanf(int (*)(void *), int (*)(int, void *), void *, const char *,
|
||||
va_list);
|
||||
int __fmt(void *, void *, const char *, va_list);
|
||||
int __fmt(void *, void *, const char *, va_list, int *);
|
||||
|
||||
#endif /* COSMOPOLITAN_LIBC_FMT_STRTOL_H_ */
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "libc/errno.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/fmt/divmod10.internal.h"
|
||||
#include "libc/fmt/internal.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/intrin/bsr.h"
|
||||
#include "libc/intrin/nomultics.h"
|
||||
|
@ -820,7 +821,7 @@ static int __fmt_noop(const char *, void *, size_t) {
|
|||
* @asyncsignalsafe if floating point isn't used
|
||||
* @vforksafe if floating point isn't used
|
||||
*/
|
||||
int __fmt(void *fn, void *arg, const char *format, va_list va) {
|
||||
int __fmt(void *fn, void *arg, const char *format, va_list va, int *wrote) {
|
||||
long ld;
|
||||
void *p;
|
||||
double x;
|
||||
|
@ -1121,7 +1122,7 @@ int __fmt(void *fn, void *arg, const char *format, va_list va) {
|
|||
}
|
||||
break;
|
||||
case 'n':
|
||||
__FMT_PUT('\n');
|
||||
*va_arg(va, int *) = *wrote;
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
|
|
|
@ -63,7 +63,7 @@ int vdprintf(int fd, const char *fmt, va_list va) {
|
|||
t.n = 0;
|
||||
t.t = 0;
|
||||
t.fd = fd;
|
||||
if (__fmt(vdprintf_putc, &t, fmt, va) == -1)
|
||||
if (__fmt(vdprintf_putc, &t, fmt, va, &t.t) == -1)
|
||||
return -1;
|
||||
if (t.n) {
|
||||
iov[0].iov_base = t.b;
|
||||
|
|
|
@ -87,7 +87,7 @@ int vfprintf_unlocked(FILE *f, const char *fmt, va_list va) {
|
|||
st.f = f;
|
||||
st.n = 0;
|
||||
st.b.n = 0;
|
||||
if ((rc = __fmt(out, &st, fmt, va)) != -1) {
|
||||
if ((rc = __fmt(out, &st, fmt, va, &st.n)) != -1) {
|
||||
if (!st.b.n) {
|
||||
rc = st.n;
|
||||
} else if (fwrite_unlocked(st.b.p, 1, st.b.n, st.f)) {
|
||||
|
|
|
@ -26,8 +26,8 @@
|
|||
|
||||
struct SprintfStr {
|
||||
char *p;
|
||||
size_t i;
|
||||
size_t n;
|
||||
int i;
|
||||
int n;
|
||||
};
|
||||
|
||||
static int vsnprintfputchar(const char *s, struct SprintfStr *t, size_t n) {
|
||||
|
@ -58,7 +58,7 @@ static int vsnprintfputchar(const char *s, struct SprintfStr *t, size_t n) {
|
|||
*/
|
||||
int vsnprintf(char *buf, size_t size, const char *fmt, va_list va) {
|
||||
struct SprintfStr str = {buf, 0, size};
|
||||
int rc = __fmt(vsnprintfputchar, &str, fmt, va);
|
||||
int rc = __fmt(vsnprintfputchar, &str, fmt, va, &str.i);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
if (str.n)
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "libc/log/log.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/mem/gc.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/x/xasprintf.h"
|
||||
|
@ -431,3 +432,10 @@ TEST(fmt, regress) {
|
|||
"User-Agent: hurl/1.o (https://github.com/jart/cosmopolitan)\r\n",
|
||||
buf);
|
||||
}
|
||||
|
||||
TEST(fmt, n) {
|
||||
int n;
|
||||
char buf[8];
|
||||
snprintf(buf, 8, ".%c%c.%n", 0, 1, &n);
|
||||
ASSERT_EQ(4, n);
|
||||
}
|
||||
|
|
|
@ -165,6 +165,8 @@ for x; do
|
|||
elif [ x"$x" = x"-moptlinux" ]; then
|
||||
MODE=optlinux
|
||||
continue
|
||||
elif [ x"$x" = x"-m64" ]; then
|
||||
continue
|
||||
elif [ x"$x" = x"-fomit-frame-pointer" ]; then
|
||||
# Quoth Apple: "The frame pointer register must always address a
|
||||
# valid frame record. Some functions — such as leaf functions or
|
||||
|
|
|
@ -172,6 +172,8 @@ for x; do
|
|||
continue
|
||||
elif [ x"$x" = x"-moptlinux" ]; then
|
||||
continue
|
||||
elif [ x"$x" = x"-m64" ]; then
|
||||
continue
|
||||
elif [ x"$x" != x"${x#-o}" ]; then
|
||||
OUTPUT=${x#-o}
|
||||
elif [ x"$x" = x"-fpic" ]; then
|
||||
|
|
Loading…
Add table
Reference in a new issue