X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fsupport.cs;h=b31507195d77b7604c1adb14513bfdf3d6566d64;hb=0c2bb8157f43826a57c39b863a1d67e3aef1b7b2;hp=45fd159bf766d121da4aa220b2ec2a80ba4ccade;hpb=8a1b556c599e7ec54147e7494dd39f226f2ce7cf;p=mono.git diff --git a/mcs/mcs/support.cs b/mcs/mcs/support.cs index 45fd159bf76..b31507195d7 100644 --- a/mcs/mcs/support.cs +++ b/mcs/mcs/support.cs @@ -5,7 +5,8 @@ // Author: // Miguel de Icaza (miguel@ximian.com) // -// (C) 2001 Ximian, Inc (http://www.ximian.com) +// Copyright 2001 Ximian, Inc (http://www.ximian.com) +// Copyright 2003-2008 Novell, Inc // using System; @@ -18,276 +19,59 @@ using System.Globalization; namespace Mono.CSharp { - public interface ParameterData { - Type ParameterType (int pos); - int Count { get; } - bool HasParams { get; } - string ParameterName (int pos); - string ParameterDesc (int pos); - Parameter.Modifier ParameterModifier (int pos); - string GetSignatureForError (); - } - - public class ReflectionParameters : ParameterData { - ParameterInfo [] pi; - bool last_arg_is_params = false; - bool is_varargs = false; - - public ReflectionParameters (MethodBase mb) + class PtrHashtable : Hashtable { + sealed class PtrComparer : IComparer +#if NET_2_0 + , IEqualityComparer +#endif { - object [] attrs; - - ParameterInfo [] pi = mb.GetParameters (); - is_varargs = (mb.CallingConvention & CallingConventions.VarArgs) != 0; - - this.pi = pi; - int count = pi.Length-1; - - if (count >= 0) { - attrs = pi [count].GetCustomAttributes (TypeManager.param_array_type, true); + private PtrComparer () {} - if (attrs == null) - return; - - if (attrs.Length == 0) - return; + public static PtrComparer Instance = new PtrComparer (); - last_arg_is_params = true; - } - } - - public string GetSignatureForError () - { - StringBuilder sb = new StringBuilder ("("); - for (int i = 0; i < pi.Length; ++i) { - if (i != 0) - sb.Append (", "); - sb.Append (ParameterDesc (i)); + public int Compare (object x, object y) + { + if (x == y) + return 0; + else + return 1; } - sb.Append (')'); - return sb.ToString (); - } - - public Type ParameterType (int pos) - { - if (last_arg_is_params && pos >= pi.Length - 1) - return pi [pi.Length - 1].ParameterType; - else if (is_varargs && pos >= pi.Length) - return TypeManager.runtime_argument_handle_type; - else { - Type t = pi [pos].ParameterType; - - return t; +#if NET_2_0 + bool IEqualityComparer.Equals (object x, object y) + { + return x == y; } - } - - public string ParameterName (int pos) - { - if (last_arg_is_params && pos >= pi.Length - 1) - return pi [pi.Length - 1].Name; - else if (is_varargs && pos >= pi.Length) - return "__arglist"; - else - return pi [pos].Name; - } - - public string ParameterDesc (int pos) - { - if (is_varargs && pos >= pi.Length) - return ""; - - StringBuilder sb = new StringBuilder (); - - if (pi [pos].IsIn) - sb.Append ("in "); - - Type partype = ParameterType (pos); - if (partype.IsByRef){ - partype = TypeManager.GetElementType (partype); - if (pi [pos].IsOut) - sb.Append ("out "); - else - sb.Append ("ref "); - } - - if (pos >= pi.Length - 1 && last_arg_is_params) - sb.Append ("params "); - sb.Append (TypeManager.CSharpName (partype).Replace ("&", "")); - - return sb.ToString (); - - } - - public Parameter.Modifier ParameterModifier (int pos) - { - if (last_arg_is_params && pos >= pi.Length - 1) - return Parameter.Modifier.PARAMS; - else if (is_varargs && pos >= pi.Length) - return Parameter.Modifier.ARGLIST; - - Type t = pi [pos].ParameterType; - if (t.IsByRef){ - if ((pi [pos].Attributes & (ParameterAttributes.Out|ParameterAttributes.In)) == ParameterAttributes.Out) - return Parameter.Modifier.ISBYREF | Parameter.Modifier.OUT; - else - return Parameter.Modifier.ISBYREF | Parameter.Modifier.REF; + int IEqualityComparer.GetHashCode (object obj) + { + return obj.GetHashCode (); } +#endif - return Parameter.Modifier.NONE; - } - - public int Count { - get { - return is_varargs ? pi.Length + 1 : pi.Length; - } - } - - public bool HasParams { - get { - return this.last_arg_is_params; - } } - - } - public class InternalParameters : ParameterData { - Type [] param_types; - bool has_varargs; - int count; - - public readonly Parameters Parameters; - - public InternalParameters (Type [] param_types, Parameters parameters) +#if NET_2_0 + public PtrHashtable () : base (PtrComparer.Instance) {} +#else + public PtrHashtable () { - this.param_types = param_types; - this.Parameters = parameters; - - has_varargs = parameters.HasArglist; - - if (param_types == null) - count = 0; - else - count = param_types.Length; - } - - public int Count { - get { - return has_varargs ? count + 1 : count; - } - } - - public bool HasParams { - get { - return Parameters.ArrayParameter != null; - } - } - - Parameter GetParameter (int pos) - { - Parameter [] fixed_pars = Parameters.FixedParameters; - if (fixed_pars != null){ - int len = fixed_pars.Length; - if (pos < len) - return Parameters.FixedParameters [pos]; - } - - return Parameters.ArrayParameter; - } - - public string GetSignatureForError () - { - StringBuilder sb = new StringBuilder ("("); - for (int i = 0; i < count; ++i) { - if (i != 0) - sb.Append (", "); - sb.Append (ParameterDesc (i)); - } - sb.Append (')'); - return sb.ToString (); - } - - public Type ParameterType (int pos) - { - if (has_varargs && pos >= count) - return TypeManager.runtime_argument_handle_type; - - if (param_types == null) - return null; - - return GetParameter (pos).ExternalType (); - } - - - public string ParameterName (int pos) - { - if (has_varargs && pos >= count) - return "__arglist"; - - return GetParameter (pos).Name; - } - - public string ParameterDesc (int pos) - { - if (has_varargs && pos >= count) - return "__arglist"; - - Type t = ParameterType (pos); - return (ModifierDesc (pos) + " " + TypeManager.CSharpName (t).Replace ("&", "")).TrimStart (); - } - - public string ModifierDesc (int pos) - { - Parameter p = GetParameter (pos); - - // - // We need to and for REF/OUT, because if either is set the - // extra flag ISBYREF will be set as well - // - if ((p.ModFlags & Parameter.Modifier.REF) != 0) - return "ref"; - if ((p.ModFlags & Parameter.Modifier.OUT) != 0) - return "out"; - if (p.ModFlags == Parameter.Modifier.PARAMS) - return "params"; - - return ""; + comparer = PtrComparer.Instance; } +#endif - public Parameter.Modifier ParameterModifier (int pos) +#if MS_COMPATIBLE + // + // Workaround System.InvalidOperationException for enums + // + protected override int GetHash (object key) { - if (has_varargs && pos >= count) - return Parameter.Modifier.ARGLIST; + TypeBuilder tb = key as TypeBuilder; + if (tb != null && tb.BaseType == TypeManager.enum_type && tb.BaseType != null) + key = tb.BaseType; - Parameter.Modifier mod = GetParameter (pos).ModFlags; - - if ((mod & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) != 0) - mod |= Parameter.Modifier.ISBYREF; - - return mod; - } - - } - - class PtrHashtable : Hashtable { - sealed class PtrComparer : IComparer { - private PtrComparer () {} - - public static PtrComparer Instance = new PtrComparer (); - - public int Compare (object x, object y) - { - if (x == y) - return 0; - else - return 1; - } - } - - public PtrHashtable () - { - comparer = PtrComparer.Instance; + return base.GetHash (key); } +#endif } /* @@ -331,12 +115,12 @@ namespace Mono.CSharp { this.len = len; comparer = new ArrComparer (len); } - } + } struct Pair { public object First; public object Second; - + public Pair (object f, object s) { First = f; @@ -344,86 +128,100 @@ namespace Mono.CSharp { } } + public class Accessors { + public Accessor get_or_add; + public Accessor set_or_remove; + + // was 'set' declared before 'get'? was 'remove' declared before 'add'? + public bool declared_in_reverse; + + public Accessors (Accessor get_or_add, Accessor set_or_remove) + { + this.get_or_add = get_or_add; + this.set_or_remove = set_or_remove; + } + } + /// - /// This is a wrapper around StreamReader which is seekable. + /// This is an arbitrarily seekable StreamReader wrapper. + /// + /// It uses a self-tuning buffer to cache the seekable data, + /// but if the seek is too far, it may read the underly + /// stream all over from the beginning. /// public class SeekableStreamReader { - public SeekableStreamReader (StreamReader reader) - { - this.reader = reader; - this.buffer = new char [DefaultCacheSize]; - - // Compute the preamble size - - // Let the StreamWriter autodetect the encoder - reader.Peek (); - - Encoding enc = reader.CurrentEncoding; - preamble_size = (int) reader.BaseStream.Position; - } + const int default_average_read_length = 1024; + const int buffer_read_length_spans = 3; - public SeekableStreamReader (Stream stream, Encoding encoding) - : this (new StreamReader (stream, encoding, true)) - { } - - StreamReader reader; - - private const int DefaultCacheSize = 1024; + TextReader reader; + Stream stream; + Encoding encoding; char[] buffer; - int buffer_start; // in bytes - int buffer_size; // in bytes + int average_read_length; + int buffer_start; // in chars int char_count; // count buffer[] valid characters int pos; // index into buffer[] - int preamble_size; + + void ResetStream (int read_length_inc) + { + average_read_length += read_length_inc; + stream.Position = 0; + reader = new StreamReader (stream, encoding, true); + buffer = new char [average_read_length * buffer_read_length_spans]; + buffer_start = char_count = pos = 0; + } + + public SeekableStreamReader (Stream stream, Encoding encoding) + { + this.stream = stream; + this.encoding = encoding; + + ResetStream (default_average_read_length); + } /// - /// The difference to the StreamReader's BaseStream.Position is that this one is reliable; ie. it - // always reports the correct position and if it's modified, it also takes care of the buffered data. + /// This value corresponds to the current position in a stream of characters. + /// The StreamReader hides its manipulation of the underlying byte stream and all + /// character set/decoding issues. Thus, we cannot use this position to guess at + /// the corresponding position in the underlying byte stream even though there is + /// a correlation between them. /// public int Position { - get { - return buffer_start + reader.CurrentEncoding.GetByteCount (buffer, 0, pos); - } + get { return buffer_start + pos; } set { - // This one is easy: we're modifying the position within our current - // buffer. - if ((value >= buffer_start) && (value < buffer_start + buffer_size)) { - int byte_offset = value - buffer_start; - - // If we have an uni-byte encoding, 'pos' will be the same as - // 'byte_offset'. If we have a multi-byte encoding, 'byte_offset' - // can be bigger than the desired value of 'pos', but not smaller. - // (IOW, the number of characters <= number of bytes) - // - // So, we start pos off at byte_offset, and fix it up. - pos = byte_offset; - if (pos > char_count) - pos = char_count; - while (reader.CurrentEncoding.GetByteCount (buffer, 0, pos) > byte_offset) - --pos; - return; + // If the lookahead was too small, re-read from the beginning. Increase the buffer size while we're at it + if (value < buffer_start) + ResetStream (average_read_length / 2); + + while (value > buffer_start + char_count) { + pos = char_count; + if (!ReadBuffer ()) + throw new InternalErrorException ("Seek beyond end of file: " + (buffer_start + char_count - value)); } - if (value == 0) // Skip preamble - value = preamble_size; - - // Ok, now we need to seek. - reader.DiscardBufferedData (); - reader.BaseStream.Position = buffer_start = value; - char_count = buffer_size = pos = 0; + pos = value - buffer_start; } } private bool ReadBuffer () { - pos = 0; - buffer_start += buffer_size; - char_count = reader.Read (buffer, 0, buffer.Length); - buffer_size = reader.CurrentEncoding.GetByteCount (buffer, 0, char_count); - return buffer_size > 0; + int slack = buffer.Length - char_count; + if (slack <= average_read_length / 2) { + // shift the buffer to make room for average_read_length number of characters + int shift = average_read_length - slack; + Array.Copy (buffer, shift, buffer, 0, char_count - shift); + pos -= shift; + char_count -= shift; + buffer_start += shift; + slack += shift; // slack == average_read_length + } + + char_count += reader.Read (buffer, char_count, slack); + + return pos < char_count; } public int Peek () @@ -445,26 +243,26 @@ namespace Mono.CSharp { public class DoubleHash { const int DEFAULT_INITIAL_BUCKETS = 100; - + public DoubleHash () : this (DEFAULT_INITIAL_BUCKETS) {} - + public DoubleHash (int size) { count = size; buckets = new Entry [size]; } - + int count; Entry [] buckets; int size = 0; - + class Entry { public object key1; public object key2; public int hash; public object value; public Entry next; - + public Entry (object key1, object key2, int hash, object value, Entry next) { this.key1 = key1; @@ -478,7 +276,7 @@ namespace Mono.CSharp { public bool Lookup (object a, object b, out object res) { int h = (a.GetHashCode () ^ b.GetHashCode ()) & 0x7FFFFFFF; - + for (Entry e = buckets [h % count]; e != null; e = e.next) { if (e.hash == h && e.key1.Equals (a) && e.key2.Equals (b)) { res = e.value; @@ -492,22 +290,22 @@ namespace Mono.CSharp { public void Insert (object a, object b, object value) { // Is it an existing one? - + int h = (a.GetHashCode () ^ b.GetHashCode ()) & 0x7FFFFFFF; - + for (Entry e = buckets [h % count]; e != null; e = e.next) { if (e.hash == h && e.key1.Equals (a) && e.key2.Equals (b)) e.value = value; } - + int bucket = h % count; buckets [bucket] = new Entry (a, b, h, value, buckets [bucket]); - + // Grow whenever we double in size if (size++ == count) { count <<= 1; count ++; - + Entry [] newBuckets = new Entry [count]; foreach (Entry root in buckets) { Entry e = root; @@ -524,4 +322,137 @@ namespace Mono.CSharp { } } } + + class PartialMethodDefinitionInfo : MethodInfo + { + MethodOrOperator mc; + MethodAttributes attrs; + + public PartialMethodDefinitionInfo (MethodOrOperator mc) + { + this.mc = mc; + if ((mc.ModFlags & Modifiers.STATIC) != 0) + attrs = MethodAttributes.Static; + } + + public override MethodInfo GetBaseDefinition () + { + throw new NotImplementedException (); + } + + public override ICustomAttributeProvider ReturnTypeCustomAttributes + { + get { throw new NotImplementedException (); } + } + + public override MethodAttributes Attributes + { + get { return attrs; } + } + + public override MethodImplAttributes GetMethodImplementationFlags () + { + throw new NotImplementedException (); + } + + public override ParameterInfo [] GetParameters () + { + throw new NotImplementedException (); + } + + public override object Invoke (object obj, BindingFlags invokeAttr, Binder binder, object [] parameters, CultureInfo culture) + { + throw new NotImplementedException (); + } + + public override RuntimeMethodHandle MethodHandle + { + get { throw new NotImplementedException (); } + } + + public override Type DeclaringType + { + get { return mc.Parent.TypeBuilder; } + } + + public override object [] GetCustomAttributes (Type attributeType, bool inherit) + { + throw new NotImplementedException (); + } + + public override object [] GetCustomAttributes (bool inherit) + { + throw new NotImplementedException (); + } + + public override Type ReturnType { + get { + return mc.MemberType; + } + } + + public override bool IsDefined (Type attributeType, bool inherit) + { + throw new NotImplementedException (); + } + + public override string Name + { + get { return mc.Name; } + } + + public override Type ReflectedType + { + get { throw new NotImplementedException (); } + } + } + + public class UnixUtils { + [System.Runtime.InteropServices.DllImport ("libc", EntryPoint="isatty")] + extern static int _isatty (int fd); + + public static bool isatty (int fd) + { + try { + return _isatty (fd) == 1; + } catch { + return false; + } + } + } + + /// + /// An exception used to terminate the compiler resolution phase and provide completions + /// + /// + /// This is thrown when we want to return the completions or + /// terminate the completion process by AST nodes used in + /// the completion process. + /// + public class CompletionResult : Exception { + string [] result; + string base_text; + + public CompletionResult (string base_text, string [] res) + { + if (base_text == null) + throw new ArgumentNullException ("base_text"); + this.base_text = base_text; + + result = res; + Array.Sort (result); + } + + public string [] Result { + get { + return result; + } + } + + public string BaseText { + get { + return base_text; + } + } + } }