Old code
[mono.git] / mcs / mbas / driver.cs
1 //\r
2 // driver.cs: The compiler command line driver.\r
3 //\r
4 // Author: Rafael Teixeira (rafaelteixeirabr@hotmail.com)\r
5 // Based on mcs by : Miguel de Icaza (miguel@gnu.org)\r
6 //\r
7 // Licensed under the terms of the GNU GPL\r
8 //\r
9 // (C) 2002 Rafael Teixeira\r
10 //\r
11 \r
12 namespace Mono.Languages\r
13 {\r
14         using System;\r
15         using System.Reflection;\r
16         using System.Reflection.Emit;\r
17         using System.Collections;\r
18         using System.IO;\r
19         using System.Globalization;\r
20         using Mono.CSharp;\r
21         \r
22         enum Target {\r
23                 Library, Exe, Module, WinExe\r
24         };\r
25 \r
26         /// <summary>\r
27         ///    The compiler driver.\r
28         /// </summary>\r
29         public class Driver\r
30         {\r
31                 //\r
32                 // Assemblies references to be linked.   Initialized with\r
33                 // mscorlib.dll elsewhere.\r
34                 static ArrayList references;\r
35 \r
36                 // Lookup paths\r
37                 static ArrayList link_paths;\r
38 \r
39                 // Whether we want to only run the tokenizer\r
40                 static bool tokenize = false;\r
41                 \r
42                 static int error_count = 0;\r
43 \r
44                 static string first_source;\r
45 \r
46                 static Target target = Target.Exe;\r
47                 static string target_ext = ".exe";\r
48 \r
49                 static bool parse_only = false;\r
50                 static bool timestamps = false;\r
51  \r
52                 static Hashtable response_file_list;\r
53                 static Hashtable source_files = new Hashtable ();\r
54                 \r
55                 //\r
56                 // An array of the defines from the command line\r
57                 //\r
58                 static ArrayList defines;\r
59 \r
60                 //\r
61                 // A list of resource files\r
62                 //\r
63                 static ArrayList resources;\r
64 \r
65                 //\r
66                 // Last time we took the time\r
67                 //\r
68                 static DateTime last_time;\r
69                 static void ShowTime (string msg)\r
70                 {\r
71                         DateTime now = DateTime.Now;\r
72                         TimeSpan span = now - last_time;\r
73                         last_time = now;\r
74                         \r
75                         Console.WriteLine (\r
76                                 "[{0:00}:{1:000}] {2}",\r
77                                 span.Seconds, span.Milliseconds, msg);\r
78                 }\r
79                                 \r
80                 static void Usage (bool is_error)\r
81                 {\r
82                         Console.WriteLine (\r
83                                 "MonoBASIC compiler, (C) 2001 Rafael Teixeira.\n" +\r
84                                 "mcs [options] source-files\n" +\r
85                                 "   --about         About the MonoBASIC compiler\n" +\r
86                                 "   --checked       Set default context to checked\n" +\r
87                                 "   --define SYM    Defines the symbol SYM\n" + \r
88                                 "   --fatal         Makes errors fatal\n" +\r
89                                 "   -L PATH         Adds PATH to the assembly link path\n" +\r
90                                 "   --nostdlib      Does not load core libraries\n" +\r
91                                 "   --nowarn XXX    Ignores warning number XXX\n" +\r
92                                 "   -o FNAME        Specifies output file\n" +\r
93                                 "   --optimize      Optimizes\n" +\r
94                                 "   --parse         Only parses the source file\n" +\r
95                                 "   --probe X       Probes for the source to generate code X on line L\n" +\r
96                                 "   --resource FILE Addds FILE as a resource\n" + \r
97                                 "   --stacktrace    Shows stack trace at error location\n" +\r
98                                 "   --target KIND   Specifies the target (KIND is one of: exe, winexe, " +\r
99                                                     "library, module)\n" +\r
100                                 "   --timestamp     Displays time stamps of various compiler events\n" +\r
101                                 "   --unsafe        Allows unsafe code\n" +\r
102                                 "   --werror        Treat warnings as errors\n" +\r
103                                 "   --wlevel LEVEL  Sets warning level (the highest is 4, the default)\n" +\r
104                                 "   -r              References an assembly\n" +\r
105                                 "   -v              Verbose parsing (for debugging the parser)\n" +\r
106                                 "   @file           Read response file for more options");\r
107                         if (is_error)\r
108                                 error_count++;\r
109                 }\r
110 \r
111                 static void About ()\r
112                 {\r
113                         Console.WriteLine (\r
114                                 "The MonoBASIC compiler is (C) 2002 Rafael Teixeira\n\n" +\r
115                                 "The compiler source code is released under the terms of the GNU GPL\n\n" +\r
116 \r
117                                 "For more information on Mono, visit the project Web site\n" +\r
118                                 "   http://www.go-mono.com\n\n" +\r
119 \r
120                                 "The compiler was written by Rafael Teixeira and Miguel de Icaza and Ravi Pratap");\r
121                 }\r
122 \r
123                 static void error (string msg)\r
124                 {\r
125                         Console.WriteLine ("Error: " + msg);\r
126                 }\r
127 \r
128                 static void notice (string msg)\r
129                 {\r
130                         Console.WriteLine (msg);\r
131                 }\r
132                 \r
133                 public static int Main(string[] args)\r
134                 {\r
135                         MainDriver(args);\r
136 \r
137                         return (error_count + Report.Errors) != 0 ? 1 : 0;\r
138                 }\r
139 \r
140                 static public int LoadAssembly (string assembly)\r
141                 {\r
142                         Assembly a;\r
143                         string total_log = "";\r
144 \r
145                         try {\r
146                                 a = Assembly.Load (assembly);\r
147                                 RootContext.TypeManager.AddAssembly (a);\r
148                                 return 0;\r
149                         } catch (FileNotFoundException){\r
150                                 foreach (string dir in link_paths){\r
151                                         string full_path = dir + "/" + assembly + ".dll";\r
152 \r
153                                         try {\r
154                                                 a = Assembly.LoadFrom (full_path);\r
155                                                 RootContext.TypeManager.AddAssembly (a);\r
156                                                 return 0;\r
157                                         } catch (FileNotFoundException ff) {\r
158                                                 total_log += ff.FusionLog;\r
159                                                 continue;\r
160                                         }\r
161                                 }\r
162                         } catch (BadImageFormatException f) {\r
163                                 error ("// Bad file format while loading assembly");\r
164                                 error ("Log: " + f.FusionLog);\r
165                                 return 1;\r
166                         } catch (FileLoadException f){\r
167                                 error ("// File Load Exception: ");\r
168                                 error ("Log: " + f.FusionLog);\r
169                                 return 1;\r
170                         } catch (ArgumentNullException){\r
171                                 error ("// Argument Null exception ");\r
172                                 return 1;\r
173                         }\r
174                         \r
175                         Report.Error (6, "Can not find assembly `" + assembly + "'" );\r
176                         Console.WriteLine ("Log: \n" + total_log);\r
177 \r
178                         return 0;\r
179                 }\r
180 \r
181                 /// <summary>\r
182                 ///   Loads all assemblies referenced on the command line\r
183                 /// </summary>\r
184                 static public int LoadReferences ()\r
185                 {\r
186                         int errors = 0;\r
187                         \r
188                         foreach (string r in references){\r
189                                 errors += LoadAssembly (r);\r
190                         }\r
191 \r
192                         return errors;\r
193                 }\r
194 \r
195 \r
196                 static void SetupDefaultDefines ()\r
197                 {\r
198                         defines = new ArrayList ();\r
199                         defines.Add ("__MonoBASIC__");\r
200                 }\r
201 \r
202                 static string [] LoadArgs (string file)\r
203                 {\r
204                         StreamReader f;\r
205                         ArrayList args = new ArrayList ();\r
206                         string line;\r
207                         try {\r
208                                 f = new StreamReader (file);\r
209                         } catch {\r
210                                 return null;\r
211                         }\r
212  \r
213                         while ((line = f.ReadLine ()) != null){\r
214                                 string [] line_args = line.Split (new char [] { ' ' });\r
215 \r
216                                 foreach (string arg in line_args)\r
217                                         args.Add (arg);\r
218                         }\r
219 \r
220                         string [] ret_value = new string [args.Count];\r
221                         args.CopyTo (ret_value, 0);\r
222 \r
223                         return ret_value;\r
224                 }\r
225 \r
226                 //\r
227                 // Returns the directory where the system assemblies are installed\r
228                 //\r
229                 static string GetSystemDir ()\r
230                 {\r
231                         Assembly [] assemblies = AppDomain.CurrentDomain.GetAssemblies ();\r
232                         foreach (Assembly a in assemblies){\r
233                                 string codebase = a.CodeBase;\r
234                                 if (codebase.EndsWith ("corlib.dll")){\r
235                                         return codebase.Substring (0, codebase.LastIndexOf ("/"));\r
236                                 }\r
237                         }\r
238 \r
239                         Report.Error (-15, "Can not compute my system path");\r
240                         return "";\r
241                 }\r
242 \r
243                 //\r
244                 // Given a path specification, splits the path from the file/pattern\r
245                 //\r
246                 static void SplitPathAndPattern (string spec, out string path, out string pattern)\r
247                 {\r
248                         int p = spec.LastIndexOf ("/");\r
249                         if (p != -1){\r
250                                 //\r
251                                 // Windows does not like /file.cs, switch that to:\r
252                                 // "\", "file.cs"\r
253                                 //\r
254                                 if (p == 0){\r
255                                         path = "\\";\r
256                                         pattern = spec.Substring (1);\r
257                                 } else {\r
258                                         path = spec.Substring (0, p);\r
259                                         pattern = spec.Substring (p + 1);\r
260                                 }\r
261                                 return;\r
262                         }\r
263 \r
264                         p = spec.LastIndexOf ("\\");\r
265                         if (p != -1){\r
266                                 path = spec.Substring (0, p - 1);\r
267                                 pattern = spec.Substring (p);\r
268                                 return;\r
269                         }\r
270 \r
271                         path = ".";\r
272                         pattern = spec;\r
273                 }\r
274 \r
275                 static int ProcessFile (string f)\r
276                 {\r
277                         if (source_files.Contains (f)){\r
278                                 Report.Error (\r
279                                         1516,\r
280                                         "Source file `" + f + "' specified multiple times");\r
281                                 Environment.Exit (1);\r
282                         } else\r
283                                 source_files.Add (f, f);\r
284                                         \r
285                         if (tokenize)\r
286                                 GenericParser.Tokenize(f);\r
287                         else \r
288                                 return GenericParser.Parse(f);\r
289 \r
290                         return 0;\r
291                 }\r
292 \r
293                 static void RecurseOn (string pattern)\r
294                 {\r
295                         // FIXME: implement.\r
296                 }\r
297 \r
298                 /// <summary>\r
299                 ///    Parses the arguments, and drives the compilation\r
300                 ///    process.\r
301                 /// </summary>\r
302                 ///\r
303                 /// <remarks>\r
304                 ///    TODO: Mostly structured to debug the compiler\r
305                 ///    now, needs to be turned into a real driver soon.\r
306                 /// </remarks>\r
307                 static void MainDriver (string [] args)\r
308                 {\r
309                         int errors = 0, i;\r
310                         bool parsing_options = true;\r
311                         string output_file = null;\r
312 \r
313                         references = new ArrayList ();\r
314                         link_paths = new ArrayList ();\r
315 \r
316                         SetupDefaultDefines ();\r
317                         link_paths.Add (GetSystemDir ());\r
318                         \r
319                         int argc = args.Length;\r
320                         for (i = 0; i < argc; i++)\r
321                         {\r
322                                 string arg = args [i];\r
323                                 \r
324                                 if (arg.StartsWith ("@"))\r
325                                 {\r
326                                         string [] new_args, extra_args;\r
327                                         string response_file = arg.Substring (1);\r
328 \r
329                                         if (response_file_list == null)\r
330                                                 response_file_list = new Hashtable ();\r
331                                         \r
332                                         if (response_file_list.Contains (response_file)){\r
333                                                 Report.Error (\r
334                                                         1515, "Response file `" + response_file +\r
335                                                         "' specified multiple times");\r
336                                                 Environment.Exit (1);\r
337                                         }\r
338                                         \r
339                                         response_file_list.Add (response_file, response_file);\r
340                                                     \r
341                                         extra_args = LoadArgs (response_file);\r
342                                         if (extra_args == null){\r
343                                                 Report.Error (2011, "Unable to open response file: " +\r
344                                                               response_file);\r
345                                                 return;\r
346                                         }\r
347 \r
348                                         new_args = new string [extra_args.Length + argc];\r
349                                         args.CopyTo (new_args, 0);\r
350                                         extra_args.CopyTo (new_args, argc);\r
351                                         args = new_args;\r
352                                         argc = new_args.Length;\r
353                                         continue;\r
354                                 }\r
355 \r
356                                 try \r
357                                 {\r
358                                         //\r
359                                         // Prepare to recurse\r
360                                         //\r
361                                 \r
362                                         if (parsing_options && (arg.StartsWith ("-") || arg.StartsWith ("/")))\r
363                                         {\r
364                                                 switch (arg){\r
365                                                 case "--":\r
366                                                         parsing_options = false;\r
367                                                         continue;\r
368 \r
369                                                 case "-v":\r
370                                                         GenericParser.yacc_verbose_flag = true;\r
371                                                         continue;\r
372 \r
373                                                 case "--parse":\r
374                                                         parse_only = true;\r
375                                                         continue;                                       \r
376  \r
377                                                 case "--main": case "-m":\r
378                                                         if ((i + 1) >= argc){\r
379                                                                 Usage (true);\r
380                                                                 return;\r
381                                                         }\r
382                                                         RootContext.MainClass = args [++i];\r
383                                                         continue;\r
384         \r
385                                                 case "--unsafe":\r
386                                                         RootContext.Unsafe = true;\r
387                                                         continue;\r
388                                                 \r
389                                                 case "--optimize":\r
390                                                         RootContext.Optimize = true;\r
391                                                         continue;\r
392 \r
393                                                 case "/?": \r
394                                                 case "/h": \r
395                                                 case "/help":\r
396                                                 case "--help":\r
397                                                         Usage (false);\r
398                                                         return;\r
399         \r
400                                                 case "--define":\r
401                                                         if ((i + 1) >= argc)\r
402                                                         {\r
403                                                                 Usage (true);\r
404                                                                 return;\r
405                                                         }\r
406                                                         defines.Add (args [++i]);\r
407                                                         continue;\r
408                                                 \r
409                                                 case "--probe": {\r
410                                                         int code = 0;\r
411                                                         try {\r
412                                                                 code = Int32.Parse (\r
413                                                                         args [++i], NumberStyles.AllowLeadingSign);\r
414                                                                 Report.SetProbe (code);\r
415                                                         } catch {\r
416                                                                 Report.Error (-14, "Invalid number specified");\r
417                                                         } \r
418                                                         continue;\r
419                                                 }\r
420          \r
421                                                 case "--tokenize": {\r
422                                                         tokenize = true;\r
423                                                         continue;\r
424                                                 }\r
425                                         \r
426                                                 case "-o": \r
427                                                 case "--output":\r
428                                                         if ((i + 1) >= argc){\r
429                                                                 Usage (true);\r
430                                                                 return;\r
431                                                         }\r
432                                                         output_file = args [++i];\r
433                                                         continue;\r
434                                                 \r
435                                                 case "--checked":\r
436                                                         RootContext.Checked = true;\r
437                                                         continue;\r
438  \r
439                                                 case "--stacktrace":\r
440                                                         Report.Stacktrace = true;\r
441                                                         continue;\r
442                                                 \r
443                                                 case "--resource":\r
444                                                         if ((i + 1) >= argc){\r
445                                                                 Usage (true);\r
446                                                                 Console.WriteLine("Missing argument to --resource"); \r
447                                                                 return;\r
448                                                         }\r
449                                                         if (resources == null)\r
450                                                                 resources = new ArrayList ();\r
451                                                 \r
452                                                         resources.Add (args [++i]);\r
453                                                         continue;\r
454                                                         \r
455                                                 case "--target":\r
456                                                         if ((i + 1) >= argc){\r
457                                                                 Usage (true);\r
458                                                                 return;\r
459                                                         }\r
460  \r
461                                                         string type = args [++i];\r
462                                                         switch (type){\r
463                                                         case "library":\r
464                                                                 target = Target.Library;\r
465                                                                 target_ext = ".dll";\r
466                                                                 break;\r
467                                                                 \r
468                                                         case "exe":\r
469                                                                 target = Target.Exe;\r
470                                                                 break;\r
471                                                                 \r
472                                                         case "winexe":\r
473                                                                 target = Target.WinExe;\r
474                                                                 break;\r
475                                                                 \r
476                                                         case "module":\r
477                                                                 target = Target.Module;\r
478                                                                 target_ext = ".dll";\r
479                                                                 break;\r
480                                                         }\r
481                                                         continue;\r
482                                                 \r
483                                                 case "-r":\r
484                                                         if ((i + 1) >= argc){\r
485                                                                 Usage (true);\r
486                                                                 return;\r
487                                                         }\r
488                                                 \r
489                                                         references.Add (args [++i]);\r
490                                                         continue;\r
491                                                 \r
492                                                 case "-L":\r
493                                                         if ((i + 1) >= argc){\r
494                                                                 Usage (true);\r
495                                                                 return;\r
496                                                         }\r
497                                                         link_paths.Add (args [++i]);\r
498                                                         continue;\r
499                                                 \r
500                                                 case "--nostdlib":\r
501                                                         RootContext.StdLib = false;\r
502                                                         continue;\r
503                                                 \r
504                                                 case "--fatal":\r
505                                                         Report.Fatal = true;\r
506                                                         continue;\r
507         \r
508                                                 case "--werror":\r
509                                                         Report.WarningsAreErrors = true;\r
510                                                         continue;\r
511 \r
512                                                 case "--nowarn":\r
513                                                         if ((i + 1) >= argc){\r
514                                                                 Usage (true);\r
515                                                                 return;\r
516                                                         }\r
517                                                         int warn;\r
518                                                         \r
519                                                         try {\r
520                                                                 warn = Int32.Parse (args [++i]);\r
521                                                         } catch {\r
522                                                                 Usage (true);\r
523                                                                 return;\r
524                                                         }\r
525                                                         Report.SetIgnoreWarning (warn);\r
526                                                         continue;\r
527 \r
528                                                 case "--wlevel":\r
529                                                         if ((i + 1) >= argc){\r
530                                                                 Usage (true);\r
531                                                                 error_count++;\r
532                                                                 return;\r
533                                                         }\r
534                                                         int level;\r
535                                                 \r
536                                                         try {\r
537                                                                 level = Int32.Parse (args [++i]);\r
538                                                         } catch {\r
539                                                                 Usage (true);\r
540                                                                 return;\r
541                                                         }\r
542                                                         if (level < 0 || level > 4){\r
543                                                                 Report.Error (1900, "Warning level must be 0 to 4");\r
544                                                                 return;\r
545                                                         } else\r
546                                                                 RootContext.WarningLevel = level;\r
547                                                         continue;\r
548                                                 \r
549                                                 case "--about":\r
550                                                         About ();\r
551                                                         return;\r
552 \r
553                                                 case "--recurse":\r
554                                                         if ((i + 1) >= argc){\r
555                                                                 Usage (true);\r
556                                                                 error_count++;\r
557                                                                 return;\r
558                                                         }\r
559                                                         RecurseOn (args [++i]);\r
560                                                         continue;\r
561                                                 \r
562                                                 case "--timestamp":\r
563                                                         timestamps = true;\r
564                                                         last_time = DateTime.Now;\r
565                                                         continue;\r
566                                                 \r
567                                                 default:\r
568                                                         Usage (true);\r
569                                                         return;\r
570                                                 }\r
571                                         }\r
572                                 } catch (System.IndexOutOfRangeException){\r
573                                         Usage (true);\r
574                                         error_count++;\r
575                                         return;\r
576                                 } catch (System.FormatException) {\r
577                                         Usage (true);\r
578                                         error_count++;\r
579                                         return;\r
580                                 }\r
581 \r
582                                 if (first_source == null)\r
583                                         first_source = arg;\r
584 \r
585                                 string path, pattern;\r
586                                 SplitPathAndPattern (arg, out path, out pattern);\r
587                                 string [] files = null;\r
588                                 try {\r
589                                         files = Directory.GetFiles (path, pattern);\r
590                                 } catch (System.IO.DirectoryNotFoundException) {\r
591                                         Report.Error (2001, "Source file `" + arg + "' could not be found");\r
592                                         continue;\r
593                                 }\r
594                                 foreach (string f in files)\r
595                                         errors += ProcessFile (f);\r
596                         }\r
597 \r
598  \r
599                         if (tokenize)\r
600                                 return;\r
601 \r
602                         if (first_source == null){\r
603                                 Report.Error (2008, "No files to compile were specified");\r
604                                 return;\r
605                         }\r
606 \r
607                         if (Report.Errors > 0)\r
608                                 return;\r
609                         \r
610                         if (parse_only)\r
611                                 return;\r
612                         \r
613                         //\r
614                         // Load Core Library for default compilation\r
615                         //\r
616                         if (RootContext.StdLib){\r
617                                 references.Insert (0, "mscorlib");\r
618                                 references.Insert (1, "System");\r
619                         }\r
620 \r
621                         if (errors > 0){\r
622                                 error ("Parsing failed");\r
623                                 return;\r
624                         }\r
625 \r
626                         //\r
627                         // Load assemblies required\r
628                         //\r
629                         if (timestamps)\r
630                                 ShowTime ("Loading references");\r
631                         errors += LoadReferences ();\r
632                         if (timestamps)\r
633                                 ShowTime ("   References loaded");\r
634 \r
635                         if (errors > 0){\r
636                                 error ("Could not load one or more assemblies");\r
637                                 return;\r
638                         }\r
639         \r
640                         error_count = errors;\r
641 \r
642                         //\r
643                         // Quick hack\r
644                         //\r
645                         if (output_file == null){\r
646                                 int pos = first_source.LastIndexOf (".");\r
647 \r
648                                 if (pos > 0)\r
649                                         output_file = first_source.Substring (0, pos) + target_ext;\r
650                                 else\r
651                                         output_file = first_source + target_ext;\r
652                         }\r
653 \r
654                         RootContext.CodeGen = new CodeGen (output_file, output_file);\r
655 \r
656                         //\r
657                         // Before emitting, we need to get the core\r
658                         // types emitted from the user defined types\r
659                         // or from the system ones.\r
660                         //\r
661                         if (timestamps)\r
662                                 ShowTime ("Initializing Core Types");\r
663                         RootContext.TypeManager.InitCoreTypes ();\r
664                         if (timestamps)\r
665                                 ShowTime ("   Core Types done");\r
666 \r
667                         RootContext.TypeManager.AddModule (RootContext.CodeGen.ModuleBuilder);\r
668                         \r
669                         //\r
670                         // The second pass of the compiler\r
671                         //\r
672                         if (timestamps)\r
673                                 ShowTime ("Resolving tree");\r
674                         RootContext.ResolveTree ();\r
675                         if (timestamps)\r
676                                 ShowTime ("Populate tree");\r
677 \r
678                         if (Report.Errors > 0){\r
679                                 error ("Compilation failed");\r
680                                 return;\r
681                         }\r
682 \r
683                         RootContext.PopulateTypes ();\r
684                         \r
685                         if (Report.Errors > 0){\r
686                                 error ("Compilation failed");\r
687                                 return;\r
688                         }\r
689                         \r
690                         //\r
691                         // The code generator\r
692                         //\r
693                         if (timestamps)\r
694                                 ShowTime ("Emitting code");\r
695                         RootContext.EmitCode ();\r
696                         if (timestamps)\r
697                                 ShowTime ("   done");\r
698                         \r
699                         if (Report.Errors > 0){\r
700                                 error ("Compilation failed");\r
701                                 return;\r
702                         }\r
703                         \r
704                         if (timestamps)\r
705                                 ShowTime ("Closing types");\r
706                         \r
707                         RootContext.CloseTypes ();\r
708 \r
709                         PEFileKinds k = PEFileKinds.ConsoleApplication;\r
710                                 \r
711                         if (target == Target.Library || target == Target.Module)\r
712                                 k = PEFileKinds.Dll;\r
713                         else if (target == Target.Exe)\r
714                                 k = PEFileKinds.ConsoleApplication;\r
715                         else if (target == Target.WinExe)\r
716                                 k = PEFileKinds.WindowApplication;\r
717 \r
718                         if (target == Target.Exe || target == Target.WinExe){\r
719                                 MethodInfo ep = RootContext.EntryPoint;\r
720 \r
721                                 if (ep == null){\r
722                                         Report.Error (5001, "Program " + output_file +\r
723                                                               " does not have an entry point defined");\r
724                                         return;\r
725                                 }\r
726                                 \r
727                                 RootContext.CodeGen.AssemblyBuilder.SetEntryPoint (ep, k);\r
728                         }\r
729 \r
730                         //\r
731                         // Add the resources\r
732                         //\r
733                         if (resources != null)\r
734                         {\r
735                                 foreach (string file in resources)\r
736                                         RootContext.CodeGen.AssemblyBuilder.AddResourceFile (file, file);\r
737                         }\r
738                         \r
739                         RootContext.CodeGen.Save (output_file);\r
740                         if (timestamps)\r
741                                 ShowTime ("Saved output");\r
742 \r
743                         if (Report.Errors > 0){\r
744                                 error ("Compilation failed");\r
745                                 return;\r
746                         } else if (Report.ProbeCode != 0){\r
747                                 error ("Failed to report code " + Report.ProbeCode);\r
748                                 Environment.Exit (124);\r
749                         }\r
750                 }\r
751 \r
752         }\r
753 }\r