Example #1
0
        private Regex /*!*/ TransformPattern(RubyEncoding encoding, RubyRegexOptions kc)
        {
            // We can reuse cached CLR regex if it was created for the same k-coding:
            if (_cachedRegex != null && kc == _cachedKCode)
            {
                return(_cachedRegex);
            }

            string pattern;

            if (kc != 0 || encoding == RubyEncoding.Binary)
            {
                pattern = _pattern.ToString(encoding.Encoding);
            }
            else
            {
                pattern = _pattern.ConvertToString();
            }

            Regex result;

            try {
                result = new Regex(RegexpTransformer.Transform(pattern, _options, out _hasGAnchor), ToClrOptions(_options));
            } catch (Exception e) {
                throw new RegexpError(e.Message);
            }

            _cachedKCode = kc;
            _cachedRegex = result;
            return(result);
        }
        internal static Process /*!*/ CreateProcess(RubyContext /*!*/ context, MutableString /*!*/ command,
                                                    bool redirectInput, bool redirectOutput, bool redirectErrorOutput)
        {
            string fileName, arguments;

            RubyProcess.GetExecutable(context.DomainManager.Platform, command.ToString(), out fileName, out arguments);
            Utils.Log(String.Format("Starting: '{0}' with args: '{1}'", fileName, arguments), "PROCESS");

            var p = new Process();

            p.StartInfo.FileName               = fileName;
            p.StartInfo.Arguments              = arguments;
            p.StartInfo.UseShellExecute        = false;
            p.StartInfo.RedirectStandardInput  = redirectInput;
            p.StartInfo.RedirectStandardOutput = redirectOutput;
            p.StartInfo.RedirectStandardError  = redirectErrorOutput;
            try {
                p.Start();
            } catch (Exception e) {
                throw RubyExceptions.CreateENOENT(fileName, e);
            }

            context.ChildProcessExitStatus = new RubyProcess.Status(p);
            return(p);
        }
Example #3
0
        private Regex /*!*/ Transform(ref RubyEncoding encoding, MutableString /*!*/ input, int start, out string strInput)
        {
            ContractUtils.RequiresNotNull(input, "input");

            // K-coding of the current operation (the current KCODE gets preference over the KCODE regex option):
            RubyRegexOptions kc = _options & RubyRegexOptions.EncodingMask;

            if (kc != 0)
            {
                encoding = _pattern.Encoding;
            }
            else
            {
                kc = RubyEncoding.ToRegexOption(encoding);
            }

            // Convert input to a string. Force k-coding if necessary.
            if (kc != 0)
            {
                // Handling multi-byte K-coded characters is not entirely correct here.
                // Three cases to be considered:
                // 1) Multi-byte character is explicitly contained in the pattern: /�*/
                // 2) Subsequent escapes form a complete character: /\342\202\254*/ or /\xe2\x82\xac*/
                // 3) Subsequent escapes form an incomplete character: /[\x7f-\xff]{1,3}/
                //
                // In the first two cases we want to "group" the byte triplet so that regex operators like *, +, ? and {n,m} operate on
                // the entire character, not just the last byte. We could unescape the bytes and replace them with complete Unicode characters.
                // Then we could encode the input using the same K-coding and we would get a match.
                // However, case 3) requires the opposite: to match the bytes we need to encode the input using binary encoding.
                // Using this encoding makes *+? operators operate on the last byte (encoded as UTF16 character).
                //
                // The right solution would require the regex engine to handle multi-byte escaped characters, which it doesn't.
                //
                // TODO:
                // A correct workaround would be to wrap the byte sequence that forms a character into a non-capturing group,
                // for example transform /\342\202\254*/ to /(?:\342\202\254)*/ and use binary encoding on both input and pattern.
                // For now, we just detect if there are any non-ascii character escapes. If so we use a binary encoding accomodating case 3),
                // but breaking cases 1 and 2. Otherwise we encode using k-coding to make case 1 match.
                if (HasEscapedNonAsciiBytes(_pattern))
                {
                    encoding = RubyEncoding.Binary;
                    kc       = 0;
                }

                strInput = ForceEncoding(input, encoding.Encoding, start);
            }
            else if (input.Encoding.IsKCoding)
            {
                strInput = input.ToString(BinaryEncoding.Instance);
            }
            else
            {
                _pattern.RequireCompatibleEncoding(input);
                input.PrepareForCharacterRead();
                strInput = input.ConvertToString();
            }

            return(TransformPattern(encoding, kc));
        }
