From 79151ebe0f298f1db302cd78daf032967a7eb96b Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 20 Aug 2024 23:29:39 +0800 Subject: [PATCH 1/9] Port genheaders to NetCoreAppToolCurrent --- src/coreclr/inc/genheaders.cs | 231 ----------------- src/coreclr/inc/genheaders/genheaders.cs | 253 +++++++++++++++++++ src/coreclr/inc/genheaders/genheaders.csproj | 9 + 3 files changed, 262 insertions(+), 231 deletions(-) delete mode 100644 src/coreclr/inc/genheaders.cs create mode 100644 src/coreclr/inc/genheaders/genheaders.cs create mode 100644 src/coreclr/inc/genheaders/genheaders.csproj diff --git a/src/coreclr/inc/genheaders.cs b/src/coreclr/inc/genheaders.cs deleted file mode 100644 index 3a39954937357..0000000000000 --- a/src/coreclr/inc/genheaders.cs +++ /dev/null @@ -1,231 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Xml; -using System.Xml.Schema; -using System.IO; - -public class GenerateHeaders { - - public static void Main(string[] args) { - - if (args.Length != 3) { - Console.WriteLine("Usage:genheaders XML-file header-file resource-file"); - return; - } - - ValidateXML(args[0]); - String Message=null; - String SymbolicName=null; - String NumericValue=null; - String tempheaderfile = "temp.h"; - String temprcfile = "temp.rc"; - - StreamWriter HSW=File.CreateText(tempheaderfile); - StreamWriter RSW=File.CreateText(temprcfile); - - int FaciltyUrt=0x13; - int SeveritySuccess=0; - int SeverityError=1; - - int minSR = MakeHresult(SeveritySuccess,FaciltyUrt,0); - int maxSR = MakeHresult(SeveritySuccess,FaciltyUrt,0xffff); - int minHR = MakeHresult(SeverityError,FaciltyUrt,0); - int maxHR = MakeHresult(SeverityError,FaciltyUrt,0xffff); - - PrintLicenseHeader(HSW); - PrintHeader(HSW); - PrintLicenseHeader(RSW); - PrintResourceHeader(RSW); - - XmlTextReader rdr = new XmlTextReader(args[0]); - rdr.WhitespaceHandling = WhitespaceHandling.None; - - while (rdr.Read()) { - - switch (rdr.NodeType) { - - case XmlNodeType.Element: - - if (rdr.Name.ToString() == "HRESULT") { - NumericValue=rdr.GetAttribute("NumericValue"); - } - if (rdr.Name.ToString() == "Message") { - Message = rdr.ReadString(); - } - if (rdr.Name.ToString() == "SymbolicName") { - SymbolicName = rdr.ReadString(); - } - - break; - - case XmlNodeType.EndElement: - if(rdr.Name.ToString() == "HRESULT"){ - - // For CLR Hresult's we take the last 4 digits as the resource strings. - - if ( (NumericValue.StartsWith("0x")) || (NumericValue.StartsWith("0X")) ) { - - String HexResult = NumericValue.Substring(2); - int num = int.Parse(HexResult, System.Globalization.NumberStyles.HexNumber); - - if ((num>minSR) && (num <= maxSR)) { - num = num & 0xffff; - HSW.WriteLine("#define " + SymbolicName + " SMAKEHR(0x" + num.ToString("x") + ")"); - } else if ((num>minHR) && (num <= maxHR)) { - num = num & 0xffff; - HSW.WriteLine("#define " + SymbolicName + " EMAKEHR(0x" + num.ToString("x") + ")"); - } else { - HSW.WriteLine("#define " + SymbolicName + " " + NumericValue ); - } - - - - } else { - HSW.WriteLine("#define " + SymbolicName + " " + NumericValue ); - } - - if (Message != null) { - RSW.Write("\tMSG_FOR_URT_HR(" + SymbolicName + ") "); - RSW.WriteLine(Message); - } - - SymbolicName = null; - NumericValue = null; - Message = null; - } - break; - - } - } - - PrintFooter(HSW); - PrintResourceFooter(RSW); - - HSW.Close(); - RSW.Close(); - - bool AreFilesEqual = false; - - if (File.Exists(args[1])) { - StreamReader sr1 = new StreamReader(tempheaderfile); - StreamReader sr2 = new StreamReader(args[1]); - AreFilesEqual = CompareFiles(sr1, sr2); - sr1.Close(); - sr2.Close(); - } - - if (!AreFilesEqual) { - File.Copy(tempheaderfile, args[1], true); - File.Copy(temprcfile, args[2], true); - } - - if (!File.Exists(args[2])) { - File.Copy(temprcfile, args[2], true); - } - - File.Delete(tempheaderfile); - File.Delete(temprcfile); - } - - private static void ValidateXML (String XMLFile) { - - // Set the validation settings on the XmlReaderSettings object. - XmlReaderSettings settings = new XmlReaderSettings(); - - settings.ValidationType = ValidationType.Schema; - settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema; - - settings.ValidationEventHandler += new ValidationEventHandler (ValidationCallBack); - - // Create the XmlReader object. - XmlReader reader = XmlReader.Create(XMLFile, settings); - - // Parse the file. - - while (reader.Read()) { - } - } - - // Display any validation errors. - private static void ValidationCallBack(object sender, ValidationEventArgs e) { - Console.WriteLine("Validation Error: {0}", e.Message); - Environment.Exit(-1); - } - - private static void PrintLicenseHeader(StreamWriter SW) { - SW.WriteLine("// Licensed to the .NET Foundation under one or more agreements."); - SW.WriteLine("// The .NET Foundation licenses this file to you under the MIT license."); - SW.WriteLine(); - } - - private static void PrintHeader(StreamWriter SW) { - - SW.WriteLine("#ifndef __COMMON_LANGUAGE_RUNTIME_HRESULTS__"); - SW.WriteLine("#define __COMMON_LANGUAGE_RUNTIME_HRESULTS__"); - SW.WriteLine(); - SW.WriteLine("#include "); - SW.WriteLine(); - SW.WriteLine(); - SW.WriteLine("//"); - SW.WriteLine("//This file is AutoGenerated -- Do Not Edit by hand!!!"); - SW.WriteLine("//"); - SW.WriteLine("//Add new HRESULTS along with their corresponding error messages to"); - SW.WriteLine("//corerror.xml"); - SW.WriteLine("//"); - SW.WriteLine(); - SW.WriteLine("#ifndef FACILITY_URT"); - SW.WriteLine("#define FACILITY_URT 0x13"); - SW.WriteLine("#endif"); - SW.WriteLine("#ifndef EMAKEHR"); - SW.WriteLine("#define SMAKEHR(val) MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_URT, val)"); - SW.WriteLine("#define EMAKEHR(val) MAKE_HRESULT(SEVERITY_ERROR, FACILITY_URT, val)"); - SW.WriteLine("#endif"); - SW.WriteLine(); - } - - private static void PrintFooter(StreamWriter SW) { - SW.WriteLine(); - SW.WriteLine(); - SW.WriteLine("#endif // __COMMON_LANGUAGE_RUNTIME_HRESULTS__"); - } - - private static void PrintResourceHeader(StreamWriter SW) { - SW.WriteLine("STRINGTABLE DISCARDABLE"); - SW.WriteLine("BEGIN"); - } - - private static void PrintResourceFooter(StreamWriter SW) { - SW.WriteLine("END"); - } - - private static bool CompareFiles(StreamReader sr1, StreamReader sr2) { - String line1,line2; - - while (true) { - line1 = sr1.ReadLine(); - line2 = sr2.ReadLine(); - - if ( (line1 == null) && (line2 == null) ) { - return true; - } - - if (line1 != line2) { - return false; - } - - } - - } - - private static int MakeHresult(int sev, int fac, int code) { - return ((sev<<31) | (fac<<16) | (code)); - } -} - - - - - - diff --git a/src/coreclr/inc/genheaders/genheaders.cs b/src/coreclr/inc/genheaders/genheaders.cs new file mode 100644 index 0000000000000..12cb4af433538 --- /dev/null +++ b/src/coreclr/inc/genheaders/genheaders.cs @@ -0,0 +1,253 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Xml; +using System.Xml.Schema; +using System.IO; +using System.Diagnostics; + +if (args.Length != 3) +{ + Console.WriteLine("Usage:genheaders XML-file header-file resource-file"); + return; +} + +ValidateXML(args[0]); +string? Message = null; +string? SymbolicName = null; +string? NumericValue = null; +string tempheaderfile = "temp.h"; +string temprcfile = "temp.rc"; + +StreamWriter HSW = File.CreateText(tempheaderfile); +StreamWriter RSW = File.CreateText(temprcfile); + +int FaciltyUrt = 0x13; +int SeveritySuccess = 0; +int SeverityError = 1; + +int minSR = MakeHresult(SeveritySuccess, FaciltyUrt, 0); +int maxSR = MakeHresult(SeveritySuccess, FaciltyUrt, 0xffff); +int minHR = MakeHresult(SeverityError, FaciltyUrt, 0); +int maxHR = MakeHresult(SeverityError, FaciltyUrt, 0xffff); + +PrintLicenseHeader(HSW); +PrintHeader(HSW); +PrintLicenseHeader(RSW); +PrintResourceHeader(RSW); + +XmlTextReader rdr = new XmlTextReader(args[0]); +rdr.WhitespaceHandling = WhitespaceHandling.None; + +while (rdr.Read()) +{ + + switch (rdr.NodeType) + { + + case XmlNodeType.Element: + + if (rdr.Name.ToString() == "HRESULT") + { + NumericValue = rdr.GetAttribute("NumericValue"); + } + if (rdr.Name.ToString() == "Message") + { + Message = rdr.ReadString(); + } + if (rdr.Name.ToString() == "SymbolicName") + { + SymbolicName = rdr.ReadString(); + } + + break; + + case XmlNodeType.EndElement: + if (rdr.Name.ToString() == "HRESULT") + { + + // For CLR Hresult's we take the last 4 digits as the resource strings. + + Debug.Assert(NumericValue != null); + if ((NumericValue.StartsWith("0x")) || (NumericValue.StartsWith("0X"))) + { + + string HexResult = NumericValue.Substring(2); + int num = int.Parse(HexResult, System.Globalization.NumberStyles.HexNumber); + + if ((num > minSR) && (num <= maxSR)) + { + num = num & 0xffff; + HSW.WriteLine("#define " + SymbolicName + " SMAKEHR(0x" + num.ToString("x") + ")"); + } + else if ((num > minHR) && (num <= maxHR)) + { + num = num & 0xffff; + HSW.WriteLine("#define " + SymbolicName + " EMAKEHR(0x" + num.ToString("x") + ")"); + } + else + { + HSW.WriteLine("#define " + SymbolicName + " " + NumericValue); + } + + + + } + else + { + HSW.WriteLine("#define " + SymbolicName + " " + NumericValue); + } + + if (Message != null) + { + RSW.Write("\tMSG_FOR_URT_HR(" + SymbolicName + ") "); + RSW.WriteLine(Message); + } + + SymbolicName = null; + NumericValue = null; + Message = null; + } + break; + + } +} + +PrintFooter(HSW); +PrintResourceFooter(RSW); + +HSW.Close(); +RSW.Close(); + +bool AreFilesEqual = false; + +if (File.Exists(args[1])) +{ + StreamReader sr1 = new StreamReader(tempheaderfile); + StreamReader sr2 = new StreamReader(args[1]); + AreFilesEqual = CompareFiles(sr1, sr2); + sr1.Close(); + sr2.Close(); +} + +if (!AreFilesEqual) +{ + File.Copy(tempheaderfile, args[1], true); + File.Copy(temprcfile, args[2], true); +} + +if (!File.Exists(args[2])) +{ + File.Copy(temprcfile, args[2], true); +} + +File.Delete(tempheaderfile); +File.Delete(temprcfile); + +void ValidateXML(string XMLFile) +{ + + // Set the validation settings on the XmlReaderSettings object. + XmlReaderSettings settings = new XmlReaderSettings(); + + settings.ValidationType = ValidationType.Schema; + settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema; + + settings.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack); + + // Create the XmlReader object. + XmlReader reader = XmlReader.Create(XMLFile, settings); + + // Parse the file. + + while (reader.Read()) + { + } +} + +// Display any validation errors. +void ValidationCallBack(object? sender, ValidationEventArgs e) +{ + Console.WriteLine("Validation Error: {0}", e.Message); + Environment.Exit(-1); +} + +void PrintLicenseHeader(StreamWriter SW) +{ + SW.WriteLine("// Licensed to the .NET Foundation under one or more agreements."); + SW.WriteLine("// The .NET Foundation licenses this file to you under the MIT license."); + SW.WriteLine(); +} + +void PrintHeader(StreamWriter SW) +{ + + SW.WriteLine("#ifndef __COMMON_LANGUAGE_RUNTIME_HRESULTS__"); + SW.WriteLine("#define __COMMON_LANGUAGE_RUNTIME_HRESULTS__"); + SW.WriteLine(); + SW.WriteLine("#include "); + SW.WriteLine(); + SW.WriteLine(); + SW.WriteLine("//"); + SW.WriteLine("//This file is AutoGenerated -- Do Not Edit by hand!!!"); + SW.WriteLine("//"); + SW.WriteLine("//Add new HRESULTS along with their corresponding error messages to"); + SW.WriteLine("//corerror.xml"); + SW.WriteLine("//"); + SW.WriteLine(); + SW.WriteLine("#ifndef FACILITY_URT"); + SW.WriteLine("#define FACILITY_URT 0x13"); + SW.WriteLine("#endif"); + SW.WriteLine("#ifndef EMAKEHR"); + SW.WriteLine("#define SMAKEHR(val) MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_URT, val)"); + SW.WriteLine("#define EMAKEHR(val) MAKE_HRESULT(SEVERITY_ERROR, FACILITY_URT, val)"); + SW.WriteLine("#endif"); + SW.WriteLine(); +} + +void PrintFooter(StreamWriter SW) +{ + SW.WriteLine(); + SW.WriteLine(); + SW.WriteLine("#endif // __COMMON_LANGUAGE_RUNTIME_HRESULTS__"); +} + +void PrintResourceHeader(StreamWriter SW) +{ + SW.WriteLine("STRINGTABLE DISCARDABLE"); + SW.WriteLine("BEGIN"); +} + +void PrintResourceFooter(StreamWriter SW) +{ + SW.WriteLine("END"); +} + +bool CompareFiles(StreamReader sr1, StreamReader sr2) +{ + string line1, line2; + + while (true) + { + line1 = sr1.ReadLine(); + line2 = sr2.ReadLine(); + + if ((line1 == null) && (line2 == null)) + { + return true; + } + + if (line1 != line2) + { + return false; + } + + } + +} + +int MakeHresult(int sev, int fac, int code) +{ + return ((sev << 31) | (fac << 16) | (code)); +} diff --git a/src/coreclr/inc/genheaders/genheaders.csproj b/src/coreclr/inc/genheaders/genheaders.csproj new file mode 100644 index 0000000000000..cb978588aafeb --- /dev/null +++ b/src/coreclr/inc/genheaders/genheaders.csproj @@ -0,0 +1,9 @@ + + + + Exe + $(NetCoreAppToolCurrent) + enable + + + From 2753b71a54144fa77bb812efe70a15fbb51a1db2 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 20 Aug 2024 23:40:16 +0800 Subject: [PATCH 2/9] Modernize --- src/coreclr/inc/genheaders/genheaders.cs | 92 +++++------------------- 1 file changed, 17 insertions(+), 75 deletions(-) diff --git a/src/coreclr/inc/genheaders/genheaders.cs b/src/coreclr/inc/genheaders/genheaders.cs index 12cb4af433538..80154735132a0 100644 --- a/src/coreclr/inc/genheaders/genheaders.cs +++ b/src/coreclr/inc/genheaders/genheaders.cs @@ -2,10 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics; +using System.IO; using System.Xml; using System.Xml.Schema; -using System.IO; -using System.Diagnostics; if (args.Length != 3) { @@ -17,11 +17,9 @@ string? Message = null; string? SymbolicName = null; string? NumericValue = null; -string tempheaderfile = "temp.h"; -string temprcfile = "temp.rc"; -StreamWriter HSW = File.CreateText(tempheaderfile); -StreamWriter RSW = File.CreateText(temprcfile); +using StreamWriter HSW = File.CreateText(args[1]); +using StreamWriter RSW = File.CreateText(args[2]); int FaciltyUrt = 0x13; int SeveritySuccess = 0; @@ -48,15 +46,15 @@ case XmlNodeType.Element: - if (rdr.Name.ToString() == "HRESULT") + if (rdr.Name == "HRESULT") { NumericValue = rdr.GetAttribute("NumericValue"); } - if (rdr.Name.ToString() == "Message") + if (rdr.Name == "Message") { Message = rdr.ReadString(); } - if (rdr.Name.ToString() == "SymbolicName") + if (rdr.Name == "SymbolicName") { SymbolicName = rdr.ReadString(); } @@ -64,26 +62,24 @@ break; case XmlNodeType.EndElement: - if (rdr.Name.ToString() == "HRESULT") + if (rdr.Name == "HRESULT") { // For CLR Hresult's we take the last 4 digits as the resource strings. Debug.Assert(NumericValue != null); - if ((NumericValue.StartsWith("0x")) || (NumericValue.StartsWith("0X"))) + if (NumericValue.StartsWith("0x", StringComparison.OrdinalIgnoreCase)) { - - string HexResult = NumericValue.Substring(2); - int num = int.Parse(HexResult, System.Globalization.NumberStyles.HexNumber); + int num = int.Parse(NumericValue.AsSpan(2), System.Globalization.NumberStyles.HexNumber); if ((num > minSR) && (num <= maxSR)) { - num = num & 0xffff; + num &= 0xffff; HSW.WriteLine("#define " + SymbolicName + " SMAKEHR(0x" + num.ToString("x") + ")"); } else if ((num > minHR) && (num <= maxHR)) { - num = num & 0xffff; + num &= 0xffff; HSW.WriteLine("#define " + SymbolicName + " EMAKEHR(0x" + num.ToString("x") + ")"); } else @@ -117,34 +113,6 @@ PrintFooter(HSW); PrintResourceFooter(RSW); -HSW.Close(); -RSW.Close(); - -bool AreFilesEqual = false; - -if (File.Exists(args[1])) -{ - StreamReader sr1 = new StreamReader(tempheaderfile); - StreamReader sr2 = new StreamReader(args[1]); - AreFilesEqual = CompareFiles(sr1, sr2); - sr1.Close(); - sr2.Close(); -} - -if (!AreFilesEqual) -{ - File.Copy(tempheaderfile, args[1], true); - File.Copy(temprcfile, args[2], true); -} - -if (!File.Exists(args[2])) -{ - File.Copy(temprcfile, args[2], true); -} - -File.Delete(tempheaderfile); -File.Delete(temprcfile); - void ValidateXML(string XMLFile) { @@ -154,7 +122,11 @@ void ValidateXML(string XMLFile) settings.ValidationType = ValidationType.Schema; settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema; - settings.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack); + settings.ValidationEventHandler += (s, e) => + { + Console.WriteLine("Validation Error: {0}", e.Message); + Environment.Exit(-1); + }; // Create the XmlReader object. XmlReader reader = XmlReader.Create(XMLFile, settings); @@ -166,13 +138,6 @@ void ValidateXML(string XMLFile) } } -// Display any validation errors. -void ValidationCallBack(object? sender, ValidationEventArgs e) -{ - Console.WriteLine("Validation Error: {0}", e.Message); - Environment.Exit(-1); -} - void PrintLicenseHeader(StreamWriter SW) { SW.WriteLine("// Licensed to the .NET Foundation under one or more agreements."); @@ -224,29 +189,6 @@ void PrintResourceFooter(StreamWriter SW) SW.WriteLine("END"); } -bool CompareFiles(StreamReader sr1, StreamReader sr2) -{ - string line1, line2; - - while (true) - { - line1 = sr1.ReadLine(); - line2 = sr2.ReadLine(); - - if ((line1 == null) && (line2 == null)) - { - return true; - } - - if (line1 != line2) - { - return false; - } - - } - -} - int MakeHresult(int sev, int fac, int code) { return ((sev << 31) | (fac << 16) | (code)); From aa41b2e982290337de4aa8c1235026b9f6bd1a8b Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 20 Aug 2024 23:57:22 +0800 Subject: [PATCH 3/9] Use XmlLinq --- src/coreclr/inc/genheaders/genheaders.cs | 106 ++++++++--------------- 1 file changed, 34 insertions(+), 72 deletions(-) diff --git a/src/coreclr/inc/genheaders/genheaders.cs b/src/coreclr/inc/genheaders/genheaders.cs index 80154735132a0..b30ec1ec8db1c 100644 --- a/src/coreclr/inc/genheaders/genheaders.cs +++ b/src/coreclr/inc/genheaders/genheaders.cs @@ -2,9 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; -using System.Diagnostics; using System.IO; using System.Xml; +using System.Xml.Linq; using System.Xml.Schema; if (args.Length != 3) @@ -14,9 +14,6 @@ } ValidateXML(args[0]); -string? Message = null; -string? SymbolicName = null; -string? NumericValue = null; using StreamWriter HSW = File.CreateText(args[1]); using StreamWriter RSW = File.CreateText(args[2]); @@ -35,78 +32,43 @@ PrintLicenseHeader(RSW); PrintResourceHeader(RSW); -XmlTextReader rdr = new XmlTextReader(args[0]); -rdr.WhitespaceHandling = WhitespaceHandling.None; - -while (rdr.Read()) +XDocument doc = XDocument.Load(args[0]); +foreach (XElement element in doc.Descendants("HRESULT")) { + string NumericValue = element.Attribute("NumericValue")!.Value; + string? Message = element.Element("Message")?.Value; + string? SymbolicName = element.Element("SymbolicName")?.Value; - switch (rdr.NodeType) - { + // For CLR Hresult's we take the last 4 digits as the resource strings. - case XmlNodeType.Element: - - if (rdr.Name == "HRESULT") - { - NumericValue = rdr.GetAttribute("NumericValue"); - } - if (rdr.Name == "Message") - { - Message = rdr.ReadString(); - } - if (rdr.Name == "SymbolicName") - { - SymbolicName = rdr.ReadString(); - } - - break; - - case XmlNodeType.EndElement: - if (rdr.Name == "HRESULT") - { - - // For CLR Hresult's we take the last 4 digits as the resource strings. - - Debug.Assert(NumericValue != null); - if (NumericValue.StartsWith("0x", StringComparison.OrdinalIgnoreCase)) - { - int num = int.Parse(NumericValue.AsSpan(2), System.Globalization.NumberStyles.HexNumber); - - if ((num > minSR) && (num <= maxSR)) - { - num &= 0xffff; - HSW.WriteLine("#define " + SymbolicName + " SMAKEHR(0x" + num.ToString("x") + ")"); - } - else if ((num > minHR) && (num <= maxHR)) - { - num &= 0xffff; - HSW.WriteLine("#define " + SymbolicName + " EMAKEHR(0x" + num.ToString("x") + ")"); - } - else - { - HSW.WriteLine("#define " + SymbolicName + " " + NumericValue); - } - - - - } - else - { - HSW.WriteLine("#define " + SymbolicName + " " + NumericValue); - } - - if (Message != null) - { - RSW.Write("\tMSG_FOR_URT_HR(" + SymbolicName + ") "); - RSW.WriteLine(Message); - } - - SymbolicName = null; - NumericValue = null; - Message = null; - } - break; + if (NumericValue.StartsWith("0x", StringComparison.OrdinalIgnoreCase)) + { + int num = int.Parse(NumericValue.AsSpan(2), System.Globalization.NumberStyles.HexNumber); + + if ((num > minSR) && (num <= maxSR)) + { + num &= 0xffff; + HSW.WriteLine("#define " + SymbolicName + " SMAKEHR(0x" + num.ToString("x") + ")"); + } + else if ((num > minHR) && (num <= maxHR)) + { + num &= 0xffff; + HSW.WriteLine("#define " + SymbolicName + " EMAKEHR(0x" + num.ToString("x") + ")"); + } + else + { + HSW.WriteLine("#define " + SymbolicName + " " + NumericValue); + } + } + else + { + HSW.WriteLine("#define " + SymbolicName + " " + NumericValue); + } + if (Message != null) + { + RSW.Write("\tMSG_FOR_URT_HR(" + SymbolicName + ") "); + RSW.WriteLine(Message); } } From b598add481001740678f3a38d2db0755e29ed3d8 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 21 Aug 2024 01:31:22 +0800 Subject: [PATCH 4/9] Update doc and add CORPROF_E_MODULE_IS_ENC --- src/coreclr/inc/corerror.xml | 5 +++++ .../pal/prebuilt/corerror/makecorerror.bat | 10 ---------- src/coreclr/pal/prebuilt/corerror/readme.md | 15 +++++++++++++++ src/coreclr/pal/prebuilt/corerror/readme.txt | 7 ------- src/coreclr/pal/prebuilt/inc/corerror.h | 2 +- 5 files changed, 21 insertions(+), 18 deletions(-) delete mode 100644 src/coreclr/pal/prebuilt/corerror/makecorerror.bat create mode 100644 src/coreclr/pal/prebuilt/corerror/readme.md delete mode 100644 src/coreclr/pal/prebuilt/corerror/readme.txt diff --git a/src/coreclr/inc/corerror.xml b/src/coreclr/inc/corerror.xml index 68c9a1aa5dfb3..a9dd81fb2c077 100644 --- a/src/coreclr/inc/corerror.xml +++ b/src/coreclr/inc/corerror.xml @@ -1176,6 +1176,11 @@ This object belongs to a non-gc heap + + CORPROF_E_MODULE_IS_ENC + The module is EnC + + CORSEC_E_POLICY_EXCEPTION "PolicyException thrown." diff --git a/src/coreclr/pal/prebuilt/corerror/makecorerror.bat b/src/coreclr/pal/prebuilt/corerror/makecorerror.bat deleted file mode 100644 index 939404f75a5b9..0000000000000 --- a/src/coreclr/pal/prebuilt/corerror/makecorerror.bat +++ /dev/null @@ -1,10 +0,0 @@ -@if "%_echo%"=="" echo off -REM Licensed to the .NET Foundation under one or more agreements. -REM The .NET Foundation licenses this file to you under the MIT license. -setlocal - -csc ..\..\..\inc\genheaders.cs - -genheaders.exe ..\..\..\inc\corerror.xml ..\inc\corerror.h mscorurt.rc - -del genheaders.exe diff --git a/src/coreclr/pal/prebuilt/corerror/readme.md b/src/coreclr/pal/prebuilt/corerror/readme.md new file mode 100644 index 0000000000000..ee69a16018cfb --- /dev/null +++ b/src/coreclr/pal/prebuilt/corerror/readme.md @@ -0,0 +1,15 @@ +# Update corerror.h and mscorurt.rc + +Execute in repo root: + +### Windows: + +``` +.\dotnet.cmd run --project .\src\coreclr\inc\genheaders\ -- .\src\coreclr\inc\corerror.xml .\src\coreclr\pal\prebuilt\inc\corerror.h .\src\coreclr\pal\prebuilt\corerror\mscorurt.rc +``` + +### Unix: + +``` +./dotnet.sh run --project ./src/coreclr/inc/genheaders/ -- ./src/coreclr/inc/corerror.xml ./src/coreclr/pal/prebuilt/inc/corerror.h ./src/coreclr/pal/prebuilt/corerror/mscorurt.rc +``` diff --git a/src/coreclr/pal/prebuilt/corerror/readme.txt b/src/coreclr/pal/prebuilt/corerror/readme.txt deleted file mode 100644 index a21a72490976a..0000000000000 --- a/src/coreclr/pal/prebuilt/corerror/readme.txt +++ /dev/null @@ -1,7 +0,0 @@ -Steps to generate corerror.h for the Unix: - -Open Razzle window -tf edit ..\inc\corerror.h -tf edit mscorurt.rc -makecorerror.bat -tf undo any files that didn't get modified \ No newline at end of file diff --git a/src/coreclr/pal/prebuilt/inc/corerror.h b/src/coreclr/pal/prebuilt/inc/corerror.h index 0b475679050fd..7106a8bbf3361 100644 --- a/src/coreclr/pal/prebuilt/inc/corerror.h +++ b/src/coreclr/pal/prebuilt/inc/corerror.h @@ -213,7 +213,7 @@ #define CORDIAGIPC_E_UNKNOWN_ERROR EMAKEHR(0x1387) #define CORPROF_E_SUSPENSION_IN_PROGRESS EMAKEHR(0x1388) #define CORPROF_E_NOT_GC_OBJECT EMAKEHR(0x1389) -#define CORPROF_E_MODULE_IS_ENC EMAKEHR(0x138A) +#define CORPROF_E_MODULE_IS_ENC EMAKEHR(0x138a) #define CORSEC_E_POLICY_EXCEPTION EMAKEHR(0x1416) #define CORSEC_E_MIN_GRANT_FAIL EMAKEHR(0x1417) #define CORSEC_E_NO_EXEC_PERM EMAKEHR(0x1418) From 5a90f824b737b009d987c623f92912af6a35ef3d Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 21 Aug 2024 01:39:35 +0800 Subject: [PATCH 5/9] Port CrstTypeTool to NetCoreAppToolCurrent --- .../inc/{ => CrstTypeTool}/CrstTypeTool.cs | 150 +++++++++--------- .../inc/CrstTypeTool/CrstTypeTool.csproj | 8 + 2 files changed, 83 insertions(+), 75 deletions(-) rename src/coreclr/inc/{ => CrstTypeTool}/CrstTypeTool.cs (92%) create mode 100644 src/coreclr/inc/CrstTypeTool/CrstTypeTool.csproj diff --git a/src/coreclr/inc/CrstTypeTool.cs b/src/coreclr/inc/CrstTypeTool/CrstTypeTool.cs similarity index 92% rename from src/coreclr/inc/CrstTypeTool.cs rename to src/coreclr/inc/CrstTypeTool/CrstTypeTool.cs index b161d13f7273c..9b552d2c48035 100644 --- a/src/coreclr/inc/CrstTypeTool.cs +++ b/src/coreclr/inc/CrstTypeTool/CrstTypeTool.cs @@ -1,4 +1,4 @@ -// Licensed to the .NET Foundation under one or more agreements. +// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // @@ -476,16 +476,16 @@ static bool Unleveled(CrstType crst) class TypeFileParser { // Remember the input file name and the dictionary we're meant to populate. - string m_typeFileName; - Dictionary m_crsts; + string m_typeFileName; + Dictionary m_crsts; // Compile regular expressions for detecting comments and tokens in the parser input. - Regex m_commentRegex = new Regex(@"//.*"); - Regex m_tokenRegex = new Regex(@"^(\s*(\S+)\s*)*"); + Regex m_commentRegex = new Regex(@"//.*"); + Regex m_tokenRegex = new Regex(@"^(\s*(\S+)\s*)*"); // Input is lexed into an array of tokens. We record the index of the token being currently parsed. - Token[] m_tokens; - int m_currToken; + Token[] m_tokens; + int m_currToken; // Parse the given file into Crst type definitions and place these definitions in the dictionary provided. // Syntax errors are signalled via ParseError derived exceptions. @@ -553,46 +553,46 @@ void ParseCrst() switch (token.Id) { - case KeywordId.AcquiredBefore: - // Simply parse the following list of Crst types into the current type's AcquiredBefore list. - ParseList(crst.AcquiredBeforeList); - break; - - case KeywordId.AcquiredAfter: - // AcquiredAfter is trickier. To make the ranking algorithm's life easier we actually - // normalize all rules to the AcquiredBefore form (see LevelCrsts() for the reasoning). So we - // capture the list of Crst types that follow the AcquiredAfter keyword and then append the - // current type to the AcquiredBefore list of each type found. - list = new List(); - ParseList(list); - foreach (CrstType priorCrst in list) - priorCrst.AcquiredBeforeList.Add(crst); - break; - - case KeywordId.SameLevelAs: - // Parse the following list of Crst types them let the CrstTypeGroup class handle the - // resulting updates to the type groups we're currently maintaining. See the comments for the - // CrstTypeGroup class for more details. - list = new List(); - ParseList(list); - foreach (CrstType sameLevelCrst in list) - CrstTypeGroup.Join(crst, sameLevelCrst); - break; - - case KeywordId.Unordered: - crst.Level = CrstType.CrstUnordered; - break; - - case KeywordId.End: - parsingCrst = false; - break; - - default: - throw new UnexpectedTokenError(token, - KeywordId.AcquiredBefore, - KeywordId.AcquiredAfter, - KeywordId.SameLevelAs, - KeywordId.Unordered); + case KeywordId.AcquiredBefore: + // Simply parse the following list of Crst types into the current type's AcquiredBefore list. + ParseList(crst.AcquiredBeforeList); + break; + + case KeywordId.AcquiredAfter: + // AcquiredAfter is trickier. To make the ranking algorithm's life easier we actually + // normalize all rules to the AcquiredBefore form (see LevelCrsts() for the reasoning). So we + // capture the list of Crst types that follow the AcquiredAfter keyword and then append the + // current type to the AcquiredBefore list of each type found. + list = new List(); + ParseList(list); + foreach (CrstType priorCrst in list) + priorCrst.AcquiredBeforeList.Add(crst); + break; + + case KeywordId.SameLevelAs: + // Parse the following list of Crst types them let the CrstTypeGroup class handle the + // resulting updates to the type groups we're currently maintaining. See the comments for the + // CrstTypeGroup class for more details. + list = new List(); + ParseList(list); + foreach (CrstType sameLevelCrst in list) + CrstTypeGroup.Join(crst, sameLevelCrst); + break; + + case KeywordId.Unordered: + crst.Level = CrstType.CrstUnordered; + break; + + case KeywordId.End: + parsingCrst = false; + break; + + default: + throw new UnexpectedTokenError(token, + KeywordId.AcquiredBefore, + KeywordId.AcquiredAfter, + KeywordId.SameLevelAs, + KeywordId.Unordered); } } } @@ -632,9 +632,9 @@ void ParseList(List list) // Lex the input file into an array of tokens. void InitTokenStream() { - StreamReader file = new StreamReader(m_typeFileName); - int lineNumber = 1; - List tokenList = new List(); + StreamReader file = new StreamReader(m_typeFileName); + int lineNumber = 1; + List tokenList = new List(); // Read the file a line at a time. string line; @@ -706,15 +706,15 @@ internal class Token static Dictionary s_keywords; // The characters comprising the text of the token from the input file. - string m_text; + string m_text; // Where the token was found (for error messages). - string m_file; - int m_line; - int m_column; + string m_file; + int m_line; + int m_column; // The ID of the keyword this token represents (or KeywordId.Id). - KeywordId m_id; + KeywordId m_id; // Static class initialization. static Token() @@ -747,9 +747,9 @@ public Token(string file, string text, int line, int column) m_id = KeywordId.Id; } - public string Text {get { return m_text; }} - public string Location {get { return String.Format("{0} line {1}, column {2}", m_file, m_line, m_column); }} - public KeywordId Id {get { return m_id; }} + public string Text { get { return m_text; } } + public string Location { get { return String.Format("{0} line {1}, column {2}", m_file, m_line, m_column); } } + public KeywordId Id { get { return m_id; } } } // Base class for all syntax errors reported by the parser. @@ -758,12 +758,12 @@ internal class ParseError : Exception // A raw error message. public ParseError(string message) : base(message) - {} + { } // An error message tagged with a file, line and column (coming from an error token). public ParseError(string message, Token errorToken) : base(String.Format("{0}: {1}", errorToken.Location, message)) - {} + { } // Produce a textual name for the given keyword type. protected static string IdToName(KeywordId id) @@ -782,7 +782,7 @@ internal class UnexpectedTokenError : ParseError // optionally the names of zero or more tokens that would have been accepted. public UnexpectedTokenError(Token errorToken, params KeywordId[] expected) : base(FormatErrorMessage(errorToken, expected)) - {} + { } static string FormatErrorMessage(Token errorToken, KeywordId[] expected) { @@ -813,7 +813,7 @@ internal class UnexpectedEofError : ParseError { public UnexpectedEofError() : base("Unexpected end of file") - {} + { } } } @@ -827,24 +827,24 @@ class CrstType : IComparable public static readonly int CrstUnassigned = -2; // Name of the type, e.g. "AppDomainCache" for the CrstAppDomainCache type. - string m_name; + string m_name; // The numeric ranking assigned to this type. Starts as CrstUnassigned and then becomes either // CrstUnordered (while parsing the input file) or a number >= 0 (during LevelCrsts()). - int m_level; + int m_level; // List of Crst types that can be legally acquired while this one is held. (AcquiredAfter relationships // are by switching the terms and adding to the second type's AcquiredBefore list). - List m_acquiredBeforeCrsts; + List m_acquiredBeforeCrsts; // Either null if this Crst type is not in (or has not yet been determined to be in) a SameLevelAs // relationship or points to a CrstTypeGroup that records all the sibling types at the same level (that // have been discovered thus far during parsing). - CrstTypeGroup m_group; + CrstTypeGroup m_group; // Set once a definition for this type has been discovered. Used to detect double definitions and types // referenced without definitions. - bool m_defined; + bool m_defined; public CrstType(string name) { @@ -855,11 +855,11 @@ public CrstType(string name) m_defined = false; } - public string Name {get { return m_name; }} - public int Level {get { return m_level; } set { m_level = value; }} - public List AcquiredBeforeList {get { return m_acquiredBeforeCrsts; } set { m_acquiredBeforeCrsts = value; }} - public CrstTypeGroup Group {get { return m_group; } set { m_group = value; }} - public bool Defined {get {return m_defined; } set { m_defined = value; }} + public string Name { get { return m_name; } } + public int Level { get { return m_level; } set { m_level = value; } } + public List AcquiredBeforeList { get { return m_acquiredBeforeCrsts; } set { m_acquiredBeforeCrsts = value; } } + public CrstTypeGroup Group { get { return m_group; } set { m_group = value; } } + public bool Defined { get { return m_defined; } set { m_defined = value; } } // Helper used to sort CrstTypes. The sort order is lexical based on the type name. public int CompareTo(object other) @@ -882,10 +882,10 @@ public int CompareTo(object other) class CrstTypeGroup { // We record every group that has been formed so far. This makes normalizing all groups easier. - static List s_groups = new List(); + static List s_groups = new List(); // Crst types that are members of the current group. There are no duplicates in this list. - List m_members = new List(); + List m_members = new List(); // Declare a SameLevelAs relationship between the two Crst types given. Groups will be assigned, created // or merged as required to maintain our guarantees (each CrstType is a member of at most one group and @@ -988,5 +988,5 @@ void NormalizeRules() crst.AcquiredBeforeList = acquiredBeforeList.GetRange(0, acquiredBeforeList.Count); } - public List Members {get { return m_members; }} + public List Members { get { return m_members; } } } diff --git a/src/coreclr/inc/CrstTypeTool/CrstTypeTool.csproj b/src/coreclr/inc/CrstTypeTool/CrstTypeTool.csproj new file mode 100644 index 0000000000000..19e3a46d17f1d --- /dev/null +++ b/src/coreclr/inc/CrstTypeTool/CrstTypeTool.csproj @@ -0,0 +1,8 @@ + + + + Exe + $(NetCoreAppToolCurrent) + + + From 012a39d4626e013d0dc49da7c3f2437f8afd6912 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 21 Aug 2024 01:42:50 +0800 Subject: [PATCH 6/9] Modernize --- src/coreclr/inc/CrstTypeTool/CrstTypeTool.cs | 106 +++++++++---------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/src/coreclr/inc/CrstTypeTool/CrstTypeTool.cs b/src/coreclr/inc/CrstTypeTool/CrstTypeTool.cs index 9b552d2c48035..0f62521c1d2a3 100644 --- a/src/coreclr/inc/CrstTypeTool/CrstTypeTool.cs +++ b/src/coreclr/inc/CrstTypeTool/CrstTypeTool.cs @@ -51,11 +51,11 @@ using System.Text.RegularExpressions; // The main application class containing the program entry point. -class CrstTypeTool +internal class CrstTypeTool { // A hash containing every Crst type defined by the input .def file along with its attributes. Keyed by // Crst type name (which is case sensitive and doesn't include the 'Crst' enum prefix). - Dictionary m_crsts = new Dictionary(); + private Dictionary m_crsts = new Dictionary(); // The program entry point. public static int Main() @@ -114,7 +114,7 @@ public static int Main() } // Emit the crsttypes_generated.h output file. - void WriteHeaderFile(string fileName) + private void WriteHeaderFile(string fileName) { FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None); StreamWriter writer = new StreamWriter(stream); @@ -220,7 +220,7 @@ void WriteHeaderFile(string fileName) // Perform checking of the Crst type definitions we've read just read. Various forms of logic error are // scanned for including cycles in the dependency graph. Returns true if no errors are found. If false is // returned a descriptive error message will have already been written to the console. - bool ValidateCrsts() + private bool ValidateCrsts() { // Look at each Crst type definition in turn. foreach (CrstType crst in m_crsts.Values) @@ -228,7 +228,7 @@ bool ValidateCrsts() // Catch Crst types that are referenced but never defined. if (!crst.Defined) { - Console.WriteLine(String.Format("Error: CrstType 'Crst{0}' is referenced without being defined", + Console.WriteLine(string.Format("Error: CrstType 'Crst{0}' is referenced without being defined", crst.Name)); return false; } @@ -238,7 +238,7 @@ bool ValidateCrsts() if (crst.Level == CrstType.CrstUnordered && (crst.AcquiredBeforeList.Count > 0 || crst.Group != null)) { - Console.WriteLine(String.Format("Error: CrstType 'Crst{0}' is declared as both unordered and acquired before 'Crst{1}'", + Console.WriteLine(string.Format("Error: CrstType 'Crst{0}' is declared as both unordered and acquired before 'Crst{1}'", crst.Name, crst.AcquiredBeforeList[0].Name)); return false; } @@ -247,7 +247,7 @@ bool ValidateCrsts() // indicates an ordering). if (crst.Level == CrstType.CrstUnordered && crst.Group != null) { - Console.WriteLine(String.Format("Error: CrstType 'Crst{0}' is declared as both unordered and in the same level as another CrstType", + Console.WriteLine(string.Format("Error: CrstType 'Crst{0}' is declared as both unordered and in the same level as another CrstType", crst.Name)); return false; } @@ -255,7 +255,7 @@ bool ValidateCrsts() // Catch the simple cycle where the Crst type depends on itself. if (crst.AcquiredBeforeList.Contains(crst)) { - Console.WriteLine(String.Format("Error: CrstType 'Crst{0}' is declared as being acquired before itself", + Console.WriteLine(string.Format("Error: CrstType 'Crst{0}' is declared as being acquired before itself", crst.Name)); return false; } @@ -264,10 +264,10 @@ bool ValidateCrsts() List cycleList = new List(); if (FindCycle(crst, crst, cycleList)) { - Console.WriteLine(String.Format("Error: CrstType 'Crst{0}' is involved in a dependency cycle with the following CrstTypes:", + Console.WriteLine(string.Format("Error: CrstType 'Crst{0}' is involved in a dependency cycle with the following CrstTypes:", crst.Name)); foreach (CrstType cycleCrst in cycleList) - Console.WriteLine(String.Format(" Crst{0}", cycleCrst.Name)); + Console.WriteLine(string.Format(" Crst{0}", cycleCrst.Name)); return false; } } @@ -286,10 +286,10 @@ bool ValidateCrsts() List cycleList = new List(); if (FindCycle(crst, crst, cycleList)) { - Console.WriteLine(String.Format("Error: CrstType 'Crst{0}' is involved in a dependency cycle with the following CrstTypes:", + Console.WriteLine(string.Format("Error: CrstType 'Crst{0}' is involved in a dependency cycle with the following CrstTypes:", crst.Name)); foreach (CrstType cycleCrst in cycleList) - Console.WriteLine(String.Format(" Crst{0}", cycleCrst)); + Console.WriteLine(string.Format(" Crst{0}", cycleCrst)); Console.WriteLine("Note that the cycle was detected only after 'SameLevelAs' processing was performed so some CrstType dependencies are implied by peer CrstTypes"); return false; } @@ -306,7 +306,7 @@ bool ValidateCrsts() // Note that this algorithm is not designed to detect general cycles in the graph, only those that involve // the 'rootCrst' directly. This is somewhat inefficient but gives us a simple way to generate clear error // messages. - bool FindCycle(CrstType rootCrst, CrstType currCrst, List cycleList) + private bool FindCycle(CrstType rootCrst, CrstType currCrst, List cycleList) { // Add the current Crst type to the list of those we've seen. cycleList.Add(currCrst); @@ -338,7 +338,7 @@ bool FindCycle(CrstType rootCrst, CrstType currCrst, List cycleList) // (Crst types that may only be acquired if a lower type is not already held). // **** NOTE: The leveling process is destructive in that we will lose all dependency information from the // Crst type definitions during the course of the algorithm. - void LevelCrsts() + private void LevelCrsts() { // Note that Crst type dependency rules have been normalized (by the input parser) so that all // AcquiredBefore/AcquiredAfter relationships have been reduced to AcquiredBefore relationships (i.e. @@ -442,7 +442,7 @@ void LevelCrsts() // call to ValidateCrsts(), so this check is pure paranoia. if (!madeProgress) { - Console.WriteLine(String.Format("{0} unsorted remain", unsorted)); + Console.WriteLine(string.Format("{0} unsorted remain", unsorted)); throw new Exception("Cycle detected trying to assign level " + currLevel.ToString()); } @@ -464,7 +464,7 @@ void LevelCrsts() // Predicate method used with List.FindAll() to locate Crst types that haven't had their rank assigned // yet. - static bool Unleveled(CrstType crst) + private static bool Unleveled(CrstType crst) { return crst.Level == CrstType.CrstUnassigned; } @@ -473,19 +473,19 @@ static bool Unleveled(CrstType crst) // Class used to parse a CrstTypes.def file into a dictionary of Crst type definitions. It uses a simple lexer // that removes comments then forms tokens out of any consecutive non-whitespace characters. An equally simple // recursive descent parser forms Crst instances by parsing the token stream. -class TypeFileParser +internal class TypeFileParser { // Remember the input file name and the dictionary we're meant to populate. - string m_typeFileName; - Dictionary m_crsts; + private string m_typeFileName; + private Dictionary m_crsts; // Compile regular expressions for detecting comments and tokens in the parser input. - Regex m_commentRegex = new Regex(@"//.*"); - Regex m_tokenRegex = new Regex(@"^(\s*(\S+)\s*)*"); + private Regex m_commentRegex = new Regex(@"//.*"); + private Regex m_tokenRegex = new Regex(@"^(\s*(\S+)\s*)*"); // Input is lexed into an array of tokens. We record the index of the token being currently parsed. - Token[] m_tokens; - int m_currToken; + private Token[] m_tokens; + private int m_currToken; // Parse the given file into Crst type definitions and place these definitions in the dictionary provided. // Syntax errors are signalled via ParseError derived exceptions. @@ -514,7 +514,7 @@ public void ParseFile(string typeFileName, Dictionary crsts) } // Parse a single Crst type definition. - void ParseCrst() + private void ParseCrst() { // The next token had better be an identifier (the Crst type name). Token token = NextToken(); @@ -529,7 +529,7 @@ void ParseCrst() { crst = m_crsts[token.Text]; if (crst.Defined) - throw new ParseError(String.Format("Duplicate definition for CrstType '{0}'", token.Text), token); + throw new ParseError(string.Format("Duplicate definition for CrstType '{0}'", token.Text), token); } else { @@ -600,7 +600,7 @@ void ParseCrst() // Parse a list of Crst type names. Any other token terminates the list (without error and without // consuming that token from the stream). The list of tokens is returned as a list of corresponding // CrstTypes (which are auto-vivified in the output dictionary if they haven't been declared yet). - void ParseList(List list) + private void ParseList(List list) { // Parse tokens until we find a non-identifier. while (true) @@ -630,7 +630,7 @@ void ParseList(List list) } // Lex the input file into an array of tokens. - void InitTokenStream() + private void InitTokenStream() { StreamReader file = new StreamReader(m_typeFileName); int lineNumber = 1; @@ -665,13 +665,13 @@ void InitTokenStream() } // Have we run out of tokens to parse? - bool IsEof() + private bool IsEof() { return m_currToken >= m_tokens.Length; } // Get the next token and throw an exception if we ran out. - Token NextToken() + private Token NextToken() { if (m_currToken >= m_tokens.Length) throw new UnexpectedEofError(); @@ -679,7 +679,7 @@ Token NextToken() } // Push the last token parsed back into the stream. - void UnwindToken() + private void UnwindToken() { if (m_currToken <= 0) throw new InvalidOperationException(); @@ -703,18 +703,18 @@ internal enum KeywordId internal class Token { // Hash of keyword text to enum values. - static Dictionary s_keywords; + private static Dictionary s_keywords; // The characters comprising the text of the token from the input file. - string m_text; + private string m_text; // Where the token was found (for error messages). - string m_file; - int m_line; - int m_column; + private string m_file; + private int m_line; + private int m_column; // The ID of the keyword this token represents (or KeywordId.Id). - KeywordId m_id; + private KeywordId m_id; // Static class initialization. static Token() @@ -748,7 +748,7 @@ public Token(string file, string text, int line, int column) } public string Text { get { return m_text; } } - public string Location { get { return String.Format("{0} line {1}, column {2}", m_file, m_line, m_column); } } + public string Location { get { return string.Format("{0} line {1}, column {2}", m_file, m_line, m_column); } } public KeywordId Id { get { return m_id; } } } @@ -762,7 +762,7 @@ public ParseError(string message) // An error message tagged with a file, line and column (coming from an error token). public ParseError(string message, Token errorToken) - : base(String.Format("{0}: {1}", errorToken.Location, message)) + : base(string.Format("{0}: {1}", errorToken.Location, message)) { } // Produce a textual name for the given keyword type. @@ -770,7 +770,7 @@ protected static string IdToName(KeywordId id) { if (id == KeywordId.Id) return "a CrstType name"; - return String.Format("'{0}'", id.ToString()); + return string.Format("'{0}'", id.ToString()); } } @@ -784,22 +784,22 @@ public UnexpectedTokenError(Token errorToken, params KeywordId[] expected) : base(FormatErrorMessage(errorToken, expected)) { } - static string FormatErrorMessage(Token errorToken, KeywordId[] expected) + private static string FormatErrorMessage(Token errorToken, KeywordId[] expected) { - StringBuilder message = new StringBuilder(String.Format("Unexpected token '{0}' at {1}", + StringBuilder message = new StringBuilder(string.Format("Unexpected token '{0}' at {1}", errorToken.Text, errorToken.Location)); if (expected.Length == 0) { } else if (expected.Length == 1) { - message.Append(String.Format("; expected {0}", IdToName(expected[0]))); + message.Append(string.Format("; expected {0}", IdToName(expected[0]))); } else { message.Append("; expected one of "); for (int i = 0; i < expected.Length - 1; i++) - message.Append(String.Format("{0}, ", IdToName(expected[i]))); + message.Append(string.Format("{0}, ", IdToName(expected[i]))); message.Append(IdToName(expected[expected.Length - 1])); } @@ -819,7 +819,7 @@ public UnexpectedEofError() // This class represents an instance of a Crst type. These are unqiuely identified by case-sensitive name (the // same as the enum name used in vm code, minus the 'Crst' prefix). -class CrstType : IComparable +internal class CrstType : IComparable { // Special level constants used to indicate unordered Crst types or those types we haven't gotten around // to ranking yet. @@ -827,24 +827,24 @@ class CrstType : IComparable public static readonly int CrstUnassigned = -2; // Name of the type, e.g. "AppDomainCache" for the CrstAppDomainCache type. - string m_name; + private string m_name; // The numeric ranking assigned to this type. Starts as CrstUnassigned and then becomes either // CrstUnordered (while parsing the input file) or a number >= 0 (during LevelCrsts()). - int m_level; + private int m_level; // List of Crst types that can be legally acquired while this one is held. (AcquiredAfter relationships // are by switching the terms and adding to the second type's AcquiredBefore list). - List m_acquiredBeforeCrsts; + private List m_acquiredBeforeCrsts; // Either null if this Crst type is not in (or has not yet been determined to be in) a SameLevelAs // relationship or points to a CrstTypeGroup that records all the sibling types at the same level (that // have been discovered thus far during parsing). - CrstTypeGroup m_group; + private CrstTypeGroup m_group; // Set once a definition for this type has been discovered. Used to detect double definitions and types // referenced without definitions. - bool m_defined; + private bool m_defined; public CrstType(string name) { @@ -879,13 +879,13 @@ public int CompareTo(object other) // parsing has finished we are guaranteed to have discovered all the distinct, disjoint groups and to have // fully populated them with the transitive closure of all related types. We can them normalize all groups // members so they share the same AcquiredBefore relationships. -class CrstTypeGroup +internal class CrstTypeGroup { // We record every group that has been formed so far. This makes normalizing all groups easier. - static List s_groups = new List(); + private static List s_groups = new List(); // Crst types that are members of the current group. There are no duplicates in this list. - List m_members = new List(); + private List m_members = new List(); // Declare a SameLevelAs relationship between the two Crst types given. Groups will be assigned, created // or merged as required to maintain our guarantees (each CrstType is a member of at most one group and @@ -967,7 +967,7 @@ public static void NormalizeAllRules() // Normalize this group. This involves adjusting the AcquiredBefore list of each member to be the union of // all such rules within the group. This step allows us to detect cycles in the dependency graph that // would otherwise remain hidden if we only examined the unnormalized AcquiredBefore rules. - void NormalizeRules() + private void NormalizeRules() { // This local will contain the union of all AcquiredBefore rules. List acquiredBeforeList = new List(); From 1da7c085df74c745b6674f3d0e3cbea6766d63ea Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 21 Aug 2024 01:51:33 +0800 Subject: [PATCH 7/9] Modernize errors --- src/coreclr/inc/CrstTypeTool/CrstTypeTool.cs | 70 +++++++++----------- 1 file changed, 31 insertions(+), 39 deletions(-) diff --git a/src/coreclr/inc/CrstTypeTool/CrstTypeTool.cs b/src/coreclr/inc/CrstTypeTool/CrstTypeTool.cs index 0f62521c1d2a3..46e1d5a25c47d 100644 --- a/src/coreclr/inc/CrstTypeTool/CrstTypeTool.cs +++ b/src/coreclr/inc/CrstTypeTool/CrstTypeTool.cs @@ -51,7 +51,7 @@ using System.Text.RegularExpressions; // The main application class containing the program entry point. -internal class CrstTypeTool +internal partial class CrstTypeTool { // A hash containing every Crst type defined by the input .def file along with its attributes. Keyed by // Crst type name (which is case sensitive and doesn't include the 'Crst' enum prefix). @@ -173,8 +173,7 @@ private void WriteHeaderFile(string fileName) foreach (CrstType crst in crsts) { string crstLine = " " + crst.Level + ","; - crstLine = crstLine + new string(' ', 16 - crstLine.Length); - writer.WriteLine(crstLine + "// Crst" + crst.Name); + writer.WriteLine(crstLine.PadRight(16) + "// Crst" + crst.Name); } writer.WriteLine("};"); writer.WriteLine(); @@ -306,7 +305,7 @@ private bool ValidateCrsts() // Note that this algorithm is not designed to detect general cycles in the graph, only those that involve // the 'rootCrst' directly. This is somewhat inefficient but gives us a simple way to generate clear error // messages. - private bool FindCycle(CrstType rootCrst, CrstType currCrst, List cycleList) + private static bool FindCycle(CrstType rootCrst, CrstType currCrst, List cycleList) { // Add the current Crst type to the list of those we've seen. cycleList.Add(currCrst); @@ -473,15 +472,18 @@ private static bool Unleveled(CrstType crst) // Class used to parse a CrstTypes.def file into a dictionary of Crst type definitions. It uses a simple lexer // that removes comments then forms tokens out of any consecutive non-whitespace characters. An equally simple // recursive descent parser forms Crst instances by parsing the token stream. -internal class TypeFileParser +internal partial class TypeFileParser { // Remember the input file name and the dictionary we're meant to populate. private string m_typeFileName; private Dictionary m_crsts; // Compile regular expressions for detecting comments and tokens in the parser input. - private Regex m_commentRegex = new Regex(@"//.*"); - private Regex m_tokenRegex = new Regex(@"^(\s*(\S+)\s*)*"); + [GeneratedRegex(@"//.*")] + private static partial Regex CommentRegex(); + + [GeneratedRegex(@"^(\s*(\S+)\s*)*")] + private static partial Regex TokenRegex(); // Input is lexed into an array of tokens. We record the index of the token being currently parsed. private Token[] m_tokens; @@ -524,10 +526,8 @@ private void ParseCrst() // The Crst instance might already exist in the dictionary (forward references to a Crst type cause // these entries to auto-vivify). But in that case the entry better not be marked as 'Defined' which // would indicate a double declaration. - CrstType crst; - if (m_crsts.ContainsKey(token.Text)) + if (m_crsts.TryGetValue(token.Text, out CrstType crst)) { - crst = m_crsts[token.Text]; if (crst.Defined) throw new ParseError(string.Format("Duplicate definition for CrstType '{0}'", token.Text), token); } @@ -615,10 +615,7 @@ private void ParseList(List list) } // Look up or add a new CrstType corresponding to this type name. - CrstType crst; - if (m_crsts.ContainsKey(token.Text)) - crst = m_crsts[token.Text]; - else + if (!m_crsts.TryGetValue(token.Text, out CrstType crst)) { crst = new CrstType(token.Text); m_crsts[crst.Name] = crst; @@ -641,10 +638,10 @@ private void InitTokenStream() while ((line = file.ReadLine()) != null) { // Remove comments from the current line. - line = m_commentRegex.Replace(line, ""); + line = CommentRegex().Replace(line, ""); // Match all contiguous non-whitespace characters as individual tokens. - Match match = m_tokenRegex.Match(line); + Match match = TokenRegex().Match(line); if (match.Success) { // For each token captured build a token instance and record the token text and the file, line @@ -703,7 +700,19 @@ internal enum KeywordId internal class Token { // Hash of keyword text to enum values. - private static Dictionary s_keywords; + // No sense building complex finite state machines to improve the efficiency of + // keyword lexing here since the input file (and keyword set) is never going to be + // big enough to justify the extra work. + private static Dictionary s_keywords = + new Dictionary(StringComparer.OrdinalIgnoreCase) + { + { "crst", KeywordId.Crst }, + { "end", KeywordId.End }, + { "acquiredbefore", KeywordId.AcquiredBefore }, + { "acquiredafter", KeywordId.AcquiredAfter }, + { "unordered", KeywordId.Unordered }, + { "samelevelas", KeywordId.SameLevelAs } + }; // The characters comprising the text of the token from the input file. private string m_text; @@ -716,21 +725,6 @@ internal class Token // The ID of the keyword this token represents (or KeywordId.Id). private KeywordId m_id; - // Static class initialization. - static Token() - { - // Populate the keyword hash. No sense building complex finite state machines to improve the - // efficiency of keyword lexing here since the input file (and keyword set) is never going to be - // big enough to justify the extra work. - s_keywords = new Dictionary(); - s_keywords.Add("crst", KeywordId.Crst); - s_keywords.Add("end", KeywordId.End); - s_keywords.Add("acquiredbefore", KeywordId.AcquiredBefore); - s_keywords.Add("acquiredafter", KeywordId.AcquiredAfter); - s_keywords.Add("unordered", KeywordId.Unordered); - s_keywords.Add("samelevelas", KeywordId.SameLevelAs); - } - public Token(string file, string text, int line, int column) { m_file = file; @@ -738,11 +732,9 @@ public Token(string file, string text, int line, int column) m_line = line; m_column = column; - // Map token text to keyword ID. True keywords (not identifiers) are case insensitive so normalize - // the text to lower case before performing the keyword hash lookup. - string canonName = m_text.ToLower(); - if (s_keywords.ContainsKey(canonName)) - m_id = s_keywords[canonName]; + // Map token text to keyword ID. + if (s_keywords.TryGetValue(m_text, out KeywordId value)) + m_id = value; else m_id = KeywordId.Id; } @@ -823,8 +815,8 @@ internal class CrstType : IComparable { // Special level constants used to indicate unordered Crst types or those types we haven't gotten around // to ranking yet. - public static readonly int CrstUnordered = -1; - public static readonly int CrstUnassigned = -2; + public const int CrstUnordered = -1; + public const int CrstUnassigned = -2; // Name of the type, e.g. "AppDomainCache" for the CrstAppDomainCache type. private string m_name; From faacd7ed3fcb5b4b62d4b091ae3199b859d166a8 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 21 Aug 2024 02:12:34 +0800 Subject: [PATCH 8/9] Modernize --- src/coreclr/inc/CrstTypeTool/CrstTypeTool.cs | 44 +++++++------------- 1 file changed, 16 insertions(+), 28 deletions(-) diff --git a/src/coreclr/inc/CrstTypeTool/CrstTypeTool.cs b/src/coreclr/inc/CrstTypeTool/CrstTypeTool.cs index 46e1d5a25c47d..314f40bb9be1d 100644 --- a/src/coreclr/inc/CrstTypeTool/CrstTypeTool.cs +++ b/src/coreclr/inc/CrstTypeTool/CrstTypeTool.cs @@ -715,7 +715,7 @@ internal class Token }; // The characters comprising the text of the token from the input file. - private string m_text; + public string Text { get; } // Where the token was found (for error messages). private string m_file; @@ -723,25 +723,23 @@ internal class Token private int m_column; // The ID of the keyword this token represents (or KeywordId.Id). - private KeywordId m_id; + public KeywordId Id { get; } public Token(string file, string text, int line, int column) { m_file = file; - m_text = text; + Text = text; m_line = line; m_column = column; // Map token text to keyword ID. - if (s_keywords.TryGetValue(m_text, out KeywordId value)) - m_id = value; + if (s_keywords.TryGetValue(Text, out KeywordId value)) + Id = value; else - m_id = KeywordId.Id; + Id = KeywordId.Id; } - public string Text { get { return m_text; } } - public string Location { get { return string.Format("{0} line {1}, column {2}", m_file, m_line, m_column); } } - public KeywordId Id { get { return m_id; } } + public string Location => $"{m_file} line {m_line}, column {m_column}"; } // Base class for all syntax errors reported by the parser. @@ -811,7 +809,7 @@ public UnexpectedEofError() // This class represents an instance of a Crst type. These are unqiuely identified by case-sensitive name (the // same as the enum name used in vm code, minus the 'Crst' prefix). -internal class CrstType : IComparable +internal class CrstType : IComparable { // Special level constants used to indicate unordered Crst types or those types we haven't gotten around // to ranking yet. @@ -819,44 +817,34 @@ internal class CrstType : IComparable public const int CrstUnassigned = -2; // Name of the type, e.g. "AppDomainCache" for the CrstAppDomainCache type. - private string m_name; + public string Name { get; } // The numeric ranking assigned to this type. Starts as CrstUnassigned and then becomes either // CrstUnordered (while parsing the input file) or a number >= 0 (during LevelCrsts()). - private int m_level; + public int Level { get; set; } = CrstUnassigned; // List of Crst types that can be legally acquired while this one is held. (AcquiredAfter relationships // are by switching the terms and adding to the second type's AcquiredBefore list). - private List m_acquiredBeforeCrsts; + public List AcquiredBeforeList { get; set; } = new List(); // Either null if this Crst type is not in (or has not yet been determined to be in) a SameLevelAs // relationship or points to a CrstTypeGroup that records all the sibling types at the same level (that // have been discovered thus far during parsing). - private CrstTypeGroup m_group; + public CrstTypeGroup Group { get; set; } // Set once a definition for this type has been discovered. Used to detect double definitions and types // referenced without definitions. - private bool m_defined; + public bool Defined { get; set; } public CrstType(string name) { - m_name = name; - m_level = CrstUnassigned; - m_acquiredBeforeCrsts = new List(); - m_group = null; - m_defined = false; + Name = name; } - public string Name { get { return m_name; } } - public int Level { get { return m_level; } set { m_level = value; } } - public List AcquiredBeforeList { get { return m_acquiredBeforeCrsts; } set { m_acquiredBeforeCrsts = value; } } - public CrstTypeGroup Group { get { return m_group; } set { m_group = value; } } - public bool Defined { get { return m_defined; } set { m_defined = value; } } - // Helper used to sort CrstTypes. The sort order is lexical based on the type name. - public int CompareTo(object other) + public int CompareTo(CrstType other) { - return m_name.CompareTo(((CrstType)other).m_name); + return Name.CompareTo(other.Name); } } From 692b52d6b54734f0cc85ee649fef0acc046a399e Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 21 Aug 2024 02:35:31 +0800 Subject: [PATCH 9/9] Update usage --- src/coreclr/inc/CrstTypeTool/CrstTypeTool.cs | 30 +++++++------------- src/coreclr/inc/crsttypes_generated.h | 2 +- 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/src/coreclr/inc/CrstTypeTool/CrstTypeTool.cs b/src/coreclr/inc/CrstTypeTool/CrstTypeTool.cs index 314f40bb9be1d..5db0a5527dae2 100644 --- a/src/coreclr/inc/CrstTypeTool/CrstTypeTool.cs +++ b/src/coreclr/inc/CrstTypeTool/CrstTypeTool.cs @@ -6,7 +6,7 @@ // acquired before or after other Crst types) into a header file that defines a enum to describe each Crst // type and tables that map type to numerical ranking and a string based name. // -// To use the tool, run "csc.exe CrstTypeTool.cs" and run the resulting executable. +// To use the tool, run "dotnet run --project src/coreclr/inc/CrstTypeTool/" from repo root. // // The Crst type definition file is written in a very simple language. Comments begin with '//' and continue // to the end of the line. All remaining tokens after comment removal are simply sequences of non-whitespace @@ -51,7 +51,7 @@ using System.Text.RegularExpressions; // The main application class containing the program entry point. -internal partial class CrstTypeTool +internal sealed partial class CrstTypeTool { // A hash containing every Crst type defined by the input .def file along with its attributes. Keyed by // Crst type name (which is case sensitive and doesn't include the 'Crst' enum prefix). @@ -63,16 +63,8 @@ public static int Main() try { // Calculate the filenames of the input and output files. - string inputFile = "CrstTypes.def"; - string outputFile = "crsttypes_generated.h"; - - // A common error is to forget to check out the crsttypes_generated.h file first. Handle this case specially - // so we can give a good error message. - if (File.Exists(outputFile) && (File.GetAttributes(outputFile) & FileAttributes.ReadOnly) != 0) - { - Console.WriteLine(outputFile + " is read-only, you must check it out of TFS/SD first"); - return 2; - } + string inputFile = Path.Combine("src", "coreclr", "inc", "CrstTypes.def"); + string outputFile = Path.Combine("src", "coreclr", "inc", "crsttypes_generated.h"); // Create an instance of our application class to store state in (specifically the collection of // Crst type definitions). @@ -141,7 +133,7 @@ private void WriteHeaderFile(string fileName) writer.WriteLine(); writer.WriteLine("// This file describes the range of Crst types available and their mapping to a numeric level (used by the"); writer.WriteLine("// runtime in debug mode to validate we're deadlock free). To modify these settings edit the"); - writer.WriteLine("// file:CrstTypes.def file and run the clr\\artifacts\\CrstTypeTool utility to generate a new version of this file."); + writer.WriteLine("// file:CrstTypes.def file and run the .\\CrstTypeTool utility to generate a new version of this file."); writer.WriteLine(); // Emit the CrstType enum to define a value for each crst type (along with the kNumberOfCrstTypes @@ -472,7 +464,7 @@ private static bool Unleveled(CrstType crst) // Class used to parse a CrstTypes.def file into a dictionary of Crst type definitions. It uses a simple lexer // that removes comments then forms tokens out of any consecutive non-whitespace characters. An equally simple // recursive descent parser forms Crst instances by parsing the token stream. -internal partial class TypeFileParser +internal sealed partial class TypeFileParser { // Remember the input file name and the dictionary we're meant to populate. private string m_typeFileName; @@ -697,7 +689,7 @@ internal enum KeywordId } // Class encapsulating a single token captured from the input file. - internal class Token + internal sealed class Token { // Hash of keyword text to enum values. // No sense building complex finite state machines to improve the efficiency of @@ -766,7 +758,7 @@ protected static string IdToName(KeywordId id) // Syntax error used when an unexpected token is encountered which further lists the valid tokens that // would otherwise have been accepted. - internal class UnexpectedTokenError : ParseError + internal sealed class UnexpectedTokenError : ParseError { // Produce an unexpected token message with a file, line and column coming from an error token and // optionally the names of zero or more tokens that would have been accepted. @@ -799,7 +791,7 @@ private static string FormatErrorMessage(Token errorToken, KeywordId[] expected) } // Syntax error used when we unexpectedly ran out of tokens. - internal class UnexpectedEofError : ParseError + internal sealed class UnexpectedEofError : ParseError { public UnexpectedEofError() : base("Unexpected end of file") @@ -809,7 +801,7 @@ public UnexpectedEofError() // This class represents an instance of a Crst type. These are unqiuely identified by case-sensitive name (the // same as the enum name used in vm code, minus the 'Crst' prefix). -internal class CrstType : IComparable +internal sealed class CrstType : IComparable { // Special level constants used to indicate unordered Crst types or those types we haven't gotten around // to ranking yet. @@ -859,7 +851,7 @@ public int CompareTo(CrstType other) // parsing has finished we are guaranteed to have discovered all the distinct, disjoint groups and to have // fully populated them with the transitive closure of all related types. We can them normalize all groups // members so they share the same AcquiredBefore relationships. -internal class CrstTypeGroup +internal sealed class CrstTypeGroup { // We record every group that has been formed so far. This makes normalizing all groups easier. private static List s_groups = new List(); diff --git a/src/coreclr/inc/crsttypes_generated.h b/src/coreclr/inc/crsttypes_generated.h index b6c3482ab079c..aa99e517ffbb2 100644 --- a/src/coreclr/inc/crsttypes_generated.h +++ b/src/coreclr/inc/crsttypes_generated.h @@ -10,7 +10,7 @@ // This file describes the range of Crst types available and their mapping to a numeric level (used by the // runtime in debug mode to validate we're deadlock free). To modify these settings edit the -// file:CrstTypes.def file and run the clr\artifacts\CrstTypeTool utility to generate a new version of this file. +// file:CrstTypes.def file and run the .\CrstTypeTool utility to generate a new version of this file. // Each Crst type is declared as a value in the following CrstType enum. enum CrstType