public static int Main()

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;
        }
    }