Example #4
0
        public static int SysOpen(RubyClass /*!*/ self, [NotNull] MutableString path, [Optional] MutableString mode, [Optional] int perm)
        {
            if (RubyFileOps.DirectoryExists(self.Context, path))
            {
                // TODO: What file descriptor should be returned for a directory?
                return(-1);
            }
            RubyIO io       = new RubyFile(self.Context, path.ToString(), IOModeEnum.Parse(mode));
            int    fileDesc = io.GetFileDescriptor();

            io.Close();
            return(fileDesc);
        }
Example #5
0
        //  declared private instance methods:
        //    initialize
        //  declared protected instance methods:
        //  declared public instance methods:

        private static Exception MakeKeyTypeException(RubyContext /*!*/ context, object key)
        {
            if (key == null)
            {
                return(RubyExceptions.CreateTypeError("nil is not a symbol"));
            }
            else
            {
                MutableString repr    = Protocols.ConvertToString(context, key);
                string        message = String.Format("{0} is not a symbol", repr.ToString());
                return(RubyExceptions.CreateArgumentError(message));
            }
        }
Example #6
0
        public static IOInfo Parse(RubyContext /*!*/ context, MutableString /*!*/ modeAndEncoding)
        {
            if (!modeAndEncoding.IsAscii())
            {
                throw IOModeEnum.IllegalMode(modeAndEncoding.ToAsciiString());
            }

            string[] parts = modeAndEncoding.ToString().Split(':');
            return(new IOInfo(
                       IOModeEnum.Parse(parts[0]),
                       (parts.Length > 1) ? TryParseEncoding(context, parts[1]) : null,
                       (parts.Length > 2) ? TryParseEncoding(context, parts[2]) : null
                       ));
        }
Example #7
0
        public static int Rename(RubyContext /*!*/ context, RubyClass /*!*/ self,
                                 [DefaultProtocol, NotNull] MutableString /*!*/ oldPath, [DefaultProtocol, NotNull] MutableString /*!*/ newPath)
        {
            string strOldPath = oldPath.ConvertToString();

            if (!FileExists(context, strOldPath) && !DirectoryExists(context, strOldPath))
            {
                throw new Errno.NoEntryError(String.Format("No such file or directory - {0}", oldPath));
            }

            // TODO: Change to raise a SystemCallError instead of a native CLR error
            File.Move(strOldPath, newPath.ToString());
            return(0);
        }
Example #8
0
        public static void RaiseException(Thread /*!*/ self, [NotNull] MutableString /*!*/ message)
        {
            if (self == Thread.CurrentThread)
            {
                KernelOps.RaiseException(self, message);
                return;
            }

#if SILVERLIGHT
            throw new NotImplementedError("Thread#raise is not implemented on Silverlight");
#else
            Exception e = RubyExceptionData.InitializeException(new RuntimeError(message.ToString()), message);
            RaiseAsyncException(self, e);
#endif
        }
Example #9
0
        private static string /*!*/ ForceEncoding(MutableString /*!*/ input, Encoding /*!*/ encoding, int start)
        {
            int byteCount = input.GetByteCount();

            if (start < 0)
            {
                start += byteCount;
            }
            if (start < 0)
            {
                return(null);
            }

            return((start <= byteCount) ? input.ToString(encoding, start, byteCount - start) : null);
        }
Example #10
0
        public static void RaiseException(Thread /*!*/ self, [NotNull] MutableString /*!*/ message)
        {
            if (self == Thread.CurrentThread)
            {
                KernelOps.RaiseException(self, message);
                return;
            }

#if FEATURE_EXCEPTION_STATE
            Exception e = RubyExceptionData.InitializeException(new RuntimeError(message.ToString()), message);
            RaiseAsyncException(self, e);
#else
            throw new NotImplementedError("Thread#raise not supported on this platform");
#endif
        }
