mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-15 01:13:30 +00:00
The current implementation of the unsigned conversion specifiers (i.e. %x, %X,
%o, %u) for fixed-size 8-, 16- and 32-bit signed integers works by casting
theses values into (word-sized) ints and then using the existing code for
formatting ints as unsigned values. This does not work for negative values as
they are being sign extended when converted to ints. For example,
io.format("%x", [i8(min_int8)], !IO)
prints:
ffffffffffffff80 (on a 64-bit machine)
rather than just:
80
Fix the above problem by casting ints, int8s, int16s etc. that are being
formatted as unsigned values to uints and using the uint formatting code.
NOTE: the formatting code for 64-bit integers follows a different code path
and is not affected by any of this.
library/string.format.m:
Implement unsigned conversion specifiers for non-64-bit signed
integers by casting to uint and using the uint formatting code.
Add predicates for converting signed integers into uints.
The format_unsigned_int_* predicates can be deleted after this change
is installed.
compiler/format_call.m:
Implement unsigned conversion specifiers for non-64-bit signed
integers by casting to uint and using the uint formatting code.
compiler/introduced_call_table.m:
Update the table of introduced predicates.
compiler/options.m:
Add an option that can be used to test whether this fix is
installed.
tests/hard_coded/Mmakefile:
tests/hard_coded/Mercury.options:
tests/hard_coded/opt_format_sign_extend.{m,exp}:
Test that formatting code introduced by the compiler does not
accidentally sign-extend negative values.
tests/string_format/string_format_{o,x,u}.{m,exp,exp2}:
Make these tests much more comprehensive then they previously
were.
42 lines
1.3 KiB
Mathematica
42 lines
1.3 KiB
Mathematica
%---------------------------------------------------------------------------%
|
|
% vim: ts=4 sw=4 et ft=mercury
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% Test the x, X specifiers of string.format with ints.
|
|
%
|
|
% The .exp file is for when int is 32-bit.
|
|
% The .exp2 file is for when int is 64-bit.
|
|
%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- module string_format_x.
|
|
:- interface.
|
|
|
|
:- import_module io.
|
|
|
|
:- pred main(io::di, io::uo) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module int.
|
|
:- import_module int16.
|
|
:- import_module int32.
|
|
:- import_module int8.
|
|
:- import_module list.
|
|
:- import_module string.
|
|
:- import_module string_format_lib.
|
|
|
|
main(!IO) :-
|
|
Ints = [
|
|
i(min_int), i(-1), i(0), i(1), i(10), i(100), i(max_int),
|
|
i8(min_int8), i8(-1i8), i8(0i8), i8(1i8), i8(max_int8),
|
|
i16(min_int16), i16(-1i16), i16(0i16), i16(1i16), i16(max_int16),
|
|
i32(min_int32), i32(-1i32), i32(0i32), i32(1i32), i32(max_int32)
|
|
],
|
|
list.foldl(output_list(Ints), format_strings("x"), !IO),
|
|
list.foldl(output_list(Ints), format_strings("X"), !IO).
|
|
|
|
%---------------------------------------------------------------------------%
|