跳轉到內容

Ada 程式設計/庫/Ada.Environment 變數

來自華夏公益教科書

Ada. Time-tested, safe and secure.
Ada.經久耐用、安全可靠。

此語言功能僅從 Ada 2005 開始提供。

Ada.Environment_Variables 是自 Ada 2005 以來 預定義語言環境 的一個單元。

The Ada.Environment_Variables 包允許 Ada 程式讀取、寫入和修改 環境變數。究竟什麼是環境變數是實現定義的。本文中的所有程式碼都編譯並在 Slackware Linux 系統上執行。使用的編譯器是 GNATMAKE GPL 2008 (20080521)

使用 Ada.Environment_Variables
[編輯 | 編輯原始碼]

環境變數是簡單的鍵值對。鍵和值都是字串。使用 Environment_Variables 包,我們可以檢查鍵是否存在,我們可以設定新的鍵值對,我們可以刪除鍵,我們可以讀取值,並且我們可以遍歷所有鍵值對(正如該包非常直接的規範所顯示的那樣)。

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;

以下所有示例都將圍繞這個簡單的核心程式構建

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;

只需在 IO.Put_Line 行之後插入以下示例中的程式碼。因此,讓我們繼續並看看如何使用 Ada 讀取環境值。

Ada.Environment_Variables.Value
[編輯 | 編輯原始碼]

Value 的規範如下所示

function Value (Name : String) return String;

讀取環境變數是使用 Value 函式完成的。它將一個字串作為其唯一引數並返回匹配環境變數的值。嘗試將其新增到核心程式中

   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.");

在我的機器上執行此程式碼時,我得到以下輸出

 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.

如您所見,如果給定的 Name 引數與任何現有環境變數不匹配,則會引發 Constraint_Error。如果目標作業系統不支援環境變數的概念,則會引發 Program_Error

Ada.Environment_Variables.Value 示例原始碼

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
[編輯 | 編輯原始碼]

Exists 的規範如下所示

function Exists (Name : String) return Boolean;

Exists 函式用於檢查給定環境變數名稱是否為作業系統所知。如果是,則該函式將返回布林值 True,否則返回布林值 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;

在我的計算機上產生的結果輸出為

 Environment_Variables test
 EXISTS!
 DOES NOT EXIST!

手冊中沒有說明在這種情況下執行環境缺乏對環境變數支援時會發生什麼,但我懷疑會引發 Program_Error,就像 Value 一樣。


Ada.Environment_Variables.Exists 示例原始碼

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
[編輯 | 編輯原始碼]

Set 的規範如下所示

procedure Set (Name : String; Value : String);

使用 Set,我們可以定義新的環境變數和更改現有環境變數

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"));

此程式碼的輸出為

 Environment_Variables test
 DOES NOT EXIST!
 FooBar
 FooBar again

如果作業系統環境禁止設定或更改給定的環境變數,則會引發 Constraint_Error。與 Value 一樣,如果執行環境沒有環境變數的概念,則會引發 Program_Error


Ada.Environment_Variables.Set 示例原始碼

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
[編輯 | 編輯原始碼]

Clear 的規範如下所示

procedure Clear (Name : String);
procedure Clear;

刪除環境變數是使用 Clear 過程之一完成的。如果給出了 Name 引數,則 Clear 將嘗試刪除所有具有該名稱的環境變數。如果沒有給出 Name 引數,Clear 將嘗試刪除所有現有的環境變數。

首先讓我們看看 Clear 在給出 Name 引數時的工作方式

   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");

以及輸出

 Environment_Variables test
 This is Foo
 Environment variable Foo does not exist

現在讓我們看看 Clear 在沒有 Name 引數的情況下如何執行

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;

輸出為

 Environment_Variables test
 This is Foo
 This is Bar
 Foo and Bar are both gone!

完全符合預期。

Ada.Environment_Variables.Clear 示例原始碼

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
[編輯 | 編輯原始碼]

Iterate 的規範如下所示

procedure Iterate (Process : not null access procedure (Name, Value : String));

Iterate 使我們能夠依次處理在執行時可用於程式的所有環境變數。我們可以透過建立一個接受兩個 String 引數的過程,然後讓 Iterate 訪問此過程來做到這一點。

這樣的程式可能看起來像這樣

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;

以下是上述程式在我的系統上生成的輸出的小樣本

 JAVA_HOME=/usr/lib/java
 HOME=/home/thomas
 SHELL=/bin/bash

手冊中有一條關於 Iterate 的非常重要的說明。它指出

與對 Environment_Variables 包的任何子程式或 Iterate 的任何例項化進行呼叫同時呼叫 Set 或 Clear 過程會導致錯誤執行。在與 Iterate 的 Process 引數相對應的實際子程式中呼叫 Set 或 Clear 過程會導致錯誤執行。

因此,您不能在使用 Iterate 時呼叫 SetClear,至少不能在不冒一定程度的未定義行為的風險的情況下。

Ada.Environment_Variables.Iterate 示例原始碼

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;
--                     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_Variables is

   pragma Preelaborate (Environment_Variables);

   function Value (Name : in String) return String;

   function 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;

另請參閱

[編輯 | 編輯原始碼]

華夏公益教科書

[編輯 | 編輯原始碼]

外部示例

[編輯原始碼]

Ada 參考手冊

[編輯 | 編輯原始碼]

開源實現

[編輯 | 編輯原始碼]

FSF GNAT

drake

華夏公益教科書