diff mbox

[3/5] Fix some "unknown format" warnings

Message ID 519BC851.5090202@ramsay1.demon.co.uk (mailing list archive)
State Rejected, archived
Headers show

Commit Message

Ramsay Jones May 21, 2013, 7:17 p.m. UTC
Signed-off-by: Ramsay Jones <ramsay@ramsay1.demon.co.uk>
---
 compile-i386.c |  7 ++++---
 example.c      |  7 ++++---
 expand.c       |  5 +++--
 linearize.c    | 15 ++++++++++-----
 parse.c        |  3 ++-
 pre-process.c  |  7 ++++++-
 show-parse.c   | 15 ++++++++++-----
 sparse.c       |  3 ++-
 tokenize.c     |  4 ++--
 9 files changed, 43 insertions(+), 23 deletions(-)

Comments

Josh Triplett May 21, 2013, 10:05 p.m. UTC | #1
On Tue, May 21, 2013 at 08:17:37PM +0100, Ramsay Jones wrote:
> 
> Signed-off-by: Ramsay Jones <ramsay@ramsay1.demon.co.uk>
> ---

%Ld for a long long int is actually broken on all architectures; L only
works for long double.  Thanks for fixing that.

Formatting nit: I think this reads better when written as:

"... blah blah " PRIx64 " blah blah ..."

, leaving spaces between the macro and the close/open doublequotes.

Further comments below.

> @@ -336,10 +337,14 @@ const char *show_instruction(struct instruction *insn)
>  			
>  		switch (expr->type) {
>  		case EXPR_VALUE:
> -			buf += sprintf(buf, "%lld", expr->value);
> +			buf += sprintf(buf, "%"PRId64, expr->value);
>  			break;
>  		case EXPR_FVALUE:
> +#if !defined(__MINGW32__)
>  			buf += sprintf(buf, "%Lf", expr->fvalue);
> +#else
> +			buf += sprintf(buf, "%f", (double)expr->fvalue);
> +#endif

This seems really sad; does MinGW really have long double but no way to
print it?  Can we at least emit something here to indicate possible
truncation or loss of precision, if no means exists to print a long
double?

> @@ -463,7 +468,7 @@ const char *show_instruction(struct instruction *insn)
>  	}
>  
>  	if (buf >= buffer + sizeof(buffer))
> -		die("instruction buffer overflowed %td\n", buf - buffer);
> +		die("instruction buffer overflowed %d\n", (int)(buf - buffer));

No, ptrdiff_t does not portably fit in int; it generally has the same
size as size_t (64-bit on 64-bit platforms).  Cast to "long long" and
use PRId64 if you must.

