//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // PLEASE DO NOT EDIT WITHOUT THE EXPLICIT CONSENT OF THE AUTHOR! \\ //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ using System; using System.Collections; namespace Ilog.Language.Tools { /** * This class implements a simple UNIX style command parser. It is meant to * be subclassed or used directly through its static methods (which is why it * has no constructor). Its method parseCommandLine(String[]) takes * the array of strings on command line (i.e., the argument of a * main method) and determines which options are used with what * values. It also defines a few utilities (1) to set and access the values of * the options and arguments specified in the parsed command, (2) to determine * if these are present, and (3) to do simple file name completion. * * @version Last modified on Sun May 22 20:37:28 2005 by hak * @author Hassan Aït-Kaci * @copyright © 2000 ILOG, S.A. */ public class Command { /** * Options storage. */ private static Hashtable optionTable = new Hashtable(); /** * Command arguments. */ private static String[] arguments = null; /** * Default argument. */ private static String defaultArgument = null; /** * The widest length of option names. */ private static int optionWidth = " Option".Length; /** * The widest length of option defaults. */ private static int defaultWidth = "(Default)".Length; /** * Sets the default argument to the specified string. * * @param arg value to use if the command argument is missing */ public static void OptionalArgument (String arg) { defaultArgument = arg; } /** * Used locally to check whether the specified option is legal. * If this option shares a prefix with one already defined, * a CommandLineException is reported. */ private static void CheckOption (String option) { foreach (DictionaryEntry entry in optionTable) { String name = (String)entry.Key; if (name.StartsWith(option) || option.StartsWith(name)) throw new CommandLineException ("option '"+option+"' conflicts with option '"+name+"'"); } } /** * Defines an option with a default value. * * @param option the option string * @param defaultValue the option's default */ public static void DefineOption (String option, String defaultValue) { CheckOption(option); optionTable[option] = new OptionData(defaultValue); optionWidth = Math.Max(optionWidth,option.Length+2); defaultWidth = Math.Max(defaultWidth,defaultValue.Length+3); } /** * Defines an option with a default value and description. * * @param option the option string * @param defaultValue the option's default * @param help option's description */ public static void DefineOption (String option, String defaultValue, String help) { CheckOption(option); optionTable[option] = new OptionData(defaultValue,help); optionWidth = Math.Max(optionWidth,option.Length+2); defaultWidth = Math.Max(defaultWidth,defaultValue.Length+3); } /** * Returns the value associated with an option. If the option is * undefined, a CommandLineException is reported. * * @param option the option */ public static String GetOption (String option) { OptionData data = (OptionData)optionTable[option]; if (data == null) throw new CommandLineException("unknown command option ("+option+")"); if (data.info == null) return data.defaultInfo; return data.info; } /** * Returns true iff the option is actually present on the command line. * If the option is undefined, a CommandLineException * is reported. * * @param option the option */ public static bool OptionIsPresent (String option) { OptionData data =(OptionData)optionTable[option]; if (data == null) throw new CommandLineException("unknown command option ("+option+")"); return (data.info != null); } /** * Returns the info of the argument. If none is specified, returns the * default argument. If many are specified, the first is returned. */ public static String GetArgument () { if (arguments == null) return defaultArgument; return arguments[0]; } /** * Returns the array of infos of all the arguments. If none is specified, * returns a one element array containing the default argument. */ public static String[] GetArguments () { if (arguments == null) { String[] a = new String[] {defaultArgument}; return a; } return arguments; } /** * This is true iff an argument is actually present on the command line. */ public static bool ArgumentIsPresent { get { return arguments != null; } } /** * Returns a file's name without its extension, but including its directory path. * * @param name the file's name */ public static String FullFileNamePrefix (String name) { return FileTools.FullPrefix(name); } /** * Returns a file's name without its extension nor its directory path. * * @param name the file's name */ public static String FileNamePrefix (String name) { return FileTools.Prefix(name); } /** * Returns a file's name's directory part. * * @param name the file's name */ public static String FileNameDir (String name) { return FileTools.Dir(name); } /** * Returns a file's name extension. * * @param name the file's name */ public static String FileNameSuffix (String name) { return FileTools.Suffix(name); } /** * Returns a file's name completed with its extension if the latter * is missing. * * @param name the file's name * @param ext the file's extension */ public static String CompleteFileName (String name, String ext) { String suffix = "."+ext; if (name.EndsWith(suffix)) return name; return name+suffix; } /** * Prints an item on a given maximum field width. */ private static void PadWrite (String item, int width) { Console.Write(item.PadRight(width)); } /** * Prints a line description of an option. */ private static void PrintHelpLine (String option, String info, String description) { PadWrite(option,optionWidth); PadWrite(info,defaultWidth); Console.WriteLine(description); } private static String usage = null; public static String GetUsage () { return usage; } public static void SetUsage (String usg) { usage = usg; } public static void PrintUsage () { if (usage != null) Console.WriteLine(usage); } /** * Prints a listing of known options, their defaults, and descriptions. */ public static void PrintHelp () { PrintUsage(); if (optionTable.Count == 0) Console.WriteLine("Sorry - no help available!"); else { PrintHelpLine("Option ","(Default)","Description"); PrintHelpLine("------ ","---------","-----------"); foreach (DictionaryEntry entry in optionTable) { OptionData data = (OptionData)entry.Value; PrintHelpLine("-"+entry.Key,"("+data.defaultInfo+")",data.help); } Console.WriteLine(); } } /** * Parses the command line recognizing the defined options and the * arguments, and storing their specified infos as appropriate. * Note that if the same option is specified more than once on the * command line, only the last one is effective. */ public static bool ParseCommandLine (String[] args) { OptionData data = null; int i = 0; while (i < args.Length) // as long as there are arguments { if (args[i][0] == '-') // if this argument starts with '-', it is an option { bool known = false; // a flag to indicate that this option is known bool hasInfo = false; // a flag to indicate that this option is "stuck" to its info args[i] = args[i].Substring(1); // keep what follows the '-' int full = args[i].Length; // the full length of the argument if (full > 0) // if there is something after the '-' foreach (DictionaryEntry entry in optionTable) // for all known options { String option = (String)entry.Key; // let option be the next known option data = (OptionData)entry.Value; // and let data be its value if (args[i].StartsWith(option)) // if it matches the start of this argument { int part = option.Length; // let part be the length of the option name if (hasInfo = (part < full))// the option has info if shorter than the argument data.info = args[i].Substring(part,full-part); // the info is the arg's tail known = true; // remember that we found this option break; // no need to look further. } } if (!known) // this is not a known option { Console.WriteLine("-{0} is not a known option!",args[i]); PrintHelp(); // tell what options are known return false; // the parsing fails } if (hasInfo) // this is a known option and its info is part of it { i++; // proceed to the next argument continue; } // is there a info for this option? if (i < args.Length-1) // if there are more arguments { if (args[i+1][0] != '-') // if the next argument arg is not an option if (data.defaultInfo.Length > 0) // it's the the previous option's info { data.info = args[i+1]; // take this value as that info i += 2; // and skip this value continue; } } if (data.info == null && data.defaultInfo.Length == 0) // this option does not need a info data.info = ""; // so just record it as present i++; } else { arguments = new String[args.Length-i]; Array.Copy(args,i,arguments,0,args.Length-i); break; } } return true; // the parse succeeds! } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ /** * This defines a structure gathering information about an an option. * An instance of this structure will be stored in the hashtable of options. */ private class OptionData { /** * Info of the option specified on the command line. */ internal String info; /** * Info to use if none is specified for this option. */ internal String defaultInfo; /** * Some description of the purpose of this option. */ internal String help = ""; /** * Constructs an OptionData with the specified default info. * * @param defaultInfo option's default */ internal OptionData (String defaultInfo) { this.defaultInfo = defaultInfo; } /** * Constructs an OptionData with the specified default info, * and some description for help. * * @param defaultInfo option's default * @param help option's description */ internal OptionData (String defaultInfo, String help) { this.defaultInfo = defaultInfo; this.help = help; } } } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ /** * Signals an anomalous situation while parsing a command line. */ public class CommandLineException : ApplicationException { /** * Constructs a new CommandLineException with a message. */ internal CommandLineException (String msg) : base("*** Command Line Exception: "+msg) {} } }