in src/RefasmerExe/Program.cs [76:241]
public static int Main(string[] args)
{
var inputs = new List<string>();
var operation = Operation.MakeRefasm;
var verbosity = LogLevel.Warning;
var showHelp = false;
var quiet = false;
var continueOnErrors = false;
var fileListAttr = new Dictionary<string, string>();
var options = new OptionSet
{
{ "v", "increase verbosity", v => { if (v != null && verbosity > LogLevel.Trace) verbosity--; } },
{ "q|quiet", "be quiet", v => quiet = v != null },
{ "h|?|help", "show help", v => showHelp = v != null },
{ "c|continue", "continue on errors", v => continueOnErrors = v != null },
{ "O|outputdir=", "set output directory", v => _outputDir = v },
{ "o|output=", "set output file, for single file only", v => _outputFile = v },
{ "r|refasm", "make reference assembly, default action", v => { if (v != null) operation = Operation.MakeRefasm; } },
{ "w|overwrite", "overwrite source files", v => _overwrite = v != null },
{ "p|public", "drop non-public types even with InternalsVisibleTo", v => _public = v != null },
{ "i|internals", "import public and internal types", v => _internals = v != null },
{ "all", "ignore visibility and import all", v => _all = v != null },
{ "omit-non-api-members=", "omit private members and types not participating in the public API (will preserve the empty vs non-empty struct semantics, but might affect unmanaged struct constraint)", x => _omitNonApiMembers = string.Equals(x, "true", StringComparison.OrdinalIgnoreCase) },
{ "m|mock", "make mock assembly instead of reference assembly", p => _makeMock = p != null },
{ "n|noattr", "omit reference assembly attribute", p => _omitReferenceAssemblyAttr = p != null },
{ "l|list", "make file list xml", v => { if (v != null) operation = Operation.MakeXmlList; } },
{ "a|attr=", "add FileList tag attribute", v => AddFileListAttr(v, fileListAttr) },
{ "g|globs", "expand globs internally: ?, *, **", p => _expandGlobs = p != null },
{ "<>", "one or more input files", v => inputs.Add(v) },
};
try
{
options.Parse(args);
}
catch (InvalidOptionException e)
{
Console.Error.WriteLine(e.Message);
return 1;
}
catch (Exception e)
{
Console.Error.WriteLine($"{e}");
return 1;
}
if (quiet)
verbosity = LogLevel.None;
if (showHelp || args.Length == 0)
{
var selfName = Path.GetFileName(Environment.GetCommandLineArgs()[0]);
Console.Out.WriteLine($"Usage: {selfName} [options] <dll> [<**/*.dll> ...]");
Console.Out.WriteLine("Options:");
options.WriteOptionDescriptions(Console.Out);
return 0;
}
if (!string.IsNullOrEmpty(_outputFile) && inputs.Count > 1)
{
Console.Error.WriteLine("Output file should not be specified for many inputs");
return 2;
}
if (!_all && _omitNonApiMembers == null)
{
Console.Error.WriteLine("Either specify --all to emit all private types, or set --omit-non-api-members to either true or false.");
return 2;
}
_logger = new LoggerBase(new VerySimpleLogger(Console.Error, verbosity));
try
{
_logger.Trace?.Invoke($"Program arguments: {string.Join(" ", args)}");
// Apply input globbing
var dirCurrent = new DirectoryInfo(Environment.CurrentDirectory);
var inputsExpanded = inputs.SelectMany(input => ExpandInput(input, dirCurrent, _logger)).OrderBy(t => t.Path, StringComparer.OrdinalIgnoreCase).ToImmutableArray();
// Re-check for the second time, after expanding globs
if (!string.IsNullOrEmpty(_outputFile) && inputs.Count > 1)
{
Console.Error.WriteLine("Output file should not be specified for many inputs");
return 2;
}
XmlTextWriter? xmlWriter = null;
if (operation == Operation.MakeXmlList)
{
xmlWriter = !string.IsNullOrEmpty(_outputFile)
? new XmlTextWriter(_outputFile, Encoding.UTF8)
: new XmlTextWriter(Console.Out);
xmlWriter.Formatting = Formatting.Indented;
xmlWriter.WriteStartDocument();
xmlWriter.WriteStartElement("FileList");
foreach (var kv in fileListAttr)
xmlWriter.WriteAttributeString(kv.Key, kv.Value);
}
_logger.Info?.Invoke($"Processing {inputs.Count} assemblies");
for (var nInput = 0; nInput < inputsExpanded.Length; nInput++)
{
var input = inputsExpanded[nInput];
_logger.Info?.Invoke($"Processing {input.Path}");
using(_logger.WithLogPrefix($"[{Path.GetFileName(input.RelativeForOutput)}]"))
{
try
{
switch (operation)
{
case Operation.MakeRefasm:
MakeRefasm(input);
break;
case Operation.MakeXmlList:
WriteAssemblyToXml(input, xmlWriter!);
break;
default:
throw new ArgumentOutOfRangeException();
}
}
catch (Exception e)
{
_logger.Error?.Invoke(e.Message);
if (continueOnErrors)
continue;
if (nInput < inputsExpanded.Length - 1) // When doing multiple files, let user know some might be left undone
_logger.Error?.Invoke($"Aborted on first error, {inputsExpanded.Length - nInput + 1:N0} files left unprocessed; pass “--continue” to try them anyway");
return 1;
}
}
}
if (xmlWriter != null)
{
xmlWriter.WriteEndElement();
xmlWriter.WriteEndDocument();
xmlWriter.Close();
}
_logger.Info?.Invoke("All done");
return 0;
}
catch (Exception e)
{
_logger.Error?.Invoke($"{e}");
_logger.Error?.Invoke("ABORTED"); // When doing multiple files, let user know some might be left undone
return 1;
}
}