> --- a/pre-process.c
> +++ b/pre-process.c
> @@ -158,12 +158,17 @@ static int expand_one_symbol(struct token **list)
>  	} else if (token->ident == &__DATE___ident) {
>  		if (!t)
>  			time(&t);
> +#if !defined(__MINGW32__)
>  		strftime(buffer, 12, "%b %e %Y", localtime(&t));
> +#else
> +		strftime(buffer, 12, "%b %d %Y", localtime(&t));
> +		if (buffer[4] == '0') buffer[4] = ' ';
> +#endif

To the best of my knowledge, nothing guarantees the length of %b, so the
[4] here seems wrong.

> @@ -980,7 +981,11 @@ static int show_fvalue(struct expression *expr)
>  	int new = new_pseudo();
>  	long double value = expr->fvalue;
>  
> +#if !defined(__MINGW32__)
>  	printf("\tmovf.%d\t\tv%d,$%Lf\n", expr->ctype->bit_size, new, value);
> +#else
> +	printf("\tmovf.%d\t\tv%d,$%f\n", expr->ctype->bit_size, new, (double)value);
> +#endif

Same comment as above regarding long double.

> --- a/tokenize.c
> +++ b/tokenize.c
> @@ -547,8 +547,8 @@ static int get_one_number(int c, int next, stream_t *stream)
>  	}
>  
>  	if (p == buffer_end) {
> -		sparse_error(stream_pos(stream), "number token exceeds %td characters",
> -		      buffer_end - buffer);
> +		sparse_error(stream_pos(stream), "number token exceeds %d characters",
> +		      (int)(buffer_end - buffer));

Same comment as above regarding ptrdiff_t.

- Josh Triplett
--
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Ramsay Jones May 22, 2013, 10:01 p.m. UTC | #2
Josh Triplett wrote:
> On Tue, May 21, 2013 at 08:17:37PM +0100, Ramsay Jones wrote:
>>
>> Signed-off-by: Ramsay Jones <ramsay@ramsay1.demon.co.uk>
>> ---
> 
> %Ld for a long long int is actually broken on all architectures; L only
> works for long double.  Thanks for fixing that.

Yep, I had forgotten about that change. I should have sent that four
years ago. Sorry about that.

> Formatting nit: I think this reads better when written as:
> 
> "... blah blah " PRIx64 " blah blah ..."
> 
> , leaving spaces between the macro and the close/open doublequotes.

OK, will do.

> 
> Further comments below.
> 
>> @@ -336,10 +337,14 @@ const char *show_instruction(struct instruction *insn)
>>  			
>>  		switch (expr->type) {
>>  		case EXPR_VALUE:
>> -			buf += sprintf(buf, "%lld", expr->value);
>> +			buf += sprintf(buf, "%"PRId64, expr->value);
>>  			break;
>>  		case EXPR_FVALUE:
>> +#if !defined(__MINGW32__)
>>  			buf += sprintf(buf, "%Lf", expr->fvalue);
>> +#else
>> +			buf += sprintf(buf, "%f", (double)expr->fvalue);
>> +#endif
> 
> This seems really sad; does MinGW really have long double but no way to
> print it?  Can we at least emit something here to indicate possible
> truncation or loss of precision, if no means exists to print a long
> double?

I couldn't find any means to do so, just from experimentation (I didn't
have any MinGW specific gcc documentation). Thus, I tried:

  $ cat -n junk.c
       1  #include <stdio.h>
       2
       3  int main(int argc, char *argv[])
       4  {
       5          long double f = 128.821L;
       6
       7          printf("sizeof(float) = %d\n", sizeof(float));
       8          printf("sizeof(double) = %d\n", sizeof(double));
       9          printf("sizeof(long double) = %d\n", sizeof(long double));
      10          printf("f = %Lf\n", f);
      11          return 0;
      12  }

  $ gcc -Wall -o junk junk.c
  junk.c: In function 'main':
  junk.c:10: warning: unknown conversion type character 'L' in format
  junk.c:10: warning: too many arguments for format
  $ ./junk.exe
  sizeof(float) = 4
  sizeof(double) = 8
  sizeof(long double) = 12
  f = -0.000000

  $ cl -W4 junk.c
  Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86
  Copyright (C) Microsoft Corporation.  All rights reserved.

  junk.c
  junk.c(3) : warning C4100: 'argv' : unreferenced formal parameter
  junk.c(3) : warning C4100: 'argc' : unreferenced formal parameter
  Microsoft (R) Incremental Linker Version 9.00.30729.01
  Copyright (C) Microsoft Corporation.  All rights reserved.

  /out:junk.exe
  junk.obj
  $ ./junk.exe
  sizeof(float) = 4
  sizeof(double) = 8
  sizeof(long double) = 8
  f = 128.821000
  $

So, msvc knows about the L size modifier, but it treats a 'long double'
the same as a 'double'.

  $ vim junk.c # change format specifier %Lf => %lf
  $ gcc -Wall -o junk junk.c
  junk.c: In function 'main':
  junk.c:10: warning: format '%lf' expects type 'double', but argument 2 has type
  'long double'
  $ ./junk.exe
  sizeof(float) = 4
  sizeof(double) = 8
  sizeof(long double) = 12
  f = -0.000000
  $

I'm sure you can guess what happens if you try "%f" instead.

The current "compat" layer has an string_to_ld() function, so maybe
there should be an ld_to_string()? dunno.

[A 64-bit MinGW system probably doesn't have this problem, of course ...]

> 
>> @@ -463,7 +468,7 @@ const char *show_instruction(struct instruction *insn)
>>  	}
>>  
>>  	if (buf >= buffer + sizeof(buffer))
>> -		die("instruction buffer overflowed %td\n", buf - buffer);
>> +		die("instruction buffer overflowed %d\n", (int)(buf - buffer));
> 
> No, ptrdiff_t does not portably fit in int; it generally has the same
> size as size_t (64-bit on 64-bit platforms).  Cast to "long long" and
> use PRId64 if you must.

Yes, for the same reason, git does:

    printf("...%" PRIuMAX "...", (uintmax_t)(buf - buffer));

so I'll do that in the re-roll.

> 
>> --- a/pre-process.c
>> +++ b/pre-process.c
>> @@ -158,12 +158,17 @@ static int expand_one_symbol(struct token **list)
>>  	} else if (token->ident == &__DATE___ident) {
>>  		if (!t)
>>  			time(&t);
>> +#if !defined(__MINGW32__)
>>  		strftime(buffer, 12, "%b %e %Y", localtime(&t));
>> +#else
>> +		strftime(buffer, 12, "%b %d %Y", localtime(&t));
>> +		if (buffer[4] == '0') buffer[4] = ' ';
>> +#endif
> To the best of my knowledge, nothing guarantees the length of %b, so the
> [4] here seems wrong.

Yes, this was just a quick hack to compensate for the lack of the
"%e" format specifier in the msvc strftime(). (elsewhere the lack
of "%T" was easier to replace). I will have to think about this.
Any ideas?

>> @@ -980,7 +981,11 @@ static int show_fvalue(struct expression *expr)
>>  	int new = new_pseudo();
>>  	long double value = expr->fvalue;
>>  
>> +#if !defined(__MINGW32__)
>>  	printf("\tmovf.%d\t\tv%d,$%Lf\n", expr->ctype->bit_size, new, value);
>> +#else
>> +	printf("\tmovf.%d\t\tv%d,$%f\n", expr->ctype->bit_size, new, (double)value);
>> +#endif
> 
> Same comment as above regarding long double.
> 
>> --- a/tokenize.c
>> +++ b/tokenize.c
>> @@ -547,8 +547,8 @@ static int get_one_number(int c, int next, stream_t *stream)
>>  	}
>>  
>>  	if (p == buffer_end) {
>> -		sparse_error(stream_pos(stream), "number token exceeds %td characters",
>> -		      buffer_end - buffer);
>> +		sparse_error(stream_pos(stream), "number token exceeds %d characters",
>> +		      (int)(buffer_end - buffer));
> 
> Same comment as above regarding ptrdiff_t.
> 
> - Josh Triplett

Thanks Josh. You hit every part of the patch that I wanted to
tidy up! :-D

ATB,
Ramsay Jones



--
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Josh Triplett May 22, 2013, 10:54 p.m. UTC | #3
On Wed, May 22, 2013 at 11:01:21PM +0100, Ramsay Jones wrote:
> Josh Triplett wrote:
> > On Tue, May 21, 2013 at 08:17:37PM +0100, Ramsay Jones wrote:
> >> @@ -336,10 +337,14 @@ const char *show_instruction(struct instruction *insn)
> >>  			
> >>  		switch (expr->type) {
> >>  		case EXPR_VALUE:
> >> -			buf += sprintf(buf, "%lld", expr->value);
> >> +			buf += sprintf(buf, "%"PRId64, expr->value);
> >>  			break;
> >>  		case EXPR_FVALUE:
> >> +#if !defined(__MINGW32__)
> >>  			buf += sprintf(buf, "%Lf", expr->fvalue);
> >> +#else
> >> +			buf += sprintf(buf, "%f", (double)expr->fvalue);
> >> +#endif
> > 
> > This seems really sad; does MinGW really have long double but no way to
> > print it?  Can we at least emit something here to indicate possible
> > truncation or loss of precision, if no means exists to print a long
> > double?
> 
> I couldn't find any means to do so, just from experimentation (I didn't
> have any MinGW specific gcc documentation). Thus, I tried:
[...]
> So, msvc knows about the L size modifier, but it treats a 'long double'
> the same as a 'double'.

Sigh.  Odd that GCC has different behavior there, but since MinGW uses
the same C library as Visual C (msvcrt), it does seem likely that the
underlying behavior would need to match.

> The current "compat" layer has an string_to_ld() function, so maybe
> there should be an ld_to_string()? dunno.

That seems like the best plan, if you can find a portable one to
include.

> >> @@ -463,7 +468,7 @@ const char *show_instruction(struct instruction *insn)
> >>  	}
> >>  
> >>  	if (buf >= buffer + sizeof(buffer))
> >> -		die("instruction buffer overflowed %td\n", buf - buffer);
> >> +		die("instruction buffer overflowed %d\n", (int)(buf - buffer));
> > 
> > No, ptrdiff_t does not portably fit in int; it generally has the same
> > size as size_t (64-bit on 64-bit platforms).  Cast to "long long" and
> > use PRId64 if you must.
> 
> Yes, for the same reason, git does:
> 
>     printf("...%" PRIuMAX "...", (uintmax_t)(buf - buffer));
> 
> so I'll do that in the re-roll.

