2004-09-14 Martin Baulig <martin@ximian.com>
[mono.git] / mcs / ilasm / Driver.cs
1 //
2 // Mono.ILASM.Driver
3 //    Main Command line interface for Mono ILasm Compiler
4 //
5 // Author(s):
6 //  Jackson Harper (Jackson@LatitudeGeo.com)
7 //
8 // (C) 2003 Jackson Harper, All rights reserved
9 //
10
11 using System;
12 using System.IO;
13 using System.Reflection;
14 using System.Collections;
15
16 namespace Mono.ILASM {
17
18         public class Driver {
19
20                 enum Target {
21                         Dll,
22                         Exe
23                 }
24
25                 public static int Main (string[] args)
26                 {
27                         // Do everything in Invariant
28                         System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture;
29
30                         DriverMain driver = new DriverMain (args);
31                         try {
32                                 if (!driver.Run ()) {
33                                         Console.WriteLine ();
34                                         Console.WriteLine ("***** FAILURE *****");
35                                         return 1;
36                                 }
37                         } catch (Exception e) {
38                                 Console.WriteLine (e);
39                                 Console.WriteLine ("Error while compiling.");
40                                 return 1;
41                         }
42                         Console.WriteLine ("Operation completed successfully");
43                         return 0;
44                 }
45
46                 private class DriverMain {
47
48                         private ArrayList il_file_list;
49                         private Report report;
50                         private string output_file;
51                         private Target target = Target.Exe;
52                         private string target_string = "exe";
53                         private bool quiet = false;
54                         private bool show_tokens = false;
55                         private bool show_method_def = false;
56                         private bool show_method_ref = false;
57                         private bool show_parser = false;
58                         private bool scan_only = false;
59                         private bool debugging_info = false;
60                         private CodeGen codegen;
61
62                         public DriverMain (string[] args)
63                         {
64                                 il_file_list = new ArrayList ();
65                                 ParseArgs (args);
66                                 report = new Report (quiet);
67                         }
68
69                         public bool Run ()
70                         {
71                                 try {
72                                         if (il_file_list.Count == 0)
73                                                 Usage ();
74                                         if (output_file == null)
75                                                 output_file = CreateOutputFile ();
76                                         codegen = new CodeGen (output_file, target == Target.Dll, true, debugging_info, report);
77                                         foreach (string file_path in il_file_list)
78                                                 ProcessFile (file_path);
79                                         if (scan_only)
80                                                 return true;
81
82                                         if (report.ErrorCount > 0)
83                                                 return false;
84                                         codegen.Write ();
85                                 } catch {
86                                         return false;
87                                 }
88
89                                 return true;
90                         }
91
92                         private void ProcessFile (string file_path)
93                         {
94                                 if (!File.Exists (file_path)) {
95                                         Console.WriteLine ("File does not exist: {0}",
96                                                 file_path);
97                                         Environment.Exit (2);
98                                 }
99                                 report.AssembleFile (file_path, null,
100                                                 target_string, output_file);
101                                 StreamReader reader = File.OpenText (file_path);
102                                 ILTokenizer scanner = new ILTokenizer (reader);
103
104                                 if (show_tokens)
105                                         scanner.NewTokenEvent += new NewTokenEvent (ShowToken);
106                                 //if (show_method_def)
107                                 //        MethodTable.MethodDefinedEvent += new MethodDefinedEvent (ShowMethodDef);
108                                 //if (show_method_ref)
109                                 //       MethodTable.MethodReferencedEvent += new MethodReferencedEvent (ShowMethodRef);
110
111                                 if (scan_only) {
112                                         ILToken tok;
113                                         while ((tok = scanner.NextToken) != ILToken.EOF) {
114                                                 Console.WriteLine (tok);
115                                         }
116                                         return;
117                                 }
118
119                                 ILParser parser = new ILParser (codegen, scanner);
120                                 codegen.BeginSourceFile (file_path);
121                                 try {
122                                         if (show_parser)
123                                                 parser.yyparse (new ScannerAdapter (scanner),
124                                                                 new yydebug.yyDebugSimple ());
125                                         else
126                                                 parser.yyparse (new ScannerAdapter (scanner),  null);
127                                 } catch (ILTokenizingException ilte) {
128                                         report.Error (file_path + "(" + ilte.Location.line + ") : error : " +
129                                                         "syntax error at token '" + ilte.Token + "'.");
130                                 } catch {
131                                         Console.WriteLine ("Error at: " + scanner.Reader.Location);
132                                         throw;
133                                 } finally {
134                                         codegen.EndSourceFile ();
135                                 }
136                         }
137
138                         public void ShowToken (object sender, NewTokenEventArgs args)
139                         {
140                                 Console.WriteLine ("token: '{0}'", args.Token);
141                         }
142                         /*
143                         public void ShowMethodDef (object sender, MethodDefinedEventArgs args)
144                         {
145                                 Console.WriteLine ("***** Method defined *****");
146                                 Console.WriteLine ("-- signature:   {0}", args.Signature);
147                                 Console.WriteLine ("-- name:        {0}", args.Name);
148                                 Console.WriteLine ("-- return type: {0}", args.ReturnType);
149                                 Console.WriteLine ("-- is in table: {0}", args.IsInTable);
150                                 Console.WriteLine ("-- method atts: {0}", args.MethodAttributes);
151                                 Console.WriteLine ("-- impl atts:   {0}", args.ImplAttributes);
152                                 Console.WriteLine ("-- call conv:   {0}", args.CallConv);
153                         }
154
155                         public void ShowMethodRef (object sender, MethodReferencedEventArgs args)
156                         {
157                                 Console.WriteLine ("***** Method referenced *****");
158                                 Console.WriteLine ("-- signature:   {0}", args.Signature);
159                                 Console.WriteLine ("-- name:        {0}", args.Name);
160                                 Console.WriteLine ("-- return type: {0}", args.ReturnType);
161                                 Console.WriteLine ("-- is in table: {0}", args.IsInTable);
162                         }
163                         */
164                         private void ParseArgs (string[] args)
165                         {
166                                 string command_arg;
167                                 foreach (string str in args) {
168                                         if ((str[0] != '-') && (str[0] != '/')) {
169                                                 il_file_list.Add (str);
170                                                 continue;
171                                         }
172                                         switch (GetCommand (str, out command_arg)) {
173                                         case "out":
174                                         case "output":
175                                                 output_file = command_arg;
176                                                 break;
177                                         case "exe":
178                                                 target = Target.Exe;
179                                                 target_string = "exe";
180                                                 break;
181                                         case "dll":
182                                                 target = Target.Dll;
183                                                 target_string = "dll";
184                                                 break;
185                                         case "quiet":
186                                                 quiet = true;
187                                                 break;
188                                         case "debug":
189                                         case "deb":
190                                                 if (str[0] != '-')
191                                                         break;
192                                                 debugging_info = true;
193                                                 break;
194                                         // Stubs to stay commandline compatible with MS 
195                                         case "listing":
196                                         case "nologo":
197                                         case "clock":
198                                         case "error":
199                                         case "subsystem":
200                                         case "flags":
201                                         case "alignment":
202                                         case "base":
203                                         case "key":
204                                         case "resource":
205                                                 break;
206                                         case "scan_only":
207                                                 scan_only = true;
208                                                 break;
209                                         case "show_tokens":
210                                                 show_tokens = true;
211                                                 break;
212                                         case "show_method_def":
213                                                 show_method_def = true;
214                                                 break;
215                                         case "show_method_ref":
216                                                 show_method_ref = true;
217                                                 break;
218                                         case "show_parser":
219                                                 show_parser = true;
220                                                 break;
221                                         case "-about":
222                                                 if (str[0] != '-')
223                                                         break;
224                                                 About ();
225                                                 break;
226                                         case "-version":
227                                                 if (str[0] != '-')
228                                                         break;
229                                                 Version ();
230                                                 break;
231                                         default:
232                                                 if (str [0] == '-')
233                                                         break;
234                                                 il_file_list.Add (str);
235                                                 break;
236                                         }
237                                 }
238                         }
239
240                         private string GetCommand (string str, out string command_arg)
241                         {
242                                 int end_index = str.IndexOfAny (new char[] {':', '='}, 1);
243                                 string command = str.Substring (1,
244                                         end_index == -1 ? str.Length - 1 : end_index - 1);
245
246                                 if (end_index != -1) {
247                                         command_arg = str.Substring (end_index+1);
248                                 } else {
249                                         command_arg = null;
250                                 }
251
252                                 return command.ToLower ();
253                         }
254
255                         /// <summary>
256                         ///   Get the first file name and makes it into an output file name
257                         /// </summary>
258                         private string CreateOutputFile ()
259                         {
260                                 string file_name = (string)il_file_list[0];
261                                 int ext_index = file_name.LastIndexOf ('.');
262
263                                 if (ext_index == -1)
264                                         ext_index = file_name.Length;
265
266                                 return String.Format ("{0}.{1}", file_name.Substring (0, ext_index),
267                                         target_string);
268                         }
269
270                         private void Usage ()
271                         {
272                                 Console.WriteLine ("Mono ILasm compiler\n" +
273                                         "ilasm [options] source-files\n" +
274                                         "   --about            About the Mono ILasm compiler\n" +
275                                         "   --version          Print the version number of the Mono ILasm compiler\n" +
276                                         "   /output:file_name  Specifies output file.\n" +
277                                         "   /exe               Compile to executable.\n" +
278                                         "   /dll               Compile to library.\n" +
279                                         "   /debug             Include debug information.\n" +
280                                         "Options can be of the form -option or /option\n");
281                                 Environment.Exit (1);
282                         }
283
284                         private void About ()
285                         {
286                                 Console.WriteLine (
287                                         "For more information on Mono, visit the project Web site\n" +
288                                         "   http://www.go-mono.com\n\n");
289                                 Environment.Exit (0);
290                         }
291
292                         private void Version ()
293                         {
294                                 string version = Assembly.GetExecutingAssembly ().GetName ().Version.ToString ();
295                                 Console.WriteLine ("Mono ILasm compiler version {0}", version);
296                                 Environment.Exit (0);
297                         }
298
299                 }
300         }
301 }
302