1f36902f43d89b368ddcf76dfd2a019403dec550
[mono.git] / mcs / tools / xbuild / Parameters.cs
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
28 #if NET_2_0
29
30 using System;
31 using System.IO;
32 using System.Collections;
33 using System.Text;
34 using System.Reflection;
35 using Microsoft.Build.BuildEngine;
36 using Microsoft.Build.Framework;
37 using Microsoft.Build.Utilities;
38
39 namespace Mono.XBuild.CommandLine {
40         public class Parameters {
41         
42                 string                  consoleLoggerParameters;
43                 bool                    displayHelp;
44                 bool                    displayVersion;
45                 IList                   flatArguments;
46                 IList                   loggers;
47                 LoggerVerbosity         loggerVerbosity;
48                 bool                    noConsoleLogger;
49                 bool                    noLogo;
50                 string                  projectFile;
51                 BuildPropertyGroup      properties;
52                 IList                   remainingArguments;
53                 Hashtable               responseFiles;
54                 string[]                targets;
55                 bool                    validate;
56                 string                  validationSchema;
57                 
58                 string                  responseFile;
59         
60                 public Parameters (string binPath)
61                 {
62                         consoleLoggerParameters = "";
63                         displayHelp = false;
64                         displayVersion = true;
65                         loggers = new ArrayList ();
66                         loggerVerbosity = LoggerVerbosity.Normal;
67                         noConsoleLogger = false;
68                         noLogo = false;
69                         properties = new BuildPropertyGroup ();
70                         targets = new string [0];
71                         
72                         responseFile = Path.Combine (
73                                         Path.GetDirectoryName (Assembly.GetExecutingAssembly ().Location),
74                                         "xbuild.rsp");
75                 }
76                 
77                 public void ParseArguments (string[] args)
78                 {
79                         bool autoResponse = true;
80                         flatArguments = new ArrayList ();
81                         remainingArguments = new ArrayList ();
82                         responseFiles = new Hashtable ();
83                         foreach (string s in args) {
84                                 if (s.StartsWith ("/noautoresponse") || s.StartsWith ("/noautorsp")) {
85                                         autoResponse = false;
86                                         continue;
87                                 }
88                                 if (s [0] != '@') {
89                                         flatArguments.Add (s);
90                                         continue;
91                                 }
92                                 string responseFilename = Path.GetFullPath (s.Substring (1));
93                                 if (responseFiles.ContainsKey (responseFilename))
94                                         ErrorUtilities.ReportError (1, String.Format ("We already have {0} file.", responseFilename));
95                                 responseFiles [responseFilename] = responseFilename;
96                                 LoadResponseFile (responseFilename);
97                         }
98                         if (autoResponse == true) {
99                                 // FIXME: we do not allow nested auto response file
100                                 LoadResponseFile (responseFile);
101                         }
102                         foreach (string s in flatArguments) {
103                                 if (s [0] != '/' || !ParseFlatArgument (s))
104                                         remainingArguments.Add (s);
105                         }
106                         if (remainingArguments.Count == 0) {
107                                 string[] sln_files = Directory.GetFiles (Directory.GetCurrentDirectory (), "*.sln");
108                                 string[] proj_files = Directory.GetFiles (Directory.GetCurrentDirectory (), "*proj");
109
110                                 if (sln_files.Length == 0 && proj_files.Length == 0)
111                                         ErrorUtilities.ReportError (3, "Please specify the project or solution file " +
112                                                         "to build, as none was found in the current directory.");
113
114                                 if (sln_files.Length + proj_files.Length > 1)
115                                         ErrorUtilities.ReportError (5, "Please specify the project or solution file " +
116                                                         "to build, as more than one solution or project file was found " +
117                                                         "in the current directory");
118
119                                 if (sln_files.Length == 1)
120                                         projectFile = sln_files [0];
121                                 else
122                                         projectFile = proj_files [0];
123                         } else if (remainingArguments.Count == 1) {
124                                 projectFile = (string) remainingArguments [0];
125                         } else {
126                                 ErrorUtilities.ReportError (4, "Too many project files specified");
127                         }
128                 }
129                 
130                 void LoadResponseFile (string filename)
131                 {
132                         StreamReader sr = null;
133                         string line;
134                         try {
135                                 sr = new StreamReader (filename);
136                                 StringBuilder sb = new StringBuilder ();
137
138                                 while ((line = sr.ReadLine ()) != null) {
139                                         int t = line.Length;
140
141                                         for (int i = 0; i < t; i++) {
142                                                 char c = line [i];
143
144                                                 if (c == '#')
145                                                         // comment, ignore rest of the line
146                                                         break;
147
148                                                 if (c == '"' || c == '\'') {
149                                                         char end = c;
150
151                                                         for (i++; i < t; i++) {
152                                                                 c = line [i];
153
154                                                                 if (c == end)
155                                                                         break;
156                                                                 sb.Append (c);
157                                                         }
158                                                 } else if (c == ' ') {
159                                                         if (sb.Length > 0) {
160                                                                 flatArguments.Add (sb.ToString ());
161                                                                 sb.Length = 0;
162                                                         }
163                                                 } else
164                                                         sb.Append (c);
165                                         }
166                                         if (sb.Length > 0){
167                                                 flatArguments.Add (sb.ToString ());
168                                                 sb.Length = 0;
169                                         }
170                                 }
171                         } catch (Exception) {
172                                 // FIXME: we lose exception message
173                                 ErrorUtilities.ReportError (2, "Error during loading response file.");
174                         } finally {
175                                 if (sr != null)
176                                         sr.Close ();
177                         }
178                 }
179                 
180                 private bool ParseFlatArgument (string s)
181                 {
182                         switch (s) {
183                         case "/help":
184                         case "/h":
185                         case "/?":
186                                 ErrorUtilities.ShowUsage ();
187                                 break;
188                         case "/nologo":
189                                 noLogo = true;
190                                 break;
191                         case "/version":
192                         case "/ver":
193                                 ErrorUtilities.ShowVersion (true);
194                                 break;
195                         case "/noconsolelogger":
196                         case "/noconlog":
197                                 noConsoleLogger = true;
198                                 break;
199                         case "/validate":
200                         case "/val":
201                                 validate = true;
202                                 break;
203                         default:
204                                 if (s.StartsWith ("/target:") || s.StartsWith ("/t:")) {
205                                         ProcessTarget (s);
206                                 } else if (s.StartsWith ("/property:") || s.StartsWith ("/p:")) {
207                                         if (!ProcessProperty (s))
208                                                 return false;
209                                 } else  if (s.StartsWith ("/logger:") || s.StartsWith ("/l:")) {
210                                         ProcessLogger (s);
211                                 } else if (s.StartsWith ("/verbosity:") || s.StartsWith ("/v:")) {
212                                         ProcessVerbosity (s);
213                                 } else if (s.StartsWith ("/consoleloggerparameters:") || s.StartsWith ("/clp:")) {
214                                         ProcessConsoleLoggerParameters (s);
215                                 } else if (s.StartsWith ("/validate:") || s.StartsWith ("/val:")) {
216                                         ProcessValidate (s);
217                                 } else
218                                         return false;
219                                 break;
220                         }
221
222                         return true;
223                 }
224                 
225                 internal void ProcessTarget (string s)
226                 {
227                         string[] temp = s.Split (':');
228                         targets = temp [1].Split (';');
229                 }
230                 
231                 internal bool ProcessProperty (string s)
232                 {
233                         string[] parameter, splittedProperties, property;
234                         parameter = s.Split (':');
235                         if (parameter.Length != 2) {
236                                 ErrorUtilities.ReportError (5, "Property name and value expected as /p:<prop name>=<prop value>");
237                                 return false;
238                         }
239
240                         splittedProperties = parameter [1].Split (';');
241                         foreach (string st in splittedProperties) {
242                                 if (st.IndexOf ('=') < 0) {
243                                         ErrorUtilities.ReportError (5,
244                                                         "Invalid syntax. Property name and value expected as " +
245                                                         "<prop name>=[<prop value>]");
246                                         return false;
247                                 }
248                                 property = st.Split ('=');
249                                 properties.SetProperty (property [0], property.Length == 2 ? property [1] : "");
250                         }
251
252                         return true;
253                 }
254                 
255                 internal void ProcessLogger (string s)
256                 {
257                         loggers.Add (new LoggerInfo (s));
258                 }
259                 
260                 internal void ProcessVerbosity (string s)
261                 {
262                         string[] temp = s.Split (':');
263                         switch (temp [1]) {
264                         case "q":
265                         case "quiet":
266                                 loggerVerbosity = LoggerVerbosity.Quiet;
267                                 break;
268                         case "m":
269                         case "minimal":
270                                 loggerVerbosity = LoggerVerbosity.Minimal;
271                                 break;
272                         case "n":
273                         case "normal":
274                                 loggerVerbosity = LoggerVerbosity.Normal;
275                                 break;
276                         case "d":
277                         case "detailed":
278                                 loggerVerbosity = LoggerVerbosity.Detailed;
279                                 break;
280                         case "diag":
281                         case "diagnostic":
282                                 loggerVerbosity = LoggerVerbosity.Diagnostic;
283                                 break;
284                         }
285                 }
286                 
287                 internal void ProcessConsoleLoggerParameters (string s)
288                 {
289                         consoleLoggerParameters = s; 
290                 }
291                 
292                 internal void ProcessValidate (string s)
293                 {
294                         string[] temp;
295                         validate = true;
296                         temp = s.Split (':');
297                         validationSchema = temp [1];
298                 }
299                 public bool DisplayHelp {
300                         get { return displayHelp; }
301                 }
302                 
303                 public bool NoLogo {
304                         get { return noLogo; }
305                 }
306                 
307                 public bool DisplayVersion {
308                         get { return displayVersion; }
309                 }
310                 
311                 public string ProjectFile {
312                         get { return projectFile; }
313                 }
314                 
315                 public string[] Targets {
316                         get { return targets; }
317                 }
318                 
319                 public BuildPropertyGroup Properties {
320                         get { return properties; }
321                 }
322                 
323                 public IList Loggers {
324                         get { return loggers; }
325                 }
326                 
327                 public LoggerVerbosity LoggerVerbosity {
328                         get { return loggerVerbosity; }
329                 }
330                 
331                 public string ConsoleLoggerParameters {
332                         get { return consoleLoggerParameters; }
333                 }
334                 
335                 public bool NoConsoleLogger {
336                         get { return noConsoleLogger; }
337                 }
338                 
339                 public bool Validate {
340                         get { return validate; }
341                 }
342                 
343                 public string ValidationSchema {
344                         get { return validationSchema; }
345                 }
346                 
347         }
348 }
349
350 #endif