[m-rev.] diff: implement io__set_environment_variable for .NET
Fergus Henderson
fjh at cs.mu.OZ.AU
Sat Nov 2 17:07:15 AEDT 2002
Estimated hours taken: 20
Branches: main
library/io.m:
Implement io__set_environment_variable for .NET.
library/Mmakefile:
A tweak needed to get things to link properly after the above
change to io.m.
Index: io.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/io.m,v
retrieving revision 1.272
diff -u -d -u -r1.272 io.m
--- io.m 31 Oct 2002 14:47:16 -0000 1.272
+++ io.m 2 Nov 2002 06:08:42 -0000
@@ -1477,11 +1477,10 @@
% Gets the value Value associated with the environment
% variable Var. Fails if the variable was not set.
-:- impure pred io__putenv(string).
-:- mode io__putenv(in) is semidet.
-% io__putenv(VarString).
-% If VarString is a string of the form "name=value",
-% sets the environment variable name to the specified
+:- impure pred io__setenv(string, string).
+:- mode io__setenv(in, in) is semidet.
+% io__setenv(NameString,ValueString).
+% Sets the named environment variable to the specified
% value. Fails if the operation does not work.
%-----------------------------------------------------------------------------%
@@ -3304,8 +3303,7 @@
:- pragma promise_pure(io__set_environment_var/4).
io__set_environment_var(Var, Value) -->
- { string__format("%s=%s", [s(Var), s(Value)], EnvString) },
- ( { impure io__putenv(EnvString) } ->
+ ( { impure io__setenv(Var, Value) } ->
[]
;
{ string__format("Could not set environment variable `%s'",
@@ -5720,9 +5718,17 @@
/*---------------------------------------------------------------------------*/
-/* io__getenv and io__putenv, from io.m */
+/* io__getenv and io__setenv */
+
+:- pragma foreign_decl("C", "
+#include <stdlib.h> /* for getenv() and putenv() */
+").
+:- pragma foreign_decl("MC++", "
+#include <stdlib.h> /* for putenv() */
+").
:- pragma promise_semipure(io__getenv/2).
+
:- pragma foreign_proc("C", io__getenv(Var::in, Value::out),
[will_not_call_mercury, tabled_for_io],
"{
@@ -5730,32 +5736,60 @@
SUCCESS_INDICATOR = (Value != 0);
}").
-:- pragma foreign_proc("C", io__putenv(VarAndValue::in),
- [will_not_call_mercury, tabled_for_io],
-"
- SUCCESS_INDICATOR = (putenv(VarAndValue) == 0);
-").
-
-:- pragma foreign_proc("MC++", io__getenv(Var::in, Value::out),
+:- pragma foreign_proc("C#", io__getenv(Var::in, Value::out),
[will_not_call_mercury, tabled_for_io],
"{
- Value = System::Environment::GetEnvironmentVariable(Var);
- SUCCESS_INDICATOR = (Value != 0);
+ Value = System.Environment.GetEnvironmentVariable(Var);
+ SUCCESS_INDICATOR = (Value != null);
}").
-:- pragma foreign_proc("MC++", io__putenv(_VarAndValue::in),
- [will_not_call_mercury, tabled_for_io],
-"
- mercury::runtime::Errors::SORRY(
- ""No SetEnvironmentVariable method appears to be available."");
- SUCCESS_INDICATOR = 0;
-").
-
io__getenv(_, _) :-
% This version is only used for back-ends for which there is no
% matching foreign_proc version.
impure private_builtin__imp,
private_builtin__sorry("io__getenv").
+
+
+io__setenv(Var, Value) :-
+ string__format("%s=%s", [s(Var), s(Value)], EnvString),
+ impure io__putenv(EnvString).
+
+
+:- impure pred io__putenv(string).
+:- mode io__putenv(in) is semidet.
+% io__putenv(VarString).
+% If VarString is a string of the form "name=value",
+% sets the environment variable name to the specified
+% value. Fails if the operation does not work.
+% Not supported for .NET.
+% This should only be called from io__setenv.
+
+:- pragma foreign_proc("C", io__putenv(VarAndValue::in),
+ [will_not_call_mercury, tabled_for_io],
+"
+ SUCCESS_INDICATOR = (putenv(VarAndValue) == 0);
+").
+
+:- pragma foreign_proc("MC++", io__putenv(VarAndValue::in),
+ [will_not_call_mercury, tabled_for_io],
+"
+ /*
+ ** Unfortunately there is no API in the .NET standard library
+ ** for setting environment variables. So we need to use
+ ** platform-specific methods. Currently we use the Posix function
+ ** putenv(), which is also supported on Windows.
+ */
+
+ /*
+ ** Convert VarAndValue from a .NET managed string (System.String)
+ ** to an unmanaged C string (`char *') on the unmanaged C heap,
+ ** and then just invoke putenv().
+ */
+ char __nogc *c_string = static_cast<char*>(
+ System::Runtime::InteropServices::Marshal::
+ StringToHGlobalAnsi(VarAndValue).ToPointer());
+ SUCCESS_INDICATOR = (putenv(c_string) == 0);
+").
io__putenv(_) :-
% This version is only used for back-ends for which there is no
Index: Mmakefile
===================================================================
RCS file: /home/mercury1/repository/mercury/library/Mmakefile,v
retrieving revision 1.99
diff -u -d -u -r1.99 Mmakefile
--- Mmakefile 2 Nov 2002 06:07:07 -0000 1.99
+++ Mmakefile 2 Nov 2002 06:08:42 -0000
@@ -212,7 +212,11 @@
# -AI sets the assembly search path (just like -I for assemblies)
MS_CLFLAGS = -AI`$(FIX_PATH_FOR_CL) $(RUNTIME_DIR)` -I`$(FIX_PATH_FOR_CL) $(RUNTIME_DIR)` $(DEBUG_MS_CLFLAGS)
-MS_CL_NOASM=:noAssembly
+# For some reason, using /clr:noAssembly results in a link error when
+# building io__cpp_code.dll, because it doesn't link in the native library
+# needed for putenv(). So we need to use /link /noassembly instead.
+# MS_CL_NOASM=:noAssembly
+MS_CL_LIBS=/link /noassembly
MS_CSCFLAGS=/t:module $(DEBUG_MS_CSCFLAGS)
MS_ILASMFLAGS=$(DEBUG_MS_ILASMFLAGS)
--------------------------------------------------------------------------
mercury-reviews mailing list
post: mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------
More information about the reviews
mailing list