uintmax_t works; I suspect it might be overkill, but it'll work.

> >> --- a/pre-process.c
> >> +++ b/pre-process.c
> >> @@ -158,12 +158,17 @@ static int expand_one_symbol(struct token **list)
> >>  	} else if (token->ident == &__DATE___ident) {
> >>  		if (!t)
> >>  			time(&t);
> >> +#if !defined(__MINGW32__)
> >>  		strftime(buffer, 12, "%b %e %Y", localtime(&t));
> >> +#else
> >> +		strftime(buffer, 12, "%b %d %Y", localtime(&t));
> >> +		if (buffer[4] == '0') buffer[4] = ' ';
> >> +#endif
> > To the best of my knowledge, nothing guarantees the length of %b, so the
> > [4] here seems wrong.
> 
> Yes, this was just a quick hack to compensate for the lack of the
> "%e" format specifier in the msvc strftime(). (elsewhere the lack
> of "%T" was easier to replace). I will have to think about this.
> Any ideas?

strftime returns the number of characters it generated; just format the
"%b " separately so you have the offset needed for the %d and the
modification.

> >> --- a/tokenize.c
> >> +++ b/tokenize.c
> >> @@ -547,8 +547,8 @@ static int get_one_number(int c, int next, stream_t *stream)
> >>  	}
> >>  
> >>  	if (p == buffer_end) {
> >> -		sparse_error(stream_pos(stream), "number token exceeds %td characters",
> >> -		      buffer_end - buffer);
> >> +		sparse_error(stream_pos(stream), "number token exceeds %d characters",
> >> +		      (int)(buffer_end - buffer));
> > 
> > Same comment as above regarding ptrdiff_t.
> > 
> > - Josh Triplett
> 
> Thanks Josh. You hit every part of the patch that I wanted to
> tidy up! :-D

No problem; thanks for working on this!  I'd love to see sparse used for
Windows compilation.

Have you managed to use it with a mingw cross-compiler, by any chance?

- Josh Triplett
--
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Christopher Li May 23, 2013, 3:42 p.m. UTC | #4
On 05/21/2013 12:17 PM, Ramsay Jones wrote:

> +#if !defined(__MINGW32__)
>  			buf += sprintf(buf, "%Lf", expr->fvalue);
> +#else
> +			buf += sprintf(buf, "%f", (double)expr->fvalue);
> +#endif

I don't like to stash !define(__MINW32__) all over the sparse
code. Let's move this to the compat abstract layer. Can you create a
function "char *print_float(float value)" function in compat-mingw.c and
the normal implementation in compat/*.c


> +#if !defined(__MINGW32__)
>  		strftime(buffer, 12, "%b %e %Y", localtime(&t));
> +#else
> +		strftime(buffer, 12, "%b %d %Y", localtime(&t));
> +		if (buffer[4] == '0') buffer[4] = ' ';
> +#endif

Same here, try to move to the compat layer.

> +#if !defined(__MINGW32__)
>  	printf("\tmovf.%d\t\tv%d,$%Lf\n", expr->ctype->bit_size, new, value);
> +#else
> +	printf("\tmovf.%d\t\tv%d,$%f\n", expr->ctype->bit_size, new, (double)value);
> +#endif

Here we can reuse the previous print_float() function.

Chris
--
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Ramsay Jones May 25, 2013, 7:26 p.m. UTC | #5
Josh Triplett wrote:
> On Wed, May 22, 2013 at 11:01:21PM +0100, Ramsay Jones wrote:
>> Josh Triplett wrote:
>>> On Tue, May 21, 2013 at 08:17:37PM +0100, Ramsay Jones wrote:

>> The current "compat" layer has an string_to_ld() function, so maybe
>> there should be an ld_to_string()? dunno.
> 
> That seems like the best plan, if you can find a portable one to
> include.

Hmm, I'm not sure I understand; in this case, ld_to_string() would just
cast to double in order to sprintf. ;-)

>>>> @@ -463,7 +468,7 @@ const char *show_instruction(struct instruction *insn)
>>>>  	}
>>>>  
>>>>  	if (buf >= buffer + sizeof(buffer))
>>>> -		die("instruction buffer overflowed %td\n", buf - buffer);
>>>> +		die("instruction buffer overflowed %d\n", (int)(buf - buffer));
>>>
>>> No, ptrdiff_t does not portably fit in int; it generally has the same
>>> size as size_t (64-bit on 64-bit platforms).  Cast to "long long" and
>>> use PRId64 if you must.
>>
>> Yes, for the same reason, git does:
>>
>>     printf("...%" PRIuMAX "...", (uintmax_t)(buf - buffer));
>>
>> so I'll do that in the re-roll.
> 
> uintmax_t works; I suspect it might be overkill, but it'll work.

Oh, I think int is probably overkill (on 32-bit systems), but this
should cater for all future needs. ;-)

>>>> --- a/pre-process.c
>>>> +++ b/pre-process.c
>>>> @@ -158,12 +158,17 @@ static int expand_one_symbol(struct token **list)
>>>>  	} else if (token->ident == &__DATE___ident) {
>>>>  		if (!t)
>>>>  			time(&t);
>>>> +#if !defined(__MINGW32__)
>>>>  		strftime(buffer, 12, "%b %e %Y", localtime(&t));
>>>> +#else
>>>> +		strftime(buffer, 12, "%b %d %Y", localtime(&t));
>>>> +		if (buffer[4] == '0') buffer[4] = ' ';
>>>> +#endif
>>> To the best of my knowledge, nothing guarantees the length of %b, so the
>>> [4] here seems wrong.
>>
>> Yes, this was just a quick hack to compensate for the lack of the
>> "%e" format specifier in the msvc strftime(). (elsewhere the lack
>> of "%T" was easier to replace). I will have to think about this.
>> Any ideas?
> 
> strftime returns the number of characters it generated; just format the
> "%b " separately so you have the offset needed for the %d and the
> modification.

Yep, I'll look into it. Having said that, I'm not sure we need to make
this string identical on all systems. dunno.

>>>> --- a/tokenize.c
>>>> +++ b/tokenize.c
>>>> @@ -547,8 +547,8 @@ static int get_one_number(int c, int next, stream_t *stream)
>>>>  	}
>>>>  
>>>>  	if (p == buffer_end) {
>>>> -		sparse_error(stream_pos(stream), "number token exceeds %td characters",
>>>> -		      buffer_end - buffer);
>>>> +		sparse_error(stream_pos(stream), "number token exceeds %d characters",
>>>> +		      (int)(buffer_end - buffer));
>>>
>>> Same comment as above regarding ptrdiff_t.
>>>
>>> - Josh Triplett
>>
>> Thanks Josh. You hit every part of the patch that I wanted to
>> tidy up! :-D
> 
> No problem; thanks for working on this!  I'd love to see sparse used for
> Windows compilation.
> 
> Have you managed to use it with a mingw cross-compiler, by any chance?

No, I'm afraid not. :(

ATB,
Ramsay Jones



--
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Josh Triplett May 25, 2013, 8:30 p.m. UTC | #6
On Sat, May 25, 2013 at 08:26:47PM +0100, Ramsay Jones wrote:
> Josh Triplett wrote:
> > On Wed, May 22, 2013 at 11:01:21PM +0100, Ramsay Jones wrote:
> >> Josh Triplett wrote:
> >>> On Tue, May 21, 2013 at 08:17:37PM +0100, Ramsay Jones wrote:
> 
> >> The current "compat" layer has an string_to_ld() function, so maybe
> >> there should be an ld_to_string()? dunno.
> > 
> > That seems like the best plan, if you can find a portable one to
> > include.
> 
> Hmm, I'm not sure I understand; in this case, ld_to_string() would just
> cast to double in order to sprintf. ;-)

I meant, you could find some code that actually knows how to turn a
long double into a string directly, and include that for compatibility.

> >>>> --- a/pre-process.c
> >>>> +++ b/pre-process.c
> >>>> @@ -158,12 +158,17 @@ static int expand_one_symbol(struct token **list)
> >>>>  	} else if (token->ident == &__DATE___ident) {
> >>>>  		if (!t)
> >>>>  			time(&t);
> >>>> +#if !defined(__MINGW32__)
> >>>>  		strftime(buffer, 12, "%b %e %Y", localtime(&t));
> >>>> +#else
> >>>> +		strftime(buffer, 12, "%b %d %Y", localtime(&t));
> >>>> +		if (buffer[4] == '0') buffer[4] = ' ';
> >>>> +#endif
> >>> To the best of my knowledge, nothing guarantees the length of %b, so the
> >>> [4] here seems wrong.
> >>
> >> Yes, this was just a quick hack to compensate for the lack of the
> >> "%e" format specifier in the msvc strftime(). (elsewhere the lack
> >> of "%T" was easier to replace). I will have to think about this.
> >> Any ideas?
> > 
> > strftime returns the number of characters it generated; just format the
> > "%b " separately so you have the offset needed for the %d and the
> > modification.
> 
> Yep, I'll look into it. Having said that, I'm not sure we need to make
> this string identical on all systems. dunno.

It needs to exactly match what GCC would produce on the same system.

- Josh Triplett
--
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/compile-i386.c b/compile-i386.c
index b470952..8ac43d8 100644
--- a/compile-i386.c
+++ b/compile-i386.c
@@ -30,6 +30,7 @@ 
 #include <unistd.h>
 #include <fcntl.h>
 #include <assert.h>
+#include <inttypes.h>
 
 #include "lib.h"
 #include "allocate.h"
@@ -435,7 +436,7 @@  static const char *stor_op_name(struct storage *s)
 		strcpy(name, s->reg->name);
 		break;
 	case STOR_VALUE:
-		sprintf(name, "$%Ld", s->value);
+		sprintf(name, "$%"PRId64, s->value);
 		break;
 	case STOR_LABEL:
 		sprintf(name, "%s.L%d", s->flags & STOR_LABEL_VAL ? "$" : "",
@@ -920,7 +921,7 @@  static void emit_scalar(struct expression *expr, unsigned int bit_size)
 
 	assert(type != NULL);
 
-	printf("\t.%s\t%Ld\n", type, ll);
+	printf("\t.%s\t%"PRId64"\n", type, ll);
 }
 
 static void emit_global_noinit(const char *name, unsigned long modifiers,
@@ -2222,7 +2223,7 @@  static struct storage *x86_symbol_expr(struct symbol *sym)
 		return new;
 	}
 	if (sym->ctype.modifiers & MOD_ADDRESSABLE) {
-		printf("\taddi.%d\t\tv%d,vFP,$%lld\n", bits_in_pointer, new->pseudo, sym->value);
+		printf("\taddi.%d\t\tv%d,vFP,$%"PRId64"\n", bits_in_pointer, new->pseudo, sym->value);
 		return new;
 	}
 	printf("\taddi.%d\t\tv%d,vFP,$offsetof(%s:%p)\n", bits_in_pointer, new->pseudo, show_ident(sym->ident), sym);
diff --git a/example.c b/example.c
index 24444c6..db768e4 100644
--- a/example.c
+++ b/example.c
@@ -6,6 +6,7 @@ 
 #include <stdarg.h>
 #include <string.h>
 #include <assert.h>
+#include <inttypes.h>
 
 #include "symbol.h"
 #include "expression.h"
@@ -187,7 +188,7 @@  static const char *show_op(struct bb_state *state, struct operand *op)
 	case OP_REG:
 		return op->reg->name;
 	case OP_VAL:
-		sprintf(p, "$%lld", op->value);
+		sprintf(p, "$%"PRId64, op->value);
 		break;
 	case OP_MEM:
 	case OP_ADDR:
@@ -597,7 +598,7 @@  static struct hardreg *fill_reg(struct bb_state *state, struct hardreg *hardreg,
 
 	switch (pseudo->type) {
 	case PSEUDO_VAL:
-		output_insn(state, "movl $%lld,%s", pseudo->value, hardreg->name);
+		output_insn(state, "movl $%"PRId64",%s", pseudo->value, hardreg->name);
 		break;
 	case PSEUDO_SYM:
 		src = find_pseudo_storage(state, pseudo, NULL);
@@ -1050,7 +1051,7 @@  static void generate_cast(struct bb_state *state, struct instruction *insn)
 		unsigned long long mask;
 		mask = ~(~0ULL << old);
 		mask &= ~(~0ULL << new);
-		output_insn(state, "andl.%d $%#llx,%s", insn->size, mask, dst->name);
+		output_insn(state, "andl.%d $%#"PRIx64",%s", insn->size, mask, dst->name);
 	}
 	add_pseudo_reg(state, insn->target, dst);
 }
diff --git a/expand.c b/expand.c
index effd27b..67a1bfb 100644
--- a/expand.c
+++ b/expand.c
@@ -17,6 +17,7 @@ 
 #include <unistd.h>
 #include <fcntl.h>
 #include <limits.h>
+#include <inttypes.h>
 
 #include "lib.h"
 #include "allocate.h"
@@ -96,7 +97,7 @@  Int:
 	if (is_bool_type(newtype)) {
 		expr->value = !!value;
 		if (!conservative && value != 0 && value != 1)
-			warning(old->pos, "odd constant _Bool cast (%llx becomes 1)", value);
+			warning(old->pos, "odd constant _Bool cast (%"PRIx64" becomes 1)", value);
 		return;
 	}
 
@@ -117,7 +118,7 @@  Int:
 	// OK if the bits were (and still are) purely sign bits
 	if (value & dropped) {
 		if (!(value & oldsignmask) || !(value & signmask) || (value & dropped) != dropped)
-			warning(old->pos, "cast truncates bits from constant value (%llx becomes %llx)",
+			warning(old->pos, "cast truncates bits from constant value (%"PRIx64" becomes %"PRIx64")",
 				value & oldmask,
 				value & mask);
 	}
diff --git a/linearize.c b/linearize.c
index 1d15cfd..d587187 100644
--- a/linearize.c
+++ b/linearize.c
@@ -15,6 +15,7 @@ 
 #include <stdlib.h>
 #include <stdio.h>
 #include <assert.h>
+#include <inttypes.h>
 
 #include "parse.h"
 #include "expression.h"
@@ -121,7 +122,7 @@  const char *show_pseudo(pseudo_t pseudo)
 		if (expr) {
 			switch (expr->type) {
 			case EXPR_VALUE:
-				snprintf(buf, 64, "<symbol value: %lld>", expr->value);
+				snprintf(buf, 64, "<symbol value: %"PRId64">", expr->value);
 				break;
 			case EXPR_STRING:
 				return show_string(expr->string);
@@ -139,9 +140,9 @@  const char *show_pseudo(pseudo_t pseudo)
 	case PSEUDO_VAL: {
 		long long value = pseudo->value;
 		if (value > 1000 || value < -1000)
-			snprintf(buf, 64, "$%#llx", value);
+			snprintf(buf, 64, "$%#"PRIx64, value);
 		else
-			snprintf(buf, 64, "$%lld", value);
+			snprintf(buf, 64, "$%"PRId64, value);
 		break;
 	}
 	case PSEUDO_ARG:
@@ -336,10 +337,14 @@  const char *show_instruction(struct instruction *insn)
 			
 		switch (expr->type) {
 		case EXPR_VALUE:
-			buf += sprintf(buf, "%lld", expr->value);
+			buf += sprintf(buf, "%"PRId64, expr->value);
 			break;
 		case EXPR_FVALUE:
+#if !defined(__MINGW32__)
 			buf += sprintf(buf, "%Lf", expr->fvalue);
+#else
+			buf += sprintf(buf, "%f", (double)expr->fvalue);
+#endif
 			break;
 		case EXPR_STRING:
 			buf += sprintf(buf, "%.40s", show_string(expr->string));
@@ -463,7 +468,7 @@  const char *show_instruction(struct instruction *insn)
 	}
 
 	if (buf >= buffer + sizeof(buffer))
-		die("instruction buffer overflowed %td\n", buf - buffer);
+		die("instruction buffer overflowed %d\n", (int)(buf - buffer));
 	do { --buf; } while (*buf == ' ');
 	*++buf = 0;
 	return buffer;
diff --git a/parse.c b/parse.c
index 7b89cc3..151e6b1 100644
--- a/parse.c
+++ b/parse.c
@@ -18,6 +18,7 @@ 
 #include <unistd.h>
 #include <fcntl.h>
 #include <limits.h>
+#include <inttypes.h>
 
 #include "lib.h"
 #include "allocate.h"
@@ -1756,7 +1757,7 @@  static struct token *handle_bitfield(struct token *token, struct decl_state *ctx
 	bitfield->bit_size = width;
 
 	if (width < 0 || width > INT_MAX) {
-		sparse_error(token->pos, "invalid bitfield width, %lld.", width);
+		sparse_error(token->pos, "invalid bitfield width, %"PRId64".", width);
 		width = -1;
 	} else if (*ctx->ident && width == 0) {
 		sparse_error(token->pos, "invalid named zero-width bitfield `%s'",
diff --git a/pre-process.c b/pre-process.c
index d521318..0becdc4 100644
--- a/pre-process.c
+++ b/pre-process.c
@@ -158,12 +158,17 @@  static int expand_one_symbol(struct token **list)
 	} else if (token->ident == &__DATE___ident) {
 		if (!t)
 			time(&t);
+#if !defined(__MINGW32__)
 		strftime(buffer, 12, "%b %e %Y", localtime(&t));
+#else
+		strftime(buffer, 12, "%b %d %Y", localtime(&t));
+		if (buffer[4] == '0') buffer[4] = ' ';
+#endif
 		replace_with_string(token, buffer);
 	} else if (token->ident == &__TIME___ident) {
 		if (!t)
 			time(&t);
-		strftime(buffer, 9, "%T", localtime(&t));
+		strftime(buffer, 9, "%H:%M:%S", localtime(&t));
 		replace_with_string(token, buffer);
 	}
 	return 1;
diff --git a/show-parse.c b/show-parse.c
index 1333e30..ad1b1c6 100644
--- a/show-parse.c
+++ b/show-parse.c
@@ -15,6 +15,7 @@ 
 #include <ctype.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include <inttypes.h>
 
 #include "lib.h"
 #include "allocate.h"
@@ -352,7 +353,7 @@  deeper:
 			append(name, " )");
 			was_ptr = 0;
 		}
-		append(name, "[%lld]", get_expression_value(sym->array_size));
+		append(name, "[%"PRId64"]", get_expression_value(sym->array_size));
 		break;
 
 	case SYM_RESTRICT:
@@ -502,10 +503,10 @@  static void show_switch_statement(struct statement *stmt)
 			printf("    default");
 		} else {
 			if (expr->type == EXPR_VALUE) {
-				printf("    case %lld", expr->value);
+				printf("    case %"PRId64, expr->value);
 				if (to) {
 					if (to->type == EXPR_VALUE) {
-						printf(" .. %lld", to->value);
+						printf(" .. %"PRId64, to->value);
 					} else {
 						printf(" .. what?");
 					}
@@ -911,7 +912,7 @@  static int show_symbol_expr(struct symbol *sym)
 		return new;
 	}
 	if (sym->ctype.modifiers & MOD_ADDRESSABLE) {
-		printf("\taddi.%d\t\tv%d,vFP,$%lld\n", bits_in_pointer, new, sym->value);
+		printf("\taddi.%d\t\tv%d,vFP,$%"PRId64"\n", bits_in_pointer, new, sym->value);
 		return new;
 	}
 	printf("\taddi.%d\t\tv%d,vFP,$offsetof(%s:%p)\n", bits_in_pointer, new, show_ident(sym->ident), sym);
@@ -971,7 +972,7 @@  static int show_value(struct expression *expr)
 	int new = new_pseudo();
 	unsigned long long value = expr->value;
 
-	printf("\tmovi.%d\t\tv%d,$%llu\n", expr->ctype->bit_size, new, value);
+	printf("\tmovi.%d\t\tv%d,$%"PRIu64"\n", expr->ctype->bit_size, new, value);
 	return new;
 }
 
@@ -980,7 +981,11 @@  static int show_fvalue(struct expression *expr)
 	int new = new_pseudo();
 	long double value = expr->fvalue;
 
+#if !defined(__MINGW32__)
 	printf("\tmovf.%d\t\tv%d,$%Lf\n", expr->ctype->bit_size, new, value);
+#else
+	printf("\tmovf.%d\t\tv%d,$%f\n", expr->ctype->bit_size, new, (double)value);
+#endif
 	return new;
 }
 
diff --git a/sparse.c b/sparse.c
index 67b7d9e..d0b7565 100644
--- a/sparse.c
+++ b/sparse.c
@@ -15,6 +15,7 @@ 
 #include <ctype.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include <inttypes.h>
 
 #include "lib.h"
 #include "allocate.h"
@@ -138,7 +139,7 @@  static void check_byte_count(struct instruction *insn, pseudo_t count)
 	if (count->type == PSEUDO_VAL) {
 		long long val = count->value;
 		if (val <= 0 || val > 100000)
-			warning(insn->pos, "%s with byte count of %lld",
+			warning(insn->pos, "%s with byte count of %"PRId64,
 				show_ident(insn->func->sym->ident), val);
 		return;
 	}
diff --git a/tokenize.c b/tokenize.c
index 3eb643d..025dd84 100644
--- a/tokenize.c
+++ b/tokenize.c
@@ -547,8 +547,8 @@  static int get_one_number(int c, int next, stream_t *stream)
 	}
 
 	if (p == buffer_end) {
-		sparse_error(stream_pos(stream), "number token exceeds %td characters",
-		      buffer_end - buffer);
+		sparse_error(stream_pos(stream), "number token exceeds %d characters",
+		      (int)(buffer_end - buffer));
 		// Pretend we saw just "1".
 		buffer[0] = '1';
 		p = buffer + 1;