From 25b979f243f0cd074dcfb91d0ecb7b3a2e07694b Mon Sep 17 00:00:00 2001 From: Robin Watts Date: Fri, 20 Mar 2015 18:59:27 +0000 Subject: Update our printf to cope with various useful extensions. Ensure that %010d works. Ensure that we can output 64 bit values (%ll{d,u,x}). Ensure that we can output size_t and fz_off_t (%z{d,u,x} and %Z{d,u,x}). fz_off_t isn't defined yet (it will be introduced by a commit that depends on this one), so for now, we put a stub definition in printf.c that we will remove later. --- include/mupdf/fitz/output.h | 5 +- source/fitz/printf.c | 136 ++++++++++++++++++++++++++++++++++++++------ source/pdf/pdf-write.c | 6 +- 3 files changed, 125 insertions(+), 22 deletions(-) diff --git a/include/mupdf/fitz/output.h b/include/mupdf/fitz/output.h index 5be32d44..6291d37e 100644 --- a/include/mupdf/fitz/output.h +++ b/include/mupdf/fitz/output.h @@ -87,13 +87,16 @@ int fz_vfprintf(fz_context *ctx, FILE *file, const char *fmt, va_list ap); int fz_fprintf(fz_context *ctx, FILE *file, const char *fmt, ...); /* - fz_vsnprintf: Our customised vsnprintf routine. Takes %c, %d, %o, %s, %x, as usual. + fz_vsnprintf: Our customised vsnprintf routine. Takes %c, %d, %o, %s, %u, %x, as usual. Modifiers are not supported except for zero-padding ints (e.g. %02d, %03o, %04x, etc). %f and %g both output in "as short as possible hopefully lossless non-exponent" form, see fz_ftoa for specifics. %C outputs a utf8 encoded int. %M outputs a fz_matrix*. %R outputs a fz_rect*. %P outputs a fz_point*. %q and %( output escaped strings in C/PDF syntax. + %ll{d,u,x} indicates that the values are 64bit. + %z{d,u,x} indicates that the value is a size_t. + %Z{d,u,x} indicates that the value is a fz_off_t. */ int fz_vsnprintf(char *buffer, int space, const char *fmt, va_list args); int fz_snprintf(char *buffer, int space, const char *fmt, ...); diff --git a/source/fitz/printf.c b/source/fitz/printf.c index 3d0ed19b..f63da293 100644 --- a/source/fitz/printf.c +++ b/source/fitz/printf.c @@ -1,5 +1,11 @@ #include "mupdf/fitz.h" +/* This definition will be made elsewhere soon, but putting it here + * temporarily means the commits can be sensibly ordered. */ +typedef int fz_off_t; + +static const char *fz_hex_digits = "0123456789abcdef"; + struct fmtbuf { char *p; @@ -54,24 +60,30 @@ static void fmtfloat(struct fmtbuf *out, float f) } } -static void fmtint(struct fmtbuf *out, int value, int z, int base) +static void fmtuint(struct fmtbuf *out, unsigned int a, int z, int base) { - static const char *digits = "0123456789abcdef"; char buf[40]; - unsigned int a; int i; - if (value < 0) - { - fmtputc(out, '-'); - a = -value; + i = 0; + while (a) { + buf[i++] = fz_hex_digits[a % base]; + a /= base; } - else - a = value; + while (i < z) + buf[i++] = '0'; + while (i > 0) + fmtputc(out, buf[--i]); +} + +static void fmtuint64(struct fmtbuf *out, uint64_t a, int z, int base) +{ + char buf[80]; + int i; i = 0; while (a) { - buf[i++] = digits[a % base]; + buf[i++] = fz_hex_digits[a % base]; a /= base; } while (i < z) @@ -80,6 +92,34 @@ static void fmtint(struct fmtbuf *out, int value, int z, int base) fmtputc(out, buf[--i]); } +static void fmtint(struct fmtbuf *out, int value, int z, int base) +{ + unsigned int a; + + if (value < 0) + { + fmtputc(out, '-'); + a = -value; + } + else + a = value; + fmtuint(out, a, z, base); +} + +static void fmtint64(struct fmtbuf *out, int64_t value, int z, int base) +{ + unsigned int a; + + if (value < 0) + { + fmtputc(out, '-'); + a = -value; + } + else + a = value; + fmtuint64(out, a, z, base); +} + static void fmtquote(struct fmtbuf *out, const char *s, int sq, int eq) { int c; @@ -117,8 +157,10 @@ fz_vsnprintf(char *buffer, int space, const char *fmt, va_list args) fz_rect *r; fz_point *p; int c, i, n, z; + int64_t i64; double f; char *s; + int length; out.p = buffer; out.s = space; @@ -134,6 +176,36 @@ fz_vsnprintf(char *buffer, int space, const char *fmt, va_list args) if (c == '0' && fmt[0] && fmt[1]) { z = *fmt++ - '0'; c = *fmt++; + if (c >= '0' && 'c' <= '9' && fmt[0]) + { + z = z*10 + c - '0'; + c = *fmt++; + } + } + /* Check for lengths */ + length = 0; + switch (c) { + case 'l': + c = *fmt++; + if (c == 'l') + length = 64; + else + fmt--; + break; + case 'z': + if (sizeof(size_t) >= 8) + length = 64; + break; + case 'Z': + if (sizeof(fz_off_t) >= 8) + length = 64; + break; + } + if (length != 0) + { + c = *fmt++; + if (c == 0) + break; /* Can't warn :( */ } switch (c) { default: @@ -143,7 +215,7 @@ fz_vsnprintf(char *buffer, int space, const char *fmt, va_list args) case '%': fmtputc(&out, '%'); break; - case 'M': + case 'M': /* fz_matrix * */ m = va_arg(args, fz_matrix*); fmtfloat(&out, m->a); fmtputc(&out, ' '); fmtfloat(&out, m->b); fmtputc(&out, ' '); @@ -152,19 +224,19 @@ fz_vsnprintf(char *buffer, int space, const char *fmt, va_list args) fmtfloat(&out, m->e); fmtputc(&out, ' '); fmtfloat(&out, m->f); break; - case 'R': + case 'R': /* fz_rect * */ r = va_arg(args, fz_rect*); fmtfloat(&out, r->x0); fmtputc(&out, ' '); fmtfloat(&out, r->y0); fmtputc(&out, ' '); fmtfloat(&out, r->x1); fmtputc(&out, ' '); fmtfloat(&out, r->y1); break; - case 'P': + case 'P': /* fz_point * */ p = va_arg(args, fz_point*); fmtfloat(&out, p->x); fmtputc(&out, ' '); fmtfloat(&out, p->y); break; - case 'C': + case 'C': /* unicode char */ c = va_arg(args, int); if (c < 128) fmtputc(&out, c); @@ -185,12 +257,40 @@ fz_vsnprintf(char *buffer, int space, const char *fmt, va_list args) fmtfloat(&out, f); break; case 'x': - i = va_arg(args, int); - fmtint(&out, i, z, 16); + if (length == 64) + { + i64 = va_arg(args, int64_t); + fmtuint64(&out, i64, z, 16); + } + else + { + i = va_arg(args, int); + fmtuint(&out, i, z, 16); + } break; case 'd': - i = va_arg(args, int); - fmtint(&out, i, z, 10); + if (length == 64) + { + i64 = va_arg(args, int64_t); + fmtint64(&out, i64, z, 10); + } + else + { + i = va_arg(args, int); + fmtint(&out, i, z, 10); + } + break; + case 'u': + if (length == 64) + { + i64 = va_arg(args, int64_t); + fmtuint64(&out, i64, z, 10); + } + else + { + i = va_arg(args, int); + fmtuint(&out, i, z, 10); + } break; case 'o': i = va_arg(args, int); diff --git a/source/pdf/pdf-write.c b/source/pdf/pdf-write.c index 5f815e03..358deb7e 100644 --- a/source/pdf/pdf-write.c +++ b/source/pdf/pdf-write.c @@ -1788,9 +1788,9 @@ static void writexrefsubsect(pdf_write_options *opts, int from, int to) for (num = from; num < to; num++) { if (opts->use_list[num]) - fprintf(opts->out, "%010d %05d n \n", opts->ofs_list[num], opts->gen_list[num]); + fprintf(opts->out, "%010Zd %05d n \n", opts->ofs_list[num], opts->gen_list[num]); else - fprintf(opts->out, "%010d %05d f \n", opts->ofs_list[num], opts->gen_list[num]); + fprintf(opts->out, "%010Zd %05d f \n", opts->ofs_list[num], opts->gen_list[num]); } } @@ -2011,7 +2011,7 @@ static void writexrefstream(fz_context *ctx, pdf_document *doc, pdf_write_option pdf_update_stream(ctx, doc, dict, fzbuf, 0); writeobject(ctx, doc, opts, num, 0, 0); - fprintf(opts->out, "startxref\n%d\n%%%%EOF\n", startxref); + fprintf(opts->out, "startxref\n%Zd\n%%%%EOF\n", startxref); } fz_always(ctx) { -- cgit v1.2.3