Updated list
[mono.git] / mcs / mbas / driver.diff
1 --- driver.cs   Tue Mar 19 19:15:50 2002
2 +++ ../mcs/driver.cs    Sat Mar 16 13:22:44 2002
3 @@ -1,15 +1,14 @@
4  //\r
5  // driver.cs: The compiler command line driver.\r
6  //\r
7 -// Author: Rafael Teixeira (rafaelteixeirabr@hotmail.com)\r
8 -// Based on mcs by : Miguel de Icaza (miguel@gnu.org)\r
9 +// Author: Miguel de Icaza (miguel@gnu.org)\r
10  //\r
11  // Licensed under the terms of the GNU GPL\r
12  //\r
13 -// (C) 2002 Rafael Teixeira\r
14 +// (C) 2001 Ximian, Inc (http://www.ximian.com)\r
15  //\r
16  \r
17 -namespace Mono.Languages\r
18 +namespace Mono.CSharp\r
19  {\r
20         using System;\r
21         using System.Reflection;\r
22 @@ -17,7 +16,7 @@
23         using System.Collections;\r
24         using System.IO;\r
25         using System.Globalization;\r
26 -       using Mono.CSharp;\r
27 +       using Mono.Languages;\r
28         \r
29         enum Target {\r
30                 Library, Exe, Module, WinExe\r
31 @@ -28,14 +27,18 @@
32         /// </summary>\r
33         public class Driver\r
34         {\r
35 +               \r
36                 //\r
37                 // Assemblies references to be linked.   Initialized with\r
38 -               // mscorlib.dll elsewhere.\r
39 +               // mscorlib.dll here.\r
40                 static ArrayList references;\r
41  \r
42                 // Lookup paths\r
43                 static ArrayList link_paths;\r
44  \r
45 +               // Whether we want Yacc to output its progress\r
46 +               static bool yacc_verbose = false;\r
47 +\r
48                 // Whether we want to only run the tokenizer\r
49                 static bool tokenize = false;\r
50                 \r
51 @@ -53,14 +56,14 @@
52                 static Hashtable source_files = new Hashtable ();\r
53                 \r
54                 //\r
55 -               // An array of the defines from the command line\r
56 +               // A list of resource files\r
57                 //\r
58 -               static ArrayList defines;\r
59 +               static ArrayList resources;\r
60  \r
61                 //\r
62 -               // A list of resource files\r
63 +               // An array of the defines from the command line\r
64                 //\r
65 -               static ArrayList resources;\r
66 +               static ArrayList defines;\r
67  \r
68                 //\r
69                 // Last time we took the time\r
70 @@ -77,17 +80,75 @@
71                                 span.Seconds, span.Milliseconds, msg);\r
72                 }\r
73                                 \r
74 +               static int tokenize_file (string input_file)\r
75 +               {\r
76 +                       Stream input;\r
77 +\r
78 +                       try {\r
79 +                               input = File.OpenRead (input_file);\r
80 +\r
81 +                       } catch {\r
82 +                               Report.Error (2001, "Source file '" + input_file + "' could not be opened");\r
83 +                               return 1;\r
84 +                       }\r
85 +\r
86 +                       using (input){\r
87 +                               Tokenizer lexer = new Tokenizer (input, input_file, defines);\r
88 +                               int token, tokens = 0, errors = 0;\r
89 +\r
90 +                               while ((token = lexer.token ()) != Token.EOF){\r
91 +                                       Location l = lexer.Location;\r
92 +                                       tokens++;\r
93 +                                       if (token == Token.ERROR)\r
94 +                                               errors++;\r
95 +                               }\r
96 +                               Console.WriteLine ("Tokenized: " + tokens + " found " + errors + " errors");\r
97 +                       }\r
98 +                       \r
99 +                       return 0;\r
100 +               }\r
101 +               \r
102 +               static int parse (string input_file)\r
103 +               {\r
104 +                       CSharpParser parser;\r
105 +                       Stream input;\r
106 +                       int errors;\r
107 +\r
108 +                       try {\r
109 +                               input = File.OpenRead (input_file);\r
110 +                       } catch {\r
111 +                               Report.Error (2001, "Source file '" + input_file + "' could not be opened");\r
112 +                               return 1;\r
113 +                       }\r
114 +\r
115 +                       parser = new CSharpParser (input_file, input, defines);\r
116 +                       parser.yacc_verbose = yacc_verbose;\r
117 +                       try {\r
118 +                               errors = parser.parse ();\r
119 +                       } catch (Exception ex) {\r
120 +                               Console.WriteLine (ex);\r
121 +                               Console.WriteLine ("Compilation aborted");\r
122 +                               return 1;\r
123 +                       } finally {\r
124 +                               input.Close ();\r
125 +                       }\r
126 +                       \r
127 +                       return errors;\r
128 +               }\r
129 +               \r
130                 static void Usage (bool is_error)\r
131                 {\r
132                         Console.WriteLine (\r
133 -                               "MonoBASIC compiler, (C) 2001 Rafael Teixeira.\n" +\r
134 +                               "Mono C# compiler, (C) 2001 Ximian, Inc.\n" +\r
135                                 "mcs [options] source-files\n" +\r
136 +                               "   --about         About the Mono C# compiler\n" +\r
137                                 "   --checked       Set default context to checked\n" +\r
138                                 "   --define SYM    Defines the symbol SYM\n" + \r
139                                 "   --fatal         Makes errors fatal\n" +\r
140                                 "   -L PATH         Adds PATH to the assembly link path\n" +\r
141                                 "   --nostdlib      Does not load core libraries\n" +\r
142                                 "   --nowarn XXX    Ignores warning number XXX\n" +\r
143 +                               "   -o FNAME        Specifies output file\n" +\r
144                                 "   --optimize      Optimizes\n" +\r
145                                 "   --parse         Only parses the source file\n" +\r
146                                 "   --probe X       Probes for the source to generate code X on line L\n" +\r
147 @@ -109,13 +170,13 @@
148                 static void About ()\r
149                 {\r
150                         Console.WriteLine (\r
151 -                               "The MonoBASIC compiler is (C) 2002 Rafael Teixeira\n\n" +\r
152 +                               "The Mono C# compiler is (C) 2001 Ximian, Inc.\n\n" +\r
153                                 "The compiler source code is released under the terms of the GNU GPL\n\n" +\r
154  \r
155                                 "For more information on Mono, visit the project Web site\n" +\r
156                                 "   http://www.go-mono.com\n\n" +\r
157  \r
158 -                               "The compiler was written by Rafael Teixeira and Miguel de Icaza and Ravi Pratap");\r
159 +                               "The compiler was written by Miguel de Icaza and Ravi Pratap");\r
160                 }\r
161  \r
162                 static void error (string msg)\r
163 @@ -128,11 +189,11 @@
164                         Console.WriteLine (msg);\r
165                 }\r
166                 \r
167 -               static int Main(string[] args)\r
168 +               public static int Main (string[] args)\r
169                 {\r
170 -                       MainDriver(args);\r
171 +                       MainDriver (args);\r
172  \r
173 -                       return error_count;\r
174 +                       return (error_count + Report.Errors) != 0 ? 1 : 0;\r
175                 }\r
176  \r
177                 static public int LoadAssembly (string assembly)\r
178 @@ -183,19 +244,16 @@
179                 {\r
180                         int errors = 0;\r
181                         \r
182 -                       foreach (string r in references){\r
183 +                       foreach (string r in references)\r
184                                 errors += LoadAssembly (r);\r
185 -                       }\r
186  \r
187                         return errors;\r
188                 }\r
189  \r
190 -\r
191                 static void SetupDefaultDefines ()\r
192                 {\r
193                         defines = new ArrayList ();\r
194                         defines.Add ("__MonoCS__");\r
195 -                       defines.Add ("__MonoBASIC__");\r
196                 }\r
197  \r
198                 static string [] LoadArgs (string file)\r
199 @@ -228,9 +286,70 @@
200                 static string GetSystemDir ()\r
201                 {\r
202                         Assembly [] assemblies = AppDomain.CurrentDomain.GetAssemblies ();\r
203 -                       string s = assemblies [0].CodeBase;\r
204                         \r
205 -                       return s.Substring (0, s.LastIndexOf ("/"));\r
206 +                       foreach (Assembly a in assemblies){\r
207 +                               string codebase = a.CodeBase;\r
208 +                               if (codebase.EndsWith ("corlib.dll")){\r
209 +                                       return codebase.Substring (0, codebase.LastIndexOf ("/"));\r
210 +                               }\r
211 +                       }\r
212 +\r
213 +                       Report.Error (-15, "Can not compute my system path");\r
214 +                       return "";\r
215 +               }\r
216 +\r
217 +               //\r
218 +               // Given a path specification, splits the path from the file/pattern\r
219 +               //\r
220 +               static void SplitPathAndPattern (string spec, out string path, out string pattern)\r
221 +               {\r
222 +                       int p = spec.LastIndexOf ("/");\r
223 +                       if (p != -1){\r
224 +                               //\r
225 +                               // Windows does not like /file.cs, switch that to:\r
226 +                               // "\", "file.cs"\r
227 +                               //\r
228 +                               if (p == 0){\r
229 +                                       path = "\\";\r
230 +                                       pattern = spec.Substring (1);\r
231 +                               } else {\r
232 +                                       path = spec.Substring (0, p);\r
233 +                                       pattern = spec.Substring (p + 1);\r
234 +                               }\r
235 +                               return;\r
236 +                       }\r
237 +\r
238 +                       p = spec.LastIndexOf ("\\");\r
239 +                       if (p != -1){\r
240 +                               path = spec.Substring (0, p - 1);\r
241 +                               pattern = spec.Substring (p);\r
242 +                               return;\r
243 +                       }\r
244 +\r
245 +                       path = ".";\r
246 +                       pattern = spec;\r
247 +               }\r
248 +\r
249 +               static int ProcessFile (string f)\r
250 +               {\r
251 +                       if (source_files.Contains (f)){\r
252 +                               Report.Error (\r
253 +                                       1516,\r
254 +                                       "Source file `" + f + "' specified multiple times");\r
255 +                               Environment.Exit (1);\r
256 +                       } else\r
257 +                               source_files.Add (f, f);\r
258 +                                       \r
259 +                       if (tokenize)\r
260 +                               tokenize_file (f);\r
261 +                       else\r
262 +                               return parse (f);\r
263 +                       return 0;\r
264 +               }\r
265 +\r
266 +               static void RecurseOn (string pattern)\r
267 +               {\r
268 +                       // FIXME: implement.\r
269                 }\r
270  \r
271                 /// <summary>\r
272 @@ -246,20 +365,26 @@
273                 {\r
274                         int errors = 0, i;\r
275                         string output_file = null;\r
276 +                       bool parsing_options = true;\r
277  \r
278                         references = new ArrayList ();\r
279                         link_paths = new ArrayList ();\r
280  \r
281                         SetupDefaultDefines ();\r
282 +                       \r
283 +                       //\r
284 +                       // Setup defaults\r
285 +                       //\r
286 +                       // This is not required because Assembly.Load knows about this\r
287 +                       // path.\r
288 +                       //\r
289                         link_paths.Add (GetSystemDir ());\r
290                         \r
291                         int argc = args.Length;\r
292 -                       for (i = 0; i < argc; i++)\r
293 -                       {\r
294 +                       for (i = 0; i < argc; i++){\r
295                                 string arg = args [i];\r
296                                 \r
297 -                               if (arg.StartsWith ("@"))\r
298 -                               {\r
299 +                               if (arg.StartsWith ("@")){\r
300                                         string [] new_args, extra_args;\r
301                                         string response_file = arg.Substring (1);\r
302  \r
303 @@ -290,13 +415,18 @@
304                                         continue;\r
305                                 }\r
306  \r
307 -                               try \r
308 -                               {\r
309 -                                       if (arg.StartsWith ("-"))\r
310 -                                       {\r
311 +                               //\r
312 +                               // Prepare to recurse\r
313 +                               //\r
314 +                               \r
315 +                               if (parsing_options && (arg.StartsWith ("-") || arg.StartsWith ("/"))){\r
316                                                 switch (arg){\r
317                                                 case "-v":\r
318 -                                                       GenericParser.yacc_verbose_flag = true;\r
319 +                                               yacc_verbose = true;\r
320 +                                               continue;\r
321 +\r
322 +                                       case "--":\r
323 +                                               parsing_options = false;\r
324                                                         continue;\r
325  \r
326                                                 case "--parse":\r
327 @@ -319,13 +449,13 @@
328                                                         RootContext.Optimize = true;\r
329                                                         continue;\r
330  \r
331 +                                       case "/?": case "/h": case "/help":\r
332                                                 case "--help":\r
333                                                         Usage (false);\r
334                                                         return;\r
335         \r
336                                                 case "--define":\r
337 -                                                       if ((i + 1) >= argc)\r
338 -                                                       {\r
339 +                                               if ((i + 1) >= argc){\r
340                                                                 Usage (true);\r
341                                                                 return;\r
342                                                         }\r
343 @@ -334,6 +464,7 @@
344                                                 \r
345                                                 case "--probe": {\r
346                                                         int code = 0;\r
347 +\r
348                                                         try {\r
349                                                                 code = Int32.Parse (\r
350                                                                         args [++i], NumberStyles.AllowLeadingSign);\r
351 @@ -349,12 +480,16 @@
352                                                         continue;\r
353                                                 }\r
354                                         \r
355 -                                               case "-o": case "--output":\r
356 +                                       case "-o": \r
357 +                                       case "--output":\r
358                                                         if ((i + 1) >= argc){\r
359                                                                 Usage (true);\r
360                                                                 return;\r
361                                                         }\r
362                                                         output_file = args [++i];\r
363 +                                               string bname = CodeGen.Basename (output_file);\r
364 +                                               if (bname.IndexOf (".") == -1)\r
365 +                                                       output_file += ".exe";\r
366                                                         continue;\r
367                                                 \r
368                                                 case "--checked":\r
369 @@ -365,6 +500,18 @@
370                                                         Report.Stacktrace = true;\r
371                                                         continue;\r
372                                                 \r
373 +                                       case "--resource":\r
374 +                                               if ((i + 1) >= argc){\r
375 +                                                       Usage (true);\r
376 +                                                       Console.WriteLine("Missing argument to --resource"); \r
377 +                                                       return;\r
378 +                                               }\r
379 +                                               if (resources == null)\r
380 +                                                       resources = new ArrayList ();\r
381 +                                               \r
382 +                                               resources.Add (args [++i]);\r
383 +                                               continue;\r
384 +                                                       \r
385                                                 case "--target":\r
386                                                         if ((i + 1) >= argc){\r
387                                                                 Usage (true);\r
388 @@ -463,51 +610,39 @@
389                                                         About ();\r
390                                                         return;\r
391  \r
392 +                                       case "--recurse":\r
393 +                                               if ((i + 1) >= argc){\r
394 +                                                       Usage (true);\r
395 +                                                       error_count++;\r
396 +                                                       return;\r
397 +                                               }\r
398 +                                               RecurseOn (args [++i]);\r
399 +                                               continue;\r
400 +                                               \r
401                                                 case "--timestamp":\r
402                                                         timestamps = true;\r
403                                                         last_time = DateTime.Now;\r
404                                                         continue;\r
405 -                                               \r
406 -                                               default:\r
407 -                                                       Usage (true);\r
408 -                                                       return;\r
409 -                                               }\r
410                                         }\r
411 -                               } catch (System.IndexOutOfRangeException){\r
412 -                                       Usage (true);\r
413 -                                       error_count++;\r
414 -                                       return;\r
415 -                               } catch (System.FormatException) {\r
416 -                                       Usage (true);\r
417 -                                       error_count++;\r
418 -                                       return;\r
419                                 }\r
420  \r
421                                 if (first_source == null)\r
422                                         first_source = arg;\r
423  \r
424 -                               string [] files = Directory.GetFiles (".", arg);\r
425 -                               \r
426 -                               foreach (string f in files)\r
427 -                               {\r
428 -                                       if (source_files.Contains(f))\r
429 -                                       {\r
430 -                                               Report.Error (\r
431 -                                                       1516,\r
432 -                                                       "Source file `" + f + "' specified multiple times");\r
433 -                                               Environment.Exit(1);\r
434 +                               string path, pattern;\r
435 +                               SplitPathAndPattern (arg, out path, out pattern);\r
436 +                               string [] files = null;\r
437 +                               try {\r
438 +                                       files = Directory.GetFiles (path, pattern);\r
439 +                               } catch (System.IO.DirectoryNotFoundException) {\r
440 +                                       Report.Error (2001, "Source file `" + arg + "' could not be found");\r
441 +                                       continue;\r
442                                         } \r
443 -                                       else\r
444 -                                               source_files.Add(f, f);\r
445                                         \r
446 -                                       if (tokenize)\r
447 -                                               GenericParser.Tokenize(f);\r
448 -                                       else \r
449 -                                               errors += GenericParser.Parse(f);\r
450 -                               }\r
451 +                               foreach (string f in files)\r
452 +                                       errors += ProcessFile (f);\r
453                         }\r
454  \r
455\r
456                         if (tokenize)\r
457                                 return;\r
458  \r
459 @@ -565,6 +700,8 @@
460  \r
461                         RootContext.CodeGen = new CodeGen (output_file, output_file);\r
462  \r
463 +                       RootContext.TypeManager.AddModule (RootContext.CodeGen.ModuleBuilder);\r
464 +\r
465                         //\r
466                         // Before emitting, we need to get the core\r
467                         // types emitted from the user defined types\r
468 @@ -576,8 +713,6 @@
469                         if (timestamps)\r
470                                 ShowTime ("   Core Types done");\r
471  \r
472 -                       RootContext.TypeManager.AddModule (RootContext.CodeGen.ModuleBuilder);\r
473 -                       \r
474                         //\r
475                         // The second pass of the compiler\r
476                         //\r
477 @@ -586,12 +721,6 @@
478                         RootContext.ResolveTree ();\r
479                         if (timestamps)\r
480                                 ShowTime ("Populate tree");\r
481 -\r
482 -                       if (Report.Errors > 0){\r
483 -                               error ("Compilation failed");\r
484 -                               return;\r
485 -                       }\r
486 -\r
487                         RootContext.PopulateTypes ();\r
488                         \r
489                         if (Report.Errors > 0){\r
490 @@ -637,6 +766,14 @@
491                                 }\r
492                                 \r
493                                 RootContext.CodeGen.AssemblyBuilder.SetEntryPoint (ep, k);\r
494 +                       }\r
495 +\r
496 +                       //\r
497 +                       // Add the resources\r
498 +                       //\r
499 +                       if (resources != null){\r
500 +                               foreach (string file in resources)\r
501 +                                       RootContext.CodeGen.AssemblyBuilder.AddResourceFile (file, file);\r
502                         }\r
503                         \r
504                         RootContext.CodeGen.Save (output_file);\r