3/09/16 Rafael Teixeira <rafaelteixeirabr@hotmail.com>
[mono.git] / mcs / mbas / driver.cs
1 //\r
2 // driver.cs: The compiler command line driver.\r
3 //\r
4 // Author: Rafael Teixeira (rafaelteixeirabr@hotmail.com)\r
5 // Based on mcs by : Miguel de Icaza (miguel@gnu.org)\r
6 //\r
7 // Licensed under the terms of the GNU GPL\r
8 //\r
9 // (C) 2002 Rafael Teixeira\r
10 //\r
11 \r
12 namespace Mono.Languages\r
13 {\r
14         using System;\r
15         using System.Reflection;\r
16         using System.Reflection.Emit;\r
17         using System.Collections;\r
18         using System.IO;\r
19         using System.Globalization;\r
20         using Mono.CSharp;\r
21         using Mono.GetOptions;\r
22 \r
23         enum Target \r
24         {\r
25                 Library, Exe, Module, WinExe\r
26         };\r
27         \r
28         enum OptionCompare\r
29         {\r
30                 Binary, Text\r
31         };\r
32         \r
33         /// <summary>\r
34         ///    The compiler driver.\r
35         /// </summary>\r
36         public class Driver : Options\r
37         {\r
38                 // Temporary options\r
39                 //------------------------------------------------------------------\r
40                 [Option("[Mono] Only parses the source file (for debugging the tokenizer)", "parse")]\r
41                 public bool parse_only = false;\r
42 \r
43                 [Option("[Mono] Only tokenizes source files")]\r
44                 public bool tokenize = false;\r
45 \r
46                 [Option("[Mono] Shows stack trace at Error location")]\r
47                 public bool stacktrace { set { Report.Stacktrace = value; } }\r
48 \r
49                 [Option("[Mono] Displays time stamps of various compiler events")]\r
50                 public bool timestamp\r
51                 {\r
52                         set\r
53                         {\r
54                                 timestamps = true;\r
55                                 last_time = DateTime.Now;\r
56                                 debug_arglist.Add("timestamp");\r
57                         }\r
58                 }\r
59 \r
60                 // Mono-specific options\r
61                 //------------------------------------------------------------------\r
62                 [Option("About the MonoBASIC compiler", "about")]\r
63                 public override WhatToDoNext DoAbout()\r
64                 {\r
65                         return base.DoAbout();\r
66                 }\r
67 \r
68                 [Option("[Mono] Don\'t assume the standard library", "nostdlib")]\r
69                 public bool nostdlib { set { RootContext.StdLib = !value; } }\r
70 \r
71                 [Option("[Mono] Disables implicit references to assemblies", "noconfig")]\r
72                 public bool NoConfig { set { load_default_config = !value; } }\r
73 \r
74                 [Option("[Mono] Allows unsafe code", "unsafe")]\r
75                 public bool AllowUnsafeCode { set { RootContext.Unsafe = value; } }\r
76 \r
77                 [Option("[Mono] Set default context to checked", "checked")]\r
78                 public bool Checked { set { RootContext.Checked = value; } }\r
79 \r
80                 [Option("[Mono] Debugger arguments", "debug-args")]\r
81                 public WhatToDoNext SetDebugArgs(string args)\r
82                 {\r
83                         char[] sep = { ',' };\r
84                         debug_arglist.AddRange (args.Split (sep));\r
85                         return WhatToDoNext.GoAhead;\r
86                 }\r
87 \r
88                 [Option("[Mono] Ignores warning number PARAM", "ignorewarn")]\r
89                 public WhatToDoNext SetIgnoreWarning(int warn)\r
90                 {\r
91                         Report.SetIgnoreWarning(warn);\r
92                         return WhatToDoNext.GoAhead;\r
93                 }       \r
94 \r
95                 [Option("[Mono] Sets warning level (the highest is 4, the default)", "wlevel")]\r
96                 public int wlevel { set { RootContext.WarningLevel = value; } }\r
97 \r
98                 [Option("[Mono] Makes errors fatal", "fatal")]\r
99                 public bool Fatal { set { Report.Fatal = value; } }\r
100 \r
101                 // Output file options\r
102                 //------------------------------------------------------------------\r
103                 [Option("Specifies the output file name", 'o', "out")]\r
104                 public string output_file = null;\r
105 \r
106                 [Option("Specifies the target type for the output file (exe [default], winexe, library, module)", "target")]\r
107                 public WhatToDoNext SetTarget(string type)\r
108                 {\r
109                         switch (type.ToLower())\r
110                         {\r
111                                 case "library":\r
112                                         target = Target.Library;\r
113                                         target_ext = ".dll";\r
114                                         break;\r
115                                                         \r
116                                 case "exe":\r
117                                         target = Target.Exe;\r
118                                         break;\r
119                                                         \r
120                                 case "winexe":\r
121                                         target = Target.WinExe;\r
122                                         break;\r
123                                                         \r
124                                 case "module":\r
125                                         target = Target.Module;\r
126                                         target_ext = ".dll";\r
127                                         break;\r
128                         }\r
129                         return WhatToDoNext.GoAhead;\r
130                 }\r
131 \r
132                 // input file options\r
133                 //------------------------------------------------------------------\r
134                 [Option("[NOT IMPLEMENTED YET]Reference metadata from specified module", "addmodule")]\r
135                 public string[] addedModules = null;\r
136 \r
137                 [Option("[NOT IMPLEMENTED YET]Include all files in the current directory and subdirectories according to the wildcard", "recurse")]\r
138                 public WhatToDoNext recurse(string wildcard)\r
139                 {\r
140                         //AddFiles (DirName, true); // TODO wrong semantics\r
141                         return WhatToDoNext.GoAhead;\r
142                 }\r
143 \r
144                 [Option(-1, "References metadata from the specified assembly", 'r', "reference")]\r
145                 public string reference { set { references.Add(value); } }\r
146 \r
147                 // resource options\r
148                 //------------------------------------------------------------------\r
149                 public ArrayList EmbeddedResources = new ArrayList();\r
150                 \r
151                 // TODO : accept a multi-letter short form: 'res'\r
152                 [Option(-1, "Adds the specified file as an embedded assembly resource", "resource")]\r
153                 public string resource { set { EmbeddedResources.Add(value); } }\r
154 \r
155                 public ArrayList LinkedResources = new ArrayList();\r
156                 \r
157                 // TODO : accept a multi-letter short form: 'linkres'\r
158                 [Option(-1, "[NOT IMPLEMENTED YET]Adds the specified file as an embedded assembly resource", "linkresource")]\r
159                 public string linkresource { set { LinkedResources.Add(value); } }\r
160 \r
161                 public ArrayList Win32Resources = new ArrayList();\r
162                 \r
163                 [Option(-1, "[NOT IMPLEMENTED YET]Specifies a Win32 resource file (.res)", "win32resource")]\r
164                 public string win32resource { set { Win32Resources.Add(value); } }\r
165 \r
166                 public ArrayList Win32Icons = new ArrayList();\r
167                 \r
168                 // TODO : accept a multi-letter short form: 'res'\r
169                 [Option(-1, "[NOT IMPLEMENTED YET]Specifies a Win32 icon file (.ico) for the default Win32 resources", "win32icon")]\r
170                 public string win32icon { set { Win32Icons.Add(value); } }\r
171 \r
172 \r
173                 // code generation options\r
174                 //------------------------------------------------------------------\r
175                 [Option("[NOT IMPLEMENTED YET]Enable optimizations")]\r
176                 public bool optimize = false;\r
177 \r
178                 [Option("[NOT IMPLEMENTED YET]Remove integer checks. Default off.")]\r
179                 public bool removeintchecks = false;\r
180 \r
181                 // TODO: handle VB.NET [+|-] boolean syntax\r
182                 [Option("Emit debugging information", "debug")]\r
183                 public bool want_debugging_support = false;\r
184 \r
185                 [Option("Emit full debugging information (default)", "debug:full")]\r
186                 public bool fullDebugging = false;\r
187 \r
188                 [Option("[IGNORED]Emit PDB file only", "debug:pdbonly")]\r
189                 public bool pdbOnly = false;\r
190 \r
191                 // errors and warnings options\r
192                 //------------------------------------------------------------------\r
193                 [Option("Treat warnings as errors", "warnaserror")]\r
194                 public bool WarningsAreErrors { set { Report.WarningsAreErrors = value; } }\r
195 \r
196                 [Option("Disable warnings")]\r
197                 public bool nowarn { set { if (value) RootContext.WarningLevel = 0; } }\r
198 \r
199 \r
200                 // language options\r
201                 //------------------------------------------------------------------\r
202                 public Hashtable Defines = new Hashtable();\r
203                 \r
204                 // TODO: Symbol-List parsing\r
205                 [Option(-1, "[NOT IMPLEMENTED YET]Declares global conditional compilation symbol(s). symbol list:name=value,...", 'd', "define")]\r
206                 public string define { \r
207                         set {\r
208                                 foreach(string item in value.Split(',')) {      \r
209                                         string[] dados = item.Split('=');\r
210                                         if (dados.Length > 1)\r
211                                                 Defines.Add(dados[0], dados[1]); \r
212                                         else\r
213                                                 Defines.Add(dados[0], string.Empty);\r
214                                 }\r
215                         } \r
216                 }\r
217                 \r
218                 private string[] importsList = null;\r
219                 \r
220                 [Option("[NOT IMPLEMENTED YET]Declare global Imports for namespaces in referenced metadata files. import list:namespace,...", "imports")]\r
221                 public WhatToDoNext imports(string importslist)\r
222                 {\r
223                         importsList = importslist.Split(';');\r
224                         return WhatToDoNext.GoAhead;\r
225                 }\r
226 \r
227                 // TODO: handle VB.NET [+|-] boolean syntax\r
228                 [Option("[NOT IMPLEMENTED YET]Require explicit declaration of variables")]\r
229                 public bool optionexplicit { set { Mono.MonoBASIC.Parser.InitialOptionExplicit = value; } }\r
230 \r
231                 // TODO: handle VB.NET [+|-] boolean syntax\r
232                 [Option("[NOT IMPLEMENTED YET]Enforce strict language semantics")]\r
233                 public bool optionstrict { set { Mono.MonoBASIC.Parser.InitialOptionStrict = value; } }\r
234                 \r
235                 [Option("[NOT IMPLEMENTED YET]Specifies binary-style string comparisons. This is the default", "optioncompare:binary")]\r
236                 public bool optioncomparebinary { set { Mono.MonoBASIC.Parser.InitialOptionCompareBinary = true; } }\r
237 \r
238                 [Option("[NOT IMPLEMENTED YET]Specifies text-style string comparisons.", "optioncompare:text")]\r
239                 public bool optioncomparetext { set { Mono.MonoBASIC.Parser.InitialOptionCompareBinary = false; } }\r
240 \r
241                 [Option("Specifies de root namespace for all type declarations")]\r
242                 public string rootnamespace { set { RootContext.RootNamespace = value; } }\r
243                 \r
244                 // Miscellaneous options        \r
245                 //------------------------------------------------------------------\r
246                 \r
247                 [Option("[NOT IMPLEMENTED YET]Do not display compiler copyright banner")]\r
248                 public bool nologo = false;\r
249                 \r
250                 [Option("[NOT IMPLEMENTED YET]Quiet output mode")]\r
251                 public bool quiet = false;\r
252                 \r
253                 // TODO: semantics are different and should be adjusted\r
254                 [Option("Display verbose messages", 'v')] \r
255                 public bool verbose     { set { GenericParser.yacc_verbose_flag = value; } }\r
256 \r
257                 // Advanced options     \r
258                 //------------------------------------------------------------------\r
259                 // TODO: force option to accept number in hex format\r
260                 [Option("[NOT IMPLEMENTED YET]The base address for a library or module (hex)")]\r
261                 public int baseaddress;\r
262                 \r
263                 [Option("[NOT IMPLEMENTED YET]Create bug report file")]\r
264                 public string bugreport;\r
265                 \r
266                 // TODO: handle VB.NET [+|-] boolean syntax\r
267                 [Option("[NOT IMPLEMENTED YET]Delay-sign the assembly using only the public portion of the strong name key")]\r
268                 public bool delaysign;\r
269                 \r
270                 [Option("[NOT IMPLEMENTED YET]Specifies a strong name key container")]\r
271                 public string keycontainer;\r
272                 \r
273                 [Option("[NOT IMPLEMENTED YET]Specifies a strong name key file")]\r
274                 public string keyfile;\r
275 \r
276                 public string[] libpath = null;\r
277                 \r
278                 [Option("List of directories to search for metada references (semi-colon delimited)", "libpath")]\r
279                 public WhatToDoNext setlibpath(string pathlist)\r
280                 {\r
281                         libpath = pathlist.Split(';');\r
282                         return WhatToDoNext.GoAhead;\r
283                 }\r
284 \r
285                 [Option(@"Specifies the Class or Module that contains Sub Main.\r
286                         It can also be a Class that inherits from System.Windows.Forms.Form.",\r
287                         'm', "main")]\r
288                 public string main { set { RootContext.MainClass = value; } }\r
289 \r
290                 // TODO: handle VB.NET [+|-] boolean syntax\r
291                 [Option("[NOT IMPLEMENTED YET]Emit compiler output in UTF8 character encoding")]\r
292                 public bool utf8output;\r
293 \r
294                 // TODO : response file support\r
295                 \r
296                 ArrayList defines = new ArrayList();\r
297                 ArrayList references = new ArrayList();\r
298                 ArrayList soft_references = new ArrayList();\r
299                 string first_source = null;\r
300                 Target target = Target.Exe;\r
301                 string target_ext = ".exe";\r
302                 ArrayList debug_arglist = new ArrayList ();\r
303                 bool timestamps = false;\r
304                 Hashtable source_files = new Hashtable ();\r
305                 bool load_default_config = true;\r
306 \r
307                 //\r
308                 // Last time we took the time\r
309                 //\r
310                 DateTime last_time;\r
311                 void ShowTime (string msg)\r
312                 {\r
313                         DateTime now = DateTime.Now;\r
314                         TimeSpan span = now - last_time;\r
315                         last_time = now;\r
316 \r
317                         Console.WriteLine (\r
318                                 "[{0:00}:{1:000}] {2}",\r
319                                 (int) span.TotalSeconds, span.Milliseconds, msg);\r
320                 }\r
321                         \r
322                 public static int Main (string[] args)\r
323                 {\r
324                         Driver Exec = new Driver();\r
325 \r
326                         return Exec.MainDriver(args);\r
327                 }\r
328 \r
329                 public int LoadAssembly (string assembly, bool soft)\r
330                 {\r
331                         Assembly a;\r
332                         string total_log = "";\r
333 \r
334                         try \r
335                         {\r
336                                 char[] path_chars = { '/', '\\' };\r
337 \r
338                                 if (assembly.IndexOfAny (path_chars) != -1)\r
339                                         a = Assembly.LoadFrom(assembly);\r
340                                 else\r
341                                         a = Assembly.Load(assembly);\r
342                                 TypeManager.AddAssembly (a);\r
343                                 return 0;\r
344                         }\r
345                         catch (FileNotFoundException)\r
346                         {\r
347                                 if (libpath != null)\r
348                                 {\r
349                                         foreach (string dir in libpath)\r
350                                         {\r
351                                                 string full_path = dir + "/" + assembly + ".dll";\r
352 \r
353                                                 try \r
354                                                 {\r
355                                                         a = Assembly.LoadFrom (full_path);\r
356                                                         TypeManager.AddAssembly (a);\r
357                                                         return 0;\r
358                                                 } \r
359                                                 catch (FileNotFoundException ff) \r
360                                                 {\r
361                                                         total_log += ff.FusionLog;\r
362                                                         continue;\r
363                                                 }\r
364                                         }\r
365                                 }\r
366                                 if (soft)\r
367                                         return 0;\r
368                         }\r
369                         catch (BadImageFormatException f) \r
370                         {\r
371                                 Error ("// Bad file format while loading assembly");\r
372                                 Error ("Log: " + f.FusionLog);\r
373                                 return 1;\r
374                         } catch (FileLoadException f){\r
375                                 Error ("File Load Exception: " + assembly);\r
376                                 Error ("Log: " + f.FusionLog);\r
377                                 return 1;\r
378                         } catch (ArgumentNullException){\r
379                                 Error ("// Argument Null exception ");\r
380                                 return 1;\r
381                         }\r
382                         \r
383                         Report.Error (6, "Can not find assembly `" + assembly + "'" );\r
384                         Console.WriteLine ("Log: \n" + total_log);\r
385 \r
386                         return 0;\r
387                 }\r
388 \r
389                 void Error(string message)\r
390                 {\r
391                         Console.WriteLine(message);\r
392                 }\r
393 \r
394                 /// <summary>\r
395                 ///   Loads all assemblies referenced on the command line\r
396                 /// </summary>\r
397                 public int LoadReferences ()\r
398                 {\r
399                         int errors = 0;\r
400 \r
401                         foreach (string r in references)\r
402                                 errors += LoadAssembly (r, false);\r
403 \r
404                         foreach (string r in soft_references)\r
405                                 errors += LoadAssembly (r, true);\r
406                         \r
407                         return errors;\r
408                 }\r
409 \r
410                 void SetupDefaultDefines ()\r
411                 {\r
412                         defines = new ArrayList ();\r
413                         defines.Add ("__MonoBASIC__");\r
414                 }\r
415 \r
416 \r
417                 //\r
418                 // Returns the directory where the system assemblies are installed\r
419                 //\r
420                 string GetSystemDir ()\r
421                 {\r
422                         Assembly [] assemblies = AppDomain.CurrentDomain.GetAssemblies ();\r
423 \r
424                         foreach (Assembly a in assemblies){\r
425                                 string codebase = a.CodeBase;\r
426                                 if (codebase.EndsWith ("corlib.dll")){\r
427                                         return codebase.Substring (0, codebase.LastIndexOf ("/"));\r
428                                 }\r
429                         }\r
430 \r
431                         Report.Error (-15, "Can not compute my system path");\r
432                         return "";\r
433                 }\r
434 \r
435                 //\r
436                 // Given a path specification, splits the path from the file/pattern\r
437                 //\r
438                 void SplitPathAndPattern (string spec, out string path, out string pattern)\r
439                 {\r
440                         int p = spec.LastIndexOf ("/");\r
441                         if (p != -1){\r
442                                 //\r
443                                 // Windows does not like /file.cs, switch that to:\r
444                                 // "\", "file.cs"\r
445                                 //\r
446                                 if (p == 0){\r
447                                         path = "\\";\r
448                                         pattern = spec.Substring (1);\r
449                                 } else {\r
450                                         path = spec.Substring (0, p);\r
451                                         pattern = spec.Substring (p + 1);\r
452                                 }\r
453                                 return;\r
454                         }\r
455 \r
456                         p = spec.LastIndexOf ("\\");\r
457                         if (p != -1){\r
458                                 path = spec.Substring (0, p);\r
459                                 pattern = spec.Substring (p + 1);\r
460                                 return;\r
461                         }\r
462 \r
463                         path = ".";\r
464                         pattern = spec;\r
465                 }\r
466 \r
467                 bool AddFiles (string spec, bool recurse)\r
468                 {\r
469                         string path, pattern;\r
470 \r
471                         SplitPathAndPattern(spec, out path, out pattern);\r
472                         if (pattern.IndexOf("*") == -1)\r
473                         {\r
474                                 AddFile(spec);\r
475                                 return true;\r
476                         }\r
477 \r
478                         string [] files = null;\r
479                         try {\r
480                                 files = Directory.GetFiles(path, pattern);\r
481                         } catch (System.IO.DirectoryNotFoundException) {\r
482                                 Report.Error (2001, "Source file `" + spec + "' could not be found");\r
483                                 return false;\r
484                         } catch (System.IO.IOException){\r
485                                 Report.Error (2001, "Source file `" + spec + "' could not be found");\r
486                                 return false;\r
487                         }\r
488                         foreach (string f in files)\r
489                                 AddFile (f);\r
490 \r
491                         if (!recurse)\r
492                                 return true;\r
493                         \r
494                         string [] dirs = null;\r
495 \r
496                         try {\r
497                                 dirs = Directory.GetDirectories(path);\r
498                         } catch {\r
499                         }\r
500                         \r
501                         foreach (string d in dirs) {\r
502                                         \r
503                                 // Don't include path in this string, as each\r
504                                 // directory entry already does\r
505                                 AddFiles (d + "/" + pattern, true);\r
506                         }\r
507 \r
508                         return true;\r
509                 }\r
510 \r
511                 void DefineDefaultConfig ()\r
512                 {\r
513                         //\r
514                         // For now the "default config" is harcoded into the compiler\r
515                         // we can move this outside later\r
516                         //\r
517                         string [] default_config = \r
518                         {\r
519                                 "System",\r
520                                 "System.Data",\r
521                                 "System.Xml",\r
522                                 "Microsoft.VisualBasic" , \r
523 #if EXTRA_DEFAULT_REFS\r
524                                 //\r
525                                 // Is it worth pre-loading all this stuff?\r
526                                 //\r
527                                 "Accessibility",\r
528                                 "System.Configuration.Install",\r
529                                 "System.Design",\r
530                                 "System.DirectoryServices",\r
531                                 "System.Drawing.Design",\r
532                                 "System.Drawing",\r
533                                 "System.EnterpriseServices",\r
534                                 "System.Management",\r
535                                 "System.Messaging",\r
536                                 "System.Runtime.Remoting",\r
537                                 "System.Runtime.Serialization.Formatters.Soap",\r
538                                 "System.Security",\r
539                                 "System.ServiceProcess",\r
540                                 "System.Web",\r
541                                 "System.Web.RegularExpressions",\r
542                                 "System.Web.Services" ,\r
543                                 "System.Windows.Forms"\r
544 #endif\r
545                         };\r
546                         \r
547                         foreach (string def in default_config)\r
548                                 soft_references.Add(def);\r
549                 }\r
550 \r
551                 [ArgumentProcessor]\r
552                 public void AddFile(string fileName)\r
553                 {\r
554                         string f = fileName;\r
555                         if (first_source == null)\r
556                                 first_source = f;\r
557 \r
558                         if (source_files.Contains(f))\r
559                                 Report.Error(1516, "Source file '" + f + "' specified multiple times");\r
560                         else\r
561                                 source_files.Add(f, f);\r
562                 }\r
563 \r
564                 void ProcessSourceFile(string filename)\r
565                 {\r
566                         if (tokenize)\r
567                                 GenericParser.Tokenize(filename);\r
568                         else\r
569                                 GenericParser.Parse(filename);\r
570                 }\r
571 \r
572                 string outputFile_Name = null;\r
573 \r
574                 string outputFileName\r
575                 {\r
576                         get \r
577                         {\r
578                                 if (outputFile_Name == null)\r
579                                 {\r
580                                         if (output_file == null)\r
581                                         {\r
582                                                 int pos = first_source.LastIndexOf(".");\r
583 \r
584                                                 if (pos > 0)\r
585                                                         output_file = first_source.Substring(0, pos);\r
586                                                 else\r
587                                                         output_file = first_source;\r
588                                         }\r
589                                         string bname = CodeGen.Basename(output_file);\r
590                                         if (bname.IndexOf(".") == -1)\r
591                                                 output_file +=  target_ext;\r
592                                         outputFile_Name = output_file;\r
593                                 }\r
594                                 return outputFile_Name;\r
595                         }\r
596                 }\r
597 \r
598                 /// <summary>\r
599                 ///    Parses the arguments, and calls the compilation process.\r
600                 /// </summary>\r
601                 int MainDriver(string [] args)\r
602                 {\r
603                         ProcessArgs(args);\r
604                         if (first_source == null)\r
605                         {\r
606                                 DoHelp();\r
607                                 return 2;\r
608                         }\r
609 \r
610                         CompileAll();\r
611 \r
612                         if (Report.Errors == 0) \r
613                         {\r
614                                 Console.Write("Compilation succeeded");\r
615                                 if (Report.Warnings > 0) \r
616                                 {\r
617                                         Console.Write(" - {0} warning(s)", Report.Warnings);\r
618                                 } \r
619                                 Console.WriteLine();\r
620                                 return 0;\r
621                         } \r
622                         Console.WriteLine("Compilation failed: {0} Error(s), {1} warnings",\r
623                                 Report.Errors, Report.Warnings);\r
624                         return 1;\r
625                 }\r
626 \r
627                 public Driver()\r
628                 {\r
629                         SetupDefaultDefines();  \r
630                 }\r
631 \r
632                 bool ParseAll() // Phase 1\r
633                 {\r
634                         if (first_source == null)\r
635                         {\r
636                                 Report.Error(2008, "No files to compile were specified");\r
637                                 return false;\r
638                         }\r
639 \r
640                         foreach(string filename in source_files.Values)\r
641                                 ProcessSourceFile(filename);\r
642 \r
643                         if (tokenize || parse_only || (Report.Errors > 0))\r
644                                 return false;           \r
645 \r
646                         return true; // everything went well go ahead\r
647                 }\r
648 \r
649                 void InitializeDebuggingSupport()\r
650                 {\r
651                         string[] debug_args = new string [debug_arglist.Count];\r
652                         debug_arglist.CopyTo(debug_args);\r
653                         CodeGen.Init(outputFileName, outputFileName, want_debugging_support, debug_args);\r
654                         TypeManager.AddModule(CodeGen.ModuleBuilder);\r
655                 }\r
656 \r
657                 public bool ResolveAllTypes() // Phase 2\r
658                 {\r
659                         // Load Core Library for default compilation\r
660                         if (RootContext.StdLib)\r
661                                 references.Insert(0, "mscorlib");\r
662 \r
663                         if (load_default_config)\r
664                                 DefineDefaultConfig();\r
665 \r
666                         if (timestamps)\r
667                                 ShowTime("Loading references");\r
668 \r
669                         // Load assemblies required\r
670                         if (LoadReferences() > 0)\r
671                         {\r
672                                 Error ("Could not load one or more assemblies");\r
673                                 return false;\r
674                         }\r
675 \r
676                         if (timestamps)\r
677                                 ShowTime("References loaded");\r
678 \r
679                         InitializeDebuggingSupport();\r
680 \r
681                         //\r
682                         // Before emitting, we need to get the core\r
683                         // types emitted from the user defined types\r
684                         // or from the system ones.\r
685                         //\r
686                         if (timestamps)\r
687                                 ShowTime ("Initializing Core Types");\r
688 \r
689                         if (!RootContext.StdLib)\r
690                                 RootContext.ResolveCore ();\r
691                         if (Report.Errors > 0)\r
692                                 return false;\r
693                         \r
694                         TypeManager.InitCoreTypes();\r
695                         if (Report.Errors > 0)\r
696                                 return false;\r
697 \r
698                         if (timestamps)\r
699                                 ShowTime ("   Core Types done");\r
700 \r
701                         if (timestamps)\r
702                                 ShowTime ("Resolving tree");\r
703 \r
704                         // The second pass of the compiler\r
705                         RootContext.ResolveTree ();\r
706                         if (Report.Errors > 0)\r
707                                 return false;\r
708                         \r
709                         if (timestamps)\r
710                                 ShowTime ("Populate tree");\r
711 \r
712                         if (!RootContext.StdLib)\r
713                                 RootContext.BootCorlib_PopulateCoreTypes();\r
714                         if (Report.Errors > 0)\r
715                                 return false;\r
716 \r
717                         RootContext.PopulateTypes();\r
718                         if (Report.Errors > 0)\r
719                                 return false;\r
720                         \r
721                         TypeManager.InitCodeHelpers();\r
722                         if (Report.Errors > 0)\r
723                                 return false;\r
724 \r
725                         return true;\r
726                 }\r
727                 \r
728                 bool IsSWFApp()\r
729                 {\r
730                         bool hasSWF = false, isForm = false;\r
731                         string mainclass = GetFQMainClass();\r
732                         \r
733                         foreach (string r in references) {\r
734                                 if (r.IndexOf ("System.Windows.Forms") >= 0) {\r
735                                         hasSWF = true;\r
736                                         break;  \r
737                                 }       \r
738                         }       \r
739                         if (mainclass != ".") {\r
740                                 Type t = TypeManager.LookupType(mainclass);\r
741                                 if (t != null) \r
742                                         isForm = t.IsSubclassOf (TypeManager.LookupType("System.Windows.Forms.Form"));\r
743                         }\r
744                         return (hasSWF && isForm);\r
745                 }\r
746                 \r
747                 string GetFQMainClass()\r
748                 {       \r
749                         if (RootContext.RootNamespace != "")\r
750                                 return RootContext.RootNamespace + "." + RootContext.MainClass;\r
751                         else\r
752                                 return RootContext.MainClass;                   \r
753                 }\r
754                 \r
755                 void FixEntryPoint()\r
756                 {\r
757                         if (target == Target.Exe || target == Target.WinExe)\r
758                         {\r
759                                 MethodInfo ep = RootContext.EntryPoint;\r
760                         \r
761                                 if (ep == null)\r
762                                 {\r
763                                         // If we don't have a valid entry point yet\r
764                                         // AND if System.Windows.Forms is included\r
765                                         // among the dependencies, we have to build\r
766                                         // a new entry point on-the-fly. Otherwise we\r
767                                         // won't be able to compile SWF code out of the box.\r
768 \r
769                                         if (IsSWFApp()) \r
770                                         {                                                                                               \r
771                                                 Type t = TypeManager.LookupType(GetFQMainClass());\r
772                                                 if (t != null) \r
773                                                 {                                                       \r
774                                                         TypeBuilder tb = t as TypeBuilder;\r
775                                                         MethodBuilder mb = tb.DefineMethod ("Main", MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, \r
776                                                                 typeof(void), new Type[0]);\r
777 \r
778                                                         Type SWFA = TypeManager.LookupType("System.Windows.Forms.Application");\r
779                                                         Type SWFF = TypeManager.LookupType("System.Windows.Forms.Form");\r
780                                                         Type[] args = new Type[1];\r
781                                                         args[0] = SWFF;\r
782                                                         MethodInfo mi = SWFA.GetMethod("Run", args);\r
783                                                         ILGenerator ig = mb.GetILGenerator();\r
784                                                         ConstructorInfo ci = TypeManager.GetConstructor (TypeManager.LookupType(t.FullName), new Type[0]);\r
785                                                         \r
786                                                         ig.Emit (OpCodes.Newobj, ci);\r
787                                                         ig.Emit (OpCodes.Call, mi);\r
788                                                         ig.Emit (OpCodes.Ret);\r
789 \r
790                                                         RootContext.EntryPoint = mb as MethodInfo;\r
791                                                 }\r
792                                         }\r
793                                 }\r
794                         }\r
795                 }\r
796 \r
797                 bool GenerateAssembly()\r
798                 {\r
799                         //\r
800                         // The code generator\r
801                         //\r
802                         if (timestamps)\r
803                                 ShowTime ("Emitting code");\r
804                         \r
805                         \r
806 \r
807                         RootContext.EmitCode();\r
808                         FixEntryPoint();\r
809                         if (Report.Errors > 0)\r
810                                 return false;\r
811 \r
812                         if (timestamps)\r
813                                 ShowTime ("   done");\r
814 \r
815 \r
816                         if (timestamps)\r
817                                 ShowTime ("Closing types");\r
818 \r
819                         RootContext.CloseTypes ();\r
820                         if (Report.Errors > 0)\r
821                                 return false;\r
822 \r
823                         if (timestamps)\r
824                                 ShowTime ("   done");\r
825 \r
826                         PEFileKinds k = PEFileKinds.ConsoleApplication;\r
827                                                         \r
828                         if (target == Target.Library || target == Target.Module)\r
829                                 k = PEFileKinds.Dll;\r
830                         else if (target == Target.Exe)\r
831                                 k = PEFileKinds.ConsoleApplication;\r
832                         else if (target == Target.WinExe)\r
833                                 k = PEFileKinds.WindowApplication;\r
834                         \r
835                         if (target == Target.Exe || target == Target.WinExe)\r
836                         {\r
837                                 MethodInfo ep = RootContext.EntryPoint;\r
838                         \r
839                                 if (ep == null)\r
840                                 {\r
841                                         Report.Error (5001, "Program " + outputFileName +\r
842                                                 " does not have an entry point defined");\r
843                                         return false;\r
844                                 }\r
845                                                         \r
846                                 CodeGen.AssemblyBuilder.SetEntryPoint (ep, k);\r
847                         }\r
848 \r
849                         // Add the resources\r
850                         if (EmbeddedResources != null)\r
851                                 foreach (string file in EmbeddedResources)\r
852                                         CodeGen.AssemblyBuilder.AddResourceFile (file, file);\r
853                         \r
854                         CodeGen.Save(outputFileName);\r
855 \r
856                         if (timestamps)\r
857                                 ShowTime ("Saved output");\r
858 \r
859                         \r
860                         if (want_debugging_support) \r
861                         {\r
862                                 CodeGen.SaveSymbols ();\r
863                                 if (timestamps)\r
864                                         ShowTime ("Saved symbols");\r
865                         }\r
866 \r
867                         return true;\r
868                 }\r
869 \r
870                 public void CompileAll()\r
871                 {\r
872 /* \r
873                     VB.NET expects the default namespace to be "" (empty string)                \r
874                     \r
875                     if (RootContext.RootNamespace == "")\r
876                     {\r
877                       RootContext.RootNamespace = System.IO.Path.GetFileNameWithoutExtension(outputFileName);\r
878                     }\r
879 */\r
880                         if (!ParseAll()) // Phase 1\r
881                                 return;\r
882 \r
883                         if (!ResolveAllTypes()) // Phase 2\r
884                                 return;\r
885 \r
886                         if (!GenerateAssembly()) // Phase 3 \r
887                                 return;\r
888 \r
889                         if (Report.ExpectedError != 0)\r
890                                 Error("Failed to report expected Error " + Report.ExpectedError);\r
891                 }\r
892 \r
893         }\r
894 }\r