Support printf %n directive

This commit is contained in:
Justine Tunney 2024-07-28 22:27:06 -07:00
parent c1a0b017e9
commit 01b09bc817
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
8 changed files with 21 additions and 8 deletions

View file

@ -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_ */

View file

@ -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':

View file

@ -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;

View file

@ -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)) {

View file

@ -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)