1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124 | ---------------------------------------------------------------------------
-- FILE : thumper_switches.adb
-- SUBJECT : Body of a package for managing command line switches.
-- AUTHOR : (C) Copyright 2015 by Peter Chapin
--
-- Please send comments or bug reports to
--
-- Peter Chapin <PChapin@vtc.vsc.edu>
---------------------------------------------------------------------------
with Ada.Command_Line;
with Ada.Containers.Ordered_Maps;
use Ada.Command_Line;
package body Thumper_Switches is
package Switch_Maps is new Ada.Containers.Ordered_Maps
(Key_Type => Character, Element_Type => Unbounded_String);
use Switch_Maps;
Switch_Map : Map;
procedure Validate
(Endpoint : in Endpoint_Type;
Valid : out Boolean;
Message : out Unbounded_String) is
Argument_Index : Positive;
procedure Check_Unknown is
Current : Cursor;
begin
Current := Switch_Map.First;
while Current /= No_Element loop
case Key(Current) is
when 'h' | 'p' =>
null;
when others =>
Valid := False;
Message := To_Unbounded_String("Unknown switch: -" & Key(Current));
end case;
Next(Current);
end loop;
end Check_Unknown;
procedure Check_Switch_Semantics is
begin
case Endpoint is
when Client =>
-- The 'h' switch is required for clients.
if not Switch_Map.Contains('h') then
Valid := False;
Message := To_Unbounded_String("The -h switch is required for clients");
end if;
when Server =>
-- The 'h' switch is illegal for servers.
if Switch_Map.Contains('h') then
Valid := False;
Message := To_Unbounded_String("The -h switch is illegal for servers");
end if;
end case;
end Check_Switch_Semantics;
begin
-- Optimistically assume everything will work.
Valid := True;
Message := To_Unbounded_String("No Error");
-- Defensive programming. Make sure the map is empty.
Switch_Map.Clear;
-- There has to be an even number of arguments (could be zero).
if Argument_Count rem 2 /= 0 then
Valid := False;
Message := To_Unbounded_String("Invalid command line syntax");
return;
end if;
-- Build the switch map assocating switch names to their values.
Argument_Index := 1;
while Argument_Index < Argument_Count loop
declare
Current_Argument : constant String := Argument(Argument_Index);
begin
if Current_Argument'Length /= 2 or else Current_Argument(1) /= '-' then
Valid := False;
Message := To_Unbounded_String("Invalid switch: " & Current_Argument);
elsif Switch_Map.Contains(Current_Argument(2)) then
Valid := False;
Message := To_Unbounded_String("Duplicate switch: " & Current_Argument);
else
Switch_Map.Insert
(Current_Argument(2), To_Unbounded_String(Argument(Argument_Index + 1)));
end if;
end;
Argument_Index := Argument_Index + 2;
end loop;
-- Set default values for optional switches that apply to both client and server.
if not Switch_Map.Contains('p') then
Switch_Map.Insert('p', To_Unbounded_String("318"));
end if;
-- Does this collection of switches contain any unknown switches?
if Valid then
Check_Unknown;
end if;
-- Does this collection of switches make sense?
if Valid then
Check_Switch_Semantics;
end if;
end Validate;
function Get_Switch(Switch : Switch_Type) return String is
(case Switch is
when Host => To_String(Switch_Map.Element('h')),
when Port => To_String(Switch_Map.Element('p')));
end Thumper_Switches;
|