2002-06-15 Rafael Teixeira <rafaelteixeirabr@hotmail.com>
[mono.git] / mcs / mbas / driver.cs
1 //
2 // driver.cs: The compiler command line driver.
3 //
4 // Author: Rafael Teixeira (rafaelteixeirabr@hotmail.com)
5 // Based on mcs by : Miguel de Icaza (miguel@gnu.org)
6 //
7 // Licensed under the terms of the GNU GPL
8 //
9 // (C) 2002 Rafael Teixeira
10 //
11
12 namespace Mono.Languages
13 {
14         using System;
15         using System.Reflection;
16         using System.Reflection.Emit;
17         using System.Collections;
18         using System.IO;
19         using System.Globalization;
20         using Mono.CSharp;
21
22         enum Target {
23                 Library, Exe, Module, WinExe
24         };
25         
26         /// <summary>
27         ///    The compiler driver.
28         /// </summary>
29         public class Driver
30         {
31                 
32                 //
33                 // Assemblies references to be linked.   Initialized with
34                 // mscorlib.dll elsewhere.
35                 static ArrayList references;
36
37                 //
38                 // If any of these fail, we ignore the problem.  This is so
39                 // that we can list all the assemblies in Windows and not fail
40                 // if they are missing on Linux.
41                 //
42                 static ArrayList soft_references;
43
44                 // Lookup paths
45                 static ArrayList link_paths;
46
47                 // Whether we want to only run the tokenizer
48                 static bool tokenize = false;
49                 
50                 static int error_count = 0;
51
52                 static string first_source;
53
54                 static Target target = Target.Exe;
55                 static string target_ext = ".exe";
56
57                 static bool want_debugging_support = false;
58                 static ArrayList debug_arglist = new ArrayList ();
59
60                 static bool parse_only = false;
61                 static bool timestamps = false;
62
63                 //
64                 // Whether to load the initial config file (what CSC.RSP has by default)
65                 // 
66                 static bool load_default_config = true;
67
68                 static Hashtable response_file_list;
69                 static Hashtable source_files = new Hashtable ();
70
71                 //
72                 // An array of the defines from the command line
73                 //
74                 static ArrayList defines;
75
76                 //
77                 // A list of resource files
78                 //
79                 static ArrayList resources = new ArrayList();
80                 
81                 //
82                 // Last time we took the time
83                 //
84                 static DateTime last_time;
85                 static void ShowTime (string msg)
86                 {
87                         DateTime now = DateTime.Now;
88                         TimeSpan span = now - last_time;
89                         last_time = now;
90
91                         Console.WriteLine (
92                                 "[{0:00}:{1:000}] {2}",
93                                 (int) span.TotalSeconds, span.Milliseconds, msg);
94                 }
95                
96                 
97                 static void Usage (bool is_error)
98                 {
99                         Console.WriteLine (     @"
100 MonoBASIC Compiler, Copyright (C)2002 Rafael Teixeira.
101 Usage: mbas [options] source-files
102 Options:
103   --about         About the MonoBASIC compiler
104   --checked       Set default context to checked
105   --define SYM    Defines the symbol SYM
106   --fatal         Makes errors fatal
107   -g, --debug     Write symbolic debugging information to FILE-debug.s
108   -h, --help      Prints this usage instructions
109   -L PATH         Adds PATH to the assembly link path
110   -m CLASS,
111   --main CLASS    Specifies CLASS as main (starting) class
112   --noconfig      Disables implicit references to assemblies
113   --nostdlib      Does not load core libraries
114   --nowarn XXX    Ignores warning number XXX
115   -o FNAME,
116   --output FNAME  Specifies output file
117   --optimize      Optimizes
118   --parse         Only parses the source file (for debugging the tokenizer)
119   --probe X       Probes for the source to generate code X on line L
120   -r ASSEMBLY     References an assembly
121   --recurse SPEC  Recursively compiles the files in SPEC ([dir]/file)
122   --resource FILE Adds FILE as a resource
123   --stacktrace    Shows stack trace at error location
124   --target KIND   Specifies the target (KIND is one of: exe, winexe, library, module)
125   --tokenize      Only tokenizes source files
126   --timestamp     Displays time stamps of various compiler events
127   --unsafe        Allows unsafe code
128   --werror        Treat warnings as errors
129   -v              Verbose parsing (for debugging the parser)
130   --wlevel LEVEL  Sets warning level (the highest is 4, the default)
131   @file           Read response file for more options
132 ");
133
134                 }
135
136
137                 static void About ()
138                 {
139                         Options.ShowAbout();
140                 }
141                 
142                 static void error (string msg)
143                 {
144                         Console.WriteLine ("Error: " + msg);
145                 }
146
147                 static void notice (string msg)
148                 {
149                         Console.WriteLine (msg);
150                 }
151                 
152                 private static Mono.GetOptions.OptionList Options;
153
154                 private static bool SetVerboseParsing(object nothing)
155                 {
156                         GenericParser.yacc_verbose_flag = true;
157                         return true;
158                 }
159
160                 public static int Main (string[] args)
161                 {
162                         Options = new Mono.GetOptions.OptionList("The compiler source code is released under the terms of the GNU GPL\n\n" +
163                                 "For more information on Mono, visit the project Web site\n" +
164                                 "   http://www.go-mono.com" , "mbas [options] source-files");
165                         Options.AddAbout(' ',"about", "About the MonoBASIC compiler");
166                         Options.AddBooleanSwitch ('v',"verbose", "Verbose parsing (for debugging the parser)", false, new Mono.GetOptions.OptionFound(SetVerboseParsing) );
167                         MainDriver(args);       
168                         return (error_count + Report.Errors) != 0 ? 1 : 0;
169                 }
170
171                 static public int LoadAssembly (string assembly, bool soft)
172                 {
173                         Assembly a;
174                         string total_log = "";
175
176                         try {
177                                 char[] path_chars = { '/', '\\', '.' };
178
179                                 if (assembly.IndexOfAny (path_chars) != -1)
180                                         a = Assembly.LoadFrom (assembly);
181                                 else
182                                         a = Assembly.Load (assembly);
183                                 TypeManager.AddAssembly (a);
184                                 return 0;
185                         } catch (FileNotFoundException){
186                                 foreach (string dir in link_paths){
187                                         string full_path = dir + "/" + assembly + ".dll";
188
189                                         try {
190                                                 a = Assembly.LoadFrom (full_path);
191                                                 TypeManager.AddAssembly (a);
192                                                 return 0;
193                                         } catch (FileNotFoundException ff) {
194                                                 total_log += ff.FusionLog;
195                                                 continue;
196                                         }
197                                 }
198                                 if (soft)
199                                         return 0;
200                         } catch (BadImageFormatException f) {
201                                 error ("// Bad file format while loading assembly");
202                                 error ("Log: " + f.FusionLog);
203                                 return 1;
204                         } catch (FileLoadException f){
205                                 error ("File Load Exception: " + assembly);
206                                 error ("Log: " + f.FusionLog);
207                                 return 1;
208                         } catch (ArgumentNullException){
209                                 error ("// Argument Null exception ");
210                                 return 1;
211                         }
212                         
213                         Report.Error (6, "Can not find assembly `" + assembly + "'" );
214                         Console.WriteLine ("Log: \n" + total_log);
215
216                         return 0;
217                 }
218
219                 /// <summary>
220                 ///   Loads all assemblies referenced on the command line
221                 /// </summary>
222                 static public int LoadReferences ()
223                 {
224                         int errors = 0;
225
226                         foreach (string r in references)
227                                 errors += LoadAssembly (r, false);
228
229                         foreach (string r in soft_references)
230                                 errors += LoadAssembly (r, true);
231                         
232                         return errors;
233                 }
234
235                 static void SetupDefaultDefines ()
236                 {
237                         defines = new ArrayList ();
238                         defines.Add ("__MonoBASIC__");
239                 }
240
241                 static string [] LoadArgs (string file)
242                 {
243                         StreamReader f;
244                         ArrayList args = new ArrayList ();
245                         string line;
246                         try {
247                                 f = new StreamReader (file);
248                         } catch {
249                                 return null;
250                         }
251
252                         while ((line = f.ReadLine ()) != null){
253                                 string [] line_args = line.Split (new char [] { ' ' });
254
255                                 foreach (string arg in line_args)
256                                         args.Add (arg);
257                         }
258
259                         string [] ret_value = new string [args.Count];
260                         args.CopyTo (ret_value, 0);
261
262                         return ret_value;
263                 }
264
265                 //
266                 // Returns the directory where the system assemblies are installed
267                 //
268                 static string GetSystemDir ()
269                 {
270                         Assembly [] assemblies = AppDomain.CurrentDomain.GetAssemblies ();
271
272                         foreach (Assembly a in assemblies){
273                                 string codebase = a.CodeBase;
274                                 if (codebase.EndsWith ("corlib.dll")){
275                                         return codebase.Substring (0, codebase.LastIndexOf ("/"));
276                                 }
277                         }
278
279                         Report.Error (-15, "Can not compute my system path");
280                         return "";
281                 }
282
283                 //
284                 // Given a path specification, splits the path from the file/pattern
285                 //
286                 static void SplitPathAndPattern (string spec, out string path, out string pattern)
287                 {
288                         int p = spec.LastIndexOf ("/");
289                         if (p != -1){
290                                 //
291                                 // Windows does not like /file.cs, switch that to:
292                                 // "\", "file.cs"
293                                 //
294                                 if (p == 0){
295                                         path = "\\";
296                                         pattern = spec.Substring (1);
297                                 } else {
298                                         path = spec.Substring (0, p);
299                                         pattern = spec.Substring (p + 1);
300                                 }
301                                 return;
302                         }
303
304                         p = spec.LastIndexOf ("\\");
305                         if (p != -1){
306                                 path = spec.Substring (0, p);
307                                 pattern = spec.Substring (p + 1);
308                                 return;
309                         }
310
311                         path = ".";
312                         pattern = spec;
313                 }
314
315                 static int AddFile(string f)
316                 {
317                         if (first_source == null)
318                                 first_source = f;
319
320                         if (source_files.Contains (f)){
321                                 Report.Error (
322                                         1516,
323                                         "Source file `" + f + "' specified multiple times");
324                                 Environment.Exit(1);
325                         } else
326                                 source_files.Add(f, f);
327                                         
328                         return 0;
329                 }
330
331                 static int ProcessSourceFile(string filename)
332                 {
333                         if (tokenize)
334                                 GenericParser.Tokenize(filename);
335                         else
336                                 return GenericParser.Parse(filename);
337
338                         return 0;
339                 }
340
341                 static int AddFiles (string spec, bool recurse)
342                 {
343                         string path, pattern;
344                         int errors = 0;
345
346                         SplitPathAndPattern (spec, out path, out pattern);
347                         if (pattern.IndexOf ("*") == -1){
348                                 return AddFile (spec);
349                         }
350
351                         string [] files = null;
352                         try {
353                                 files = Directory.GetFiles (path, pattern);
354                         } catch (System.IO.DirectoryNotFoundException) {
355                                 Report.Error (2001, "Source file `" + spec + "' could not be found");
356                                 return 1;
357                         } catch (System.IO.IOException){
358                                 Report.Error (2001, "Source file `" + spec + "' could not be found");
359                                 return 1;
360                         }
361                         foreach (string f in files)
362                                 errors += AddFile (f);
363
364                         if (!recurse)
365                                 return errors;
366                         
367                         string [] dirs = null;
368
369                         try {
370                                 dirs = Directory.GetDirectories (path);
371                         } catch {
372                         }
373                         
374                         foreach (string d in dirs) {
375                                         
376                                 // Don't include path in this string, as each
377                                 // directory entry already does
378                                 errors += AddFiles (d + "/" + pattern, true);
379                         }
380                         
381
382                         return errors;
383                 }
384
385                 static void DefineDefaultConfig ()
386                 {
387                         //
388                         // For now the "default config" is harcoded into the compiler
389                         // we can move this outside later
390                         //
391                         string [] default_config = 
392                         {
393                                 "System",
394                                 "System.Data",
395                                 "System.Xml",
396                                 "Microsoft.VisualBasic", // just for now
397 #if false
398                                 //
399                                 // Is it worth pre-loading all this stuff?
400                                 //
401                                 "Accessibility",
402                                 "System.Configuration.Install",
403                                 "System.Design",
404                                 "System.DirectoryServices",
405                                 "System.Drawing.Design",
406                                 "System.Drawing",
407                                 "System.EnterpriseServices",
408                                 "System.Management",
409                                 "System.Messaging",
410                                 "System.Runtime.Remoting",
411                                 "System.Runtime.Serialization.Formatters.Soap",
412                                 "System.Security",
413                                 "System.ServiceProcess",
414                                 "System.Web",
415                                 "System.Web.RegularExpressions",
416                                 "System.Web.Services",
417                                 "System.Windows.Forms"
418 #endif
419                         };
420                         
421                         int p = 0;
422                         foreach (string def in default_config)
423                                 soft_references.Insert (p++, def);
424                 }
425                 
426                 /// <summary>
427                 ///    Parses the arguments, and drives the compilation
428                 ///    process.
429                 /// </summary>
430                 ///
431                 /// <remarks>
432                 ///    TODO: Mostly structured to debug the compiler
433                 ///    now, needs to be turned into a real driver soon.
434                 /// </remarks>
435                 static void MainDriver (string [] args)
436                 {
437                         int errors = 0, i;
438                         string output_file = null;
439                         bool parsing_options = true;
440                         
441                         references = new ArrayList ();
442                         soft_references = new ArrayList ();
443                         link_paths = new ArrayList ();
444                         SetupDefaultDefines ();
445                         
446                         //
447                         // Setup defaults
448                         //
449                         // This is not required because Assembly.Load knows about this
450                         // path.
451                         //
452                         link_paths.Add (GetSystemDir ());
453
454                         Options.ProcessArgs(args);
455                         return; 
456
457                         int argc = args.Length;
458                         for (i = 0; i < argc; i++){
459                                 string arg = args [i];
460
461                                 if (arg.StartsWith ("@")){
462                                         string [] new_args, extra_args;
463                                         string response_file = arg.Substring (1);
464
465                                         if (response_file_list == null)
466                                                 response_file_list = new Hashtable ();
467                                         
468                                         if (response_file_list.Contains (response_file)){
469                                                 Report.Error (
470                                                         1515, "Response file `" + response_file +
471                                                         "' specified multiple times");
472                                                 Environment.Exit (1);
473                                         }
474                                         
475                                         response_file_list.Add (response_file, response_file);
476                                                     
477                                         extra_args = LoadArgs (response_file);
478                                         if (extra_args == null){
479                                                 Report.Error (2011, "Unable to open response file: " +
480                                                               response_file);
481                                                 return;
482                                         }
483
484                                         new_args = new string [extra_args.Length + argc];
485                                         args.CopyTo (new_args, 0);
486                                         extra_args.CopyTo (new_args, argc);
487                                         args = new_args;
488                                         argc = new_args.Length;
489                                         continue;
490                                 }
491
492                                 //
493                                 // Prepare to recurse
494                                 //
495                                 
496                                 if (parsing_options && (arg.StartsWith ("-"))){
497                                         switch (arg){
498                                         case "-v":
499                                                 GenericParser.yacc_verbose_flag = true;
500                                                 continue;
501
502                                         case "--":
503                                                 parsing_options = false;
504                                                 continue;
505
506                                         case "--parse":
507                                                 parse_only = true;
508                                                 continue;
509
510                                         case "--main": case "-m":
511                                                 if ((i + 1) >= argc){
512                                                         Usage (true);
513                                                         return;
514                                                 }
515                                                 RootContext.MainClass = args [++i];
516                                                 continue;
517
518                                         case "--unsafe":
519                                                 RootContext.Unsafe = true;
520                                                 continue;
521                                                 
522                                         case "--optimize":
523                                                 RootContext.Optimize = true;
524                                                 continue;
525
526                                         case "/?": case "/h": case "/help":
527                                         case "--help":
528                                                 Usage (false);
529                                                 return;
530
531                                         case "--define":
532                                                 if ((i + 1) >= argc){
533                                                         Usage (true);
534                                                         return;
535                                                 }
536                                                 defines.Add (args [++i]);
537                                                 continue;
538                                                 
539                                         case "--probe": {
540                                                 int code = 0;
541
542                                                 try {
543                                                         code = Int32.Parse (
544                                                                 args [++i], NumberStyles.AllowLeadingSign);
545                                                         Report.SetProbe (code);
546                                                 } catch {
547                                                         Report.Error (-14, "Invalid number specified");
548                                                 } 
549                                                 continue;
550                                         }
551
552                                         case "--tokenize": {
553                                                 tokenize = true;
554                                                 continue;
555                                         }
556                                         
557                                         case "-o": 
558                                         case "--output":
559                                                 if ((i + 1) >= argc){
560                                                         Usage (true);
561                                                         return;
562                                                 }
563                                                 output_file = args [++i];
564                                                 string bname = CodeGen.Basename (output_file);
565                                                 if (bname.IndexOf (".") == -1)
566                                                         output_file += ".exe";
567                                                 continue;
568
569                                         case "--checked":
570                                                 RootContext.Checked = true;
571                                                 continue;
572
573                                         case "--stacktrace":
574                                                 Report.Stacktrace = true;
575                                                 continue;
576
577                                         case "--target":
578                                                 if ((i + 1) >= argc){
579                                                         Usage (true);
580                                                         return;
581                                                 }
582
583                                                 string type = args [++i];
584                                                 switch (type){
585                                                 case "library":
586                                                         target = Target.Library;
587                                                         target_ext = ".dll";
588                                                         break;
589                                                         
590                                                 case "exe":
591                                                         target = Target.Exe;
592                                                         break;
593                                                         
594                                                 case "winexe":
595                                                         target = Target.WinExe;
596                                                         break;
597                                                         
598                                                 case "module":
599                                                         target = Target.Module;
600                                                         target_ext = ".dll";
601                                                         break;
602                                                 default:
603                                                         Usage (true);
604                                                         return;
605                                                 }
606                                                 continue;
607
608                                         case "-r":
609                                                 if ((i + 1) >= argc){
610                                                         Usage (true);
611                                                         return;
612                                                 }
613                                                 
614                                                 references.Add(args [++i]);
615                                                 continue;
616                                         
617                                         case "--resource":
618                                                 if ((i + 1) >= argc)
619                                                 {
620                                                         Usage (true);
621                                                         Console.WriteLine("Missing argument to --resource"); 
622                                                         return;
623                                                 }
624                                                 
625                                                 resources.Add(args [++i]);
626                                                 continue;
627                                         
628                                         
629                                         case "-L":
630                                                 if ((i + 1) >= argc){
631                                                         Usage (true);
632                                                         return;
633                                                 }
634                                                 link_paths.Add (args [++i]);
635                                                 continue;
636                                                 
637                                         case "--nostdlib":
638                                                 RootContext.StdLib = false;
639                                                 continue;
640                                                 
641                                         case "--fatal":
642                                                 Report.Fatal = true;
643                                                 continue;
644
645                                         case "--werror":
646                                                 Report.WarningsAreErrors = true;
647                                                 continue;
648
649                                         case "--nowarn":
650                                                 if ((i + 1) >= argc){
651                                                         Usage (true);
652                                                         return;
653                                                 }
654                                                 int warn;
655                                                 
656                                                 try {
657                                                         warn = Int32.Parse (args [++i]);
658                                                 } catch {
659                                                         Usage (true);
660                                                         return;
661                                                 }
662                                                 Report.SetIgnoreWarning (warn);
663                                                 continue;
664
665                                         case "--wlevel":
666                                                 if ((i + 1) >= argc){
667                                                         Report.Error (
668                                                                 1900,
669                                                                 "--wlevel requires an value from 0 to 4");
670                                                         error_count++;
671                                                         return;
672                                                 }
673                                                 int level;
674                                                 
675                                                 try {
676                                                         level = Int32.Parse (args [++i]);
677                                                 } catch {
678                                                         Report.Error (
679                                                                 1900,
680                                                                 "--wlevel requires an value from 0 to 4");
681                                                         return;
682                                                 }
683                                                 if (level < 0 || level > 4){
684                                                         Report.Error (1900, "Warning level must be 0 to 4");
685                                                         return;
686                                                 } else
687                                                         RootContext.WarningLevel = level;
688                                                 continue;
689                                                 
690                                         case "--about":
691                                                 About ();
692                                                 return;
693
694                                         case "--recurse":
695                                                 if ((i + 1) >= argc){
696                                                         Console.WriteLine ("--recurse requires an argument");
697                                                         error_count++;
698                                                         return;
699                                                 }
700                                                 errors += AddFiles (args [++i], true);
701                                                 continue;
702                                                 
703                                         case "--timestamp":
704                                                 timestamps = true;
705                                                 last_time = DateTime.Now;
706                                                 debug_arglist.Add("timestamp");
707                                                 continue;
708
709                                         case "--debug": case "-g":
710                                                 want_debugging_support = true;
711                                                 continue;
712
713                                         case "--debug-args":
714                                                 if ((i + 1) >= argc){
715                                                         Console.WriteLine ("--debug-args requires an argument");
716                                                         error_count++;
717                                                         return;
718                                                 }
719                                                 char[] sep = { ',' };
720                                                 debug_arglist.AddRange (args [++i].Split (sep));
721                                                 continue;
722
723                                         case "--noconfig":
724                                                 load_default_config = false;
725                                                 continue;
726
727                                         default:
728                                                 Console.WriteLine ("Unknown option: " + arg);
729                                                 errors++;
730                                                 continue;
731                                         }
732                                 }
733
734                                 // Rafael: Does not compile them yet!!!
735                                 errors += AddFiles(arg, false); 
736                         }
737
738                         //Rafael: Compile all source files!!!
739                         foreach(string filename in source_files.Values)
740                                 errors += ProcessSourceFile(filename);
741
742                         if (first_source == null)
743                         {
744                                 Report.Error (2008, "No files to compile were specified");
745                                 return;
746                         }
747
748                         if (tokenize)
749                                 return;
750                         
751                         if (Report.Errors > 0)
752                                 return;
753                         
754                         if (parse_only)
755                                 return;
756                         
757                         //
758                         // Load Core Library for default compilation
759                         //
760                         if (RootContext.StdLib)
761                                 references.Insert (0, "mscorlib");
762
763                         if (load_default_config)
764                                 DefineDefaultConfig ();
765
766                         if (errors > 0){
767                                 error ("Parsing failed");
768                                 return;
769                         }
770
771                         //
772                         // Load assemblies required
773                         //
774                         if (timestamps)
775                                 ShowTime ("Loading references");
776                         errors += LoadReferences ();
777                         if (timestamps)
778                                 ShowTime ("   References loaded");
779                         
780                         if (errors > 0){
781                                 error ("Could not load one or more assemblies");
782                                 return;
783                         }
784
785                         error_count = errors;
786
787                         //
788                         // Quick hack
789                         //
790                         if (output_file == null){
791                                 int pos = first_source.LastIndexOf (".");
792
793                                 if (pos > 0)
794                                         output_file = first_source.Substring (0, pos) + target_ext;
795                                 else
796                                         output_file = first_source + target_ext;
797                         }
798
799                         string[] debug_args = new string [debug_arglist.Count];
800                         debug_arglist.CopyTo(debug_args);
801                         CodeGen.Init (output_file, output_file, want_debugging_support, debug_args);
802
803                         TypeManager.AddModule (CodeGen.ModuleBuilder);
804
805                         //
806                         // Before emitting, we need to get the core
807                         // types emitted from the user defined types
808                         // or from the system ones.
809                         //
810                         if (timestamps)
811                                 ShowTime ("Initializing Core Types");
812                         if (!RootContext.StdLib){
813                                 RootContext.ResolveCore ();
814                                 if (Report.Errors > 0)
815                                         return;
816                         }
817                         
818                         TypeManager.InitCoreTypes ();
819                         if (timestamps)
820                                 ShowTime ("   Core Types done");
821                 
822                         //
823                         // The second pass of the compiler
824                         //
825                         if (timestamps)
826                                 ShowTime ("Resolving tree");
827                         RootContext.ResolveTree ();
828                         if (timestamps)
829                                 ShowTime ("Populate tree");
830
831                         if (Report.Errors > 0){
832                                 error ("Compilation failed");
833                                 return;
834                         }
835
836                         if (!RootContext.StdLib)
837                                 RootContext.BootCorlib_PopulateCoreTypes ();
838                         RootContext.PopulateTypes ();
839                         
840                         TypeManager.InitCodeHelpers ();
841                                 
842                         if (Report.Errors > 0){
843                                 error ("Compilation failed");
844                                 return;
845                         }
846                         
847                         //
848                         // The code generator
849                         //
850                         if (timestamps)
851                                 ShowTime ("Emitting code");
852                         RootContext.EmitCode ();
853                         if (timestamps)
854                                 ShowTime ("   done");
855
856                         if (Report.Errors > 0){
857                                 error ("Compilation failed");
858                                 return;
859                         }
860
861                         if (timestamps)
862                                 ShowTime ("Closing types");
863                         
864                         RootContext.CloseTypes ();
865
866 //                      PEFileKinds k = PEFileKinds.ConsoleApplication;
867 //                              
868 //                      if (target == Target.Library || target == Target.Module)
869 //                              k = PEFileKinds.Dll;
870 //                      else if (target == Target.Exe)
871 //                              k = PEFileKinds.ConsoleApplication;
872 //                      else if (target == Target.WinExe)
873 //                              k = PEFileKinds.WindowApplication;
874 //
875 //                      if (target == Target.Exe || target == Target.WinExe){
876 //                              MethodInfo ep = RootContext.EntryPoint;
877 //
878 //                              if (ep == null){
879 //                                      Report.Error (5001, "Program " + output_file +
880 //                                                            " does not have an entry point defined");
881 //                                      return;
882 //                              }
883 //                              
884 //                              CodeGen.AssemblyBuilder.SetEntryPoint (ep, k);
885 //                      }
886
887                         //
888                         // Add the resources
889                         //
890                         if (resources != null){
891                                 foreach (string file in resources)
892                                         CodeGen.AssemblyBuilder.AddResourceFile (file, file);
893                         }
894                         
895                         CodeGen.Save (output_file);
896                         if (timestamps)
897                                 ShowTime ("Saved output");
898
899                         if (want_debugging_support) {
900                                 CodeGen.SaveSymbols ();
901                                 if (timestamps)
902                                         ShowTime ("Saved symbols");
903                         }
904
905                         if (Report.Errors > 0){
906                                 error ("Compilation failed");
907                                 return;
908                         } else if (Report.ProbeCode != 0){
909                                 error ("Failed to report code " + Report.ProbeCode);
910                                 Environment.Exit (124);
911                         }
912                 }
913
914         }
915 }