Example #11
0
        internal static Process /*!*/ CreateProcess(RubyContext /*!*/ context, MutableString /*!*/ command, MutableString[] /*!*/ args)
        {
            var psi = new ProcessStartInfo(command.ToString(), JoinArguments(args).ToString());

            psi.UseShellExecute       = false;
            psi.RedirectStandardError = true;
            try {
                Utils.Log(String.Format("Starting: '{0}' with args: '{1}'", psi.FileName, psi.Arguments), "PROCESS");
                Process p = Process.Start(psi);
                p.WaitForExit();
                context.ChildProcessExitStatus = new RubyProcess.Status(p);
                return(p);
            } catch (Exception e) {
                throw RubyExceptions.CreateENOENT(psi.FileName, e);
            }
        }
Example #12
0
        public static string GetSubstring(RubyScope /*!*/ scope, string /*!*/ self, [NotNull] RubyRegex /*!*/ regex, [DefaultProtocol] int occurrance)
        {
            if (regex.IsEmpty)
            {
                return(String.Empty);
            }

            MatchData match = RegexpOps.Match(scope, regex, MutableString.Create(self, RubyEncoding.UTF8));

            if (match == null || !RegexpOps.NormalizeGroupIndex(ref occurrance, match.GroupCount))
            {
                return(null);
            }

            MutableString result = match.GetGroupValue(occurrance);

            return(result != null?result.ToString() : null);
        }
Example #13
0
        public IOInfo AddEncoding(RubyContext /*!*/ context, MutableString /*!*/ encoding)
        {
            if (!encoding.IsAscii())
            {
                context.ReportWarning(String.Format("Unsupported encoding {0} ignored", encoding.ToAsciiString()));
                return(this);
            }

            if (HasEncoding)
            {
                throw RubyExceptions.CreateArgumentError("encoding specified twice");
            }

            string[] parts = encoding.ToString().Split(':');
            return(new IOInfo(
                       _mode,
                       TryParseEncoding(context, parts[0]),
                       (parts.Length > 1) ? TryParseEncoding(context, parts[1]) : null
                       ));
        }
Example #14
0
            private string ReadSymbol(int typeFlag)
            {
                string result = null;

                if (typeFlag == ';')
                {
                    int position = ReadInt32();
                    if (!_symbols.TryGetValue(position, out result))
                    {
                        throw RubyExceptions.CreateArgumentError("bad symbol");
                    }
                }
                else
                {
                    // Ruby appears to assume that it's a ':' in this context
                    MutableString symbolName = ReadString();
                    result = symbolName.ToString();
                    int position = _symbols.Count;
                    _symbols[position] = result;
                }
                return(result);
            }
Example #15
0
 public static string /*!*/ Concatenate(string /*!*/ self, [DefaultProtocol, NotNull] MutableString /*!*/ other)
 {
     return(self + other.ToString());
 }
Example #16
0
 public override string /*!*/ ToString()
 {
     return(_string.ToString());
 }
Example #17
0
 public static string /*!*/ Create(RubyClass /*!*/ self, [DefaultProtocol] MutableString /*!*/ str)
 {
     return(str.ToString());
 }
Example #18
0
        public static MutableString /*!*/ FormatTime(DateTime self, [DefaultProtocol, NotNull] MutableString /*!*/ format)
        {
            bool          inEscape = false;
            StringBuilder builder  = new StringBuilder();

            foreach (char c in format.ToString())
            {
                if (c == '%' && !inEscape)
                {
                    inEscape = true;
                    continue;
                }
                if (inEscape)
                {
                    string   thisFormat = null;
                    DateTime firstDay;
                    int      week;
                    switch (c)
                    {
                    case 'a':
                        thisFormat = "ddd";
                        break;

                    case 'A':
                        thisFormat = "dddd";
                        break;

                    case 'b':
                        thisFormat = "MMM";
                        break;

                    case 'B':
                        thisFormat = "MMMM";
                        break;

                    case 'c':
                        thisFormat = "g";
                        break;

                    case 'd':
                        thisFormat = "dd";
                        break;

                    case 'H':
                        thisFormat = "HH";
                        break;

                    case 'I':
                        thisFormat = "hh";
                        break;

                    case 'j':
                        builder.AppendFormat("{0:000}", self.DayOfYear);
                        break;

                    case 'm':
                        thisFormat = "MM";
                        break;

                    case 'M':
                        thisFormat = "mm";
                        break;

                    case 'p':
                        thisFormat = "tt";
                        break;

                    case 'S':
                        thisFormat = "ss";
                        break;

                    case 'U':
                        firstDay = self.AddDays(1 - self.DayOfYear);
                        DateTime firstSunday = firstDay.AddDays((7 - (int)firstDay.DayOfWeek) % 7);
                        week = 1 + (int)Math.Floor((self - firstSunday).Days / 7.0);
                        builder.AppendFormat("{0:00}", week);
                        break;

                    case 'W':
                        firstDay = self.AddDays(1 - self.DayOfYear);
                        DateTime firstMonday = firstDay.AddDays((8 - (int)firstDay.DayOfWeek) % 7);
                        week = 1 + (int)Math.Floor((self - firstMonday).Days / 7.0);
                        builder.AppendFormat("{0:00}", week);
                        break;

                    case 'w':
                        builder.Append((int)self.DayOfWeek);
                        break;

                    case 'x':
                        thisFormat = "d";
                        break;

                    case 'X':
                        thisFormat = "t";
                        break;

                    case 'y':
                        thisFormat = "yy";
                        break;

                    case 'Y':
                        thisFormat = "yyyy";
                        break;

                    case 'Z':
                        thisFormat = "%K";
                        break;

                    default:
                        builder.Append(c);
                        break;
                    }
                    if (thisFormat != null)
                    {
                        builder.Append(self.ToString(thisFormat));
                    }
                    inEscape = false;
                }
                else
                {
                    builder.Append(c);
                }
            }

            return(MutableString.Create(builder.ToString()));
        }
