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