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