[Mono-list] Mcs Tools

Jonathan Pryor jonpryor@vt.edu
07 Jul 2002 22:06:50 -0400


--=-4+k6PhhG0PrO0BNyBn9N
Content-Type: text/plain
Content-Transfer-Encoding: 7bit

Must anything in particular be done to add a new tool to the mcs/tools
directory?

I've been working on a reflection tool which would display most of the
information available through System.Type for a given type.  I call it
`type-reflector', and it's attached.

To use it, just specify the type to view on the command line with the
`-S' (show all) and `-v' (verbose) options specified.

It currently doesn't display *all* System.Type information due to
deficiencies with Mono.  Some reflection attributes aren't present in
Mono (such as Assembly.EscapedCodeBase), while others generate run-time
exceptions when invoked (Assembly.ToString() is currently giving me
problems).  All information available through the public Attributes of
the System.Type and related classes can be viewed by compiling with "-D
MONO_BROKEN" and executing with `-K' (show broKen attributes).

It also provides a simple way to view the values of enumeration
constants.  (I was never able to make `EnumCheck.exe' work, so this
provides an alternative.)  For an example, run the program as:

	mono type-reflector.exe -Afv type-reflector.exe TestEnum

and look for "Enumeration Value" in the output.

Thanks,
 - Jon


--=-4+k6PhhG0PrO0BNyBn9N
Content-Disposition: attachment; filename=type-reflector.cs
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; name=type-reflector.cs; charset=UTF-8

//
// type-reflector.cs:=20
//   Finds types and (optionally) shows reflection information about=20
//   the types.
//
// Author: Jonathan Pryor (jonpryor@vt.edu)
//
// (C) 2002 Jonathan Pryor
//
// Permission is hereby granted, free of charge, to any          =20
// person obtaining a copy of this software and associated       =20
// documentation files (the "Software"), to deal in the          =20
// Software without restriction, including without limitation    =20
// the rights to use, copy, modify, merge, publish,              =20
// distribute, sublicense, and/or sell copies of the Software,   =20
// and to permit persons to whom the Software is furnished to    =20
// do so, subject to the following conditions:                   =20
//                                                                =20
// The above copyright notice and this permission notice         =20
// shall be included in all copies or substantial portions       =20
// of the Software.                                              =20
//                                                                =20
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY     =20
// KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO        =20
// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A              =20
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL     =20
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,     =20
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, =20
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION      =20
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//

// #define TRACE

using System;
using System.Collections;
using System.IO;
using System.Diagnostics;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;

namespace Testing
{
	interface IFoo {}
	interface IBar {}
	interface IBaz {}

	delegate void FooEventHandler ();

	[CLSCompliant(false)]
	class TestClass : IFoo, IBar, IBaz {
		private int PrivateField;
		protected float ProtectedField;
		public double PublicField;
		internal long InternalField;

		public TestClass (short s) {PublicField =3D 3.14;}
		protected TestClass (long l) {ProtectedField =3D 2.71F;}
		private TestClass (int i) {PrivateField =3D 13;}
		internal TestClass (float f) {InternalField =3D 64;}

		public int PublicGetSet {
			get {return 0;}
			set {PublicField =3D value;}
		}

		protected short ProtectedGetter {
			get {return -1;}
		}

		private char PrivateSetter {
			set {PrivateField =3D value;}
		}

		internal float InternalProperty {
			get {return ProtectedField;}
			set {ProtectedField =3D value;}
		}

		public event FooEventHandler PubFoo;
		protected event FooEventHandler ProFoo;
		private event FooEventHandler PrivFoo;
		internal event FooEventHandler IntFoo;

		public short PublicMethod (short s) {return s;}
		private int PrivateMethod (int i) {return i;}
		protected long ProtectedMethod (long l) {return l;}
		internal float InternalMethod (float f) {return f;}
	}

	enum TestEnum {
		Foo,=20
		Bar,=20
		Baz,=20
		Qux,=20
		Quux
	}
}

namespace Mono.TypeReflector
{
	public delegate void BaseTypeEventHandler (object sender, BaseTypeEventArg=
s e);
	public delegate void TypeEventHandler (object sender, TypeEventArgs e);
	public delegate void InterfacesEventHandler (object sender, InterfacesEven=
tArgs e);
	public delegate void FieldsEventHandler (object sender, FieldsEventArgs e)=
;
	public delegate void PropertiesEventHandler (object sender, PropertiesEven=
tArgs e);
	public delegate void EventsEventHandler (object sender, EventsEventArgs e)=
;
	public delegate void ConstructorsEventHandler (object sender, Constructors=
EventArgs e);
	public delegate void MethodsEventHandler (object sender, MethodsEventArgs =
e);

	public class BaseTypeEventArgs : EventArgs {

		private Type _base;

		internal BaseTypeEventArgs (Type type)
		{
			_base =3D type;
		}

		public Type BaseType {
			get {return _base;}
		}
	}

	public class TypeEventArgs : EventArgs {

		private Type _type;

		internal TypeEventArgs (Type type)
		{
			_type =3D type;
		}

		public Type Type {
			get {return _type;}
		}
	}

	public class InterfacesEventArgs : EventArgs {

		private Type[] _interfaces;

		internal InterfacesEventArgs (Type[] interfaces)
		{
			_interfaces =3D interfaces ;
		}

		public Type[] Interfaces {
			get {return _interfaces;}
		}
	}

	public class FieldsEventArgs : EventArgs {
		private FieldInfo[] _fields;

		internal FieldsEventArgs (FieldInfo[] fields)
		{
			_fields =3D fields;
		}

		public FieldInfo[] Fields {
			get {return _fields;}
		}
	}

	public class PropertiesEventArgs : EventArgs {

		private PropertyInfo[] _props;

		internal PropertiesEventArgs (PropertyInfo[] properties)
		{
			_props =3D properties;
		}

		public PropertyInfo[] Properties {
			get {return _props;}
		}
	}

	public class EventsEventArgs : EventArgs {

		private EventInfo[] _events;

		internal EventsEventArgs (EventInfo[] events)
		{
			_events =3D events;
		}

		public EventInfo[] Events {
			get {return _events;}
		}
	}

	public class ConstructorsEventArgs : EventArgs {

		private ConstructorInfo[] _ctors;

		internal ConstructorsEventArgs (ConstructorInfo[] ctors)
		{
			_ctors =3D ctors;
		}

		public ConstructorInfo[] Constructors {
			get {return _ctors;}
		}
	}

	public class MethodsEventArgs : EventArgs {

		private MethodInfo[] _methods;

		internal MethodsEventArgs (MethodInfo[] methods)
		{
			_methods =3D methods;
		}

		public MethodInfo[] Methods {
			get {return _methods;}
		}
	}

	public class TypeDisplayer {

		private bool showBase =3D false;
		private bool showConstructors =3D false;
		private bool showEvents =3D false;
		private bool showFields =3D false;
		private bool showInterfaces =3D false;
		private bool showMethods =3D false;
		private bool showProperties =3D false;
		private bool showTypeProperties =3D false;
		private bool showInheritedMembers =3D false;
		private bool verboseOutput =3D false;
		private bool flattenHierarchy =3D false;
		private bool showNonPublic =3D false;
		private bool showMonoBroken =3D false;

		public bool ShowBase {
			get {return showBase;}
			set {showBase =3D value;}
		}

		public bool ShowConstructors {
			get {return showConstructors;}
			set {showConstructors =3D value;}
		}

		public bool ShowEvents {
			get {return showEvents;}
			set {showEvents =3D value;}
		}

		public bool ShowFields {
			get {return showFields;}
			set {showFields =3D value;}
		}

		public bool ShowInterfaces {
			get {return showInterfaces;}
			set {showInterfaces =3D value;}
		}

		public bool ShowMethods {
			get {return showMethods;}
			set {showMethods =3D value;}
		}

		public bool ShowProperties {
			get {return showProperties;}
			set {showProperties =3D value;}
		}

		public bool ShowTypeProperties {
			get {return showTypeProperties;}
			set {showTypeProperties =3D value;}
		}

		public bool ShowInheritedMembers {
			get {return showInheritedMembers;}
			set {showInheritedMembers =3D value;}
		}

		public bool ShowNonPublic {
			get {return showNonPublic;}
			set {showNonPublic =3D value;}
		}

		public bool ShowMonoBroken {
			get {return showMonoBroken;}
			set {showMonoBroken =3D value;}
		}

		public bool FlattenHierarchy {
			get {return flattenHierarchy;}
			set {flattenHierarchy =3D value;}
		}

		public bool VerboseOutput {
			get {return verboseOutput;}
			set {verboseOutput =3D value;}
		}

		private static BindingFlags bindingFlags =3D=20
			BindingFlags.DeclaredOnly |=20
			BindingFlags.Public |=20
			BindingFlags.Instance |=20
			BindingFlags.Static;

		public void Parse (Type type)
		{
			BindingFlags bf =3D bindingFlags;

			if (FlattenHierarchy)
				bf |=3D BindingFlags.FlattenHierarchy;
			if (ShowInheritedMembers)
				bf &=3D ~BindingFlags.DeclaredOnly;
			if (ShowNonPublic)
				bf |=3D BindingFlags.NonPublic;

			Type (type);

			BaseType (type.BaseType);
			Interfaces (type.GetInterfaces ());
			Fields (type.GetFields(bf));
			Constructors (type.GetConstructors(bf));
			Properties (type.GetProperties(bf));
			Events (type.GetEvents(bf));
			Methods (type.GetMethods(bf));
		}

		private void Type (Type t)
		{
			TypeEventArgs ea =3D new TypeEventArgs (t);
			try {
				OnType (ea);
			} finally {
				if (ReceiveTypes !=3D null)
					ReceiveTypes (this, ea);
			}
		}

		protected virtual void OnType (TypeEventArgs e) {}

		private void BaseType (Type t)
		{
			if (ShowBase) {
				BaseTypeEventArgs ea =3D new BaseTypeEventArgs (t);
				try {
					OnBaseType (ea);
				} finally {
					if (ReceiveBaseType !=3D null)
						ReceiveBaseType (this, ea);
				}
			}
		}

		protected virtual void OnBaseType (BaseTypeEventArgs e) {}

		private void Interfaces (Type[] i)
		{
			if (ShowInterfaces) {
				InterfacesEventArgs ea =3D new InterfacesEventArgs (i);
				try {
					OnInterfaces (ea);
				} finally {
					if (ReceiveInterfaces !=3D null)
						ReceiveInterfaces (this, ea);
				}
			}
		}

		protected virtual void OnInterfaces (InterfacesEventArgs e) {}

		private void Fields (FieldInfo[] f)
		{
			if (ShowFields) {
				FieldsEventArgs ea =3D new FieldsEventArgs (f);
				try {
					OnFields (ea);
				} finally {
					if (ReceiveFields !=3D null)
						ReceiveFields (this, ea);
				}
			}
		}

		protected virtual void OnFields (FieldsEventArgs e) {}

		private void Properties (PropertyInfo[] p)
		{
			if (ShowProperties) {
				PropertiesEventArgs ea =3D new PropertiesEventArgs (p);
				try {
					OnProperties (ea);
				} finally {
					if (ReceiveProperties !=3D null)
						ReceiveProperties (this, ea);
				}
			}
		}

		protected virtual void OnProperties (PropertiesEventArgs e) {}

		private void Events (EventInfo[] e)
		{
			if (ShowEvents) {
				EventsEventArgs ea =3D new EventsEventArgs (e);
				try {
					OnEvents (ea);
				} finally {
					if (ReceiveEvents !=3D null)
						ReceiveEvents (this, ea);
				}
			}
		}

		protected virtual void OnEvents (EventsEventArgs e) {}

		private void Constructors (ConstructorInfo[] c)
		{
			if (ShowConstructors) {
				ConstructorsEventArgs ea =3D new ConstructorsEventArgs (c);
				try {
					OnConstructors (ea);
				} finally {
					if (ReceiveConstructors !=3D null)
						ReceiveConstructors (this, ea);
				}
			}
		}

		protected virtual void OnConstructors (ConstructorsEventArgs e)
		{
		}

		private void Methods (MethodInfo[] m)
		{
			if (ShowMethods) {
				MethodsEventArgs ea =3D new MethodsEventArgs (m);
				try {
					OnMethods (ea);
				} finally {
					if (ReceiveMethods !=3D null)
						ReceiveMethods (this, ea);
				}
			}
		}

		protected virtual void OnMethods (MethodsEventArgs e) {}

		public event TypeEventHandler         ReceiveTypes;
		public event BaseTypeEventHandler     ReceiveBaseType;
		public event InterfacesEventHandler   ReceiveInterfaces;
		public event FieldsEventHandler       ReceiveFields;
		public event PropertiesEventHandler   ReceiveProperties;
		public event EventsEventHandler       ReceiveEvents;
		public event ConstructorsEventHandler ReceiveConstructors;
		public event MethodsEventHandler      ReceiveMethods;
	}

	public class IndentingTextWriter : TextWriter {

		private TextWriter _writer;

		private int indentLevel =3D 0;
		private int indentSize =3D 4;
		private bool needIndent =3D true;
		private char indentChar =3D ' ';

		public IndentingTextWriter (TextWriter writer)
		{
			_writer =3D writer;
		}

		public int IndentLevel {
			get {return indentLevel;}
			set {indentLevel =3D value;}
		}

		public int IndentSize {
			get {return indentSize;}
			set {indentSize =3D value;}
		}

		public char IndentChar {
			get {return indentChar;}
			set {indentChar =3D value;}
		}

		public void Indent ()
		{
			++IndentLevel;
		}

		public void Unindent ()
		{
			--IndentLevel;
		}

		protected bool NeedIndent {
			get {return needIndent;}
			set {needIndent =3D value;}
		}

		protected virtual void WriteIndent ()
		{
			NeedIndent =3D false;
			Trace.WriteLine (String.Format(
				"** WriteIndent: char=3D'{0}',level=3D{1},size=3D{2}",
				IndentChar, IndentLevel, IndentSize));
			string indent =3D new string (IndentChar,=20
					IndentLevel * IndentSize);
			Write (indent);
		}

		protected override void Dispose (bool disposing)
		{
			if (disposing)
				_writer.Close ();
		}

		public override System.Text.Encoding Encoding {
			get {return _writer.Encoding;}
		}

		public override void Write (string value)
		{
			if (NeedIndent)
				WriteIndent ();
			_writer.Write (value);
		}

		public override void WriteLine ()
		{
			if (NeedIndent)
				WriteIndent ();
			_writer.WriteLine ();
			NeedIndent =3D true;
		}

		public override void WriteLine (string value)
		{
			Trace.WriteLine (String.Format(
				"** WriteLine: NeedIndent=3D{0}", NeedIndent));
			if (NeedIndent)
				WriteIndent ();
			_writer.WriteLine (value);
			NeedIndent =3D true;
		}
	}

	public class Indenter : IDisposable {

		private IndentingTextWriter _writer;
		// private int level;

		public Indenter (IndentingTextWriter writer)=20
			: this (writer, 1)
		{
		}

		public Indenter (IndentingTextWriter writer, int level)
		{
			_writer =3D writer;
			// XXX: _writer.IndentLevel +=3D level;
			_writer.Indent ();
		}

		public void Dispose ()
		{
			// XXX: _writer.IndentLevel -=3D level;
			_writer.Unindent ();
			Trace.WriteLine (String.Format(
				"** Disposing; indentlevel=3D{0}",=20
				_writer.IndentLevel));
		}
	}

	class VerboseTreeTypeDisplayer : TypeDisplayer {

		private IndentingTextWriter _writer;

		public VerboseTreeTypeDisplayer (TextWriter writer)
		{
			_writer =3D new IndentingTextWriter (writer);
			_writer.IndentChar =3D ' ';
			_writer.IndentSize =3D 2;
		}

		public IndentingTextWriter Writer {
			get {return _writer;}
		}

		private void PrintMemberInfo (MemberInfo mi)
		{
			Writer.WriteLine ("DeclaringType=3D{0}", mi.DeclaringType);
			Writer.WriteLine ("MemberType=3D{0}", mi.MemberType);
			Writer.WriteLine ("Name=3D{0}", mi.Name);
			Writer.WriteLine ("ReflectedType=3D{0}", mi.ReflectedType);
			/*
			 * Not liked by Constructors: on type MethodsEventHandler
			Writer.WriteLine ("GetCustomAttributes():");
			using (Indenter n1 =3D new Indenter (Writer)) {
				object[] attrs =3D mi.GetCustomAttributes (true);
				foreach (object a in attrs)
					Writer.WriteLine (a);
			}
			 */
		}

		protected override void OnType (TypeEventArgs e)
		{
			string t =3D null;

			if (e.Type.IsClass)
				t =3D "class";
			else if (e.Type.IsEnum)
				t =3D "enum";
			else if (e.Type.IsValueType)
				t =3D "struct";
			else if (e.Type.IsInterface)
				t =3D "interface";
			else
				t =3D "type";

			Writer.WriteLine (String.Format ("{0,-11}{1}", t, e.Type.ToString()));
			using (Indenter n1 =3D new Indenter (Writer)) {
				if (ShowTypeProperties) {
					Writer.WriteLine ("System.Type Properties:");
					using (Indenter n2 =3D new Indenter (Writer))
						PrintType (e.Type);
				}
			}
		}

		protected string PrintEnumValue (Type enumType, object value)
		{
			return Enum.Format(enumType, value, "f") + " (" + value + ")";
		}

		protected void PrintType (Type i)
		{
			PrintMemberInfo (i);
			Writer.WriteLine ("Delimiter=3D{0}", Type.Delimiter);
			if (ShowMonoBroken)
				Writer.WriteLine ("EmptyTypes=3D{0}", Type.EmptyTypes.ToString());
			Writer.WriteLine ("FilterAttribute=3D{0}", Type.FilterAttribute);
			Writer.WriteLine ("FilterName=3D{0}", Type.FilterName);
			Writer.WriteLine ("FilterNameIgnoreCase=3D{0}", Type.FilterNameIgnoreCas=
e);
			if (ShowMonoBroken)
				Writer.WriteLine ("Missing=3D{0}", Type.Missing);

			if (ShowMonoBroken)
				Writer.WriteLine ("Assembly=3D{0}", i.Assembly);
			using (Indenter n1 =3D new Indenter (Writer)) {
				if (ShowMonoBroken)
					Writer.WriteLine ("CodeBase=3D{0}", i.Assembly.CodeBase);
				Writer.WriteLine ("EntryPoint=3D{0}", i.Assembly.EntryPoint);
#if MONO_BROKEN
				if (ShowMonoBroken)
					Writer.WriteLine ("EscapedCodeBase=3D{0}", i.Assembly.EscapedCodeBase)=
;
#endif
				Writer.WriteLine ("Evidence=3D{0}", i.Assembly.Evidence);
				if (ShowMonoBroken)
					Writer.WriteLine ("FullName=3D{0}", i.Assembly.FullName);
#if MONO_BROKEN
				if (ShowMonoBroken)
					Writer.WriteLine ("GlobalAssemblyCache=3D{0}", i.Assembly.GlobalAssemb=
lyCache);
#endif
				Writer.WriteLine ("Location=3D{0}", i.Assembly.Location);
			}
			if (ShowMonoBroken)
				Writer.WriteLine ("AssemblyQualifiedName=3D{0}", i.AssemblyQualifiedNam=
e);
			Writer.WriteLine ("Attributes=3D{0}",=20
				PrintEnumValue (typeof(TypeAttributes), i.Attributes));
			Writer.WriteLine ("BaseType=3D{0}", i.BaseType);
			Writer.WriteLine ("DeclaringType=3D{0}", i.DeclaringType);
			Writer.WriteLine ("DefaultBinder=3D{0}", Type.DefaultBinder);
			Writer.WriteLine ("FullName=3D{0}", i.FullName);
			Writer.WriteLine ("GUID=3D{0}", i.GUID);
			Writer.WriteLine ("HasElementType=3D{0}", i.HasElementType);
			Writer.WriteLine ("IsAbstract=3D{0}", i.IsAbstract);
			Writer.WriteLine ("IsAnsiClass=3D{0}", i.IsAnsiClass);
			Writer.WriteLine ("IsArray=3D{0}", i.IsArray);
			Writer.WriteLine ("IsAutoClass=3D{0}", i.IsAutoClass);
			Writer.WriteLine ("IsAutoLayout=3D{0}", i.IsAutoLayout);
			Writer.WriteLine ("IsByRef=3D{0}", i.IsByRef);
			Writer.WriteLine ("IsClass=3D{0}", i.IsClass);
			Writer.WriteLine ("IsCOMObject=3D{0}", i.IsCOMObject);
			Writer.WriteLine ("IsContextful=3D{0}", i.IsContextful);
			Writer.WriteLine ("IsEnum=3D{0}", i.IsEnum);
			Writer.WriteLine ("IsExplicitLayout=3D{0}", i.IsExplicitLayout);
			Writer.WriteLine ("IsImport=3D{0}", i.IsImport);
			Writer.WriteLine ("IsInterface=3D{0}", i.IsInterface);
			Writer.WriteLine ("IsLayoutSequential=3D{0}", i.IsLayoutSequential);
			Writer.WriteLine ("IsMarshalByRef=3D{0}", i.IsMarshalByRef);
			Writer.WriteLine ("IsNestedAssembly=3D{0}", i.IsNestedAssembly);
			Writer.WriteLine ("IsNestedFamORAssem=3D{0}", i.IsNestedFamORAssem);
			Writer.WriteLine ("IsNestedPrivate=3D{0}", i.IsNestedPrivate);
			Writer.WriteLine ("IsNotPublic=3D{0}", i.IsNotPublic);
			Writer.WriteLine ("IsPointer=3D{0}", i.IsPointer);
			Writer.WriteLine ("IsPrimitive=3D{0}", i.IsPrimitive);
			Writer.WriteLine ("IsPublic=3D{0}", i.IsPublic);
			Writer.WriteLine ("IsSealed=3D{0}", i.IsSealed);
			Writer.WriteLine ("IsSerializable=3D{0}", i.IsSerializable);
			Writer.WriteLine ("IsSpecialName=3D{0}", i.IsSpecialName);
			Writer.WriteLine ("IsUnicodeClass=3D{0}", i.IsUnicodeClass);
			Writer.WriteLine ("IsValueType=3D{0}", i.IsValueType);
			Writer.WriteLine ("Module=3D{0}", i.Module);
			Writer.WriteLine ("Namespace=3D{0}", i.Namespace);
			Writer.WriteLine ("TypeHandle=3D{0}", i.TypeHandle);
			if (ShowMonoBroken)
				Writer.WriteLine ("TypeInitializer=3D{0}", i.TypeInitializer);
			Writer.WriteLine ("UnderlyingSystemType=3D{0}", i.UnderlyingSystemType);
		}

		protected override void OnInterfaces (InterfacesEventArgs e)
		{=20
			using (Indenter n =3D new Indenter (Writer)) {
				Writer.WriteLine ("Interfaces:");
				using (Indenter n2 =3D new Indenter (Writer)) {
					foreach (Type i in e.Interfaces) {
						Writer.WriteLine (i);
						if (VerboseOutput) {
							using (Indenter n3 =3D new Indenter (Writer)) {
								PrintType (i);
							}
						}
					}
				}
			}
		}

		protected void PrintFieldInfo (FieldInfo f)
		{
			if (VerboseOutput) {
				PrintMemberInfo (f);
				Writer.WriteLine ("Attributes=3D{0}",=20
					PrintEnumValue (typeof(FieldAttributes), f.Attributes));
				Writer.WriteLine ("FieldHandle=3D{0}", f.FieldHandle);
				Writer.WriteLine ("FieldType=3D{0}", f.FieldType);
				Writer.WriteLine ("IsAssembly=3D{0}", f.IsAssembly);
				Writer.WriteLine ("IsFamily=3D{0}", f.IsFamily);
				Writer.WriteLine ("IsFamilyAndAssembly=3D{0}", f.IsFamilyAndAssembly);
				Writer.WriteLine ("IsFamilyOrAssembly=3D{0}", f.IsFamilyOrAssembly);
				Writer.WriteLine ("IsInitOnly=3D{0}", f.IsInitOnly);
				Writer.WriteLine ("IsLiteral=3D{0}", f.IsLiteral);
				Writer.WriteLine ("IsNotSerialized=3D{0}", f.IsNotSerialized);
				Writer.WriteLine ("IsPinvokeImpl=3D{0}", f.IsPinvokeImpl);
				Writer.WriteLine ("IsPrivate=3D{0}", f.IsPrivate);
				Writer.WriteLine ("IsPublic=3D{0}", f.IsPublic);
				Writer.WriteLine ("IsSpecialName=3D{0}", f.IsSpecialName);
				Writer.WriteLine ("IsStatic=3D{0}", f.IsStatic);
				if (f.IsStatic && f.IsLiteral) {
					Writer.Write ("Enumeration Value: ");
					string s =3D Enum.Format (f.DeclaringType, f.GetValue(null), "x");
					Writer.WriteLine ("0x{0}", s);
				}
				/*
				if (f.DeclaringType.IsEnum && f.IsStatic) {
					Writer.Write ("Enumeration Value (2): ");
					string s =3D Enum.Format (f.DeclaringType, f.GetValue(null), "x");
					Writer.WriteLine ("0x{0}", s);
				}
				 */
			}
		}

		protected override void OnFields (FieldsEventArgs e)
		{
			using (Indenter n1 =3D new Indenter (Writer)) {
				Writer.WriteLine ("Fields:");
				using (Indenter n2 =3D new Indenter (Writer)) {
					foreach (FieldInfo f in e.Fields) {
						Writer.WriteLine (f);
						using (Indenter n3 =3D new Indenter (Writer)) {
							PrintFieldInfo (f);
						}
					}
				}
			}
		}

		protected void PrintPropertyInfo (PropertyInfo p)
		{
			if (VerboseOutput) {
				PrintMemberInfo (p);
				Writer.WriteLine ("Attributes=3D{0}",=20
					PrintEnumValue (typeof(PropertyAttributes), p.Attributes));
				Writer.WriteLine ("CanRead=3D{0}", p.CanRead);
				Writer.WriteLine ("CanWrite=3D{0}", p.CanWrite);
				Writer.WriteLine ("IsSpecialName=3D{0}", p.IsSpecialName);
				Writer.WriteLine ("PropertyType=3D{0}", p.PropertyType);
			}
		}

		protected override void OnProperties (PropertiesEventArgs e)
		{
			using (Indenter n1 =3D new Indenter (Writer)) {
				Writer.WriteLine ("Properties:");
				using (Indenter n2 =3D new Indenter (Writer)) {
					foreach (PropertyInfo p in e.Properties) {
						Writer.WriteLine (p);
						using (Indenter n3 =3D new Indenter (Writer)) {
							PrintPropertyInfo (p);
						}
					}
				}
			}
		}

		protected void PrintEventInfo (EventInfo i)
		{
			if (VerboseOutput) {
				PrintMemberInfo (i);
				Writer.WriteLine ("Attributes=3D{0}", PrintEnumValue (typeof(EventAttri=
butes), i.Attributes));
				Writer.WriteLine ("EventHandlerType=3D{0}", i.EventHandlerType);
				Writer.WriteLine ("IsMulticast=3D{0}", i.IsMulticast);
				Writer.WriteLine ("IsSpecialName=3D{0}", i.IsSpecialName);
			}
		}

		protected override void OnEvents (EventsEventArgs e)
		{
			using (Indenter n1 =3D new Indenter (Writer)) {
				Writer.WriteLine ("Events:");
				using (Indenter n2 =3D new Indenter (Writer)) {
					foreach (EventInfo i in e.Events) {
						Writer.WriteLine (i);
						using (Indenter n3 =3D new Indenter (Writer)) {
							PrintEventInfo (i);
						}
					}
				}
			}
		}

		private void PrintMethodBase (MethodBase mb)
		{
			PrintMemberInfo (mb);
			Writer.WriteLine ("Attributes=3D{0}",=20
				PrintEnumValue (typeof(MethodAttributes), mb.Attributes));
			Writer.WriteLine ("CallingConvention=3D{0}", mb.CallingConvention);
			Writer.WriteLine ("IsAbstract=3D{0}", mb.IsAbstract);
			Writer.WriteLine ("IsAssembly=3D{0}", mb.IsAssembly);
			Writer.WriteLine ("IsConstructor=3D{0}", mb.IsConstructor);
			Writer.WriteLine ("IsFamily=3D{0}", mb.IsFamily);
			Writer.WriteLine ("IsFamilyAndAssembly=3D{0}", mb.IsFamilyAndAssembly);
			Writer.WriteLine ("IsFamilyOrAssembly=3D{0}", mb.IsFamilyOrAssembly);
			Writer.WriteLine ("IsFinal=3D{0}", mb.IsFinal);
			Writer.WriteLine ("IsHideBySig=3D{0}", mb.IsHideBySig);
			Writer.WriteLine ("IsPrivate=3D{0}", mb.IsPrivate);
			Writer.WriteLine ("IsPublic=3D{0}", mb.IsPublic);
			Writer.WriteLine ("IsSpecialName=3D{0}", mb.IsSpecialName);
			Writer.WriteLine ("IsStatic=3D{0}", mb.IsStatic);
			Writer.WriteLine ("IsVirtual=3D{0}", mb.IsVirtual);
			Writer.WriteLine ("MethodHandle=3D{0}", mb.MethodHandle);
		}

		protected void PrintConstructorInfo (ConstructorInfo c)
		{
			if (VerboseOutput) {
				PrintMethodBase (c);
			}
		}

		protected override void OnConstructors (ConstructorsEventArgs e)
		{
			using (Indenter n1 =3D new Indenter (Writer)) {
				Writer.WriteLine ("Constructors:");
				using (Indenter n2 =3D new Indenter (Writer)) {
					foreach (ConstructorInfo c in e.Constructors) {
						Writer.WriteLine (c);
						using (Indenter n3 =3D new Indenter (Writer)) {
							PrintConstructorInfo (c);
						}
					}
				}
			}
		}

		protected void PrintMethodInfo (MethodInfo m)
		{
			if (VerboseOutput) {
				PrintMethodBase (m);
				Writer.WriteLine ("ReturnType=3D{0}", m.ReturnType);
				Writer.WriteLine ("ReturnTypeCustomAttributes=3D{0}",=20
					/* PrintEnumValue (typeof(m.ReturnTypeCustomAttributes), m.ReturnTypeC=
ustomAttributes) */
					m.ReturnTypeCustomAttributes);
			}
		}

		protected override void OnMethods (MethodsEventArgs e)
		{
			using (Indenter n1 =3D new Indenter (Writer)) {
				Writer.WriteLine ("Methods:");
				using (Indenter n2 =3D new Indenter (Writer)) {
					foreach (MethodInfo m in e.Methods) {
						Writer.WriteLine (m);
						using (Indenter n3 =3D new Indenter (Writer)) {
							PrintMethodInfo (m);
						}
					}
				}
			}
		}
	}

	public class TypeLoader {

		// String collection
		private ICollection assemblies =3D null;

		private bool matchFullName =3D true;
		private bool matchName =3D false;
		private bool matchBase =3D false;
		private bool matchMethodReturnType =3D false;
		private bool matchNamespace =3D false;

		public bool MatchFullName {
			get {return matchFullName;}
			set {matchFullName =3D value;}
		}

		public bool MatchClassName {
			get {return matchName;}
			set {matchName =3D value;}
		}

		public bool MatchBase {
			get {return matchBase;}
			set {matchBase =3D value;}
		}

		public bool MatchMethodReturnType {
			get {return matchMethodReturnType;}
			set {matchMethodReturnType =3D value;}
		}

		public bool MatchNamespace {
			get {return matchNamespace;}
			set {matchNamespace =3D value;}
		}

		public TypeLoader ()
		{
		}

		public TypeLoader (ICollection assemblies)
		{
			this.assemblies =3D assemblies;
		}

		public ICollection Assemblies {
			get {return assemblies;}
			set {assemblies =3D value;}
		}

		public ICollection LoadTypes (string match)
		{
			if (assemblies =3D=3D null)
				throw new ArgumentNullException ("Assemblies");

			IList found =3D new ArrayList ();

			foreach (string a in assemblies) {
				LoadMatchingTypesFrom (a, match, found);
			}

			return found;
		}

		private void LoadMatchingTypesFrom (string where, string match, IList typ=
es)
		{
			Regex re =3D new Regex (match);
			try {
				Assembly a =3D Assembly.LoadFrom (where);
				Type[] _types =3D a.GetTypes();
				foreach (Type t in _types) {
					if (Matches (re, t))
						types.Add (t);
				}
			} catch (Exception e) {
				Trace.WriteLine (String.Format (
					"Unable to load type regex `{0}' from `{1}'.",
					match, where));
				Trace.WriteLine (e.ToString());
			}
		}

		private bool Matches (Regex r, Type t)
		{
			bool f, c, b, rt, n;
			f =3D c =3D b =3D rt =3D n =3D false;
			if (MatchFullName)
				f =3D r.Match(t.FullName).Success;
			if (MatchClassName)
				c =3D r.Match(t.Name).Success;
			if (MatchNamespace)
				n =3D r.Match(t.Namespace).Success;
			if (MatchBase) {
				b =3D (!MatchFullName ? false : r.Match (t.BaseType.FullName).Success) =
||
				    (!MatchClassName ? false : r.Match (t.BaseType.Name).Success) ||
				    (!MatchNamespace ? false : r.Match (t.BaseType.Namespace).Success);
			}
			// TODO: MatchMethodReturnType
			Trace.WriteLine (String.Format("TypeLoader.Matches: c=3D{0}, b=3D{1}, rt=
=3D{2}, n=3D{3}", c, b, rt, n));
			return f || c || b || rt || n;
		}
	}

	internal class TextGrouper {
		private int leftMargin =3D 0;
		private int rightMargin =3D 80;
		private int subsequentIndent =3D 0;

		public int LeftMargin {
			get {return leftMargin;}
			set {leftMargin =3D value;}
		}

		public int RightMargin {
			get {return rightMargin;}
			set {rightMargin =3D value;}
		}

		public int SubsequentIndent {
			get {return subsequentIndent;}
			set {subsequentIndent =3D value;}
		}

		public TextGrouper ()
			: this (0)
		{
		}

		public TextGrouper (int leftMargin)
			: this (leftMargin, 80)
		{
		}

		public TextGrouper (int leftMargin, int rightMargin)
			: this (leftMargin, rightMargin, 0)
		{
		}

		public TextGrouper (int leftMargin, int rightMargin, int subsequentIndent=
)
		{
			this.leftMargin =3D leftMargin;
			this.rightMargin =3D rightMargin;
			this.subsequentIndent =3D subsequentIndent;
		}

		private void WrapText (string text, int width, IList lines)
		{
			if (text.Length <=3D width) {
				lines.Add (text);
				return;
			}

			while (text.Length > width) {
				int b =3D width;
				if (!Char.IsWhiteSpace(text[b])) {
					b =3D text.LastIndexOf (' ', b);
					if (b =3D=3D -1)
						// couldn't find an earlier word break
						b =3D width;
				}
				lines.Add (text.Substring (0, b));
				text =3D text.Substring (b).Trim();
			}
			lines.Add (text);
		}

		private ICollection WrapText (string text, int width)
		{
			ArrayList lines =3D new ArrayList ();
			string[] paragraphs =3D text.Split(new char[] {'\n'});
			foreach (string p in paragraphs)
				WrapText (p, width, lines);
			return lines;
		}

		public string Group (string text)
		{
			// should be "- followingIndent", but need an extra space for the '\n'.
			int width =3D (RightMargin - LeftMargin) - (SubsequentIndent+1);
			StringBuilder sb =3D new StringBuilder ();
			string format1 =3D "{1}";
			string formatN =3D "{0,-" + (LeftMargin + SubsequentIndent) + "}{1}";
			ICollection c =3D WrapText (text, width);
			int last =3D c.Count;
			string format =3D format1;
			foreach (string s in c) {
				string line =3D String.Format (format, "", s);
				sb.Append (line);
				if (--last !=3D 0) {
					format =3D formatN;
					sb.Append ("\n");
				}
			}
			return sb.ToString();
		}
	}

	internal class OptionException : Exception {

		public char ShortForm;

		public OptionException (string reason, char shortForm )
			: base (reason)
		{
			this.ShortForm =3D shortForm;
		}

		public OptionException (string reason)
			: base (reason)
		{
		}

		public OptionException (string reason, Exception inner)
			: base (reason, inner)
		{
		}
	}

	internal class ProgramOptions {

		private class Option {
			public char   ShortForm =3D '\0';
			public string LongForm =3D null;
			public string Description =3D null;
			public bool   Found =3D false;
			public bool   HasArgument =3D false;
			public string ArgumentValue =3D null;
			public string ArgumentDescription =3D null;

			public Option (char shortForm, string longForm, string description, stri=
ng argDesc, bool hasArgument)
			{
				ShortForm =3D shortForm;
				LongForm =3D longForm;
				Description =3D description;
				HasArgument =3D hasArgument;
				ArgumentDescription =3D argDesc;
			}

			public Option (char shortForm, string description)
			{
				ShortForm =3D shortForm;
				Description =3D description;
			}

			public Option (string longForm, string description)
			{
				LongForm =3D longForm;
				Description =3D description;
			}
		}

		// Option array
		private ArrayList options =3D new ArrayList ();

		// string array
		private ArrayList unmatched =3D new ArrayList ();

		public IList UnmatchedOptions {
			get {return unmatched;}
		}

		public ProgramOptions ()
		{
		}

		private void AddOption (Option opt)
		{
			options.Add (opt);
		}

		public void AddHelpOption ()
		{
			AddOption (new Option ('h', "help", "Display this help and exit.", null,=
 false));
		}

		public void AddOption (char shortForm, string description)
		{
			AddOption (new Option (shortForm, description));
		}

		public void AddArgumentOption (char shortForm, string description, string=
 argument)
		{
			AddOption (new Option (shortForm, null, description, argument, true));
		}

		public void AddOption (string longForm, string description)
		{
			AddOption (new Option (longForm, description));
		}

		public void AddArgumentOption (string longForm, string description, strin=
g argument)
		{
			AddOption (new Option ('\0', longForm, description, argument, true));
		}

		public void AddOption (char shortForm, string longForm, string descriptio=
n)
		{
			AddOption (new Option (shortForm, longForm, description, null, false));
		}

		public void AddArgumentOption (char shortForm, string longForm, string de=
scription, string argument)
		{
			AddOption (new Option (shortForm, longForm, description, argument, true)=
);
		}

		public virtual void ParseOptions (string[] options)
		{
			int len =3D options.Length;
			bool handle =3D true;
			for (int cur =3D 0; cur !=3D len; ++cur) {
				string option =3D options[cur];
				// necessary?
				if (option =3D=3D null || option.Length =3D=3D 0)
					continue;
				if (handle) {
					if (option.StartsWith ("-")) {
						// possible option
						if (option =3D=3D "--")
							handle =3D false;
						else if (option.StartsWith ("--"))
							ParseLongOption (options, ref cur);
						else
							ParseShortOptions (options, ref cur);
					}
					else
						unmatched.Add (option);
				}
				else
					unmatched.Add (option);
			}
		}

		private void ParseLongOption (string[] args, ref int currentIndex)
		{
			// get rid of "--"
			string arg =3D args[currentIndex].Substring (2);
			bool found =3D false;
			foreach (Option o in options) {
				if (o.LongForm =3D=3D null)
					continue;
				if (!arg.StartsWith(o.LongForm))
					continue;
				found =3D true;
				o.Found =3D true;
				if (o.HasArgument) {
					try {
						o.ArgumentValue =3D arg.Substring (arg.IndexOf('=3D')+1);
					} catch (Exception e) {
						throw new OptionException (
							"missing argument to option --" + o.LongForm,
							e);
					}
				}
			}

			if (!found)
				throw new OptionException (
					String.Format ("Unrecognized option `{0}'", args[currentIndex]));
		}

		private void ParseShortOptions (string[] args, ref int currentIndex)
		{
			string arg =3D args[currentIndex].Substring (1);
			int needsArg =3D 0;
			Option forArg =3D null;
			for (int i =3D 0; i !=3D arg.Length; ++i) {
				bool found =3D false;
				foreach (Option o in options) {
					if (o.ShortForm !=3D arg[i])
						continue;
					found =3D true;
					o.Found =3D true;
					if (o.HasArgument) {
						++needsArg;
						forArg =3D o;
					}
				}
				if (!found)
					throw new OptionException (
						String.Format("Unrecognized option `-{0}'", arg[i]));
			}

			if (needsArg > 1)
				throw new OptionException ("too many options requiring arguments specif=
ied");
			else if (needsArg =3D=3D 1) {
				if (currentIndex =3D=3D (args.Length - 1))
					throw new OptionException ("missing argument to option -" + forArg.Sho=
rtForm);
				++currentIndex;
				forArg.ArgumentValue =3D args[currentIndex];
			}
		}

		public virtual void Clear ()
		{
			foreach (Option o in options) {
				o.Found =3D false;
				o.ArgumentValue =3D null;
			}
		}

		private static readonly string[] OptionFormats =3D=20
			{
			// 0: no short, no long, no arg
			"<invalid option format: 0>",
			// 1: short only
			"  -{0}",
			// 2: long only
			"      --{1}",
			// 3: long & short
			"  -{0}, --{1}",
			// 4: no short, no long, arg
			"<invalid option format: 4>",
			// 5: short w/ arg
			"  -{0} {2}",
			// 6: long w/ arg
			"      --{1}=3D{2}",
			// 7: short & long w/ arg
			"  -{0}, --{1}=3D{2}"
			};

		public virtual string OptionsHelp {
			get {
				StringBuilder sb =3D new StringBuilder ();
				foreach (Option o in options) {
					uint f_s =3D  Convert.ToUInt32 (o.ShortForm !=3D '\0');
					uint f_l =3D  Convert.ToUInt32 (o.LongForm !=3D null);
					uint f_h =3D  Convert.ToUInt32 (o.HasArgument);
					uint format =3D (f_s << 0) | (f_l << 1) | (f_h << 2);
					string opt =3D String.Format (OptionFormats[format],=20
							o.ShortForm,=20
							o.LongForm,=20
							o.ArgumentDescription);
					string fmt =3D null;
					if (opt.Length < 30)
						fmt =3D "{0,-30}{1}";
					else
						fmt =3D "{0,-30}\n{2,-30}{1}";
					string d =3D new TextGrouper (30, 80, 2).Group (o.Description);
					sb.Append (String.Format (fmt, opt, d, ""));
					sb.Append ("\n");
				}
				return sb.ToString ();
			}
		}

		public static readonly string ProgramName =3D Environment.GetCommandLineA=
rgs()[0];

		public bool FoundOption (char shortForm)
		{
			foreach (Option o in options) {
				if (o.ShortForm !=3D shortForm)
					continue;
				return o.Found;
			}
			return false;
		}

		public bool FoundOption (string longForm)
		{
			foreach (Option o in options) {
				if (o.LongForm !=3D longForm)
					continue;
				return o.Found;
			}
			return false;
		}

		public string FoundOptionValue (char shortForm)
		{
			foreach (Option o in options) {
				if (o.ShortForm !=3D shortForm)
					continue;
				return o.ArgumentValue;
			}
			return null;
		}

		public string FoundOptionValue (string longForm)
		{
			foreach (Option o in options) {
				if (o.LongForm !=3D longForm)
					continue;
				return o.ArgumentValue;
			}
			return null;
		}

		public bool FoundHelp {
			get {return FoundOption ('h');}
		}
	}

	internal class TypeIntrospectorOptions : ProgramOptions {

		private static char onlyAssemblies      =3D 'A';
		private static char addAssemblies       =3D 'a';
		private static char matchAll            =3D 'M';
		private static char matchFullName       =3D 'f';
		private static char matchClass          =3D 'C';
		private static char matchBase           =3D 'B';
		private static char matchNamespace      =3D 'N';
		private static char matchReturnType     =3D 'R';
		private static char showBase            =3D 'b';
		private static char showConstructors    =3D 'c';
		private static char showEvents          =3D 'e';
		private static char showFields          =3D 'f';
		private static char showInterfaces      =3D 'i';
		private static char showMethods         =3D 'm';
		private static char showProperties      =3D 'p';
		private static char showTypeProperties  =3D 't';
		private static char showNonPublic       =3D 'U';
		private static char showMonoBroken      =3D 'K';
		private static char showAll             =3D 'S';
		private static char showInheritedMembers=3D 'r';
		private static char verboseOutput       =3D 'v';
		private static char flattenHierarchy    =3D 'F';

		public TypeIntrospectorOptions ()
		{
			AddArgumentOption (onlyAssemblies,  "only-assemblies",
				"Only search for types within the specified " +
				"assemblies.  Assemblies are searched for " +
				"within the directories specified with " +
				"--only-directories.",=20
				"<assembly-list>");
			AddArgumentOption (addAssemblies,   "add-assemblies",
				"Add the specified assemblies to the list of " +
				"assemblies searched for types.",=20
				"<assembly-list>");
			AddOption (matchAll,                "match-all",
				"Type names should be matched in all locations"
				);
			AddOption (matchFullName,           "match-full-name",
				"Match type names against the full type name " +
				"(Namespace + Class Name).\n" +
				"This is the default.");
			AddOption (matchClass,              "match-class",
				"Match type names against only the class name");
			AddOption (matchBase,               "match-base",
				"Match type names against the base class " +=20
				"name.\nMatching of the base name is " +
				"identical to top-level type matches--it " +
				"matches the namespace, class name, or full " +
				"type name.");
			AddOption (matchNamespace,          "match-namespace",
				"Match the type's namespace.");
			/*
			AddOption (matchReturnType,         "match-return-type",
				"Match the return type of methods");
			 */
			AddOption (showBase,                "show-base",
				"Show the base class.");
			AddOption (showConstructors,        "show-constructors",
				"Show the type's constructors.");
			AddOption (showEvents,              "show-events",
				"Show the type's events.");
			AddOption (showFields,              "show-fields",
				"Show the type's fields.");
			AddOption (showInterfaces,          "show-interfaces",
				"Show the type's interfaces");
			AddOption (showMethods,             "show-methods",
				"Show the type's methods.");
			AddOption (showProperties,          "show-properties",
				"Show the type's properties.");
			AddOption (showTypeProperties,      "show-type-properties",
				"Show the properties of the type's System.Type"+
				"object.\nThis is not set by -S.");
			AddOption (showInheritedMembers,    "show-inherited-members",
				"Show inherited members (members declared by " +
				"base classes).\nThis is not set by -S.");
			AddOption (showNonPublic,           "show-non-public",
				"Show non-public members.\n" +=20
				"This is not set by -S.");
			AddOption (showMonoBroken,          "show-mono-broken",
				"Some attributes shown in verbose output " +
				"cause exceptions when run under Mono.  " +
				"These attributes are not shown by default.  "+
				"This option shows these disabled attributes."+
				"\nThis is not set by -S.");
			AddOption (showAll,                 "show-all",
				"Show everything except System.Type "+
				"properties, inherited members, non-public "+
				"members, and \"broken\" Mono attributes.");
			AddOption (verboseOutput,           "verbose-output",
				"Print the contents of all the public " +=20
				"attributes of the reflection information " +
				"classes.");
			AddOption (flattenHierarchy,        "flatten-hierarchy",
				"Static members of base types should be " +=20
				"displayed.");
			AddHelpOption ();
		}

		public override void ParseOptions (string[] options)
		{
			base.ParseOptions (options);

			_showAll =3D base.FoundOption (showAll);
			_matchAll =3D base.FoundOption (matchAll);
		}

		public IList Types {
			get {return base.UnmatchedOptions;}
		}

		private bool _matchAll;

		public bool MatchAll {
			get {return _matchAll;}
		}

		// default: true;
		public bool MatchFullName {
			get {
				if (!MatchClassName && !MatchNamespace && !MatchBase &&=20
				    !MatchReturnType)
					return true;
				return MatchAll || base.FoundOption (matchFullName);
			}
		}

		public bool MatchClassName {
			get {
				return MatchAll || base.FoundOption (matchClass);
			}
		}

		public bool MatchNamespace {
			get {
				return MatchAll || base.FoundOption (matchNamespace);
			}
		}

		public bool MatchBase {
			get {
				return MatchAll || base.FoundOption (matchBase);
			}
		}

		public bool MatchReturnType {
			get {
				return MatchAll || base.FoundOption (matchReturnType);
			}
		}

		private bool _showAll;

		public bool ShowAll {
			get {
				return _showAll;
			}
		}

		public bool ShowBase {
			get {
				return ShowAll || base.FoundOption (showBase);
			}
		}

		public bool ShowConstructors {
			get {
				return ShowAll || base.FoundOption (showConstructors);
			}
		}

		public bool ShowEvents {
			get {
				return ShowAll || base.FoundOption (showEvents);
			}
		}

		public bool ShowFields {
			get {
				return ShowAll || base.FoundOption (showFields);
			}
		}

		public bool ShowInterfaces {
			get {
				return ShowAll || base.FoundOption (showInterfaces);
			}
		}

		public bool ShowMethods {
			get {
				return ShowAll || base.FoundOption (showMethods);
			}
		}

		public bool ShowProperties {
			get {
				return ShowAll || base.FoundOption (showProperties);
			}
		}

		public bool ShowTypeProperties {
			get {
				return base.FoundOption (showTypeProperties);
			}
		}

		public bool ShowInheritedMembers {
			get {
				return base.FoundOption (showInheritedMembers);
			}
		}

		public bool ShowNonPublic {
			get {
				return base.FoundOption (showNonPublic);
			}
		}

		public bool ShowMonoBroken {
			get {
				return base.FoundOption (showMonoBroken);
			}
		}

		public bool FlattenHierarchy {
			get {
				return base.FoundOption (flattenHierarchy);
			}
		}

		public bool VerboseOutput {
			get {
				return base.FoundOption (verboseOutput);
			}
		}

		private static string[] GetDefaultAssemblies ()
		{
			Assembly[] assemblies =3D AppDomain.CurrentDomain.GetAssemblies ();

			string sysdir =3D null;

			foreach (Assembly a in assemblies) {
				string codebase =3D a.CodeBase;
				if (codebase.EndsWith ("corlib.dll")) {
					sysdir =3D codebase.Substring (0, codebase.LastIndexOf ("/"));
					break;
				}
			}

			return Directory.GetFiles (new Uri (sysdir).LocalPath, "*.dll");
		}

		public ICollection Assemblies {
			get {
				string o =3D base.FoundOptionValue (onlyAssemblies);
				string a =3D base.FoundOptionValue (addAssemblies);
				ArrayList r =3D new ArrayList ();

				if (o =3D=3D null) {
					r.AddRange (GetDefaultAssemblies ());
				}
				else {
					r.AddRange (o.Split (Path.PathSeparator));
				}

				if (a !=3D null)
					r.AddRange (a.Split (Path.PathSeparator));

				return r;
			}
		}

		public override string OptionsHelp {
			get {
				StringBuilder sb =3D new StringBuilder ();
				TextGrouper tg0 =3D new TextGrouper ();
				TextGrouper tg4 =3D new TextGrouper (4, 80, 0);
				sb.Append (
					"Prints out type information\n" +
					"\n" +
					"Usage: " + ProgramName + " [options] <types>\n" +
					"\n" +
					"Where [options] can include:\n");
				sb.Append (base.OptionsHelp);
				sb.Append (
					"\n" +=20
					tg0.Group (
						"<assembly-list> is a `" + Path.PathSeparator + "'-delimited list.  "=
 +=20
						"For example, `" +=20
						String.Format ("foo{0}bar{0}baz",=20
							Path.PathSeparator) + "' is a valid list.\n") +
					"\n" +
					tg0.Group (
						"<types> is interpreted as a regular expression.  As regular expressi=
on " +=20
						"meta-characters are seldom used in class names, specifying a type na=
me " +
						"looks for all types that have the specified type name as a substring=
.") +
					"\n\n"
					);
				sb.Append ("The default assemblies are:\n");
				foreach (string s in GetDefaultAssemblies ()) {
					sb.Append (String.Format ("  {0}\n", s));
				}
				sb.Append ("\n");
				sb.Append (String.Format (
					"Examples:\n" +
					"  {0} Type\n", ProgramName));
				sb.Append (String.Format ("    {0}", tg4.Group ("Finds all types that h=
ave `Type' (case-sensitive) as part of their name.")));
				sb.Append (String.Format (
						"\n\n" +
						"  {0} [Tt][Yy][Pp][Ee]\n", ProgramName));
				sb.Append (String.Format ("    {0}", tg4.Group ("Finds all types that h=
ave `Type' (case-insensitive) as part of their name.")));
				sb.Append (String.Format (
						"\n\n" +
						"  {0} -A my-assembly.dll MyType\n", ProgramName));
				sb.Append (String.Format ("    {0}", tg4.Group ("Finds all types that h=
ave `MyType' as part of their name within the assembly `my-assembly'.")));
				sb.Append (String.Format (
						"\n\n" +
						"  {0} -SKt MyType\n", ProgramName));
				sb.Append (String.Format ("    {0}", tg4.Group ("Find all types that ha=
ve `MyType' as part of their name, and for those types show all information=
 (-S) including information Mono generates exceptions for (-K) and show the=
 values of the public attributes of the System.Type object for the type."))=
);
				return sb.ToString ();
			}
		}
	}

	public class ConsoleOutput {

		private static void TraceStringArray (string message, IEnumerable content=
s)
		{
			Trace.WriteLine (message);
			foreach (string s in contents) {
				Trace.WriteLine ("  " + s);
			}
		}

		public static void Main (string[] args)
		{
			TypeIntrospectorOptions options =3D new TypeIntrospectorOptions ();

			try {
				options.ParseOptions (args);
			} catch (Exception e) {
				Console.WriteLine (e.Message);
				Console.WriteLine ("See `{0} --help' for more information", ProgramOpti=
ons.ProgramName);
				// Console.WriteLine ("** Full Message continues:\n" + e);
				return;
			}

			if (options.FoundHelp) {
				Console.WriteLine (options.OptionsHelp);
				return;
			}

			if (options.Types.Count =3D=3D 0) {
				Console.WriteLine ("No types specified.");
				Console.WriteLine ("See `{0} --help' for more information", ProgramOpti=
ons.ProgramName);
				return;
			}

			TraceStringArray ("Search Assemblies: ", options.Assemblies);
			TraceStringArray ("Search for Types: ", options.Types);

			TypeLoader loader =3D new TypeLoader (options.Assemblies);
			loader.MatchBase =3D options.MatchBase;
			loader.MatchFullName =3D options.MatchFullName;
			loader.MatchClassName =3D options.MatchClassName;
			loader.MatchNamespace =3D options.MatchNamespace;
			loader.MatchMethodReturnType =3D options.MatchReturnType;

			TypeDisplayer p =3D new VerboseTreeTypeDisplayer (Console.Out);
			p.VerboseOutput =3D options.VerboseOutput;
			p.ShowBase =3D options.ShowBase;
			p.ShowConstructors =3D options.ShowConstructors;
			p.ShowEvents =3D options.ShowEvents;
			p.ShowFields =3D options.ShowFields;
			p.ShowInterfaces =3D options.ShowInterfaces;
			p.ShowMethods =3D options.ShowMethods;
			p.ShowProperties =3D options.ShowProperties;
			p.ShowTypeProperties =3D options.ShowTypeProperties;
			p.ShowInheritedMembers =3D options.ShowInheritedMembers;
			p.ShowNonPublic =3D options.ShowNonPublic;
			p.ShowMonoBroken =3D options.ShowMonoBroken;
			p.FlattenHierarchy =3D options.FlattenHierarchy;

			foreach (string t in options.Types) {
				try {
					ICollection typesFound =3D loader.LoadTypes (t);
					if (typesFound.Count > 0)
						foreach (Type type in loader.LoadTypes(t))
							p.Parse (type);
					else
						Console.WriteLine ("Unable to find type `{0}'.", t);
				} catch (Exception e) {
					Console.WriteLine ("Unable to parse type `{0}': {1}.", t, e.ToString()=
);
				}
			}
		}
	}
}


--=-4+k6PhhG0PrO0BNyBn9N--