2005-09-13 Cesar Lopez Nataren <cnataren@novell.com>
authorCésar Natarén <cesar@mono-cvs.ximian.com>
Wed, 14 Sep 2005 04:06:13 +0000 (04:06 -0000)
committerCésar Natarén <cesar@mono-cvs.ximian.com>
Wed, 14 Sep 2005 04:06:13 +0000 (04:06 -0000)
* mjs.cs: Add support for flags parsing.
* Makefile: Reference mcs.exe we use the Namespace semantic logic
from it.

svn path=/trunk/mcs/; revision=50005

mcs/tools/mjs/ChangeLog
mcs/tools/mjs/Makefile
mcs/tools/mjs/mjs.cs

index 2042e17a46a75d9a103c879d6ffc101967e63961..36803c3a5bc513ccda67f810fcb3cfdf3c16223d 100644 (file)
@@ -1,3 +1,9 @@
+2005-09-13  Cesar Lopez Nataren  <cnataren@novell.com>
+
+       * mjs.cs: Add support for flags parsing.
+       * Makefile: Reference mcs.exe we use the Namespace semantic logic
+       from it.
+
 2005-02-14  Cesar Lopez Nataren  <cnataren@novell.com>
 
        * Added this file.
index e465837c91ff95bbb3f91a022b3a291f4078168f..7148dcbdba4264a0653d1dd7ec4820a18e99067f 100644 (file)
@@ -3,6 +3,6 @@ SUBDIRS =
 include ../../build/rules.make
 
 PROGRAM = mjs.exe
-LOCAL_MCS_FLAGS = -r:Microsoft.JScript.dll -r:Microsoft.Vsa.dll
+LOCAL_MCS_FLAGS = /r:Microsoft.JScript.dll /r:Microsoft.Vsa.dll /r:mcs.exe /debug+
 
 include ../../build/executable.make
index 91e7bf16e55bea6130e995dccd6f235ffd467993..0944a3e99e1722d4b219298e3d0c4b2f49a6aaca 100644 (file)
@@ -5,7 +5,7 @@
 //     Cesar Lopez Nataren (cesar@ciencias.unam.mx)
 //
 // (C) 2003, Cesar Lopez Nataren
-// (C) 2005, Novell Inc. (http://www.novell.com)
+// (C) Copyright 2005, Novell Inc. (http://www.novell.com)
 //
 
 //
 
 using System;
 using System.IO;
+using System.Text;
 using Microsoft.Vsa;
 using Microsoft.JScript;
+using System.Reflection;
+using System.Collections;
 using Microsoft.JScript.Vsa;
+using System.Reflection.Emit;
+using Mono.CSharp;
 
