跳转至内容

Ada 编程/库/Ada.Command_Line

来自 Wikibooks,开放的书籍,开放的世界

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

此语言功能从 Ada 95 开始提供。

Ada.Command_Line 是自 Ada 95 以来 预定义语言环境 的一个单元。

Ada.Command_Line 包允许 Ada 程序访问调用该程序的命令设置的命令行参数。它是 C argvargc[n] 系统的 Ada 版本。

如果环境支持,还可以使用 Ada.Command_Line 设置 Ada 程序的退出状态。

重要的是要注意,本文中的所有代码都是在 Slackware Linux 系统上编译和执行的。使用的编译器是 GNATMAKE GPL 2008 (20080521),外壳是 BASH。这很重要,因为参考手册明确指出

如果外部执行环境支持向程序传递参数,则 Argument_Count 返回传递给调用该函数的程序的参数数量。否则,它返回 0。 “参数数量” 的含义由实现定义。

注意结尾句:“参数数量” 的含义由实现定义。这意味着您不能相信给定的参数字符串在所有环境中都能产生相同的结果。Argument_Count 高度依赖于操作系统、外壳和编译器等因素。

使用 Ada.Command_Line

[编辑 | 编辑源代码]

我们将在本文中使用的程序实际上什么也不做,只是报告我们在调用该程序时使用的各种参数。基本程序如下所示

with Ada.Text_IO;
with Ada.Command_Line;
 
procedure Args is
   package IO renames Ada.Text_IO;
   package CLI renames Ada.Command_Line;
