Ada GNAT.Command_Line.Getopt-如何强制所有命令行选项有效?

Ada GNAT.Command_Line.Getopt-如何强制所有命令行选项有效?,ada,getopt,Ada,Getopt,下面我尝试创建一个只接受两个选项的命令行程序 我向getopt传递一个字符串,该字符串表示哪些选项有效: Getopt ("-project= -help") 这意味着可以给出'--projectfoo',也可以不加争论地给出'--help'。我希望非常严格—project需要一个参数,而help不应接受参数。但是,上面的参数似乎很乐意接受(并忽略)命令行中给出的其他参数,只要它们不以减号开头: $ ./getopt_invalid_option.exe --project

下面我尝试创建一个只接受两个选项的命令行程序

我向getopt传递一个字符串,该字符串表示哪些选项有效:

Getopt ("-project= -help")
这意味着可以给出'--projectfoo',也可以不加争论地给出'--help'。我希望非常严格—project需要一个参数,而help不应接受参数。但是,上面的参数似乎很乐意接受(并忽略)命令行中给出的其他参数,只要它们不以减号开头:

$ ./getopt_invalid_option.exe --project foo these options are all invalid
Project := foo

$ ./getopt_invalid_option.exe things
Project :=

$ ./getopt_invalid_option.exe --switch

raised GNAT.COMMAND_LINE.INVALID_SWITCH : Unrecognized option '--switch'

$ ./getopt_invalid_option.exe -sss

raised GNAT.COMMAND_LINE.INVALID_SWITCH : Unrecognized option '-s'
我如何不允许上面的前两个例子

我的情况有点复杂,因为我有一个部分,之后一切都应该被允许。通过阅读
GNAT.Command_Line
的规范,我认为这可以通过在进入相应的部分后调用
Getopt(“*”)
来实现,该部分可以工作,但无论是否有部分,我都无法捕获无效的开关(除非它们以“-”开头)

在下面的代码中,我已经注释了与本节相关的部分;但关键是,完整的解决方案也需要与该部分配合使用

带有Ada.Text\u IO;使用Ada.Text\u IO;
使用GNAT.Command_行;使用GNAT.Command_行;
使用Ada.Strings.Unbounded;使用Ada.Strings.Unbounded;
主要程序是
项目:无界_字符串;
开始
--初始化选项扫描(部分分隔符=>“任何内容”);
--Goto_段(“”);
环
case Getopt(“-project=-help”)是
当'-'=>
如果满_开关=“-project”,则
项目:=To_无界_字符串(参数);
elsif Full_开关=“-help”然后
放线(“用法:等…”);
返回;
如果结束;
当ASCII.Nul=>
出口
当其他人=>
Put_线(“错误:无法识别的开关”&完全_开关);
返回;
终例;
端环;
--Goto_区(“任何”);
--环路
--当Getopt(“*”)=ASCII.Nul时退出;
--Put_线(“已接受:&Full_开关”);
--端环;
放线(“项目:=”&到字符串(项目));
端干管;
我已尝试将第一个Getopt更改为:

      case Getopt ("-project= -help *") is
这根本不会改变行为!还尝试:

      case Getopt ("*") is

奇怪的是,它不允许任何东西。

我稍微修改了示例程序。以下似乎有效:

main.adb

with Ada.Text_IO;           use Ada.Text_IO;
with Ada.Exceptions;        use Ada.Exceptions;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with GNAT.Command_Line;     use GNAT.Command_Line;

procedure Main is
   
   Usage_Error : exception;
   
   -----------------------
   -- Raise_Usage_Error --
   -----------------------
   
   procedure Raise_Usage_Error (Switch : String) is
   begin
      raise Usage_Error with "error: unrecognized switch " & Switch;
   end Raise_Usage_Error;
   
   --------------------
   --  Display_Usage --
   --------------------   
   
   procedure Display_Usage is
   begin
      Put_Line ("usage: etc... ");
   end Display_Usage;
   
      
   Project : Unbounded_String;
   
begin
   
   Initialize_Option_Scan (Section_Delimiters => "anything");   
   
   --  Scan the first section.

   loop
      case Getopt ("* project= help") is
         
         when ASCII.Nul =>
            exit;            
         
         when 'p' =>
            if Full_Switch = "project" then
               Project := To_Unbounded_String (Parameter);
            else
               Raise_Usage_Error (Full_Switch);
            end if;
            
         when 'h' =>
            if Full_Switch = "help" then
               Display_Usage;
               return;
            else
               Raise_Usage_Error (Full_Switch);
            end if;            
        
         when others =>
            Raise_Usage_Error (Full_Switch);
            
      end case;
   end loop;
      
   Put ("OK: project = " & To_String (Project));
      
   --  Scan the "anything" section.

   Goto_Section ("anything");
   while Getopt ("*") /= ASCII.Nul loop
      Put (", arg = " & Full_Switch);
   end loop;    
   
exception
   when UE : Usage_Error =>
      Put_Line (Exception_Message (UE));
      --  Optional: Display_Usage
   
end Main;
test.sh

#!/bin/bash

function run_test ()
{
    echo "------------------------------"
    echo "  input   : $1"
    echo "  output  : $($1)"
}

run_test "./obj/main -project=foo"
run_test "./obj/main -project foo"
run_test "./obj/main -help"
run_test "./obj/main -project=foo -anything ddd eee fff"
run_test "./obj/main -help -anything ddd eee fff"
run_test "./obj/main -project=foo aaa bbb ccc"
run_test "./obj/main -help aaa bbb ccc"
run_test "./obj/main -project=foo aaa bbb ccc -anything ddd eee fff"
run_test "./obj/main -help aaa bbb ccc -anything ddd eee fff"
run_test "./obj/main --sss"
run_test "./obj/main -sss"
输出

$ ./test.sh 
------------------------------
  input     : ./obj/main -project=foo
  output    : OK: project = foo
------------------------------
  input     : ./obj/main -project foo
  output    : OK: project = foo
------------------------------
  input     : ./obj/main -help
  output    : usage: etc... 
------------------------------
  input     : ./obj/main -project=foo -anything ddd eee fff
  output    : OK: project = foo, arg = ddd, arg = eee, arg = fff
------------------------------
  input     : ./obj/main -help -anything ddd eee fff
  output    : usage: etc... 
------------------------------
  input     : ./obj/main -project=foo aaa bbb ccc
  output    : error: unrecognized switch aaa
------------------------------
  input     : ./obj/main -help aaa bbb ccc
  output    : usage: etc... 
------------------------------
  input     : ./obj/main -project=foo aaa bbb ccc -anything ddd eee fff
  output    : error: unrecognized switch aaa
------------------------------
  input     : ./obj/main -help aaa bbb ccc -anything ddd eee fff
  output    : usage: etc... 
------------------------------
  input     : ./obj/main --sss
  output    : error: unrecognized switch --sss
------------------------------
  input     : ./obj/main -sss
  output    : error: unrecognized switch -sss

Getopt移动到下一个开关,非开关需要Get_参数