Code archives/Miscellaneous/GetOpts

This code has been declared by its author to be Public Domain code.

Download source code

GetOpts by Jim Teeuwen2009
This code is based on the unix shell version of getopts.

This function offers a simple interface for parsing commandline parameters using named key/value pairs.
Options may be supplied in any order and even combined.

Supplying a token string like "i:o:hdtqe" will define the options your application supports. GetOpts will use it to look for options named i, o, h, d, t, q and e.
The Options followed by ':' have to supply a value.
For example:

myapp.exe -h -dtq -e -i "myval" -o "and more value"


As you can see the options 'dtq' are combined into a single entry. This is not required and can be done for all options. Just be sure to give any options which require
a value, their own entry.

A more compact and equally valid version of the above would be:

myapp.exe -dqhtei "myval" -o "and more value"


GetOpts does not ensure required parameters are present. This is up to you to verify. All options are case-sensitive. So -e is not the same as -E.

GetOpts will report an error on a few occasions:
- A user calls your program with an unrecognized option. Eg: it is not listed in the token string.
- A user specifies an option that requires a value, but omits the value.

Using it is simple:
superstrict
Framework brl.basic

Import brl.blitz
Include "getopts.bmx"

'// @opt will contain the name of the currently checked option.
'// @optarg will contain the value for this option (if any).
Local opt:String, optarg:String;
While(GetOpts("i:o:hdtqe", opt, optarg))
	Select(opt)
	 Case "h"; PrintUsage(); end;
	 Case "i"; Print("option i: " + optarg);
	 Case "o"; Print("option o: " + optarg);
	 Case "d"; '...
	 Case "e"; '...
	 Case "q"; '...
	 Case "t"; '...
	 Default;
	 	'// This will yield any values which are not
	 	'// associated with any specific options.
	 	'//   eg: copy.exe -rq /path/to/source /path/to/dest
	 	'// @opt will yield the 2 paths in this section.
	 	print("unspecified option: " + opt);
	End Select
Wend

'.. rest of your program


Known Issues:
- Due to the way Blitz supplies us the Commandline options in AppArgs$[], it is problematic to provide an option value which is itself an option.

Example:
  myapp.exe -c "-lGLU"

This example will cause GetOpts() to throw an error "Missing value for option -c". The reason for this, is that AppArgs will list '-lGLU' without the quotes and this will result in '-lGLU' being considered a new and distinct option, instead of a value. This is a common problem for most GetOpts implementations, but there is a way around it.

We can fix it by escaping the quotes around "-lGLU". For example:
  myapp.exe -c \"-lGLU\"

Now GetOpts() will correctly recognize "-lGLU" as an option value.
Function GetOpts:Int(tokens:String, opt:String Var, optarg:String Var)
	Global av:String[] = Null;
	global isparsed:int = false;
	If(not isparsed) Then
		av = New String[0];
		For Local n:Int = 1 Until AppArgs.Length
			If(AppArgs[n][0..1] = "-") Then
				For Local i:Int = 1 Until AppArgs[n].Length
					av = av[..av.Length + 1];
					av[av.length - 1] = "-" + AppArgs[n][i..i+1];
				Next
			Else
				av = av[..av.Length + 1];
				av[av.length - 1] = AppArgs[n];
			End If
		Next
		isparsed = true;
	End If

	opt = ""; optarg = "";
	If(av.Length = 0) Then Return False;
	opt = av[0]; av = av[1..];

	if(opt[0..1] <> "-") then return true;

	Local idx:Int = tokens.Find(opt[1..]);
	If(idx = -1) Then
		WriteStdErr("Unrecognized option '" + opt + "' specified.~n");
		end;
	End If

	If(idx < tokens.length - 1) Then
		If(tokens[idx+1..idx+2] = ":") Then
			If(av.length = 0 or av[0][0..1] = "-") Then
				WriteStdErr("Missing value for option '" + opt + "'~n");
				end;
			End If
			optarg = av[0]; av = av[1..];
		End If
	End If

	opt = opt[1..];
	Return True;
End Function

Comments

TaskMaster2009
Can you still send a value without an option?

Like the cp command. It is options then source and destination directory...


Jim Teeuwen2009
Excellent point. You can now :)
I modified the entry and example code above accordingly.


Code Archives Forum