[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