private static int TransformIL()

in src/tools/MakePIAPortableTool/MakePIAPortableTool.cs [117:283]


        private static int TransformIL(string inputFilePath, string outputFile)
        {
            bool isInterface = false;
            Regex mscorlibType = new Regex(@"\[mscorlib\][A-Za-z][A-Za-z\.]+");
            Regex paramCustomAttributeRegex = new Regex(@"^ *.param \[[0-9]+\]$");
            HashSet<string> emittedUnknownTypes = new HashSet<string>();

            using (InputFile inputFile = new InputFile(inputFilePath))
            using (StreamWriter output = new StreamWriter(File.OpenWrite(outputFile)))
            {
                while (true)
                {
                    string inputLine = inputFile.ReadLine();
                    if (inputLine == null)
                        break;


                    if (isInterface)
                    {
                        if (inputLine.Contains(" internalcall"))
                        {
                            inputLine = inputLine.Replace(" internalcall", "");
                        }

                        if (inputLine.Contains(" runtime "))
                        {
                            inputLine = inputLine.Replace(" runtime ", " ");
                        }
                    }

                    if (inputLine == ".assembly extern mscorlib")
                    {
                        if (!IsAssemblyReferenceBody(inputFile))
                        {
                            Error.Emit(Error.Code.BadMscorlibReference, inputFile, "Unexpected text near '.assembly extern mscorlib'. Unable to transform.");
                            return -1;
                        }

                        foreach (var assembly in s_contractAssemblies)
                        {
                            output.Write(".assembly extern ");
                            output.WriteLine(assembly.Item1);
                            output.WriteLine("{");
                            output.WriteLine("  .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A )");
                            output.Write("  .ver ");
                            output.WriteLine(assembly.Item2);
                            output.WriteLine("}");
                        }

                        continue;
                    }
                    else if (inputLine == ".assembly extern stdole")
                    {
                        if (!IsAssemblyReferenceBody(inputFile))
                        {
                            Error.Emit(Error.Code.BadStdoleReference, inputFile, "Unexpected text near '.assembly extern stdole'. Unable to transform.");
                            return -1;
                        }

                        // Drop the stdole reference on the floor. It wasn't actually used.
                        continue;
                    }
                    else if (inputLine.StartsWith("  .publickey = (00 24 00 00 04 80 00 00 94 00 00 00 06 02 00 00", StringComparison.Ordinal))
                    {
                        output.WriteLine("  .custom instance void [System.Runtime]System.Reflection.AssemblyDelaySignAttribute::.ctor(bool)");
                        output.WriteLine("           = { bool(true)}");
                        output.WriteLine("  .custom instance void [System.Runtime]System.Reflection.AssemblySignatureKeyAttribute::.ctor(string, string)");
                        output.WriteLine("           = {string('002400000c800000140100000602000000240000525341310008000001000100613399aff18ef1a2c2514a273a42d9042b72321f1757102df9ebada69923e2738406c21e5b801552ab8d200a65a235e001ac9adc25f2d811eb09496a4c6a59d4619589c69f5baf0c4179a47311d92555cd006acc8b5959f2bd6e10e360c34537a1d266da8085856583c85d81da7f3ec01ed9564c58d93d713cd0172c8e23a10f0239b80c96b07736f5d8b022542a4e74251a5f432824318b3539a5a087f8e53d2f135f9ca47f3bb2e10aff0af0849504fb7cea3ff192dc8de0edad64c68efde34c56d302ad55fd6e80f302d5efcdeae953658d3452561b5f36c542efdbdd9f888538d374cef106acf7d93a4445c3c73cd911f0571aaf3d54da12b11ddec375b3')");
                        output.WriteLine("              string('a5a866e1ee186f807668209f3b11236ace5e21f117803a3143abb126dd035d7d2f876b6938aaf2ee3414d5420d753621400db44a49c486ce134300a2106adb6bdb433590fef8ad5c43cba82290dc49530effd86523d9483c00f458af46890036b0e2c61d077d7fbac467a506eba29e467a87198b053c749aa2a4d2840c784e6d')}");

                        // fall through to outputting the input line
                    }
                    else if (inputLine.Contains("[mscorlib]"))
                    {
                        if (IsIgnoredCustomAttributeLine(inputLine))
                        {
                            SkipCustomAttribute(inputLine, inputFile);
                            continue;
                        }

                        StringBuilder lineBuilder = new StringBuilder();
                        Match match = mscorlibType.Match(inputLine);
                        int nextStartPos = 0;
                        while (match.Success)
                        {
                            lineBuilder.Append(inputLine, nextStartPos, match.Index - nextStartPos);
                            nextStartPos = match.Index + match.Length;

                            string typeName = match.Value.Substring("[mscorlib]".Length);
                            string assemblyName;
                            if (!s_typeToContractAssemblyMap.TryGetValue(typeName, out assemblyName))
                            {
                                if (!emittedUnknownTypes.Contains(typeName))
                                {
                                    emittedUnknownTypes.Add(typeName);
                                    Error.Emit(Error.Code.UnknownType, inputFile, "Unknown type '{0}'. Unable to map to contract assembly.", typeName);
                                }

                                assemblyName = "unknown_assembly";
                            }

                            lineBuilder.Append('[');
                            lineBuilder.Append(assemblyName);
                            lineBuilder.Append(']');
                            lineBuilder.Append(typeName);

                            match = match.NextMatch();
                        }

                        lineBuilder.Append(inputLine, nextStartPos, inputLine.Length - nextStartPos);
                        output.WriteLine(lineBuilder);
                        continue;
                    }
                    else if (paramCustomAttributeRegex.IsMatch(inputLine))
                    {
                        string customAttributeLine = inputFile.TestNextLine(IsIgnoredCustomAttributeLine);
                        if (customAttributeLine != null)
                        {
                            SkipCustomAttribute(customAttributeLine, inputFile);

                            inputFile.SkipBlankLines();

                            // The '.param' directive contains an integer with the custom attribute index. We currently don't have code to rewrite that index, so 
                            // error out if we detect we need such code. If we need to implement this in the future, we could do so by getting a bunch of lines, rewriting them
                            // and then unreading them (InputFile.UnreadLine)
                            string[] problemLines = inputFile.TestNextLines(
                                l1 => paramCustomAttributeRegex.IsMatch(l1),
                                l2 => !IsIgnoredCustomAttributeLine(l2));
                            if (problemLines != null)
                            {
                                Error.Emit(Error.Code.UnsupportedCustomAttribute, inputFile, "Non-ignored custom attribute found after ignored custom attribute. This is not currently supported by this script.");
                            }

                            continue;
                        }
                    }
                    else if (inputLine.StartsWith("// Metadata version: v", StringComparison.Ordinal))
                    {
                        // This line doesn't hurt, but it is slightly confusing since this isn't the metadata version we will use, so strip it.
                        continue;
                    }
                    // Remove 'import' from the interfaces
                    else if (inputLine.StartsWith(".class ", StringComparison.Ordinal))
                    {
                        // Remove '_EventProvider' classes from MS.VS.Interop since they
                        // use ArrayList which is not in netstandard 1.3
                        if (inputLine.Contains("_EventProvider"))
                        {
                            inputLine = "";
                            SkipClass(inputFile);
                        }
                        else
                        {
                            isInterface = inputLine.Contains(" interface");

                            if (inputLine.Contains(" import "))
                            {
                                inputLine = inputLine.Replace(" import ", " ");
                            }
                        }
                    }
                    output.WriteLine(inputLine);
                }
            }

            return Error.HasError ? 1 : 0;
        }