Hi all,

Attached to this email you'll find the latest
version of the ILASM task as well as a proposal
version of the ILDASM task.

Let me know,
j3d.


----------------------------------------
Giuseppe Greco

::agamura::

phone:  +41 (0)91 604 67 65
mobile: +41 (0)76 390 60 32
email:  [EMAIL PROTECTED]
web:    www.agamura.com
----------------------------------------
// NAnt - A .NET build tool
// Copyright (C) 2001-2002 Gerry Shaw
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
// Giuseppe Greco ([EMAIL PROTECTED])

using System.IO;

using NAnt.Core;
using NAnt.Core.Attributes;
using NAnt.Core.Tasks;
using NAnt.Core.Types;
using NAnt.Core.Util;

namespace NAnt.DotNet.Tasks {
    /// <summary>
    /// Compiles ILASM programs.
    /// </summary>
    /// <example>
    ///   <para>Compiles <c>helloworld.il</c> to <c>helloworld.exe</c>.</para>
    ///   <code>
    ///     <![CDATA[
    /// <ilasm target="exe" output="helloworld.exe" debug="true">
    ///     <sources>
    ///         <include name="helloworld.il" />
    ///     </sources>
    /// </ilasm>
    ///     ]]>
    ///   </code>
    /// </example>
    [TaskName("ilasm")]
    [ProgramLocation(LocationType.FrameworkDir)]
    public class IlasmTask : ExternalProgramBase {
#region Private Instance Fields
        private bool _clock;
        private bool _debug;
        private bool _error;
        private bool _forceRebuild;
        private bool _listing;
        private int _alignment;
        private int _base;
        private int _flags;
        private int _subsystem;
        private string _target;
        private string _keySource;
        private FileInfo _keyFile;
        private FileInfo _outputFile;
        private FileInfo _resourceFile;
        private FileSet _sources;
        private string _options;
#endregion Private Instance Fields

#region Public Instance Properties
        /// <summary>
        /// Specifies whether or not the compiler should measure and report
        /// the compilation times.
        /// </summary>
        /// <value>
        /// <see langword="true" /> if the compilation times should be
        /// measured and reported; otherwise, <see langword="false" />. The
        /// default is <see langword="false" />.
        /// </value>
        /// <remarks>
        /// <para>
        /// Corresponds to the <c>/CLOCK</c> flag.
        /// </para>
        /// </remarks>
        [TaskAttribute("clock")]
        [BooleanValidator()]
        public bool Clock {
            get { return _clock; }
            set { _clock = value; }
        }

        /// <summary>
        /// Specifies whether or not the compiler should generate debug
        /// information.
        /// </summary>
        /// <value>
        /// <see langword="true" /> if debug information should be generated;
        /// otherwise, <see langword="false" />. The default is
        /// <see langword="false" />.
        /// </value>
        /// <remarks>
        /// <para>
        /// Corresponds to the <c>/DEBUG</c> flag.
        /// </para>
        /// </remarks>
        [TaskAttribute("debug")]
        [BooleanValidator()]
        public bool Debug {
            get { return _debug; }
            set { _debug = value; }
        }

        /// <summary>
        /// Specifies whether or not the compiler should attempt to create a
        /// PE file even if compilation errors have been reported.
        /// </summary>
        /// <value>
        /// <see langword="true" /> if a PE file has to be created even if
        /// compilation errors have been reported; otherwise,
        /// <see langword="false" />. The default is <see langword="false" />.
        /// </value>
        /// <remarks>
        /// <para>
        /// Corresponds to the <c>/ERROR</c> flag.
        /// </para>
        /// </remarks>
        [TaskAttribute("error")]
        [BooleanValidator()]
        public bool Error {
            get { return _error; }
            set { _error = value; }
        }

        /// <summary>
        /// Instructs NAnt to recompile the output file regardless of the file
        /// timestamps.
        /// </summary>
        /// <value>
        /// <see langword="true" /> if the output file should be recompiled
        /// regardless of its timestamps; otherwise <see langword="false" />.
        /// The default is <see langword="false" />.
        /// </value>
        [TaskAttribute("rebuild")]
        [BooleanValidator()]
        public bool ForceRebuild {
            get { return _forceRebuild; }
            set { _forceRebuild = value; }
        }

