Skip to main content

GNU GetOpt

Package Available Assertions
AdaCL.Command_Line.GetOpt GNU GetOpt style command line parser with wide character support

A modern object oriented version of GetOpt made for Ada - that’s without the C style ugliness.

Also, unlike for example GNAT.Command_Line this package is re-entrant. All internal states are kept inside the class instance so two tasks can parse the command line in parallel.

Last not least this command line parser has wide character support for short options, long options and file names.

Specifying parser. #

Since the parser is object oriented and re-entrant using it take a bit more effort of creating a child class to perform the parsing operation.

   type Object is new AdaCL.Command_Line.GetOpt.Object with private;

   overriding procedure Parse (This : in out Object);
   overriding procedure WriteHelp (This : in out Object);
   overriding procedure Analyze_WithoutArgument (This : in out Object);
   overriding procedure Analyze_WithArgument (This : in out Object);
   overriding procedure Analyze_GNU (This : in out Object);
   overriding procedure Analyze_File (This : in out Object);

private

   package Inherited renames AdaCL.Command_Line.GetOpt;

   type Object is new Inherited.Object with record
      Operation : Operation_Type                         := None;
      In_File   : Ada.Strings.Unbounded.Unbounded_String := Ada.Strings.Unbounded.Null_Unbounded_String;
      Out_File  : Ada.Strings.Unbounded.Unbounded_String := Ada.Strings.Unbounded.Null_Unbounded_String;
      With_Code : Boolean                                := True;
      Quotes    : Quotes_Type                            := HP;
   end record;

Implementing a parser #

Most command line parser are based around a loop and a huge case but AdaCL.Command_Line.GetOpt is object orientated and based around overriding procedures.

Parse #

Override Parse to set the parameter you wish to use for the scan. At least the pattern for short options need to be set.

   Decode_Long   : constant Wide_Wide_String    := "decode";
   Decode_Short  : constant Wide_Wide_Character := 'd';
   Encode_Long   : constant Wide_Wide_String    := "encode";
   Encode_Short  : constant Wide_Wide_Character := 'e';
   Quotes_Long   : constant Wide_Wide_String    := "quotes";
   Quotes_Short  : constant Wide_Wide_Character := 'q';
   Quotes_HP     : constant Wide_Wide_String    := "hp";
   Quotes_Single : constant Wide_Wide_String    := "single";
   Quotes_Double : constant Wide_Wide_String    := "double";
   Quotes_Back   : constant Wide_Wide_String    := "back";

   Pattern : constant Wide_Wide_String :=
      [GetOpt.Option_Error,
      Decode_Short,
      Encode_Short,
      Quotes_Short,
      GetOpt.Option_Argument];

   overriding procedure Parse (This : in out Object) is
      Super : Inherited.Object renames Inherited.Object (This);
   begin
      This.Set_Pattern (Pattern);
      This.Set_ExceptionOnError (True);
      This.Set_ExtractGNU (True);

      Super.Parse;

      return;
   end Parse

WriteHelp #

