PageRenderTime 51ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/mcs/tools/xbuild/Parameters.cs

https://bitbucket.org/foobar22/mono
C# | 428 lines | 379 code | 19 blank | 30 comment | 35 complexity | a0e244a05bf51b551e3908d23a3b7e88 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0, Unlicense, Apache-2.0, LGPL-2.0
  1. //
  2. // Parameters.cs: Class that contains information about command line parameters
  3. //
  4. // Author:
  5. // Marek Sieradzki (marek.sieradzki@gmail.com)
  6. //
  7. // (C) 2005 Marek Sieradzki
  8. //
  9. // Permission is hereby granted, free of charge, to any person obtaining
  10. // a copy of this software and associated documentation files (the
  11. // "Software"), to deal in the Software without restriction, including
  12. // without limitation the rights to use, copy, modify, merge, publish,
  13. // distribute, sublicense, and/or sell copies of the Software, and to
  14. // permit persons to whom the Software is furnished to do so, subject to
  15. // the following conditions:
  16. //
  17. // The above copyright notice and this permission notice shall be
  18. // included in all copies or substantial portions of the Software.
  19. //
  20. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  21. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  22. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  23. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  24. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  25. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  26. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  27. #if NET_2_0
  28. using System;
  29. using System.IO;
  30. using System.Collections;
  31. using System.Collections.Generic;
  32. using System.Linq;
  33. using System.Text;
  34. using System.Reflection;
  35. using Microsoft.Build.BuildEngine;
  36. using Microsoft.Build.Framework;
  37. using Microsoft.Build.Utilities;
  38. namespace Mono.XBuild.CommandLine {
  39. public class Parameters {
  40. string consoleLoggerParameters;
  41. bool displayHelp;
  42. IList flatArguments;
  43. IList loggers;
  44. LoggerVerbosity loggerVerbosity;
  45. bool noConsoleLogger;
  46. bool noLogo;
  47. string projectFile;
  48. BuildPropertyGroup properties;
  49. IList remainingArguments;
  50. Hashtable responseFiles;
  51. string[] targets;
  52. bool validate;
  53. string validationSchema;
  54. string toolsVersion;
  55. string responseFile;
  56. public Parameters ()
  57. {
  58. consoleLoggerParameters = "";
  59. displayHelp = false;
  60. loggers = new ArrayList ();
  61. loggerVerbosity = LoggerVerbosity.Normal;
  62. noConsoleLogger = false;
  63. noLogo = false;
  64. properties = new BuildPropertyGroup ();
  65. targets = new string [0];
  66. responseFile = Path.Combine (
  67. Path.GetDirectoryName (Assembly.GetExecutingAssembly ().Location),
  68. "xbuild.rsp");
  69. }
  70. public void ParseArguments (string[] args)
  71. {
  72. bool autoResponse = true;
  73. flatArguments = new ArrayList ();
  74. remainingArguments = new ArrayList ();
  75. responseFiles = new Hashtable ();
  76. FileLoggerParameters = new string[10];
  77. foreach (string s in args) {
  78. if (s.StartsWith ("/noautoresponse") || s.StartsWith ("/noautorsp")) {
  79. autoResponse = false;
  80. continue;
  81. }
  82. if (s [0] != '@') {
  83. flatArguments.Add (s);
  84. continue;
  85. }
  86. string responseFilename = Path.GetFullPath (UnquoteIfNeeded (s.Substring (1)));
  87. if (responseFiles.ContainsKey (responseFilename))
  88. ReportError (1, String.Format ("We already have {0} file.", responseFilename));
  89. responseFiles [responseFilename] = responseFilename;
  90. LoadResponseFile (responseFilename);
  91. }
  92. if (autoResponse == true) {
  93. // FIXME: we do not allow nested auto response file
  94. LoadResponseFile (responseFile);
  95. }
  96. foreach (string s in flatArguments) {
  97. if (s [0] != '/' || !ParseFlatArgument (s))
  98. remainingArguments.Add (s);
  99. }
  100. if (remainingArguments.Count == 0) {
  101. string[] sln_files = Directory.GetFiles (Directory.GetCurrentDirectory (), "*.sln");
  102. string[] proj_files = Directory.GetFiles (Directory.GetCurrentDirectory (), "*proj");
  103. if (sln_files.Length == 0 && proj_files.Length == 0)
  104. ReportError (3, "Please specify the project or solution file " +
  105. "to build, as none was found in the current directory.");
  106. if (sln_files.Length == 1 && proj_files.Length > 0) {
  107. var projects_table = new Dictionary<string, string> ();
  108. foreach (string pfile in SolutionParser.GetAllProjectFileNames (sln_files [0])) {
  109. string full_path = Path.GetFullPath (pfile);
  110. projects_table [full_path] = full_path;
  111. }
  112. if (!proj_files.Any (p => !projects_table.ContainsKey (Path.GetFullPath (p))))
  113. // if all the project files in the cur dir, are referenced
  114. // from the single .sln in the cur dir, then pick the sln
  115. proj_files = new string [0];
  116. }
  117. if (sln_files.Length + proj_files.Length > 1)
  118. ReportError (5, "Please specify the project or solution file " +
  119. "to build, as more than one solution or project file was found " +
  120. "in the current directory");
  121. if (sln_files.Length == 1)
  122. projectFile = sln_files [0];
  123. else
  124. projectFile = proj_files [0];
  125. } else if (remainingArguments.Count == 1) {
  126. projectFile = (string) remainingArguments [0];
  127. } else {
  128. ReportError (4, "Too many project files specified");
  129. }
  130. }
  131. private string UnquoteIfNeeded(string arg)
  132. {
  133. if (arg.StartsWith("\""))
  134. return arg.Substring(1, arg.Length - 2);
  135. return arg;
  136. }
  137. void LoadResponseFile (string filename)
  138. {
  139. StreamReader sr = null;
  140. string line;
  141. try {
  142. sr = new StreamReader (filename);
  143. StringBuilder sb = new StringBuilder ();
  144. while ((line = sr.ReadLine ()) != null) {
  145. int t = line.Length;
  146. for (int i = 0; i < t; i++) {
  147. char c = line [i];
  148. if (c == '#')
  149. // comment, ignore rest of the line
  150. break;
  151. if (c == '"' || c == '\'') {
  152. char end = c;
  153. for (i++; i < t; i++) {
  154. c = line [i];
  155. if (c == end)
  156. break;
  157. sb.Append (c);
  158. }
  159. } else if (c == ' ') {
  160. if (sb.Length > 0) {
  161. flatArguments.Add (sb.ToString ());
  162. sb.Length = 0;
  163. }
  164. } else
  165. sb.Append (c);
  166. }
  167. if (sb.Length > 0){
  168. flatArguments.Add (sb.ToString ());
  169. sb.Length = 0;
  170. }
  171. }
  172. } catch (IOException x) {
  173. ErrorUtilities.ReportWarning (2, String.Format (
  174. "Error loading response file. (Exception: {0}). Ignoring.",
  175. x.Message));
  176. } finally {
  177. if (sr != null)
  178. sr.Close ();
  179. }
  180. }
  181. private bool ParseFlatArgument (string s)
  182. {
  183. switch (s) {
  184. case "/help":
  185. case "/h":
  186. case "/?":
  187. ErrorUtilities.ShowUsage ();
  188. break;
  189. case "/nologo":
  190. noLogo = true;
  191. break;
  192. case "/version":
  193. case "/ver":
  194. ErrorUtilities.ShowVersion (true);
  195. break;
  196. case "/noconsolelogger":
  197. case "/noconlog":
  198. noConsoleLogger = true;
  199. break;
  200. case "/validate":
  201. case "/val":
  202. validate = true;
  203. break;
  204. case "/fl":
  205. case "/filelogger":
  206. if (FileLoggerParameters [0] == null)
  207. FileLoggerParameters [0] = String.Empty;
  208. break;
  209. default:
  210. if (s.StartsWith ("/fl") && s.Length == 4 && Char.IsDigit (s[3])) {
  211. int index = Int32.Parse (s[3].ToString ());
  212. if (FileLoggerParameters [index] == null)
  213. FileLoggerParameters [index] = String.Empty;
  214. } else if (s.StartsWith ("/fileloggerparameters") || s.StartsWith ("/flp")) {
  215. ProcessFileLoggerParameters (s);
  216. } else if (s.StartsWith ("/target:") || s.StartsWith ("/t:")) {
  217. ProcessTarget (s);
  218. } else if (s.StartsWith ("/property:") || s.StartsWith ("/p:")) {
  219. if (!ProcessProperty (s))
  220. return false;
  221. } else if (s.StartsWith ("/logger:") || s.StartsWith ("/l:")) {
  222. ProcessLogger (s);
  223. } else if (s.StartsWith ("/verbosity:") || s.StartsWith ("/v:")) {
  224. ProcessVerbosity (s);
  225. } else if (s.StartsWith ("/consoleloggerparameters:") || s.StartsWith ("/clp:")) {
  226. ProcessConsoleLoggerParameters (s);
  227. } else if (s.StartsWith ("/validate:") || s.StartsWith ("/val:")) {
  228. ProcessValidate (s);
  229. } else if (s.StartsWith ("/toolsversion:") || s.StartsWith ("/tv:")) {
  230. ToolsVersion = s.Split (':') [1];
  231. } else
  232. return false;
  233. break;
  234. }
  235. return true;
  236. }
  237. internal void ProcessTarget (string s)
  238. {
  239. TryProcessMultiOption (s, "Target names must be specified as /t:Target1;Target2",
  240. out targets);
  241. }
  242. internal bool ProcessProperty (string s)
  243. {
  244. string[] splitProperties;
  245. if (!TryProcessMultiOption (s, "Property name and value expected as /p:<prop name>=<prop value>",
  246. out splitProperties))
  247. return false;
  248. foreach (string st in splitProperties) {
  249. if (st.IndexOf ('=') < 0) {
  250. ReportError (5,
  251. "Invalid syntax. Property name and value expected as " +
  252. "<prop name>=[<prop value>]");
  253. return false;
  254. }
  255. string [] property = st.Split ('=');
  256. properties.SetProperty (property [0], property.Length == 2 ? property [1] : "");
  257. }
  258. return true;
  259. }
  260. bool TryProcessMultiOption (string s, string error_message, out string[] values)
  261. {
  262. values = null;
  263. int colon = s.IndexOf (':');
  264. if (colon + 1 == s.Length) {
  265. ReportError (5, error_message);
  266. return false;
  267. }
  268. values = s.Substring (colon + 1).Split (';');
  269. return true;
  270. }
  271. private void ReportError (int errorCode, string message)
  272. {
  273. throw new CommandLineException (message, errorCode);
  274. }
  275. private void ReportError (int errorCode, string message, Exception cause)
  276. {
  277. throw new CommandLineException (message, cause, errorCode);
  278. }
  279. internal void ProcessLogger (string s)
  280. {
  281. loggers.Add (new LoggerInfo (s));
  282. }
  283. internal void ProcessVerbosity (string s)
  284. {
  285. string[] temp = s.Split (':');
  286. switch (temp [1]) {
  287. case "q":
  288. case "quiet":
  289. loggerVerbosity = LoggerVerbosity.Quiet;
  290. break;
  291. case "m":
  292. case "minimal":
  293. loggerVerbosity = LoggerVerbosity.Minimal;
  294. break;
  295. case "n":
  296. case "normal":
  297. loggerVerbosity = LoggerVerbosity.Normal;
  298. break;
  299. case "d":
  300. case "detailed":
  301. loggerVerbosity = LoggerVerbosity.Detailed;
  302. break;
  303. case "diag":
  304. case "diagnostic":
  305. loggerVerbosity = LoggerVerbosity.Diagnostic;
  306. break;
  307. }
  308. }
  309. void ProcessFileLoggerParameters (string s)
  310. {
  311. int colon = s.IndexOf (':');
  312. if (colon + 1 == s.Length)
  313. ReportError (5, "Invalid syntax, specify parameters as /fileloggerparameters[n]:parameters");
  314. int index = 0;
  315. string key = s.Substring (0, colon);
  316. if (Char.IsDigit (key [key.Length - 1]))
  317. //if (key.Length == 22 && Char.IsDigit (key [21]))
  318. index = Int32.Parse (key [key.Length - 1].ToString ());
  319. FileLoggerParameters [index] = s.Substring (colon + 1);
  320. }
  321. internal void ProcessConsoleLoggerParameters (string s)
  322. {
  323. int colon = s.IndexOf (':');
  324. if (colon + 1 == s.Length)
  325. ReportError (5, "Invalid syntax, specify parameters as /clp:parameters");
  326. consoleLoggerParameters = s.Substring (colon + 1);
  327. }
  328. internal void ProcessValidate (string s)
  329. {
  330. string[] temp;
  331. validate = true;
  332. temp = s.Split (':');
  333. validationSchema = temp [1];
  334. }
  335. public bool DisplayHelp {
  336. get { return displayHelp; }
  337. }
  338. public bool NoLogo {
  339. get { return noLogo; }
  340. }
  341. public string ProjectFile {
  342. get { return projectFile; }
  343. }
  344. public string[] Targets {
  345. get { return targets; }
  346. }
  347. public BuildPropertyGroup Properties {
  348. get { return properties; }
  349. }
  350. public IList Loggers {
  351. get { return loggers; }
  352. }
  353. public LoggerVerbosity LoggerVerbosity {
  354. get { return loggerVerbosity; }
  355. }
  356. public string ConsoleLoggerParameters {
  357. get { return consoleLoggerParameters; }
  358. }
  359. public bool NoConsoleLogger {
  360. get { return noConsoleLogger; }
  361. }
  362. public string[] FileLoggerParameters { get; set; }
  363. public bool Validate {
  364. get { return validate; }
  365. }
  366. public string ValidationSchema {
  367. get { return validationSchema; }
  368. }
  369. public string ToolsVersion {
  370. get { return toolsVersion; }
  371. private set { toolsVersion = value; }
  372. }
  373. }
  374. }
  375. #endif