        /// <summary>
        /// Specifies whether or not the compiler should type a formatted
        /// listing of the compilation result.
        /// </summary>
        /// <value>
        /// <see langword="true" /> if a formatted listing of the compilation
        /// result should be typed; otherwise, <see langword="false" />. The
        /// default is <see langword="false" />.
        /// </value>
        /// <remarks>
        /// <para>
        /// Corresponds to the <c>/LISTING</c> flag.
        /// </para>
        /// </remarks>
        [TaskAttribute("listing")]
        [BooleanValidator()]
        public bool Listing {
            get { return _listing; }
            set { _listing = value; }
        }

        /// <summary>
        /// Instructs the compiler to set the <i>FileAlignment</i> value in
        /// the PE header.
        /// </summary>
        /// <value>
        /// An <see cref="System.Int32" /> that represents the <i>FileAlignment</i>
        /// value to set in the PE header. The value must be a power of 2, in
        /// range from 512 to 65536.
        /// </value>
        /// <remarks>
        /// <para>
        /// Corresponds to the <c>/ALIGNMENT</c> flag.
        /// </para>
        /// </remarks>
        [TaskAttribute("alignment")]
        [Int32Validator()]
        public int Alignment {
            get { return _alignment; }
            set { _alignment = value; }
        }

        /// <summary>
        /// Instructs the compiler to set the <i>ImageBase</i> value in
        /// the PE header.
        /// </summary>
        /// <value>
        /// A <see cref="System.Int32" /> that represents the <i>ImageBase</i>
        /// value to set in the PE header.
        /// </value>
        /// <remarks>
        /// <para>
        /// Corresponds to the <c>/BASE</c> flag.
        /// </para>
        /// </remarks>
        [TaskAttribute("base")]
        [Int32Validator()]
        public int Base {
            get { return _base; }
            set { _base = value; }
        }

        /// <summary>
        /// Instructs the compiler to set the <i>Flags</i> value in the CLR
        /// header.
        /// </summary>
        /// <value>
        /// An <see cref="System.Int32" /> that represents the <i>Flags</i>
        /// value to set in the CLR header. The most frequently value are 1
        /// (pre-IL code) and 2 (mixed code). The third bit indicating that
        /// the PE file is strong signed, is ignored.
        /// </value>
        /// <remarks>
        /// <para>
        /// Corresponds to the <c>/FLAGS</c> flag.
        /// </para>
        /// </remarks>
        [TaskAttribute("flags")]
        [Int32Validator()]
        public int Flags {
            get { return _flags; }
            set { _flags = value; }
        }

        /// <summary>
        /// Instructs the compiler to set the <i>Subsystem</i> value in the PE
        /// header.
        /// </summary>
        /// <value>
        /// An <see cref="System.Int32" /> that represents the <i>Subsystem</i>
        /// value to set in the PE header. The most frequently value are 3
        /// (console application) and 2 (GUI application).
        /// </value>
        /// <remarks>
        /// <para>
        /// Corresponds to the <c>/SUBSYSTEM</c> flag.
        /// </para>
        /// </remarks>
        [TaskAttribute("subsystem")]
        [Int32Validator()]
        public int Subsystem {
            get { return _subsystem; }
            set { _subsystem = value; }
        }

        /// <summary>
        /// Specifies which output type should be generated.
        /// </summary>
        /// <value>
        /// A <see cref="System.String" /> that contains the target type.
        /// Possible values are <c>dll</c> and <c>exe</c>.
        /// </value>
        /// <remarks>
        /// <para>
        /// Corresponds to the <c>/OUTPUT</c> flag.
        /// </para>
        /// </remarks>
        [TaskAttribute("target", Required=true)]
        [StringValidator(AllowEmpty=false)]
        public string Target  {
            get { return _target; }
            set { _target = StringUtils.ConvertEmptyToNull(value); }
        }

        /// <summary>
        /// Instructs the compiler to generate a strong signature of the PE
        /// file.
        /// </summary>
        /// <value>
        /// A <see cref="System.String" /> that contains the private
        /// encryption key.
        /// </value>
        /// <remarks>
        /// <para>
        /// Corresponds to the <c>/KEY=<![CDATA[@<]]>keysource<![CDATA[>]]></c>
        /// flag.
        /// </para>
        /// </remarks>
        [TaskAttribute("keysource")]
        public string KeySource {
            get { return _keySource; }
            set { _keySource = value; }
        }