-class Driver {         
-       public static void Main (string [] args) {
+namespace Mono.JScript {
        
-               if (args.Length < 1) {
-                       Console.WriteLine ("Usage: mjs filename.js");
+       class Driver {
+               //
+               // Assemblies references to be linked. Initialized with
+               // mscorlib.dll
+               //
+               private static ArrayList references;
+
+               // Lookup paths
+               private static ArrayList link_paths;
+
+               // jscript files
+               private static ArrayList files;
+                       
+               private static string first_source;
+
+               private static bool want_debugging_support = false;
+
+               private static string output_file;
+
+               private static Assembly [] assemblies = new Assembly [0];
+
+               private static bool StdLib;
+
+               private static void Usage ()
+               {
+                       Console.WriteLine ("Mono JScript compiler\n" +
+                                          "(C) 2003 - 2004 Cesar Lopez Nataren\n" +
+                                          "(C) 2004 - 2005 Novell Inc (http://novell.com)\n\n" +
+                                          "mjs [options] source-file\n" +
+                                          "   /about              About the Mono JScript compiler\n" +
+                                          "   /lib:PATH1,PATH2    Adds the paths to the assembly link path\n" +
+                                          "   /r[eference]:ASS    Reference the specified assembly\n");
+               }
+
+               private static void About ()
+               {
+                       Console.WriteLine (
+                                          "The Mono JScript compiler is:\n" +
+                                          "(C) 2003 - 2004 Cesar Lopez Nataren\n" +
+                                          "(C) 2004 - 2005 Novell Inc.\n\n" +
+                                          "The compiler source code is released under the terms of both the MIT X11 and MPL\n" +
+                                          "The compiler was written by Cesar Lopez Nataren");
                        Environment.Exit (0);
                }
 
-               VsaEngine engine = new VsaEngine ();
-               engine.InitVsaEngine ("mjs:com.mono-project", new MonoEngineSite ());
+               /// <summary>
+               ///   Loads all assemblies referenced on the command line
+               /// </summary>
+               private static void LoadReferences ()
+               {
+                       foreach (string r in references)
+                               LoadAssembly (r, false);
+                       return;
+               }
+
+               private static void LoadAssembly (string assembly, bool soft)
+               {
+                       Assembly a;
+                       string total_log = "";
+
+                       try {
+                               char [] path_chars = { '/', '\\' };
+
+                               if (assembly.IndexOfAny (path_chars) != -1) {
+                                       a = Assembly.LoadFrom (assembly);
+                               } else {
+                                       string ass = assembly;
+                                       if (ass.EndsWith (".dll") || ass.EndsWith (".exe"))
+                                               ass = assembly.Substring (0, assembly.Length - 4);
+                                       a = Assembly.Load (ass);
+                               }
+                               AddAssembly (a);
+
+                       } catch (FileNotFoundException){
+                               foreach (string dir in link_paths){
+                                       string full_path = Path.Combine (dir, assembly);
+                                       if (!assembly.EndsWith (".dll") && !assembly.EndsWith (".exe"))
+                                               full_path += ".dll";
+
+                                       try {
+                                               a = Assembly.LoadFrom (full_path);
+                                               AddAssembly (a);
+                                               return;
+                                       } catch (FileNotFoundException ff) {
+                                               total_log += ff.FusionLog;
+                                               continue;
+                                       }
+                               }
+                               if (!soft)
+                                       Console.WriteLine ("Cannot find assembly `" + assembly + "'" );
+                       } catch (BadImageFormatException f) {
+                               Console.WriteLine ("Cannot load assembly (bad file format)" + f.FusionLog);
+                       } catch (FileLoadException f){
+                               Console.WriteLine ("Cannot load assembly " + f.FusionLog);
+                       } catch (ArgumentNullException){
+                               Console.WriteLine ("Cannot load assembly (null argument)");
+                       }
+               }       
+
+               /// <summary>
+               ///   Registers an assembly to load types from.
+               /// </summary>
+               private static void AddAssembly (Assembly a)
+               {
+                       foreach (Assembly assembly in assemblies) {
+                               if (a == assembly)
+                                       return;
+                       }
+
+                       int top = assemblies.Length;
+                       Assembly [] n = new Assembly [top + 1];
+
+                       assemblies.CopyTo (n, 0);
+               
+                       n [top] = a;
+                       assemblies = n;
+               }
+
+               static string [] LoadArgs (string file)
+               {
+                       StreamReader f;
+                       ArrayList args = new ArrayList ();
+                       string line;
+                       try {
+                               f = new StreamReader (file);
+                       } catch {
+                               return null;
+                       }
+
+                       StringBuilder sb = new StringBuilder ();
+                       
+                       while ((line = f.ReadLine ()) != null){
+                               int t = line.Length;
+
+                               for (int i = 0; i < t; i++){
+                                       char c = line [i];
+                                       
+                                       if (c == '"' || c == '\''){
+                                               char end = c;
+                                               
+                                               for (i++; i < t; i++){
+                                                       c = line [i];
+
+                                                       if (c == end)
+                                                               break;
+                                                       sb.Append (c);
+                                               }
+                                       } else if (c == ' '){
+                                               if (sb.Length > 0){
+                                                       args.Add (sb.ToString ());
+                                                       sb.Length = 0;
+                                               }
+                                       } else
+                                               sb.Append (c);
+                               }
+                               if (sb.Length > 0){
+                                       args.Add (sb.ToString ());
+                                       sb.Length = 0;
+                               }
+                       }
+
+                       string [] ret_value = new string [args.Count];
+                       args.CopyTo (ret_value, 0);
+
+                       return ret_value;
+               }       
+
+               //
+               // Returns the directory where the system assemblies are installed
+               //
+               static string GetSystemDir ()
+               {
+                       return Path.GetDirectoryName (typeof (object).Assembly.Location);
 
-               foreach (string fn in args) {
-                       IVsaCodeItem item = (IVsaCodeItem) engine.Items.CreateItem (fn, VsaItemType.Code, VsaItemFlag.None);
-                       item.SourceText = GetCodeFromFile (fn);
                }
-               engine.Compile ();
-       }
 
-       static string GetCodeFromFile (string fn)
-       {
-               try {
-                       StreamReader reader = new StreamReader (fn);
-                       return reader.ReadToEnd ();
-               } catch (FileNotFoundException) {
-                       throw new JScriptException (JSError.FileNotFound);
-               } catch (ArgumentNullException) {
-                       throw new JScriptException (JSError.FileNotFound);
-               } catch (ArgumentException) {
-                       throw new JScriptException (JSError.FileNotFound);
-               } catch (IOException) {
-                       throw new JScriptException (JSError.NoError);
-               } catch (OutOfMemoryException) {
-                       throw new JScriptException (JSError.OutOfMemory);
+               static void SetOutputFile (string name)
+               {
+                       output_file = name;
                }
-       }
-}
 
-class MonoEngineSite : IVsaSite {
-       public void GetCompiledState (out byte [] pe, out byte [] debugInfo)
-       {
-               throw new NotImplementedException ();
-       }
+               static void Version ()
+               {
+                       string version = Assembly.GetExecutingAssembly ().GetName ().Version.ToString ();
+                       Console.WriteLine ("Mono JScript compiler version {0}", version);
+                       Environment.Exit (0);
+               }
+       
+               static bool UnixParseOption (string arg, ref string [] args, ref int i)
+               {
+                       switch (arg){
+                       case "--version":
+                               Version ();
+                               return true;
+                               
+                       case "/?": case "/h": case "/help":
+                       case "--help":
+                               Usage ();
+                               Environment.Exit (0);
+                               return true;
+                       case "-o": 
+                       case "--output":
+                               if ((i + 1) >= args.Length){
+                                       Usage ();
+                                       Environment.Exit (1);
+                               }
+                               SetOutputFile (args [++i]);
+                               return true;
+                       case "-r":
+                               if ((i + 1) >= args.Length){
+                                       Usage ();
+                                       Environment.Exit (1);
+                               }
+                               
+                               references.Add (args [++i]);
+                               return true;
+                               
+                       case "-L":
+                               if ((i + 1) >= args.Length){
+                                       Usage ();       
+                                       Environment.Exit (1);
+                               }
+                               link_paths.Add (args [++i]);
+                               return true;
+                               
+                       case "--about":
+                               About ();
+                               return true;
+                       }
+                       return false;
+               }
 
-       public object GetEventSourceInstance (string itemName, string eventSourceName)
-       {
-               throw new NotImplementedException ();
-       }
+               //
+               // This parses the -arg and /arg options to the compiler, even if the strings
+               // in the following text use "/arg" on the strings.
+               //
+               static bool CSCParseOption (string option, ref string [] args, ref int i)
+               {
+                       int idx = option.IndexOf (':');
+                       string arg, value;
+                       if (idx == -1){
+                               arg = option;
+                               value = "";
+                       } else {
+                               arg = option.Substring (0, idx);
 
-       public object GetGlobalInstance (string name)
-       {
-               throw new NotImplementedException ();
-       }
+                               value = option.Substring (idx + 1);
+                       }
+
+                       switch (arg){
+                       case "/nologo":
+                               return true;
+
+                       case "/out":
+                               if (value == ""){
+                                       Usage ();
+                                       Environment.Exit (1);
+                               }
+                               SetOutputFile (value);
+                               return true;
+
+                       case "/r":
+                       case "/reference": {
+                               if (value == ""){
+                                       Console.WriteLine ("/reference requires an argument");
+                                       Environment.Exit (1);
+                               }
+
+                               string [] refs = value.Split (new char [] { ';', ',' });
+                               foreach (string r in refs){
+                                       references.Add (r);
+                               }
+                               return true;
+                       }
+
+                       case "/lib": {
+                               string [] libdirs;
+                               
+                               if (value == ""){
+                                       Console.WriteLine ("/lib requires an argument");
+                                       Environment.Exit (1);
+                               }
+
+                               libdirs = value.Split (new Char [] { ',' });
+                               foreach (string dir in libdirs)
+                                       link_paths.Add (dir);
+                               return true;
+                       }
+                       }
+                       return false;
+               }
+       
+               static string [] AddArgs (string [] args, string [] extra_args)
+               {
+                       string [] new_args;
+                       new_args = new string [extra_args.Length + args.Length];
+
+                       // if args contains '--' we have to take that into account
+                       // split args into first half and second half based on '--'
+                       // and add the extra_args before --
+                       int split_position = Array.IndexOf (args, "--");
+                       if (split_position != -1)
+                               {
+                                       Array.Copy (args, new_args, split_position);
+                                       extra_args.CopyTo (new_args, split_position);
+                                       Array.Copy (args, split_position, new_args, split_position + extra_args.Length, args.Length - split_position);
+                               }
+                       else
+                               {
+                                       args.CopyTo (new_args, 0);
+                                       extra_args.CopyTo (new_args, args.Length);
+                               }
 
-       public void Notify (string notify, object info)
-       {
-               throw new NotImplementedException ();
+                       return new_args;
+               }
+
+               //
+               // Given a path specification, splits the path from the file/pattern
+               //
+               static void SplitPathAndPattern (string spec, out string path, out string pattern)
+               {
+                       int p = spec.LastIndexOf ('/');
+                       if (p != -1){
+                               //
+                               // Windows does not like /file.cs, switch that to:
+                               // "\", "file.cs"
+                               //
+                               if (p == 0){
+                                       path = "\\";
+                                       pattern = spec.Substring (1);
+                               } else {
+                                       path = spec.Substring (0, p);
+                                       pattern = spec.Substring (p + 1);
+                               }
+                               return;
+                       }
+
+                       p = spec.LastIndexOf ('\\');
+                       if (p != -1){
+                               path = spec.Substring (0, p);
+                               pattern = spec.Substring (p + 1);
+                               return;
+                       }
+
+                       path = ".";
+                       pattern = spec;
+               }
+
+               static void ProcessFile (string f)
+               {
+                       if (first_source == null)
+                               first_source = f;
+
+                       files.Add (f);
+               }
+
+               static void CompileFiles (string spec, bool recurse)
+               {
+                       string path, pattern;
+
+                       SplitPathAndPattern (spec, out path, out pattern);
+                       if (pattern.IndexOf ('*') == -1){
+                               ProcessFile (spec);
+                               return;
+                       }
+
+                       string [] files = null;
+                       try {
+                               files = Directory.GetFiles (path, pattern);
+                       } catch (System.IO.DirectoryNotFoundException) {
+                               Console.WriteLine ("Source file `" + spec + "' could not be found");
+                               return;
+                       } catch (System.IO.IOException){
+                               Console.WriteLine ("Source file `" + spec + "' could not be found");
+                               return;
+                       }
+                       foreach (string f in files)
+                               ProcessFile (f);
+
+                       if (!recurse)
+                               return;
+                       
+                       string [] dirs = null;
+
+                       try {
+                               dirs = Directory.GetDirectories (path);
+                       } catch {
+                       }
+                       
+                       foreach (string d in dirs) {
+                                       
+                               // Don't include path in this string, as each
+                               // directory entry already does
+                               CompileFiles (d + "/" + pattern, true);
+                       }
+               }
+
+               internal static bool MainDriver (string [] args)
+               {
+                       int i;
+                       bool parsing_options = true;
+
+                       references = new ArrayList ();
+                       link_paths = new ArrayList ();
+                       files = new ArrayList ();
+
+                       Hashtable response_file_list = null;
+
+                       for (i = 0; i < args.Length; i++){
+                               string arg = args [i];
+                               if (arg == "")
+                                       continue;
+                               
+                               if (arg.StartsWith ("@")){
+                                       string [] extra_args;
+                                       string response_file = arg.Substring (1);
+
+                                       if (response_file_list == null)
+                                               response_file_list = new Hashtable ();
+                                       
+                                       if (response_file_list.Contains (response_file)){
+                                               Console.WriteLine ("Response file `" + response_file + "' specified multiple times");
+                                               Environment.Exit (1);
+                                       }
+                                       
+                                       response_file_list.Add (response_file, response_file);
+                                                   
+                                       extra_args = LoadArgs (response_file);
+                                       if (extra_args == null){
+                                               Console.WriteLine ("Unable to open response file: " + response_file);
+                                               return false;
+                                       }
+
+                                       args = AddArgs (args, extra_args);
+                                       continue;
+                               }
+
+                               if (parsing_options){
+                                       if (arg == "--"){
+                                               parsing_options = false;
+                                               continue;
+                                       }
+                                       
+                                       if (arg.StartsWith ("-")){
+                                               if (UnixParseOption (arg, ref args, ref i))
+                                                       continue;
+
+                                               // Try a -CSCOPTION
+                                               string csc_opt = "/" + arg.Substring (1);
+                                               if (CSCParseOption (csc_opt, ref args, ref i))
+                                                       continue;
+                                       } else {
+                                               if (arg.StartsWith ("/")){
+                                                       if (CSCParseOption (arg, ref args, ref i))
+                                                               continue;
+                                               }
+                                       }
+                               }
+                               CompileFiles (arg, false); 
+                       }
+
+                       //
+                       // If there is nothing to put in the assembly, and we are not a library
+                       //
+                       if (first_source == null) /* && embedded_resources == null && resources == null) */ {
+                               Console.WriteLine ("fatal error JS2026: No input sources specified");
+                               return false;
+                       }
+
+                       //
+                       // Load Core Library for default compilation
+                       //
+                       if (StdLib)
+                               references.Insert (0, "mscorlib");
+
+
+                       //
+                       // Load assemblies required
+                       //
+                       link_paths.Add (GetSystemDir ());
+                       link_paths.Add (Directory.GetCurrentDirectory ());
+                       LoadReferences ();
+                       return true;
+               }
+       
+               //
+               // Entry point
+               //
+               private static void Main (string [] args) {
+       
+                       if (args.Length < 1) {
+                               Usage ();
+                               Environment.Exit (0);
+                       }                       
+                       MainDriver (args);
+                       VsaEngine engine = new VsaEngine ();
+                       engine.InitVsaEngine ("mjs:com.mono-project", new MonoEngineSite ());
+                       
+                       foreach (string asm in references) {
+                               IVsaReferenceItem item = (IVsaReferenceItem) engine.Items.CreateItem (asm, VsaItemType.Reference, VsaItemFlag.None);
+                               item.AssemblyName = asm;
+                       }
+
+                       string asm_name = String.Empty;
+                       
+                       foreach (Assembly assembly in assemblies) {
+                               asm_name = assembly.GetName ().FullName;
+                               IVsaReferenceItem item = (IVsaReferenceItem) engine.Items.CreateItem (asm_name, VsaItemType.Reference, VsaItemFlag.None);
+                               item.AssemblyName = asm_name;
+                       }
+
+                       foreach (string file in files) {
+                               IVsaCodeItem item = (IVsaCodeItem) engine.Items.CreateItem (file, VsaItemType.Code, VsaItemFlag.None);
+                               item.SourceText = GetCodeFromFile (file);
+                       }
+                       engine.SetOption ("debug", want_debugging_support);
+                       engine.SetOption ("link_path", link_paths);
+                       engine.SetOption ("first_source", first_source);
+                       engine.SetOption ("assemblies", assemblies);
+                       engine.Compile ();
+               }
+
+               static string GetCodeFromFile (string fn)
+               {
+                       try {
+                               StreamReader reader = new StreamReader (fn);
+                               return reader.ReadToEnd ();
+                       } catch (FileNotFoundException) {
+                               throw new JScriptException (JSError.FileNotFound);
+                       } catch (ArgumentNullException) {
+                               throw new JScriptException (JSError.FileNotFound);
+                       } catch (ArgumentException) {
+                               throw new JScriptException (JSError.FileNotFound);
+                       } catch (IOException) {
+                               throw new JScriptException (JSError.NoError);
+                       } catch (OutOfMemoryException) {
+                               throw new JScriptException (JSError.OutOfMemory);
+                       }
+               }
        }
 
-       public bool OnCompilerError (IVsaError error)
-       {
-               throw new NotImplementedException ();
+       class MonoEngineSite : IVsaSite {
+               public void GetCompiledState (out byte [] pe, out byte [] debugInfo)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               public object GetEventSourceInstance (string itemName, string eventSourceName)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               public object GetGlobalInstance (string name)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               public void Notify (string notify, object info)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               public bool OnCompilerError (IVsaError error)
+               {
+                       throw new NotImplementedException ();
+               }
        }
 }