Example #19
0
 public static IOMode Parse(MutableString mode, IOMode defaultMode)
 {
     return((mode != null) ? IOModeEnum.Parse(mode.ToString()) : defaultMode);
 }
Example #20
0
        public static MutableString /*!*/ Basename(RubyClass /*!*/ self,
                                                   [DefaultProtocol, NotNull] MutableString /*!*/ path, [DefaultProtocol, NotNull, Optional] MutableString suffix)
        {
            if (path.IsEmpty)
            {
                return(path);
            }

            string strPath = path.ConvertToString();

            string[] parts = strPath.Split(new[] { DirectorySeparatorChar, AltDirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries);

            if (parts.Length == 0)
            {
                return(MutableString.CreateMutable(path.Encoding).Append((char)path.GetLastChar()).TaintBy(path));
            }

            if (Environment.OSVersion.Platform != PlatformID.Unix && Environment.OSVersion.Platform != PlatformID.MacOSX)
            {
                string first = parts[0];
                if (strPath.Length >= 2 && IsDirectorySeparator(strPath[0]) && IsDirectorySeparator(strPath[1]))
                {
                    // UNC: skip 2 parts
                    if (parts.Length <= 2)
                    {
                        return(MutableString.CreateMutable(path.Encoding).Append(DirectorySeparatorChar).TaintBy(path));
                    }
                }
                else if (first.Length == 2 && Tokenizer.IsLetter(first[0]) && first[1] == ':')
                {
                    // skip drive letter "X:"
                    if (parts.Length <= 1)
                    {
                        var result = MutableString.CreateMutable(path.Encoding).TaintBy(path);
                        if (strPath.Length > 2)
                        {
                            result.Append(strPath[2]);
                        }
                        return(result);
                    }
                }
            }

            string last = parts[parts.Length - 1];

            if (MutableString.IsNullOrEmpty(suffix))
            {
                return(MutableString.CreateMutable(last, path.Encoding));
            }

            StringComparison comparison = Environment.OSVersion.Platform == PlatformID.Unix ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase;
            int matchLength             = last.Length;

            if (suffix != null)
            {
                string strSuffix = suffix.ToString();
                if (strSuffix.LastCharacter() == '*' && strSuffix.Length > 1)
                {
                    int suffixIdx = last.LastIndexOf(
                        strSuffix.Substring(0, strSuffix.Length - 1),
                        comparison
                        );
                    if (suffixIdx >= 0 && suffixIdx + strSuffix.Length <= last.Length)
                    {
                        matchLength = suffixIdx;
                    }
                }
                else if (last.EndsWith(strSuffix, comparison))
                {
                    matchLength = last.Length - strSuffix.Length;
                }
            }

            return(MutableString.CreateMutable(path.Encoding).Append(last, 0, matchLength).TaintBy(path));
        }
Example #21
0
 public static RubyEncoding /*!*/ GetEncoding(RubyClass /*!*/ self, [NotNull] MutableString /*!*/ name)
 {
     return(RubyEncoding.GetRubyEncoding(name.ToString()));
 }