Ada Programming/Libraries/Ada.Command Line
This language feature is available from Ada 95 on.
Ada.Command_Line is a unit of the Predefined Language Environment since Ada 95.
Introduction
[edit | edit source]The Ada.Command_Line
package enables the Ada program to access the command line arguments set by the command that invoked the program. It is the Ada version of the C argv
and argc[n]
system.
If the environment supports it, it is also possible to set the Ada program's exit status with Ada.Command_Line
.
It is important to note, that all the code in this article is compiled and executed on a Slackware Linux system. The compiler used is GNATMAKE GPL 2008 (20080521) and the shell is BASH. This is important because the reference manual clearly states that:
If the external execution environment supports passing arguments to a program, then Argument_Count returns the number of arguments passed to the program invoking the function. Otherwise, it returns 0. The meaning of “number of arguments” is implementation defined.
Note the closing sentence: The meaning of “number of arguments” is implementation defined. What this means, is that you cannot trust a given argument string to yield the same result for all environments. Argument_Count
is highly dependent on factors such as operating system, shell, and compiler.
Using Ada.Command_Line
[edit | edit source]The program we'll be using throughout this article doesn't actually do anything, except report the various arguments we've used when invoking the program. The basic program looks like this:
with
Ada.Text_IO;with
Ada.Command_Line;procedure
Argsis
package
IOrenames
Ada.Text_IO;package
CLIrenames
Ada.Command_Line;begin
IO.Put_Line (Item => "Argument Count:" & CLI.Argument_Count'Img);end
Args;
When executing the above program with no arguments given, you should get the following output:
Argument Count: 0
Let's quickly go over the program: On lines 1 and 2 we add the Text_IO
and Command_Line
packages to the program. On lines 5 and 6 we rename those packages to the shorter IO
and CLI
and finally on line 8 we output the current argument count. And that is really all that is required to enable access to the command line arguments given to the program.
The full specification of the Command_Line
package is about as simple as such specifications can be.
We've already encountered the Argument_Count
function in the Args
program, but lets see what happens when we invoke the Args
program with some arguments.
Ada.Command_Line.Argument_Count
[edit | edit source]The specification for Argument_Count
looks like this:
function
Argument_Countreturn
Natural;
The basic Args
program already use the Argument_Count
function, so to see how it works, all we have to do is supply the program with a variety of arguments:
$ ./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
A pattern should've emerged by now. Of particular interest is the last example: Because the whitespace is escaped, the entire string is treated as one argument. One could easily imagine that another environment might treat such an argument differently and perhaps ignore the backslash. The same holds for the double quotes example ("Thomas Løcke"). Other shells/environments might very well treat "Thomas Løcke" as two separate arguments because of the whitespace. The key thing is to be aware of such details when using Ada.Command_Line
.
Ada.Command_Line.Argument
[edit | edit source]The specification for Argument
looks like this:
function
Argument (Number : Positive)return
String;
Argument
returns a String
argument corresponding to the relative position Number
. Note that Number
is of type Positive
. This means that the valid range of Number
is 1 .. Argument_Count
. If Number
is outside this range, a Constraint_Error
is raised.
To see how it works, we add 3 more lines to our small Args
program:
for
iin
1 .. CLI.Argument_Countloop
IO.Put_Line (Item => CLI.Argument (Number => i));end
loop
;
If we run Args
with the same arguments as given in the Argument_Count
example, we get these results:
$ ./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
There are no big surprises here.
If no arguments are given when running the program, you will end up with a null range
loop: (1 .. 0)
. This is perfectly valid and the result is as expected: The loop is terminated immediately.
with
Ada.Text_IO;with
Ada.Command_Line;procedure
Argsis
package
IOrenames
Ada.Text_IO;package
CLIrenames
Ada.Command_Line;begin
IO.Put_Line (Item => "Argument Count:" & CLI.Argument_Count'Img);for
iin
1 .. CLI.Argument_Countloop
IO.Put (Item => i'Img & ": "); IO.Put_Line (Item => CLI.Argument (Number => i));end
loop
;end
Args;
Ada.Command_Line.Command_Name
[edit | edit source]The specification for Command_Name
looks like this:
function
Command_Namereturn
String;
Command_Name
returns the string command used to invoke the program. As is the case with Argument_Count
, this is implementation-defined, so Command_Name
might return X on system A, Y on system B and null on system C. You cannot rely on this value being the same across all combinations of compilers, shells, and operating systems.
To see how it works, add this line to the Args
program:
IO.Put_Line (CLI.Command_Name);
If we execute the program, without any arguments, from within GNAT Studio (using Shift+F2), the result will be this:
Argument Count: 0 /home/thomas/wiki_examples/Args/args
Notice how GNAT Studio uses the full path to the Args
program to invoke it.
If I change directory to /home/thomas/wiki_examples/Args/
, and execute the Args
program from the commandline, I get this:
$ args Argument Count: 0 args
If I use the common ./
syntax to execute the program, I get this:
$ ./args Argument Count: 0 ./args
As you can see, in an environment that supports argument passing, the Command_Name
function returns the exact string used to invoke the program.
Ada.Command_Line.Set_Exit_Status
[edit | edit source]The specification for Set_Exit_Status
looks like this:
procedure
Set_Exit_Status (Code : Exit_Status);
If the environment supports the return of an task completion code, Set_Exit_Status
allows you to set an exit status for the program. If you look at the specification for Ada.Command_Line
, you will notice the type Exit_Status
and the two variables Success
and Failure
. These two are defined as 0 and 1, respectively, but it is entirely possible to define your own exit status codes.
To see how that works, add this to the specification of the Args
program:
More_Than_One_Arg : constant
CLI.Exit_Status := 3;
And this to the body of the program:
if
CLI.Argument_Count = 0then
CLI.Set_Exit_Status (Code => CLI.Failure);elsif
CLI.Argument_Count = 1then
CLI.Set_Exit_Status (Code => CLI.Success);else
CLI.Set_Exit_Status (Code => More_Than_One_Arg);end
if
;
What we do here is set the exit status depending on the number of arguments given to the program. This is what happens when we execute the program with various arguments:
$ ./args Argument Count: 0 $ echo $? 1 $ ./args one Argument Count: 1 $ echo $? 0 $ ./args one two Argument Count: 2 $ echo $? 3
echo $?
outputs the exit code of the most recently executed program. On the first execution, we get a failure because no arguments are given. On the second execution, we get a success because exactly one argument is given. On the third execution, we get the special exit code 3 because more than one argument is given.
with
Ada.Text_IO;with
Ada.Command_Line;procedure
Argsis
package
IOrenames
Ada.Text_IO;package
CLIrenames
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 = 0then
CLI.Set_Exit_Status (Code => CLI.Failure);elsif
CLI.Argument_Count = 1then
CLI.Set_Exit_Status (Code => CLI.Success);else
CLI.Set_Exit_Status (Code => More_Than_One_Arg);end
if
;end
Args;
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.Command_Lineis
pragma
Preelaborate (Command_Line);function
Argument_Countreturn
Natural;function
Argument (Number :in
Positive)return
String;function
Command_Namereturn
String;type
Exit_Statusis
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;
See also
[edit | edit source]Wikibook
[edit | edit source]External examples
[edit source]- Search for examples of
Ada.Command_Line
in: Rosetta Code, GitHub (gists), any Alire crate or this Wikibook. - Search for posts related to
Ada.Command_Line
in: Stack Overflow, comp.lang.ada or any Ada related page.
Ada Reference Manual
[edit | edit source]Ada 95
[edit | edit source]Ada 2005
[edit | edit source]Ada 2012
[edit | edit source]Open-Source Implementations
[edit | edit source]FSF GNAT
- Specification: a-comlin.ads
- Body: a-comlin.adb
drake
- Specification: environment/a-comlin.ads
- Body: environment/a-comlin.adb