        /// <summary>
        /// Instructs the compiler to generate a strong signature of the PE
        /// file.
        /// </summary>
        /// <value>
        /// A <see cref="System.IO.FileInfo" /> that represents the file
        /// containing the private encryption key.
        /// </value>
        /// <remarks>
        /// <para>
        /// Corresponds to the <c>/KEY=<![CDATA[<]]>keyfile<![CDATA[>]]></c>
        /// flag.
        /// </para>
        /// </remarks>
        [TaskAttribute("keyfile")]
        public FileInfo KeyFile {
            get { return _keyFile; }
            set { _keyFile = value; }
        }

        /// <summary>
        /// Specifies the name of the output file created by the compiler.
        /// </summary>
        /// <value>
        /// A <see cref="System.IO.FileInfo" /> that represents the name of
        /// the output file.
        /// </value>
        /// <remarks>
        /// <para>
        /// Corresponds to the <c>/OUTPUT</c> flag.
        /// </para>
        /// </remarks>
        [TaskAttribute("output")]
        public FileInfo OutputFile {
            get { return _outputFile; }
            set { _outputFile = value; }
        }

        /// <summary>
        /// Instructs the compiler to link the specified unmanaged resource
        /// file into the resulting PE file.
        /// </summary>
        /// <value>
        /// A <see cref="System.IO.FileInfo" /> that represents the unmanaged
        /// resource file to link.
        /// </value>
        /// <remarks>
        /// <para>
        /// Corresponds to the <c>/RESOURCE</c> flag.
        /// </para>
        /// </remarks>
        [TaskAttribute("resourcefile")]
        public FileInfo ResourceFile {
            get { return _resourceFile; }
            set { _resourceFile = value; }
        }

        /// <summary>
        /// Specifies the set of source files to compile.
        /// </summary>
        /// <value>
        /// A <see cref="NAnt.Core.Types.FileSet" /> that represents the set
        /// of source files to compile.
        /// </value>
        [BuildElement("sources", Required=true)]
        public FileSet Sources {
            get { return _sources; }
            set { _sources = value; }
        }
#endregion Public Instance Properties

#region Public Instance Methods
        /// <summary>
        /// Gets the command-line arguments for the external program.
        /// </summary>
        /// <value>
        /// A <see cref="System.String" /> that contains the command-line
        /// arguments for the external program.
        /// </value>
        public override string ProgramArguments {
            get { return _options; }
        }
#endregion Public Instance Methods

#region Protected Instance Methods
        /// <summary>
        /// Compiles the sources.
        /// </summary>
        protected override void ExecuteTask() {
            if (NeedsCompiling()) {
                //
                // ensure base directory is set, even if fileset has not been
                // initialized in build file
                //
                if (Sources.BaseDirectory == null) {   
                    Sources.BaseDirectory = new DirectoryInfo(Project.BaseDirectory);
                }

                Log(Level.Info, LogPrefix + "Compiling {0} files to '{1}'.",
                    Sources.FileNames.Count, OutputFile.FullName);

                //
                // set command-line arguments for the ILASM compiler
                //
                WriteOptions();

                //
                // call base class to do the work
                //
                base.ExecuteTask();
            }
        }
#endregion Protected Instance Methdos

#region Private Instance Methods
        /// <summary>
        /// Writes the compiler options.
        /// </summary>
        private void WriteOptions() {
            StringWriter writer = new StringWriter();

            try {
                //
                // always suppress logo and copyright statements
                //
                WriteOption(writer, "NOLOGO");

                //
                // suppress reporting compilation progress
                // unless Verbose is true
                //
                if (!Verbose) {
                    WriteOption(writer, "QUIET");
                }

                if (Clock) {
                    WriteOption(writer, "CLOCK");
                }

                if (Debug) {
                    WriteOption(writer, "DEBUG");
                }

                if (Error) {
                    WriteOption(writer, "ERROR");
                }

                if (Listing) {
                    WriteOption(writer, "LISTING");
                }

                if (Alignment > 0) {
                    WriteOption(writer, "ALIGNMENT", Alignment.ToString());
                }

                if (Base > 0) {
                    WriteOption(writer, "BASE", Base.ToString());
                }

                if (Flags > 0) {
                    WriteOption(writer, "FLAGS", Flags.ToString());
                }

                if (Subsystem > 0) {
                    WriteOption(writer, "SUBSYSTEM", Subsystem.ToString());
                }

                if (Target != null) {
                    WriteOption(writer, Target.ToUpper());
                }

                if (KeySource != null) {
                    WriteOption(writer, "KEY", "@" + KeySource);
                }

                if (KeyFile != null) {
                    WriteOption(writer, "KEY", KeyFile.FullName);
                }

                if (OutputFile != null) {
                    WriteOption(writer, "OUTPUT", OutputFile.FullName);
                }

                if (ResourceFile != null) {
                    WriteOption(writer, "RESOURCE", ResourceFile.FullName);
                }

                foreach (string fileName in Sources.FileNames) {
                    writer.Write("\"" + fileName + "\"");
                }

                _options = writer.ToString();
            } finally {
                //
                // close the StringWriter and the underlying stream
                //
                writer.Close();
            }
        }

