The conversion INT has an unsigned counterpart UINT but there is no
corresponding unsigned version of LONG. In order to use LONG to pass
unsigned values, it is necessary to adjust the value on the SML side
(which is an int) so that the range checking of LONG does not reject
valid values. For example, see my definition of ULONG below.
However, I can't see way to define ULONG portably - the SML side
adjustment needs to know the size of an unsigned long. Is this
available somewhere? Is there some clever way to define a portable
ULONG in terms of LONG?
Phil
local
val m =
case PolyML.architecture () of
"X86_64" => IntInf.pow (2, 64)
| "I386" => IntInf.pow (2, 32)
| _ => raise Fail "unknown architecture"
val half_m = m div 2
fun fromLong x =
(* Assume x in range of (signed) long int. *)
if x < 0
then x + m
else x
fun toLong x =
(*
* Ensure result outside range of (signed) long int if and only
* if x is outside the range of unsigned long int by swapping
* regions [~m/2, 0) and [m/2, m).
*)
if half_m <= x andalso x < m
then x - m
else if ~ half_m <= x andalso x < 0
then x + m
else x
in
val ULONG =
CInterface.mapConversion (fromLong, toLong) CInterface.LONG
end
(* Test ULONG *)
local
open CInterface
in
fun printULong n =
call2
(get_sym "libc.so.6" "printf")
(STRING, ULONG)
VOID
("n = %lX\n", n)
end
val pow_2_32 = IntInf.pow (2, 32);
val pow_2_64 = IntInf.pow (2, 64);
printULong ~1; (* should fail *)
printULong 0; (* always ok *)
printULong (pow_2_32 - 1); (* always ok *)
printULong pow_2_32; (* should fail when long is 32 bits *)
printULong (pow_2_64 - 1); (* ok when long is at least 64 bits *)
printULong pow_2_64; (* should fail when long is 64 bits *)
_______________________________________________
polyml mailing list
polyml@inf.ed.ac.uk
http://lists.inf.ed.ac.uk/mailman/listinfo/polyml