+++ /dev/null
--- sarge.adb - Implementation file for the Sarge command line argument parser project.
-
--- Revision 0
-
--- Features:
--- -
-
--- Notes:
--- -
-
--- 2019/04/10, Maya Posch
-
-
-
-with Ada.Command_Line;
-with Ada.Text_IO;
-use Ada.Text_IO;
-with Ada.Strings.Unbounded.Text_IO;
-use Ada.Strings.Unbounded.Text_IO;
-
-
-package body Sarge is
- --- SET ARGUMENT ---
- procedure setArgument(arg_short: in Unbounded_String; arg_long: in Unbounded_String; desc: in Unbounded_String; hasVal: in boolean) is
- arg: aliased Argument := (arg_short => arg_short, arg_long => arg_long, description => desc, hasValue => hasVal, value => +"", parsed => False);
- begin
- args.append(arg);
-
- -- Set up links.
- if length(arg_short) > 0 then
- argNames.include(arg_short, args.Last_Index);
- end if;
-
- if length(arg_long) > 0 then
- argNames.include(arg_long, args.Last_Index);
- end if;
-
- end setArgument;
-
-
- --- SET DESCRIPTION ---
- procedure setDescription(desc: in Unbounded_String) is
- begin
- description := desc;
- end setDescription;
-
-
- --- SET USAGE ---
- procedure setUsage(usage: in Unbounded_String) is
- begin
- usageStr := usage;
- end setUsage;
-
-
- --- PARSE ARGUMENTS ---
- function parseArguments return boolean is
- flag_it: argNames_map.Cursor;
- expectValue: boolean := False;
- arg: Unbounded_String;
- short_arg: Unbounded_String;
- begin
- --
- execName := +Ada.Command_Line.command_name;
- for arg_i in 1..Ada.Command_Line.argument_count loop
- arg := +Ada.Command_Line.Argument(arg_i);
- -- Each flag will start with a '-' character. Multiple flags can be joined together in
- -- the same string if they're the short form flag type (one character per flag).
- if expectValue = True then
- -- Copy value.
- args.Reference(argNames_map.Element(flag_it)).value := arg;
- expectValue := False;
- elsif Ada.Strings.Unbounded.Slice(arg, 1, 1) = "-" then
- -- Parse flag.
- -- First check for the long form.
- if Ada.Strings.Unbounded.Slice(arg, 1, 2) = "--" then
- -- Long form of the flag.
- -- First delete the preceding dashes.
- arg := Ada.Strings.Unbounded.Delete(arg, 1, 2);
- if not argNames.contains(arg) then
- -- Flag wasn't found. Abort.
- Ada.Strings.Unbounded.Text_IO.put_line("Long flag " & arg & " wasn't found");
- return False;
- end if;
-
- -- Mark as found.
- flag_it := argNames.find(arg);
- args(argNames_map.Element(flag_it)).parsed := True;
- flagCounter := flagCounter + 1;
-
- if args(argNames_map.Element(flag_it)).hasValue = True then
- expectValue := True;
- end if;
- else
- -- Parse short form flag. Parse all of them sequentially. Only the last one
- -- is allowed to have an additional value following it.
- -- First delete the preceding dash.
- arg := Ada.Strings.Unbounded.Delete(arg, 1, 1);
- for i in 1 .. Ada.Strings.Unbounded.Length(arg) loop
- Ada.Strings.Unbounded.Append(short_arg, Ada.Strings.Unbounded.Element(arg, i));
- if argNames_map.Contains(argNames, short_arg) /= True then
- -- Flag wasn't found. Abort.
- put_line("Short flag " & short_arg & " wasn't found.");
- return False;
- end if;
-
- flag_it := argNames.find(short_arg);
-
- -- Mark as found.
- args(argNames_map.Element(flag_it)).parsed := True;
- flagCounter := flagCounter + 1;
-
- if args(argNames_map.Element(flag_it)).hasValue = True then
- if i /= (Ada.Strings.Unbounded.Length(arg)) then
- -- Flag isn't at end, thus cannot have value.
- put_line("Flag " & short_arg & " needs to be followed by a value string.");
- return False;
- else
- expectValue := True;
- end if;
- end if;
-
- Ada.Strings.Unbounded.Delete(short_arg, 1, 1);
- end loop;
- end if;
- else
- -- Add to text argument vector.
- textArguments.append(arg);
- end if;
- end loop;
-
- parsed := True;
-
- return True;
- end parseArguments;
-
-
- --- GET FLAG ---
- function getFlag(arg_flag: in Unbounded_String; arg_value: out Unbounded_String) return boolean is
- flag_it: argNames_map.Cursor;
- use argNames_map;
- begin
- if parsed /= True then
- return False;
- end if;
-
- flag_it := argNames.find(arg_flag);
- if flag_it = argNames_map.No_Element then
- return False;
- elsif args(argNames_map.Element(flag_it)).parsed /= True then
- return False;
- end if;
-
- if args(argNames_map.Element(flag_it)).hasValue = True then
- arg_value := args(argNames_map.Element(flag_it)).value;
- end if;
-
- return True;
- end getFlag;
-
-
- --- EXISTS ---
- function exists(arg_flag: in Unbounded_String) return boolean is
- flag_it: argNames_map.Cursor;
- use argNames_map;
- begin
- if parsed /= True then
- return False;
- end if;
-
- flag_it := argNames.find(arg_flag);
- if flag_it = argNames_map.No_Element then
- return False;
- elsif args(argNames_map.Element(flag_it)).parsed /= True then
- return False;
- end if;
-
- return True;
- end exists;
-
-
- --- GET TEXT ARGUMENT ---
- function getTextArgument(index: in Integer; value: out Unbounded_String) return boolean is
- begin
- if index < Integer(tArgVector.length(textArguments)) then
- value := textArguments(index);
- return True;
- end if;
-
- return False;
- end getTextArgument;
-
-
- --- PRINT HELP ---
- procedure printHelp is
- count: Integer := 1;
- spaceCnt: Integer;
- begin
- put_line("");
- put_line(description);
- put_line("Usage:");
- put_line(usageStr);
- put_line("");
- put_line("Options:");
-
- -- Determine whitespace needed between arg_long and description.
- for flag in args.Iterate loop
- if Integer(Ada.Strings.Unbounded.length(args(flag).arg_long)) > count then
- count := Integer(Ada.Strings.Unbounded.length(args(flag).arg_long));
- end if;
- end loop;
-
- count := count + 3; -- Number of actual spaces between the longest arg_long and description.
-
- -- Print out the options.
- for opt in args.Iterate loop
- --spaceStr := Unbound_String(count - Ada.Strings.Unbounded.length(args(opt).arg_long)
- spaceCnt := (count - Integer(Ada.Strings.Unbounded.length(args(opt).arg_long)));
- if Ada.Strings.Unbounded.length(args(opt).arg_short) < 1 then
- Ada.Strings.Unbounded.Text_IO.put_line(" " & args(opt).arg_short
- & "--" & args(opt).arg_long
- & spaceCnt * " " & args(opt).description);
- else
- Ada.Strings.Unbounded.Text_IO.put_line("-" & args(opt).arg_short
- & ", --" & args(opt).arg_long
- & spaceCnt * " " & args(opt).description);
- end if;
- end loop;
- end printHelp;
-
-
- --- FLAG COUNT ---
- function flagCount return integer is
- begin
- return flagCounter;
- end flagCount;
-
-
- --- EXECUTABLE NAME ---
- function executableName return Unbounded_String is
- begin
- return execName;
- end executableName;
-end Sarge;
-