1+ using System . Collections . Generic ;
12using System . Diagnostics ;
23using System . IO ;
4+ using System . Linq ;
35using System . Runtime . InteropServices ;
46
57namespace Semmle . Extraction . CSharp
@@ -53,24 +55,34 @@ public CompilerVersion(Options options)
5355 var versionInfo = FileVersionInfo . GetVersionInfo ( SpecifiedCompiler ) ;
5456
5557 var compilerDir = Path . GetDirectoryName ( SpecifiedCompiler ) ;
56- bool known_compiler_name = versionInfo . OriginalFilename == "csc.exe" || versionInfo . OriginalFilename == "csc2.exe" ;
57- bool copyright_microsoft = versionInfo . LegalCopyright != null && versionInfo . LegalCopyright . Contains ( "Microsoft" ) ;
58- bool mscorlib_exists = File . Exists ( Path . Combine ( compilerDir , "mscorlib.dll" ) ) ;
58+ var knownCompilerNames = new Dictionary < string , string >
59+ {
60+ { "csc.exe" , "Microsoft" } ,
61+ { "csc2.exe" , "Microsoft" } ,
62+ { "csc.dll" , "Microsoft" } ,
63+ { "mcs.exe" , "Novell" }
64+ } ;
65+ var mscorlibExists = File . Exists ( Path . Combine ( compilerDir , "mscorlib.dll" ) ) ;
5966
60- if ( specifiedFramework == null && mscorlib_exists )
67+ if ( specifiedFramework == null && mscorlibExists )
6168 {
6269 specifiedFramework = compilerDir ;
6370 }
6471
65- if ( ! known_compiler_name )
72+ if ( ! knownCompilerNames . TryGetValue ( versionInfo . OriginalFilename , out var vendor ) )
6673 {
67- SkipExtractionBecause ( "the exe name is not recognised" ) ;
74+ SkipExtractionBecause ( "the compiler name is not recognised" ) ;
75+ return ;
6876 }
69- else if ( ! copyright_microsoft )
77+
78+ if ( versionInfo . LegalCopyright == null || ! versionInfo . LegalCopyright . Contains ( vendor ) )
7079 {
71- SkipExtractionBecause ( "the exe isn't copyright Microsoft" ) ;
80+ SkipExtractionBecause ( $ "the compiler isn't copyright { vendor } , but instead { versionInfo . LegalCopyright ?? "<null>" } ") ;
81+ return ;
7282 }
7383 }
84+
85+ ArgsWithResponse = AddDefaultResponse ( CscRsp , options . CompilerArguments ) . ToArray ( ) ;
7486 }
7587
7688 void SkipExtractionBecause ( string reason )
@@ -87,7 +99,7 @@ void SkipExtractionBecause(string reason)
8799 /// <summary>
88100 /// The file csc.rsp.
89101 /// </summary>
90- public string CscRsp => Path . Combine ( FrameworkPath , csc_rsp ) ;
102+ string CscRsp => Path . Combine ( FrameworkPath , csc_rsp ) ;
91103
92104 /// <summary>
93105 /// Should we skip extraction?
@@ -103,5 +115,25 @@ public bool SkipExtraction
103115 /// Gets additional reference directories - the compiler directory.
104116 /// </summary>
105117 public string AdditionalReferenceDirectories => SpecifiedCompiler != null ? Path . GetDirectoryName ( SpecifiedCompiler ) : null ;
118+
119+ /// <summary>
120+ /// Adds @csc.rsp to the argument list to mimic csc.exe.
121+ /// </summary>
122+ /// <param name="responseFile">The full pathname of csc.rsp.</param>
123+ /// <param name="args">The other command line arguments.</param>
124+ /// <returns>Modified list of arguments.</returns>
125+ static IEnumerable < string > AddDefaultResponse ( string responseFile , IEnumerable < string > args )
126+ {
127+ return SuppressDefaultResponseFile ( args ) && File . Exists ( responseFile ) ?
128+ args :
129+ new [ ] { "@" + responseFile } . Concat ( args ) ;
130+ }
131+
132+ static bool SuppressDefaultResponseFile ( IEnumerable < string > args )
133+ {
134+ return args . Any ( arg => new [ ] { "/noconfig" , "-noconfig" } . Contains ( arg . ToLowerInvariant ( ) ) ) ;
135+ }
136+
137+ public readonly string [ ] ArgsWithResponse ;
106138 }
107139}
0 commit comments