        /// <summary>
        /// Writes an option using the default output format.
        /// </summary>
        /// <param name="writer">
        /// The <see cref="StringWriter" /> to which the compiler options should
        /// be written.
        ///</param>
        /// <param name="name">
        /// A <see cref="System.String" /> that contains the name of the
        /// option which should be passed to the compiler.
        /// </param>
        private void WriteOption(StringWriter writer, string name) {
            writer.Write("/{0} ", name);
        }

        /// <summary>
        /// Writes an option and its value using the default output format.
        /// </summary>
        /// <param name="writer">
        /// The <see cref="StringWriter" /> to which the compiler options should
        /// be written.
        /// </param>
        /// <param name="name">
        /// A <see cref="System.String" /> that contains the name of the
        /// option which should be passed to the compiler.
        /// </param>
        /// <param name="arg">
        /// A <see cref="System.String" /> that contains the value of the
        /// option which should be passed to the compiler.
        /// </param>
        private void WriteOption(StringWriter writer, string name, string arg) {
            //
            // always quote arguments
            //
            writer.Write("\"/{0}={1}\" ", name, arg);
        }

        /// <summary>
        /// Determines whether or not compilation is needed.
        /// </summary>
        /// <returns>
        /// <see langword="true" /> if compilation is needed; otherwise,
        /// <see langword="false" />.
        /// </returns>
        private bool NeedsCompiling() {
            if (ForceRebuild) {
                Log(Level.Verbose, LogPrefix +
                    "'rebuild' attribute set to true, recompiling.");

                return true;
            }

            //
            // check if output file already exists
            //
            if (!OutputFile.Exists) {
                return true;
            }

            //
            // check if sources have been updated
            //
            string fileName = FileSet.FindMoreRecentLastWriteTime(
                Sources.FileNames, OutputFile.LastWriteTime);

            if (fileName != null) {
                Log(Level.Verbose, LogPrefix +
                    "'{0}' has been updated, recompiling.", fileName);

                return true;
            }

            //
            // check if unmanaged resources have been updated
            //
            if (ResourceFile != null) {
                fileName = FileSet.FindMoreRecentLastWriteTime(
                    ResourceFile.FullName, OutputFile.LastWriteTime);

                if (fileName != null) {
                    Log(Level.Verbose, LogPrefix +
                        "'{0}' has been updated, recompiling.", fileName);

                    return true;
                }
            }

            //
            // check if strong name signature has been updated
            //
            if (KeyFile != null) {
                fileName = FileSet.FindMoreRecentLastWriteTime(
                    KeyFile.FullName, OutputFile.LastWriteTime);

                if (fileName != null) {
                    Log(Level.Verbose, LogPrefix +
                        "'{0}' has been updated, recompiling.", fileName);

                    return true;
                }
            }

            //
            // compilation not needed
            //
            return false;
        }
#endregion Private Instance Methods
    }
}
// NAnt - A .NET build tool
// Copyright (C) 2001-2002 Gerry Shaw
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
// Giuseppe Greco ([EMAIL PROTECTED])

using System.IO;

using NAnt.Core;
using NAnt.Core.Attributes;
using NAnt.Core.Tasks;
using NAnt.Core.Types;
using NAnt.Core.Util;