Use WriteHelp to write help informations when the user uses the -h or --help options.

   overriding procedure WriteHelp (This : in out Object) is
      pragma Debug (AdaCL.Trace.Entering (AdaCL.Trace.Parameter & This'Image));

      use Ada.Text_IO;
      use GetOpt;

      Super : Inherited.Object renames Inherited.Object (This);
   begin
      New_Line;
      Put_Line ("hp41cx_tools-main:");
      New_Line;
      Put_Line ("     PX-41CX memory dump tool");
      New_Line;
      Put_Line ("Usage:");
      New_Line;
      Put_Line ("    hp41cx_tools-main [command] in_file out_file");
      New_Line;
      Put_Line ("Commands:");
      New_Line;
      Put_Help_Line (Decode_Short, Decode_Long, "Decode PX-41CX memory dump to source code.");
      Put_Help_Line (Encode_Short, Encode_Long, "Encode PX-41CX source code to memory dump.");
      New_Line;
      Put_Line ("General options:");
      New_Line;
      Put_Help_Line (Quotes_Short, Quotes_Long, Quotes_HP, "Use HP-41CX style quotes (⊤) for alpha strings.");
      Put_Help_Line (Quotes_Short, Quotes_Long, Quotes_Single, "Use single quote (') for alpha strings.");
      Put_Help_Line (Quotes_Short, Quotes_Long, Quotes_Double, "Use double quote ("") for alpha strings.");
      Put_Help_Line (Quotes_Short, Quotes_Long, Quotes_Back, "Use backicks (`) for alpha strings.");
      New_Line;
      Put_Line ("Other options:");
      New_Line;

      Put_Line
         ("Version " & Hp41cx_Tools_Config.Crate_Version &
          " (https://calculator-scripts.sourceforge.io/hp41cx-tools/).");
      New_Line;

      Super.WriteHelp;

      pragma Debug (AdaCL.Trace.Exiting);
      return;
   end WriteHelp;

The call to Super.WriteHelp; will print the help for the common options like --help/-h and --verbose/-h.

Analyze_WithoutArgument #

The Analyze_WithoutArgument procedure analyses short options without extra arguments.

   overriding procedure Analyze_WithoutArgument (This : in out Object) is
      Super : Inherited.Object renames Inherited.Object (This);
      Option : constant Wide_Wide_Character := This.Get_Option;
   begin
      if Option = Decode_Short then
         This.Check_Command_None;
         This.Operation := Decode;
      elsif Option = Encode_Short then
         This.Check_Command_None;
         This.Operation := Encode;
      else
         Super.Analyze_WithoutArgument;
      end if;

      return;
   end Analyze_WithoutArgument;

The call to Super.Analyze_WithArgument; will analyse the common options like -h and -v.

Analyze_WithArgument #

The Analyze_WithoutArgument procedure analyses short options with extra arguments.

   overriding procedure Analyze_WithArgument (This : in out Object) is
      Super   : Inherited.Object renames Inherited.Object (This);
      Option   : constant Wide_Wide_Character := This.Get_Option;
      Argument : constant Wide_Wide_String    := This.Get_Argument;
   begin
      if Option = Quotes_Short then
         This.Set_Quotes (Argument);
      else
         Super.Analyze_WithArgument;
      end if;

      return;
   end Analyze_WithArgument;

Analyze_GNU #

The Analyze_WithoutArgument procedure analyses long options with or without extra arguments.

   overriding procedure Analyze_GNU (This : in out Object) is
      Super   : Inherited.Object renames Inherited.Object (This);
      Option   : constant Wide_Wide_String := This.Get_GNUOption;
      Argument : constant Wide_Wide_String := This.Get_Argument;
   begin
      if Option = Decode_Long then
         This.Check_Command_None;
         This.Operation := Decode;
      elsif Option = Encode_Long then
         This.Check_Command_None;
         This.Operation := Encode;
      elsif Option = Quotes_Long then
         This.Set_Quotes (Argument);
      else
         Super.Analyze_GNU;
      end if;

      return;
   end Analyze_GNU;

The call to Super.Analyze_GNU; will analyse the common options like --help and --verbose.

Analyze_File #

The Analyze_File processes all file names or other text which is not part of any option.

   overriding procedure Analyze_File (This : in out Object) is
      Super   : Inherited.Object renames Inherited.Object (This);
      Argument : constant Wide_Wide_String := This.Get_Argument;
   begin
      Super.Analyze_File;

      if This.In_File = Ada.Strings.Unbounded.Null_Unbounded_String then
         This.In_File := Unbounded.To_Unbounded_String (AdaCL.To_UTF_String (Argument));
      elsif This.Out_File = Ada.Strings.Unbounded.Null_Unbounded_String then
         This.Out_File := Unbounded.To_Unbounded_String (AdaCL.To_UTF_String (Argument));
      end if;

      return;
   end Analyze_File;

Executing the parser. #

The actuall parsing

   Try :
   declare
      Options : CommandLine.Object;
   begin
      Options.Parse;

	  --  Options should now contains all the parsed options and filenames. 
   exception
      when AnException : GetOpt.Option_Parse_Error =>
		 --  command line error handler.
      when AnException : others                    =>
		 --  other error handler
   end Try;

Examples: #

AdaCL.Trace
Simple parser to mange the trace setting in procedure Initialize
HP41CX_Tools.Commandline
Full features parser for HP-41CX emulator Tools.
Atr_Tools.CommandLine
Full features parser for Atari / SIO2PC tools for ATR-files
Check_EXE.CommandLine
Full features parser for Atari tools for for handling EXE-files