Skip to content

Commit 01b09bc

Browse files
committed
Support printf %n directive
1 parent c1a0b01 commit 01b09bc

File tree

8 files changed

+21
-8
lines changed

8 files changed

+21
-8
lines changed

libc/fmt/internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,6 @@
4747

4848
int __vcscanf(int (*)(void *), int (*)(int, void *), void *, const char *,
4949
va_list);
50-
int __fmt(void *, void *, const char *, va_list);
50+
int __fmt(void *, void *, const char *, va_list, int *);
5151

5252
#endif /* COSMOPOLITAN_LIBC_FMT_STRTOL_H_ */

libc/stdio/fmt.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#include "libc/errno.h"
4444
#include "libc/fmt/conv.h"
4545
#include "libc/fmt/divmod10.internal.h"
46+
#include "libc/fmt/internal.h"
4647
#include "libc/fmt/itoa.h"
4748
#include "libc/intrin/bsr.h"
4849
#include "libc/intrin/nomultics.h"
@@ -820,7 +821,7 @@ static int __fmt_noop(const char *, void *, size_t) {
820821
* @asyncsignalsafe if floating point isn't used
821822
* @vforksafe if floating point isn't used
822823
*/
823-
int __fmt(void *fn, void *arg, const char *format, va_list va) {
824+
int __fmt(void *fn, void *arg, const char *format, va_list va, int *wrote) {
824825
long ld;
825826
void *p;
826827
double x;
@@ -1121,7 +1122,7 @@ int __fmt(void *fn, void *arg, const char *format, va_list va) {
11211122
}
11221123
break;
11231124
case 'n':
1124-
__FMT_PUT('\n');
1125+
*va_arg(va, int *) = *wrote;
11251126
break;
11261127

11271128
case 'F':

libc/stdio/vdprintf.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ int vdprintf(int fd, const char *fmt, va_list va) {
6363
t.n = 0;
6464
t.t = 0;
6565
t.fd = fd;
66-
if (__fmt(vdprintf_putc, &t, fmt, va) == -1)
66+
if (__fmt(vdprintf_putc, &t, fmt, va, &t.t) == -1)
6767
return -1;
6868
if (t.n) {
6969
iov[0].iov_base = t.b;

libc/stdio/vfprintf_unlocked.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ int vfprintf_unlocked(FILE *f, const char *fmt, va_list va) {
8787
st.f = f;
8888
st.n = 0;
8989
st.b.n = 0;
90-
if ((rc = __fmt(out, &st, fmt, va)) != -1) {
90+
if ((rc = __fmt(out, &st, fmt, va, &st.n)) != -1) {
9191
if (!st.b.n) {
9292
rc = st.n;
9393
} else if (fwrite_unlocked(st.b.p, 1, st.b.n, st.f)) {

libc/stdio/vsnprintf.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@
2626

2727
struct SprintfStr {
2828
char *p;
29-
size_t i;
30-
size_t n;
29+
int i;
30+
int n;
3131
};
3232

3333
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) {
5858
*/
5959
int vsnprintf(char *buf, size_t size, const char *fmt, va_list va) {
6060
struct SprintfStr str = {buf, 0, size};
61-
int rc = __fmt(vsnprintfputchar, &str, fmt, va);
61+
int rc = __fmt(vsnprintfputchar, &str, fmt, va, &str.i);
6262
if (rc < 0)
6363
return rc;
6464
if (str.n)

test/libc/stdio/fmt_test.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "libc/log/log.h"
2121
#include "libc/math.h"
2222
#include "libc/mem/gc.h"
23+
#include "libc/stdio/stdio.h"
2324
#include "libc/str/str.h"
2425
#include "libc/testlib/testlib.h"
2526
#include "libc/x/xasprintf.h"
@@ -431,3 +432,10 @@ TEST(fmt, regress) {
431432
"User-Agent: hurl/1.o (https://github.com/jart/cosmopolitan)\r\n",
432433
buf);
433434
}
435+
436+
TEST(fmt, n) {
437+
int n;
438+
char buf[8];
439+
snprintf(buf, 8, ".%c%c.%n", 0, 1, &n);
440+
ASSERT_EQ(4, n);
441+
}

tool/cosmocc/bin/cosmocc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,8 @@ for x; do
165165
elif [ x"$x" = x"-moptlinux" ]; then
166166
MODE=optlinux
167167
continue
168+
elif [ x"$x" = x"-m64" ]; then
169+
continue
168170
elif [ x"$x" = x"-fomit-frame-pointer" ]; then
169171
# Quoth Apple: "The frame pointer register must always address a
170172
# valid frame record. Some functions — such as leaf functions or

tool/cosmocc/bin/cosmocross

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,8 @@ for x; do
172172
continue
173173
elif [ x"$x" = x"-moptlinux" ]; then
174174
continue
175+
elif [ x"$x" = x"-m64" ]; then
176+
continue
175177
elif [ x"$x" != x"${x#-o}" ]; then
176178
OUTPUT=${x#-o}
177179
elif [ x"$x" = x"-fpic" ]; then

0 commit comments

Comments
 (0)