namespace NAnt.DotNet.Tasks {
    /// <summary>
    /// Disassembles any portable executable (PE) file that contains
    /// intermediate language (IL) code.
    /// </summary>
    /// <example>
    ///   <para>Disassembles <c>helloworld.exe</c> to <c>helloworld.il</c>.</para>
    ///   <code>
    ///     <![CDATA[
    /// <ildasm input="helloworld.exe" output="helloworld.il" />
    ///     ]]>
    ///   </code>
    /// </example>
    [TaskName("ildasm")]
    [ProgramLocation(LocationType.FrameworkDir)]
    public class IldasmTask : ExternalProgramBase {
#region Private Instance Fields
        private bool _all;
        private bool _bytes;
        private bool _forceRebuild;
        private bool _header;
        private bool _lineNumbers;
        private bool _noIL;
        private bool _publicOnly;
        private bool _quoteAllNames;
        private bool _rawExceptionHandling;
        private bool _source;
        private bool _tokens;
        private bool _unicode;
        private bool _utf8;
        private string _item;
        private string _visibility;
        private FileInfo _inputFile;
        private FileInfo _outputFile;
        private string _options;
#endregion Private Instance Fields

#region Public Instance Properties
        /// <summary>
        /// Specifies whether or not the disassembler should combine the
        /// <c>/HEADER</c>, <c>/BYTE</c>, and <c>TOKENS</c> options.
        /// </summary>
        /// <value>
        /// <see langword="true" /> if the disassembler should combine the
        /// <c>/HEADER</c>, <c>/BYTE</c>, and <c>TOKENS</c> options;
        /// otherwise, <see langword="false" />. The default is
        /// <see langword="false" />.
        /// </value>
        /// <remarks>
        /// <para>
        /// Corresponds to the <c>/ALL</c> flag.
        /// </para>
        /// </remarks>
        [TaskAttribute("all")]
        [BooleanValidator()]
        public bool All {
            get { return _all; }
            set { _all = value; }
        }

        /// <summary>
        /// Specifies whether or not the disassembler should generate the
        /// IL stream bytes (in hexadecimal notation) as instruction comments.
        /// </summary>
        /// <value>
        /// <see langword="true" /> if the IL stream bytes should be generated
        /// as instruction comments; otherwise, <see langword="false" />. The
        /// default is <see langword="false" />.
        /// </value>
        /// <remarks>
        /// <para>
        /// Corresponds to the <c>/BYTE</c> flag.
        /// </para>
        /// </remarks>
        [TaskAttribute("bytes")]
        [BooleanValidator()]
        public bool Bytes {
            get { return _bytes; }
            set { _bytes = value; }
        }

        /// <summary>
        /// Instructs NAnt to rebuild the output file regardless of the file
        /// timestamps.
        /// </summary>
        /// <value>
        /// <see langword="true" /> if the output file should be rebuilt
        /// regardless of its timestamps; otherwise <see langword="false" />.
        /// The default is <see langword="false" />.
        /// </value>
        [TaskAttribute("rebuild")]
        [BooleanValidator()]
        public bool ForceRebuild {
            get { return _forceRebuild; }
            set { _forceRebuild = value; }
        }

        /// <summary>
        /// Specifies whether or not the disassembler should include PE header
        /// information and runtime header information in the output.
        /// </summary>
        /// <value>
        /// <see langword="true" /> if PE header information and runtime header
        /// information should be included in the output; otherwise,
        /// <see langword="false" />. The default is <see langword="false" />.
        /// </value>
        /// <remarks>
        /// <para>
        /// Corresponds to the <c>/HEADER</c> flag.
        /// </para>
        /// </remarks>
        [TaskAttribute("header")]
        [BooleanValidator()]
        public bool Header {
            get { return _header; }
            set { _header = value; }
        }

        /// <summary>
        /// Specifies the PE file to disassemble.
        /// </summary>
        /// <value>
        /// A <see cref="System.IO.FileInfo" /> that represents the PE file
        /// to disassemble.
        /// </value>
        [TaskAttribute("input", Required=true)]
        public FileInfo InputFile {
            get { return _inputFile; }
            set { _inputFile = value; }
        }

