[Mono-list] A vaguely POSIXy Getopt class.
Juli Mallett
jmallett@FreeBSD.ORG
Fri, 13 Dec 2002 14:51:02 -0800
I wanted to write some apps that'd take arguments in the POSIXy way,
and so I decided to implement a Getopt class which provides all the
common things, and aside from the fact that I use an exception to
show the end of args (other than using an output parameter boolean
and checking that, I couldn't think of a saneish way), I'm fairly
happy with it. I have no idea if anyone but me would even begin to
find this useful, but it follows in this message, and the usage is
such (it will even do a lazy usage() style message for you, if you
don't want to construct a prettier one yourself):
% public static void Main(string[] args)
% {
% Getopt getopt = new Getopt(args, "a:b");
% char ch;
% for (;;) {
% try {
% ch = getopt.Next();
% } catch (IndexOutOfRangeException) {
% goto EndOfArgs;
% } catch (Exception e) {
% Console.WriteLine("Getopt got {0}", e);
% System.Environment.Exit(1);
% //Notreached.
% return;
% }
% switch (ch) {
% case 'a':
% Console.WriteLine("Got -a with arg {0}", getopt.OptionArgument);
% break;
% case 'b':
% Console.WriteLine("Got -b");
% break;
% case '?':
% default:
% getopt.Usage();
% System.Environment.Exit(1);
% //Notreached.
% return;
% }
% }
% EndOfArgs:
% // Finished argument parsing.
And here's getopt.cs:
%%%
using System;
using System.Reflection;
class Getopt
{
public static char BadCharacter = '?';
public static char BadArgument = ':';
public bool Error = true;
public int Index = 0;
public char Option;
public bool Reset;
public string OptionArgument;
public string ProgramName;
private Assembly CallingAssembly;
private int Length;
private string[] Array;
private string Options;
private string Place;
public Getopt(string progname, int argc, string[] argv, string ostr)
{
CallingAssembly = System.Reflection.Assembly.GetEntryAssembly();
Length = argc;
Array = argv;
Options = ostr;
if (progname == null)
progname = CallingAssembly.ToString();
ProgramName = progname;
}
public Getopt(string progname, string[] argv, string ostr)
: this(progname, argv.Length, argv, ostr)
{
}
public Getopt(int argc, string[] argv, string ostr)
: this(null, argc, argv, ostr)
{
}
public Getopt(string[] argv, string ostr)
: this(argv.Length, argv, ostr)
{
}
public void Usage()
{
string iterator;
string usageString;
usageString = String.Format("usage: {0}", ProgramName);
iterator = Options;
if (iterator == null) {
Console.WriteLine(usageString);
return;
}
if (iterator[0] == ':') {
iterator = GetStringNext(iterator);
}
if (iterator == null) {
Console.WriteLine(usageString);
return;
}
do {
if (iterator.Length == 0)
break;
char optionFlag = iterator[0];
usageString += String.Format(" -{0}", optionFlag);
if (iterator.Length > 1) {
if (iterator[1] == ':') {
usageString += " <argument>";
iterator = GetStringNext(iterator);
}
}
iterator = GetStringNext(iterator);
} while (iterator != null);
Console.WriteLine(usageString);
}
public char Next()
{
if (Place == null)
Place = "";
if (Reset || Place.Length == 0) {
Reset = false;
if (Index >= Length || (Place = Array[Index])[0] != '-') {
Place = null;
throw new IndexOutOfRangeException();
}
if (Place[0] == '-' && Place[1] == '-') {
Index++;
Place = null;
throw new IndexOutOfRangeException();
}
Place = GetStringNext(Place);
}
Option = Place[0];
Place = GetStringNext(Place);
if (Place == null)
throw new IndexOutOfRangeException();
int optionLetterIndex = Options.IndexOf(Option);
if (Option == ':' || optionLetterIndex == -1) {
if (Option == '-')
throw new IndexOutOfRangeException();
if (Place.Length == 0)
Index++;
if (Error && Options[0] != ':' && Option != BadCharacter)
Console.WriteLine("{0}: illegal option -- {1}", ProgramName, Option);
return BadCharacter;
}
if (Options[optionLetterIndex + 1] != ':') {
OptionArgument = null;
if (Place.Length == 0)
Index++;
} else {
if (Place.Length != 0)
OptionArgument = Place;
else if (Length <= ++Index) {
Place = null;
if (Options[0] != ':')
return BadArgument;
if (Error)
Console.WriteLine("{0}: option requires an argument -- {1}", ProgramName, Option);
return BadCharacter;
} else
OptionArgument = Array[Index];
Place = null;
Index++;
}
return Option;
}
private string GetStringNext(string ThisString)
{
try {
ThisString = ThisString.Substring(1);
} catch {
ThisString = null;
}
return ThisString;
}
}
%%%
Thanx & let me know if you find it useful,
juli.
--
Juli Mallett <jmallett@FreeBSD.org>
OpenDarwin, Mono, FreeBSD Developer.
ircd-hybrid Developer, EFnet addict.
FreeBSD on MIPS-Anything on FreeBSD.