TEAM-ADA Archives

Team Ada: Ada Programming Language Advocacy

TEAM-ADA@LISTSERV.ACM.ORG

Options: Use Forum View

Use Monospaced Font
Show Text Part by Default
Show All Mail Headers

Message: [<< First] [< Prev] [Next >] [Last >>]
Topic: [<< First] [< Prev] [Next >] [Last >>]
Author: [<< First] [< Prev] [Next >] [Last >>]

Print Reply
Subject:
From:
"David C. Hoos, Sr." <[log in to unmask]>
Reply To:
David C. Hoos, Sr.
Date:
Tue, 20 Apr 1999 06:12:41 -0500
Content-Type:
text/plain
Parts/Attachments:
text/plain (81 lines)
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.

ATOM RSS1 RSS2