        /// <summary>
        /// Specifies whether or not the disassembler should include
        /// references to original source lines.
        /// </summary>
        /// <value>
        /// <see langword="true" /> if references to original source lines
        /// should be included; otherwise, <see langword="false" />. The
        /// default is <see langword="false" />.
        /// </value>
        /// <remarks>
        /// <para>
        /// Corresponds to the <c>/LINENUM</c> flag.
        /// </para>
        /// </remarks>
        [TaskAttribute("linenumbers")]
        [BooleanValidator()]
        public bool LineNumbers {
            get { return _lineNumbers; }
            set { _lineNumbers = value; }
        }

        /// <summary>
        /// Specifies whether or not the disassembler should suppress ILASM
        /// code output.
        /// </summary>
        /// <value>
        /// <see langword="true" /> if ILASM code output should be suppresses;
        /// otherwise, <see langword="false" />. The default is
        /// <see langword="false" />.
        /// </value>
        /// <remarks>
        /// <para>
        /// Corresponds to the <c>/NOIL</c> flag.
        /// </para>
        /// </remarks>
        [TaskAttribute("noil")]
        [BooleanValidator()]
        public bool NoIL {
            get { return _noIL; }
            set { _noIL = value; }
        }

        /// <summary>
        /// Specifies whether or not the disassembler should disassemble
        /// public items only. This is a shortcut for <c>visibility="pub"</c>.
        /// </summary>
        /// <value>
        /// <see langword="true" /> if public itmes only should be
        /// disassembled; otherwise, <see langword="false" />. The default is
        /// <see langword="false" />.
        /// </value>
        /// <remarks>
        /// <para>
        /// Corresponds to the <c>/PUBONLY</c> flag.
        /// </para>
        /// </remarks>
        [TaskAttribute("publiconly")]
        [BooleanValidator()]
        public bool PublicOnly {
            get { return _publicOnly; }
            set { _publicOnly = value; }
        }

        /// <summary>
        /// Specifies whether or not the disassembler should enclose all names
        /// in single quotation marks. By default, only names that don't match
        /// the ILASM definition of a simple name are quoted.
        /// </summary>
        /// <value>
        /// <see langword="true" /> if all names should be enclosed in single
        /// quotation marks; otherwise, <see langword="false" />. The default
        /// is <see langword="false" />.
        /// </value>
        /// <remarks>
        /// <para>
        /// Corresponds to the <c>/QUOTEALLNAMES</c> flag.
        /// </para>
        /// </remarks>
        [TaskAttribute("quoteallnames")]
        [BooleanValidator()]
        public bool QuoteAllNames {
            get { return _quoteAllNames; }
            set { _quoteAllNames = value; }
        }

        /// <summary>
        /// Specifies whether or not the disassembler should generate
        /// structured exception handling clauses in canonical (label) form.
        /// </summary>
        /// <value>
        /// <see langword="true" /> if structured exception handling clauses
        /// should be generated in canonical form; otherwise,
        /// <see langword="false" />. The default is <see langword="false" />.
        /// </value>
        /// <remarks>
        /// <para>
        /// Corresponds to the <c>/RAWEH</c> flag.
        /// </para>
        /// </remarks>
        [TaskAttribute("rawexceptionhandling")]
        [BooleanValidator()]
        public bool RawExceptionHandling {
            get { return _rawExceptionHandling; }
            set { _rawExceptionHandling = value; }
        }

        /// <summary>
        /// Specifies whether or not the disassembler should generate
        /// original source lines as comments.
        /// </summary>
        /// <value>
        /// <see langword="true" /> if original source lines should be
        /// generated as comments; otherwise, <see langword="false" />.
        /// The default is <see langword="false" />.
        /// </value>
        /// <remarks>
        /// <para>
        /// Corresponds to the <c>/SOURCE</c> flag.
        /// </para>
        /// </remarks>
        [TaskAttribute("source")]
        [BooleanValidator()]
        public bool Source {
            get { return _source; }
            set { _source = value; }
        }

