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