Ada Programming/Libraries/Ada.Environment Variables
This language feature is only available from Ada 2005 on.
Ada.Environment_Variables is a unit of the Predefined Language Environment since Ada 2005.
Introduction
[edit | edit source]The Ada.Environment_Variables package allows an Ada program to read, write and modify environment variables. Exactly what constitutes an environment variable is implementation defined. All the code in this article is compiled and executed on a Slackware Linux system. The compiler used is GNATMAKE GPL 2008 (20080521)
.
Using Ada.Environment_Variables
[edit | edit source]Environment variables are simple key/value pairs. Both the key and the value are strings. With the Environment_Variables
package we can check if a key exists, we can set new key/value pairs, we can delete keys, we can read values, and we can iterate through all the key/value pairs (as can be seen from the very straightforward specification of the package):
package Ada.Environment_Variables is
pragma Preelaborate (Environment_Variables);
function Value (Name : String) return String;
function Exists (Name : String) return Boolean;
procedure Set (Name : String; Value : String);
procedure Clear (Name : String);
procedure Clear;
procedure Iterate (Process : not null access procedure (Name, Value : String));
end Ada.Environment_Variables;
All of the following examples will be built around this simple core program:
with Ada.Text_IO;
with Ada.Environment_Variables;
procedure Env is
package IO renames Ada.Text_IO;
package EV renames Ada.Environment_Variables;
begin
IO.Put_Line (Item => "Environment_Variables test");
end Env;
Simply insert the code from the following examples after the IO.Put_Line
line. So, let's move on and see how we can read an environment value using Ada.
Ada.Environment_Variables.Value
[edit | edit source]The specification for Value
looks like this:
function Value (Name : String) return String;
Reading an environment variable is done using the Value
function. It takes a string as its sole parameter and returns the value of a matching environment variable. Try adding this to the core program:
IO.Put_Line (Item => EV.Value (Name => "VISUAL"));
IO.Put_Line (Item => EV.Value (Name => "NONEXISTENT"));
exception
when Constraint_Error =>
IO.Put_Line (Item => "No such environment variable.");
When running this on my machine, I get the following output:
Environment_Variables test /usr/local/bin:/usr/bin:/bin:/usr/games:/usr/lib/java/bin:/usr/lib/java/jre/bin:/usr/lib/qt/bin:.:/usr/local/texlive/2008/bin/i386-linux/ No such environment variable.
As you can see, a Constraint_Error
is raised if the given Name
parameter does not match any existing environment variable. If the notion of environment variables isn't supported in the target operating system, a Program_Error
is raised instead.
Ada.Environment_Variables.Value Example Source
with Ada.Text_IO;
with Ada.Environment_Variables;
procedure Env is
package IO renames Ada.Text_IO;
package EV renames Ada.Environment_Variables;
begin
IO.Put_Line (Item => "Environment_Variables test");
IO.Put_Line (Item => EV.Value (Name => "PATH"));
IO.Put_Line (Item => EV.Value (Name => "NONEXISTENT"));
exception
when Constraint_Error =>
IO.Put_Line (Item => "No such environment variable.");
end Env;
Ada.Environment_Variables.Exists
[edit | edit source]The specification for Exists
looks like this:
function Exists (Name : String) return Boolean;
The Exists
function is used to check whether or not a given environment variable name is known to the operating system. If it is, the function will return boolean True
, otherwise it returns boolean False
.
if EV.Exists (Name => "PATH") then
IO.Put_Line (Item => "EXISTS!");
else
IO.Put_Line (Item => "DOES NOT EXIST!");
end if;
if EV.Exists (Name => "NONEXISTENT") then
IO.Put_Line (Item => "EXISTS!");
else
IO.Put_Line (Item => "DOES NOT EXIST!");
end if;
The resulting output on my computer is:
Environment_Variables test EXISTS! DOES NOT EXIST!
The manual does not say anything about what happens if the execution environment lacks support for environment variables in this case, but I suspect a Program_Error
is raised, as with Value.
Ada.Environment_Variables.Exists Example Source
with Ada.Text_IO;
with Ada.Environment_Variables;
procedure Env is
package IO renames Ada.Text_IO;
package EV renames Ada.Environment_Variables;
begin
IO.Put_Line (Item => "Environment_Variables test");
if EV.Exists (Name => "PATH") then
IO.Put_Line (Item => "EXISTS!");
else
IO.Put_Line (Item => "DOES NOT EXIST!");
end if;
if EV.Exists (Name => "NONEXISTENT") then
IO.Put_Line (Item => "EXISTS!");
else
IO.Put_Line (Item => "DOES NOT EXIST!");
end if;
end Env;
Ada.Environment_Variables.Set
[edit | edit source]The specification for Set
looks like this:
procedure Set (Name : String; Value : String);
With Set
we can define new and alter existing environment variables:
if not EV.Exists (Name => "NONEXISTENT") then
IO.Put_Line (Item => "DOES NOT EXIST!");
end if;
EV.Set (Name => "NONEXISTENT",
Value => "FooBar");
IO.Put_Line (Item => EV.Value (Name => "NONEXISTENT"));
EV.Set (Name => "NONEXISTENT",
Value => "FooBar again");
IO.Put_Line (Item => EV.Value (Name => "NONEXISTENT"));
The output of this is:
Environment_Variables test DOES NOT EXIST! FooBar FooBar again
If setting or altering a given environment variable is prohibited by the operating environment, a Constraint_Error
is raised. As with Value, a Program_Error
is raised if the execution environment has no notion of environment variables.
Ada.Environment_Variables.Set Example Source
with Ada.Text_IO;
with Ada.Environment_Variables;
procedure Env is
package IO renames Ada.Text_IO;
package EV renames Ada.Environment_Variables;
begin
IO.Put_Line (Item => "Environment_Variables test");
if not EV.Exists (Name => "NONEXISTANT") then
IO.Put_Line (Item => "DOES NOT EXIST!");
end if;
EV.Set (Name => "NONEXISTANT",
Value => "FooBar");
IO.Put_Line (Item => EV.Value (Name => "NONEXISTENT"));
EV.Set (Name => "NONEXISTANT",
Value => "FooBar again");
IO.Put_Line (Item => EV.Value (Name => "NONEXISTENT"));
end Env;
Ada.Environment_Variables.Clear
[edit | edit source]The specification for Clear
looks like this:
procedure Clear (Name : String);
procedure Clear;
Deleting environment variables is done using one of the Clear
procedures. If a Name
parameter is given, Clear
will try to delete all environment variables with that name. If no Name
parameter is given, Clear
will try to delete all existing environment variables.
First lets see how Clear
works when given a Name
parameter:
EV.Set (Name => "Foo",
Value => "This is Foo");
IO.Put_Line (Item => EV.Value (Name => "Foo"));
EV.Clear (Name => "Foo");
IO.Put_Line (Item => EV.Value (Name => "Foo"));
exception
when Constraint_Error =>
IO.Put_Line (Item => "Environment variable Foo does not exist");
And the output:
Environment_Variables test This is Foo Environment variable Foo does not exist
Now lets see Clear
in action with no Name
parameter:
EV.Set (Name => "Foo",
Value => "This is Foo");
IO.Put_Line (Item => EV.Value (Name => "Foo"));
EV.Set (Name => "Bar",
Value => "This is Bar");
IO.Put_Line (Item => EV.Value (Name => "Bar"));
EV.Clear;
if not EV.Exists (Name => "Foo") and not EV.Exists (Name => "Bar") then
IO.Put_Line (Item => "Foo and Bar are both gone!");
end if;
And the output is:
Environment_Variables test This is Foo This is Bar Foo and Bar are both gone!
Exactly as expected.
Ada.Environment_Variables.Clear Example Source
with Ada.Text_IO;
with Ada.Environment_Variables;
procedure Env is
package IO renames Ada.Text_IO;
package EV renames Ada.Environment_Variables;
begin
IO.Put_Line (Item => "Environment_Variables test");
EV.Set (Name => "Foo",
Value => "This is Foo");
IO.Put_Line (Item => EV.Value (Name => "Foo"));
EV.Clear (Name => "Foo");
IO.Put_Line (Item => EV.Value (Name => "Foo"));
exception
when Constraint_Error =>
IO.Put_Line (Item => "Environment variable Foo does not exist");
end Env;
with Ada.Text_IO;
with Ada.Environment_Variables;
procedure Env is
package IO renames Ada.Text_IO;
package EV renames Ada.Environment_Variables;
begin
IO.Put_Line (Item => "Environment_Variables test");
EV.Set (Name => "Foo",
Value => "This is Foo");
IO.Put_Line (Item => EV.Value (Name => "Foo"));
EV.Set (Name => "Bar",
Value => "This is Bar");
IO.Put_Line (Item => EV.Value (Name => "Bar"));
EV.Clear;
if not EV.Exists (Name => "Foo") and not EV.Exists (Name => "Bar") then
IO.Put_Line (Item => "Foo and Bar are both gone!");
end if;
end Env;
Ada.Environment_Variables.Iterate
[edit | edit source]The specification for Iterate
looks like this:
procedure Iterate (Process : not null access procedure (Name, Value : String));
Iterate
enables us to serially act upon all the environment variables that are available to the program at the time of execution. We can do this by creating a procedure that takes two String
parameters and then give Iterate
access to this procedure.
Such a program could look something like this:
with Ada.Text_IO;
with Ada.Environment_Variables;
procedure Env is
package IO renames Ada.Text_IO;
package EV renames Ada.Environment_Variables;
procedure Print_EV (Name, Value : in String) is
begin
IO.Put_Line (Item => Name & "=" & Value);
end Print_EV;
begin
IO.Put_Line (Item => "Environment_Variables test");
EV.Iterate (Process => Print_EV'Access);
end Env;
Here's a small sample of the output generated by the above program on my system:
JAVA_HOME=/usr/lib/java HOME=/home/thomas SHELL=/bin/bash
There's a very important note about Iterate
in the manual. It states:
Making calls to the procedures Set or Clear concurrently with calls to any subprogram of package Environment_Variables, or to any instantiation of Iterate, results in erroneous execution. Making calls to the procedures Set or Clear in the actual subprogram corresponding to the Process parameter of Iterate results in erroneous execution.
So you cannot call either Set
or Clear
while using Iterate
, at least not without risking a certain amount of undefined behavior.
Ada.Environment_Variables.Iterate Example Source
with Ada.Text_IO;
with Ada.Environment_Variables;
procedure Env is
package IO renames Ada.Text_IO;
package EV renames Ada.Environment_Variables;
procedure Print_EV (Name, Value : in String) is
begin
IO.Put_Line (Item => Name & "=" & Value);
end Print_EV;
begin
IO.Put_Line (Item => "Environment_Variables test");
EV.Iterate (Process => Print_EV'Access);
end Env;
Specification
[edit | edit source]-- Standard Ada library specification -- Copyright (c) 2003-2018 Maxim Reznik <reznikmm@gmail.com> -- Copyright (c) 2004-2016 AXE Consultants -- Copyright (c) 2004, 2005, 2006 Ada-Europe -- Copyright (c) 2000 The MITRE Corporation, Inc. -- Copyright (c) 1992, 1993, 1994, 1995 Intermetrics, Inc. -- SPDX-License-Identifier: BSD-3-Clause and LicenseRef-AdaReferenceManual -- -------------------------------------------------------------------------package
Ada.Environment_Variablesis
pragma
Preelaborate (Environment_Variables);function
Value (Name :in
String)return
String;function
Value (Name :in
String; Default :in
String)return
String; -- Added in Ada 2012function
Exists (Name :in
String)return
Boolean;procedure
Set (Name :in
String; Value :in
String);procedure
Clear (Name :in
String);procedure
Clear;procedure
Iterate (Process :not
null
access
procedure
(Name :in
String; Value :in
String));end
Ada.Environment_Variables;
See also
[edit | edit source]Wikibook
[edit | edit source]External examples
[edit source]- Search for examples of
Ada.Environment_Variables
in: Rosetta Code, GitHub (gists), any Alire crate or this Wikibook. - Search for posts related to
Ada.Environment_Variables
in: Stack Overflow, comp.lang.ada or any Ada related page.
Ada Reference Manual
[edit | edit source]Ada 2005
[edit | edit source]Ada 2012
[edit | edit source]Open-Source Implementations
[edit | edit source]FSF GNAT
- Specification: a-envvar.ads
- Body: a-envvar.adb
drake
- Specification: environment/a-envvar.ads
- Body: environment/a-envvar.adb