        /// <summary>
        /// Specifies whether or not the disassembler should generate metadata
        /// token values as comments.
        /// </summary>
        /// <value>
        /// <see langword="true" /> if metadata token values should be
        /// generated as comments; otherwise, <see langword="false" />. The
        /// default is <see langword="false" />.
        /// </value>
        /// <remarks>
        /// <para>
        /// Corresponds to the <c>/TOKENS</c> flag.
        /// </para>
        /// </remarks>
        [TaskAttribute("tokens")]
        [BooleanValidator()]
        public bool Tokens {
            get { return _tokens; }
            set { _tokens = value; }
        }

        /// <summary>
        /// Specifies whether or not the disassembler should use the UNICODE
        /// encoding when generating the output. The default is ANSI.
        /// </summary>
        /// <value>
        /// <see langword="true" /> if the output should be generated using
        /// the UNICODE encoding; otherwise, <see langword="false" />. The
        /// default is <see langword="false" />.
        /// </value>
        /// <remarks>
        /// <para>
        /// Corresponds to the <c>/UNICODE</c> flag.
        /// </para>
        /// </remarks>
        [TaskAttribute("unicode")]
        [BooleanValidator()]
        public bool Unicode {
            get { return _unicode; }
            set { _unicode = value; }
        }

        /// <summary>
        /// Specifies whether or not the disassembler should use the UTF-8
        /// encoding when generating the output. The default is ANSI.
        /// </summary>
        /// <value>
        /// <see langword="true" /> if the output should be generated using
        /// the UTF-8 encoding; otherwise, <see langword="false" />. The
        /// default is <see langword="false" />.
        /// </value>
        /// <remarks>
        /// <para>
        /// Corresponds to the <c>/UTF8</c> flag.
        /// </para>
        /// </remarks>
        [TaskAttribute("utf8")]
        [BooleanValidator()]
        public bool Utf8 {
            get { return _utf8; }
            set { _utf8 = value; }
        }

        /// <summary>
        /// Instructs the disassembler to disassemble the specified item only.
        /// </summary>
        /// <value>
        /// A <see cref="System.String" /> that specifies the item to
        /// disassemble.
        /// </value>
        /// <remarks>
        /// <para>
        /// Corresponds to the <c>/ITEM</c> flag.
        /// </para>
        /// </remarks>
        [TaskAttribute("item", Required=false)]
        [StringValidator(AllowEmpty=false)]
        public string Item {
            get { return _item; }
            set { _item = value; }
        }

        /// <summary>
        /// Instructs the disassembler to disassemble only the items with the
        /// specified visibility.
        /// </summary>
        /// <value>
        /// A <see cref="System.String" /> that contains the visibility
        /// suboptions. Possible values are <c>PUB</c>, <c>PRI</c>,
        /// <c>FAM</c>, <c>ASM</c>, <c>FAA</c>, <c>FOA</c>, <c>PSC</c>,
        /// or any combination of them separated by <c>+</c>.
        /// </value>
        /// <remarks>
        /// <para>
        /// Corresponds to the <c>/VISIBILITY</c> flag.
        /// </para>
        /// </remarks>
        [TaskAttribute("visibility", Required=false)]
        [StringValidator(AllowEmpty=false)]
        public string Visibility {
            get { return _visibility; }
            set { _visibility = value; }
        }

