Tue, 20 Apr 1999 06:12:41 -0500
|
Matthew Heaney's solution works if the environment variable exists,
but raises an exception if it does not. I offer this refinement of
Matthew's solution, where the exception is raised, but with
information supplied which quickly pinpoints the cause of the
exception.
If Matthew's solution were incorporated in a large program, it
might take some time for the user to etermine what is wrong.
---- begin source code ----
with Ada.Exceptions;
with Interfaces.C.Strings;
function Getenv (Name : String) return String is
use Interfaces.C;
use Interfaces.C.Strings;
C_Name_Buf : aliased Char_Array :=
To_C (Name);
C_Name : constant Chars_Ptr :=
To_Chars_Ptr (C_Name_Buf'Unchecked_Access);
function C_Getenv (Name : Chars_Ptr) return Chars_Ptr;
pragma Import (C, C_Getenv, "getenv");
C_Val : constant Chars_Ptr := C_Getenv (C_Name);
begin
if C_Val = Null_Ptr then
Ada.Exceptions.Raise_Exception
(E => Dereference_Error'identity,
Message => "Environment variable """ & Name &
""" does not exist");
end if;
return To_Ada (Value (C_Val));
end Getenv;
--- end source code ---
Actually, there are two other solutions worthy of mention, viz.:
1. There is a package Gnat.OS_Lib in GNAT which provides a
compiler-specific solution which does not raise the exception, but
does not distinguish between the case of the environment variable
being defined but empty, and the case where it's undefined.
Furthermore, the GNAT solution is an allocator function which
means that the memory deallocation is the responsibility of the caller.
2. This third solution is my preference -- the POSIX binding
provided by florist -- available at
ftp://ftp.cs.fsu.edu/pub/PART/FLORIST/
This binding has the Boolean function
POSIX.Process_Environment.Is_Environment_Variable
which permits testing for existence before getting the value
with a call to POSIX.Process_Environment.Environment_Value_Of.
Not only does this binding provide the process environment
functionality, it has clean interfaces to many OS-related
runtime library functions.
One final comment --
The use of verbs as the names of functions is not considered
good style by many authorities. The POSIX bindings adhere to
the following subprogram naming conventions:
Procedure names -- verb_phrase -- e.g. Set_Environment_Variable
Boolean functions -- predicate phrase -- e.g Is_Environment_Variable
Non-Boolean functions -- Noun_Phrase -- e.g. Environment_Value_Of
These naming conventions -- along with the naming conventions for
types, objects and tasks go a long way toward making code more
readily comprehensible -- either to the author some time after
writing it -- or to the unfortunate maintainer who has never seen
the code before he has to fix or enhance it.
|
|
|