begin
   IO.Put_Line (Item => "Argument Count:" & CLI.Argument_Count'Img);
end Args;

在没有给出任何参数的情况下执行上述程序时,您应该得到以下输出

 Argument Count: 0

让我们快速回顾一下程序:在第 1 行和第 2 行,我们将 Text_IOCommand_Line 包添加到程序中。在第 5 行和第 6 行,我们将这些包重命名为较短的 IOCLI,最后在第 8 行,我们输出当前的参数计数。这实际上是访问传递给程序的命令行参数所需的全部内容。

Command_Line 包的完整规范与这种 规范 可以说的一样简单。

我们已经在 Args 程序中遇到了 Argument_Count 函数,但是让我们看看当我们用一些参数调用 Args 程序时会发生什么。

Ada.Command_Line.Argument_Count

[编辑 | 编辑源代码]

Argument_Count 的规范如下所示

function Argument_Count return Natural;

基本 Args 程序已经使用 Argument_Count 函数,所以要查看它的工作原理,我们只需为该程序提供各种参数即可

 $ ./args --option=value
 Argument Count: 1
 
 $ ./args --option=value --foo=bar
 Argument Count: 2
 
 $ ./args --name=Thomas Løcke
 Argument Count: 2
 
 $ ./args --option="Thomas Løcke"
 Argument Count: 1
 
 $ ./args /path/to/file with spaces in name
 Argument Count: 5
 
 $ ./args /path/to/file with spaces in name
 Argument Count: 1

到目前为止应该出现了一种模式。最后一个例子尤其引人注目:由于空格被转义,整个字符串被视为一个参数。可以很容易地想象,另一个环境可能会对这样的参数进行不同的处理,并且可能会忽略反斜杠。对于双引号示例(“Thomas Løcke”)也是如此。其他外壳/环境可能会将“Thomas Løcke” 视为两个单独的参数,因为空格。关键是要在使用 Ada.Command_Line 时注意这些细节。

Ada.Command_Line.Argument

[编辑 | 编辑源代码]

Argument 的规范如下所示

function Argument (Number : Positive) return String;

Argument 返回与相对位置 Number 对应的 String 参数。请注意,Number 的类型为 Positive。这意味着 Number 的有效范围为 1 .. Argument_Count。如果 Number 超出此范围,则会引发 Constraint_Error

要查看它的工作原理,我们将在小型 Args 程序中添加 3 行

for i in 1 .. CLI.Argument_Count loop
   IO.Put_Line (Item => CLI.Argument (Number => i));
end loop;

如果我们使用与 Argument_Count 示例中相同的参数运行 Args,我们将获得以下结果

 $ ./args --option=value
 Argument Count: 1
 1: --option=value
 
 $ ./args --option=value --foo=bar
 Argument Count: 2
 1: --option=value
 2: --foo=bar
 
 $ ./args --name=Thomas Løcke
 Argument Count: 2
 1: --name=Thomas
 2: Løcke
 
 $ ./args --option="Thomas Løcke"
 Argument Count: 1
 1: --option=Thomas Løcke
 
 $ ./args /path/to/file with spaces in name
 Argument Count: 5
 1: /path/to/file
 2: with
 3: spaces
 4: in
 5: name
 
 $ ./args /path/to/file with spaces in name
 Argument Count: 1
 1: /path/to/file with spaces in name

这里没有什么大惊喜。

如果在运行程序时没有给出任何参数,您将得到一个 null range 循环:(1 .. 0)。这完全有效,结果与预期一致:循环立即终止。

with Ada.Text_IO;
with Ada.Command_Line;
 
procedure Args is
   package IO renames Ada.Text_IO;
   package CLI renames Ada.Command_Line;
begin
   IO.Put_Line (Item => "Argument Count:" & CLI.Argument_Count'Img);
   for i in 1 .. CLI.Argument_Count loop
      IO.Put (Item => i'Img & ": ");
      IO.Put_Line (Item => CLI.Argument (Number => i));
   end loop;
end Args;

Ada.Command_Line.Command_Name

[编辑 | 编辑源代码]

Command_Name 的规范如下所示

function Command_Name return String;

Command_Name 返回用于调用该程序的字符串命令。与 Argument_Count 一样,这是由实现定义的,因此 Command_Name 可能会在系统 A 上返回 X,在系统 B 上返回 Y,在系统 C 上返回 null。您不能依赖此值在所有编译器、外壳和操作系统的组合中都相同。

要查看它的工作原理,请将此行添加到 Args 程序中

IO.Put_Line (CLI.Command_Name);

如果我们在没有参数的情况下从 GNAT Studio(使用 Shift+F2)中执行程序,结果将是

 Argument Count: 0
 /home/thomas/wiki_examples/Args/args

请注意 GNAT Studio 如何使用 Args 程序的完整路径来调用它。

如果我将目录更改为 /home/thomas/wiki_examples/Args/,并从命令行执行 Args 程序,我得到的是

 $ args
 Argument Count: 0
 args

如果我使用常见的 ./ 语法来执行程序,我得到的是

 $ ./args
 Argument Count: 0
 ./args

如您所见,在支持参数传递的环境中,Command_Name 函数返回用于调用该程序的确切字符串。

Ada.Command_Line.Set_Exit_Status

[编辑 | 编辑源代码]

Set_Exit_Status 的规范如下所示

procedure Set_Exit_Status (Code : Exit_Status);

如果环境支持返回任务完成代码,则 Set_Exit_Status 允许您设置程序的退出状态。如果您查看 Ada.Command_Line 的规范,您会注意到 Exit_Status 类型以及 SuccessFailure 两个变量。这两个变量分别定义为 0 和 1,但完全可以定义自己的退出状态代码。

要查看它的工作原理,请将以下内容添加到 Args 程序的规范中

More_Than_One_Arg : constant CLI.Exit_Status := 3;

以及以下内容添加到程序的主体中

if CLI.Argument_Count = 0 then
   CLI.Set_Exit_Status (Code => CLI.Failure);
elsif CLI.Argument_Count = 1 then
   CLI.Set_Exit_Status (Code => CLI.Success);
else
   CLI.Set_Exit_Status (Code => More_Than_One_Arg);
end if; 

我们在这里做的是根据传递给程序的参数数量来设置退出状态。以下是在我们使用各种参数执行程序时发生的情况

 $ ./args
 Argument Count: 0
 $ echo $?
 1
 
 $ ./args one
 Argument Count: 1
 $ echo $?
 0
 
 $ ./args one two
 Argument Count: 2
 $ echo $?
 3

echo $? 输出最近执行程序的退出代码。第一次执行时,由于没有给出任何参数,因此会失败。第二次执行时,由于只给了一个参数,因此会成功。第三次执行时,由于给出了多个参数,因此会得到特殊的退出代码 3。

with Ada.Text_IO;
with Ada.Command_Line;

procedure Args is
   package IO renames Ada.Text_IO;
   package CLI renames Ada.Command_Line;
   More_Than_One_Arg : constant CLI.Exit_Status := 3;
begin
   IO.Put_Line (Item => "Argument Count:" & CLI.Argument_Count'Img);
   if CLI.Argument_Count = 0 then
      CLI.Set_Exit_Status (Code => CLI.Failure);
   elsif CLI.Argument_Count = 1 then
      CLI.Set_Exit_Status (Code => CLI.Success);
   else
      CLI.Set_Exit_Status (Code => More_Than_One_Arg);
   end if; 
end Args;
--                     Standard Ada library specification
--   Copyright (c) 2003-2018 Maxim Reznik <[email protected]>
--   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.Command_Line is
   pragma Preelaborate (Command_Line);

   function Argument_Count return Natural;

   function Argument (Number : in Positive) return String;

   function Command_Name return String;

   type Exit_Status is range implementation_defined .. implementation_defined;

   Success : constant Exit_Status;
   Failure : constant Exit_Status;

   procedure Set_Exit_Status (Code : in Exit_Status);

private

   pragma Import (Ada, Success);
   pragma Import (Ada, Failure);

end Ada.Command_Line;

另请参阅

[编辑 | 编辑源代码]

维基教科书

[编辑 | 编辑源代码]

外部示例

[编辑源代码]

Ada 参考手册

[编辑 | 编辑源代码]

开源实现

[编辑 | 编辑源代码]

FSF GNAT

drake

华夏公益教科书