        /// <summary>
        /// Specifies the name of the output file created by the disassembler.
        /// </summary>
        /// <value>
        /// A <see cref="System.IO.FileInfo" /> that represents the name of
        /// the output file.
        /// </value>
        /// <remarks>
        /// <para>
        /// Corresponds to the <c>/OUT</c> flag.
        /// </para>
        /// </remarks>
        [TaskAttribute("output", Required=true)]
        [StringValidator(AllowEmpty=false)]
        public FileInfo OutputFile {
            get { return _outputFile; }
            set { _outputFile = value; }
        }
#endregion Public Instance Properties

#region Public Instance Methods
        /// <summary>
        /// Gets the command-line arguments for the external program.
        /// </summary>
        /// <value>
        /// A <see cref="System.String" /> that contains the command-line
        /// arguments for the external program.
        /// </value>
        public override string ProgramArguments {
            get { return _options; }
        }
#endregion Public Instance Methods

#region Protected Instance Methods
        /// <summary>
        /// Compiles the sources.
        /// </summary>
        protected override void ExecuteTask() {
            if (NeedsDisassembling()) {
                if (InputFile == null) {
                    throw new BuildException("Disassebler needs an input attribute.");
                }

                Log(Level.Info, LogPrefix + "Disassembling {0} to '{1}'.",
                    InputFile.FullName, OutputFile.FullName);

                //
                // set command-line arguments for the disassembler
                //
                WriteOptions();

                //
                // call base class to do the work
                //
                base.ExecuteTask();
            }
        }
#endregion Protected Instance Methdos

#region Private Instance Methods
        /// <summary>
        /// Writes the disassembler options.
        /// </summary>
        private void WriteOptions() {
            StringWriter writer = new StringWriter();

            try {
                //
                // always direct the output to console
                //
                WriteOption(writer, "TEXT");

                if (All) {
                    WriteOption(writer, "ALL");
                }

                if (Bytes) {
                    WriteOption(writer, "BYTES");
                }

                if (Header) {
                    WriteOption(writer, "HEADER");
                }

                if (LineNumbers) {
                    WriteOption(writer, "LINENUM");
                }

                if (NoIL) {
                    WriteOption(writer, "NOIL");
                }

                if (PublicOnly) {
                    WriteOption(writer, "PUBONLY");
                }

                if (QuoteAllNames) {
                    WriteOption(writer, "QUOTEALLNAMES");
                }

                if (RawExceptionHandling) {
                    WriteOption(writer, "RAWEH");
                }

                if (Source) {
                    WriteOption(writer, "SOURCE");
                }

                if (Tokens) {
                    WriteOption(writer, "TOKENS");
                }

                if (Unicode) {
                    WriteOption(writer, "UNICODE");
                }

                if (Utf8) {
                    WriteOption(writer, "UTF8");
                }

                if (Item != null) {
                    WriteOption(writer, "ITEM", Item);
                }

                if (Visibility != null) {
                    WriteOption(writer, "VISIBILITY", Visibility.ToUpper());
                }

                if (OutputFile != null) {
                    WriteOption(writer, "OUT", OutputFile.FullName);
                }

                if (InputFile != null) {
                    writer.Write("\"" + InputFile.FullName + "\"");
                }

                _options = writer.ToString();
            } finally {
                //
                // close the StringWriter and the underlying stream
                //
                writer.Close();
            }
        }

        /// <summary>
        /// Writes an option using the default output format.
        /// </summary>
        /// <param name="writer">
        /// The <see cref="StringWriter" /> to which the disassembler options
        /// should be written.
        ///</param>
        /// <param name="name">
        /// A <see cref="System.String" /> that contains the name of the
        /// option which should be passed to the disassembler.
        /// </param>
        private void WriteOption(StringWriter writer, string name) {
            writer.Write("/{0} ", name);
        }

        /// <summary>
        /// Writes an option and its value using the default output format.
        /// </summary>
        /// <param name="writer">
        /// The <see cref="StringWriter" /> to which the disassembler options
        /// should be written.
        /// </param>
        /// <param name="name">
        /// A <see cref="System.String" /> that contains the name of the
        /// option which should be passed to the disassembler.
        /// </param>
        /// <param name="arg">
        /// A <see cref="System.String" /> that contains the value of the
        /// option which should be passed to the disassembler.
        /// </param>
        private void WriteOption(StringWriter writer, string name, string arg) {
            //
            // always quote arguments
            //
            writer.Write("\"/{0}={1}\" ", name, arg);
        }

        /// <summary>
        /// Determines whether or not disassembling is needed.
        /// </summary>
        /// <returns>
        /// <see langword="true" /> if disassembling is needed; otherwise,
        /// <see langword="false" />.
        /// </returns>
        private bool NeedsDisassembling() {
            if (ForceRebuild) {
                Log(Level.Verbose, LogPrefix +
                    "'rebuild' attribute set to true, disassembling.");

                return true;
            }

            //
            // check if output file already exists
            //
            if (!OutputFile.Exists) {
                return true;
            }

            //
            // check if the source assembly has been updated
            //
            string fileName = FileSet.FindMoreRecentLastWriteTime(
                InputFile.FullName, OutputFile.LastWriteTime);

            if (fileName != null) {
                Log(Level.Verbose, LogPrefix +
                    "'{0}' has been updated, disassembling.", fileName);

                return true;
            }

            //
            // disassembling not needed
            //
            return false;
        }
#endregion Private Instance Methods
    }
}

Reply via email to