Example #1
0
            /// <summary>Evaluates a terminfo formatting string, using the supplied arguments.</summary>
            /// <param name="format">The format string.</param>
            /// <param name="args">The arguments to the format string.</param>
            /// <returns>The formatted string.</returns>
            public static string Evaluate(string format, params FormatParam[] args)
            {
                if (format == null)
                {
                    throw new ArgumentNullException(nameof(format));
                }
                if (args == null)
                {
                    throw new ArgumentNullException(nameof(args));
                }

                // Initialize the stack to use for processing.
                LowLevelStack <FormatParam> stack = t_cachedStack;

                if (stack == null)
                {
                    t_cachedStack = stack = new LowLevelStack <FormatParam>();
                }
                else
                {
                    stack.Clear();
                }

                // "dynamic" and "static" variables are much less often used (the "dynamic" and "static"
                // terminology appears to just refer to two different collections rather than to any semantic
                // meaning).  As such, we'll only initialize them if we really need them.
                FormatParam[] dynamicVars = null, staticVars = null;

                int pos = 0;

                return(EvaluateInternal(format, ref pos, args, stack, ref dynamicVars, ref staticVars));

                // EvaluateInternal may throw IndexOutOfRangeException and InvalidOperationException
                // if the format string is malformed or if it's inconsistent with the parameters provided.
            }
Example #2
0
 public ILInterpreter(TypeSystemContext context, MethodDesc method, MethodIL methodIL)
 {
     _context  = context;
     _method   = method;
     _methodIL = methodIL;
     _stack    = new LowLevelStack <StackItem>();
 }
Example #3
0
 public ILInterpreter(TypeSystemContext context, MethodDesc method, MethodIL methodIL)
 {
     _context  = context;
     _method   = method;
     _methodIL = methodIL;
     _locals   = new StackItem[methodIL.GetLocals().Length];
     _stack    = new LowLevelStack <StackItem>();
 }
Example #4
0
                /// <summary>Evaluates a terminfo formatting string, using the supplied arguments and processing data structures.</summary>
                /// <param name="format">The format string.</param>
                /// <param name="pos">The position in <paramref name="format"/> to start processing.</param>
                /// <param name="args">The arguments to the format string.</param>
                /// <param name="stack">The stack to use as the format string is evaluated.</param>
                /// <param name="dynamicVars">A lazily-initialized collection of variables.</param>
                /// <param name="staticVars">A lazily-initialized collection of variables.</param>
                /// <returns>
                /// The formatted string; this may be empty if the evaluation didn't yield any output.
                /// The evaluation stack will have a 1 at the top if all processing was completed at invoked level
                /// of recursion, and a 0 at the top if we're still inside of a conditional that requires more processing.
                /// </returns>
                private static string EvaluateInternal(
			string format, ref int pos, FormatParam[] args, LowLevelStack stack,
			ref FormatParam[] dynamicVars, ref FormatParam[] staticVars)
		{
			// Create a StringBuilder to store the output of this processing.  We use the format's length as an 
			// approximation of an upper-bound for how large the output will be, though with parameter processing,
			// this is just an estimate, sometimes way over, sometimes under.
			StringBuilder output = new StringBuilder(format.Length);

			// Format strings support conditionals, including the equivalent of "if ... then ..." and
			// "if ... then ... else ...", as well as "if ... then ... else ... then ..."
			// and so on, where an else clause can not only be evaluated for string output but also
			// as a conditional used to determine whether to evaluate a subsequent then clause.
			// We use recursion to process these subsequent parts, and we track whether we're processing
			// at the same level of the initial if clause (or whether we're nested).
			bool sawIfConditional = false;

			// Process each character in the format string, starting from the position passed in.
			for (; pos < format.Length; pos++){
				// '%' is the escape character for a special sequence to be evaluated.
				// Anything else just gets pushed to output.
				if (format[pos] != '%') {
					output.Append(format[pos]);
					continue;
				}
				// We have a special parameter sequence to process.  Now we need
				// to look at what comes after the '%'.
				++pos;
				switch (format[pos]) {
				// Output appending operations
				case '%': // Output the escaped '%'
					output.Append('%');
					break;
				case 'c': // Pop the stack and output it as a char
					output.Append((char)stack.Pop().Int32);
					break;
				case 's': // Pop the stack and output it as a string
					output.Append(stack.Pop().String);
					break;
				case 'd': // Pop the stack and output it as an integer
					output.Append(stack.Pop().Int32);
					break;
				case 'o':
				case 'X':
				case 'x':
				case ':':
				case '0':
				case '1':
				case '2':
				case '3':
				case '4':
				case '5':
				case '6':
				case '7':
				case '8':
				case '9':
					// printf strings of the format "%[[:]flags][width[.precision]][doxXs]" are allowed
					// (with a ':' used in front of flags to help differentiate from binary operations, as flags can
					// include '-' and '+').  While above we've special-cased common usage (e.g. %d, %s),
					// for more complicated expressions we delegate to printf.
					int printfEnd = pos;
					for (; printfEnd < format.Length; printfEnd++) // find the end of the printf format string
					{
						char ec = format[printfEnd];
						if (ec == 'd' || ec == 'o' || ec == 'x' || ec == 'X' || ec == 's')
						{
							break;
						}
					}
					if (printfEnd >= format.Length)
						throw new InvalidOperationException("Terminfo database contains invalid values");
					string printfFormat = format.Substring(pos - 1, printfEnd - pos + 2); // extract the format string
					if (printfFormat.Length > 1 && printfFormat[1] == ':')
						printfFormat = printfFormat.Remove(1, 1);
					output.Append(FormatPrintF(printfFormat, stack.Pop().Object)); // do the printf formatting and append its output
					break;

					// Stack pushing operations
				case 'p': // Push the specified parameter (1-based) onto the stack
					pos++;
					stack.Push(args[format[pos] - '1']);
					break;
				case 'l': // Pop a string and push its length
					stack.Push(stack.Pop().String.Length);
					break;
				case '{': // Push integer literal, enclosed between braces
					pos++;
					int intLit = 0;
					while (format[pos] != '}')
					{
						intLit = (intLit * 10) + (format[pos] - '0');
						pos++;
					}
					stack.Push(intLit);
					break;
				case '\'': // Push literal character, enclosed between single quotes
					stack.Push((int)format[pos + 1]);
					pos += 2;
					break;

					// Storing and retrieving "static" and "dynamic" variables
				case 'P': // Pop a value and store it into either static or dynamic variables based on whether the a-z variable is capitalized
					pos++;
					int setIndex;
					FormatParam[] targetVars = GetDynamicOrStaticVariables(format[pos], ref dynamicVars, ref staticVars, out setIndex);
					targetVars[setIndex] = stack.Pop();
					break;
				case 'g': // Push a static or dynamic variable; which is based on whether the a-z variable is capitalized
					pos++;
					int getIndex;
					FormatParam[] sourceVars = GetDynamicOrStaticVariables(format[pos], ref dynamicVars, ref staticVars, out getIndex);
					stack.Push(sourceVars[getIndex]);
					break;

					// Binary operations
				case '+':
				case '-':
				case '*':
				case '/':
				case 'm':
				case '^': // arithmetic
				case '&':
				case '|':                                         // bitwise
				case '=':
				case '>':
				case '<':                               // comparison
				case 'A':
				case 'O':                                         // logical
					int second = stack.Pop().Int32; // it's a stack... the second value was pushed last
					int first = stack.Pop().Int32;
					int res;
					switch (format[pos]) {
					case '+':
						res = first + second;
						break;
					case '-':
						res = first - second;
						break;
					case '*':
						res = first * second;
						break;
					case '/':
						res = first / second;
						break;
					case 'm':
						res = first % second;
						break;
					case '^':
						res = first ^ second;
						break;
					case '&':
						res = first & second;
						break;
					case '|':
						res = first | second;
						break;
					case '=':
						res = AsInt(first == second);
						break;
					case '>':
						res = AsInt(first > second);
						break;
					case '<':
						res = AsInt(first < second);
						break;
					case 'A':
						res = AsInt(AsBool(first) && AsBool(second));
						break;
					case 'O':
						res = AsInt(AsBool(first) || AsBool(second));
						break;
					default:
						res = 0;
						break;
					}
					stack.Push(res);
					break;

					// Unary operations
				case '!':
				case '~':
					int value = stack.Pop().Int32;
					stack.Push(
						format[pos] == '!' ? AsInt(!AsBool(value)) :
						~value);
					break;

					// Augment first two parameters by 1
				case 'i':
					args[0] = 1 + args[0].Int32;
					args[1] = 1 + args[1].Int32;
					break;

					// Conditional of the form %? if-part %t then-part %e else-part %;
					// The "%e else-part" is optional.
				case '?':
					sawIfConditional = true;
					break;
				case 't':
					// We hit the end of the if-part and are about to start the then-part.
					// The if-part left its result on the stack; pop and evaluate.
					bool conditionalResult = AsBool(stack.Pop().Int32);

					// Regardless of whether it's true, run the then-part to get past it.
					// If the conditional was true, output the then results.
					pos++;
					string thenResult = EvaluateInternal(format, ref pos, args, stack, ref dynamicVars, ref staticVars);
					if (conditionalResult)
					{
						output.Append(thenResult);
					}

					// We're past the then; the top of the stack should now be a Boolean
					// indicating whether this conditional has more to be processed (an else clause).
					if (!AsBool(stack.Pop().Int32))
					{
						// Process the else clause, and if the conditional was false, output the else results.
						pos++;
						string elseResult = EvaluateInternal(format, ref pos, args, stack, ref dynamicVars, ref staticVars);
						if (!conditionalResult)
						{
							output.Append(elseResult);
						}
						// Now we should be done (any subsequent elseif logic will have bene handled in the recursive call).
						if (!AsBool(stack.Pop().Int32))
						{
							throw new InvalidOperationException("Terminfo database contains invalid values");
						}
					}

					// If we're in a nested processing, return to our parent.
					if (!sawIfConditional)
					{
						stack.Push(1);
						return output.ToString();
					}
					// Otherwise, we're done processing the conditional in its entirety.
					sawIfConditional = false;
					break;
				case 'e':
				case ';':
					// Let our caller know why we're exiting, whether due to the end of the conditional or an else branch.
					stack.Push(AsInt(format[pos] == ';'));
					return output.ToString();

					// Anything else is an error
				default:
					throw new InvalidOperationException("Terminfo database contains invalid values");
				}
			}
			stack.Push(1);
			return output.ToString();
		}
Example #5
0
                /// <summary>Evaluates a terminfo formatting string, using the supplied arguments.</summary>
                /// <param name="format">The format string.</param>
                /// <param name="args">The arguments to the format string.</param>
                /// <returns>The formatted string.</returns>
                public static string Evaluate(string format, params FormatParam[] args)
		{
			if (format == null)
				throw new ArgumentNullException("format");
			if (args == null)
				throw new ArgumentNullException("args");

			// Initialize the stack to use for processing.
			LowLevelStack stack = _cachedStack;
			if (stack == null)
				_cachedStack = stack = new LowLevelStack();
			else
				stack.Clear();

			// "dynamic" and "static" variables are much less often used (the "dynamic" and "static"
			// terminology appears to just refer to two different collections rather than to any semantic
			// meaning).  As such, we'll only initialize them if we really need them.
			FormatParam[] dynamicVars = null, staticVars = null;
			
			int pos = 0;
			return EvaluateInternal(format, ref pos, args, stack, ref dynamicVars, ref staticVars);
			
			// EvaluateInternal may throw IndexOutOfRangeException and InvalidOperationException
			// if the format string is malformed or if it's inconsistent with the parameters provided.
		}
Example #6
0
            /// <summary>Evaluates a terminfo formatting string, using the supplied arguments and processing data structures.</summary>
            /// <param name="format">The format string.</param>
            /// <param name="pos">The position in <paramref name="format"/> to start processing.</param>
            /// <param name="args">The arguments to the format string.</param>
            /// <param name="stack">The stack to use as the format string is evaluated.</param>
            /// <param name="dynamicVars">A lazily-initialized collection of variables.</param>
            /// <param name="staticVars">A lazily-initialized collection of variables.</param>
            /// <returns>
            /// The formatted string; this may be empty if the evaluation didn't yield any output.
            /// The evaluation stack will have a 1 at the top if all processing was completed at invoked level
            /// of recursion, and a 0 at the top if we're still inside of a conditional that requires more processing.
            /// </returns>
            private static string EvaluateInternal(
                string format, ref int pos, FormatParam[] args, LowLevelStack <FormatParam> stack,
                ref FormatParam[] dynamicVars, ref FormatParam[] staticVars)
            {
                // Create a StringBuilder to store the output of this processing.  We use the format's length as an
                // approximation of an upper-bound for how large the output will be, though with parameter processing,
                // this is just an estimate, sometimes way over, sometimes under.
                StringBuilder output = StringBuilderCache.Acquire(format.Length);

                // Format strings support conditionals, including the equivalent of "if ... then ..." and
                // "if ... then ... else ...", as well as "if ... then ... else ... then ..."
                // and so on, where an else clause can not only be evaluated for string output but also
                // as a conditional used to determine whether to evaluate a subsequent then clause.
                // We use recursion to process these subsequent parts, and we track whether we're processing
                // at the same level of the initial if clause (or whether we're nested).
                bool sawIfConditional = false;

                // Process each character in the format string, starting from the position passed in.
                for (; pos < format.Length; pos++)
                {
                    // '%' is the escape character for a special sequence to be evaluated.
                    // Anything else just gets pushed to output.
                    if (format[pos] != '%')
                    {
                        output.Append(format[pos]);
                        continue;
                    }

                    // We have a special parameter sequence to process.  Now we need
                    // to look at what comes after the '%'.
                    ++pos;
                    switch (format[pos])
                    {
                    // Output appending operations
                    case '%':     // Output the escaped '%'
                        output.Append('%');
                        break;

                    case 'c':     // Pop the stack and output it as a char
                        output.Append((char)stack.Pop().Int32);
                        break;

                    case 's':     // Pop the stack and output it as a string
                        output.Append(stack.Pop().String);
                        break;

                    case 'd':     // Pop the stack and output it as an integer
                        output.Append(stack.Pop().Int32);
                        break;

                    case 'o':
                    case 'X':
                    case 'x':
                    case ':':
                    case '0':
                    case '1':
                    case '2':
                    case '3':
                    case '4':
                    case '5':
                    case '6':
                    case '7':
                    case '8':
                    case '9':
                        // printf strings of the format "%[[:]flags][width[.precision]][doxXs]" are allowed
                        // (with a ':' used in front of flags to help differentiate from binary operations, as flags can
                        // include '-' and '+').  While above we've special-cased common usage (e.g. %d, %s),
                        // for more complicated expressions we delegate to printf.
                        int printfEnd = pos;
                        for (; printfEnd < format.Length; printfEnd++)     // find the end of the printf format string
                        {
                            char ec = format[printfEnd];
                            if (ec == 'd' || ec == 'o' || ec == 'x' || ec == 'X' || ec == 's')
                            {
                                break;
                            }
                        }
                        if (printfEnd >= format.Length)
                        {
                            throw new InvalidOperationException(SR.IO_TermInfoInvalid);
                        }
                        string printfFormat = format.Substring(pos - 1, printfEnd - pos + 2);     // extract the format string
                        if (printfFormat.Length > 1 && printfFormat[1] == ':')
                        {
                            printfFormat = printfFormat.Remove(1, 1);
                        }
                        output.Append(FormatPrintF(printfFormat, stack.Pop().Object));     // do the printf formatting and append its output
                        break;

                    // Stack pushing operations
                    case 'p':     // Push the specified parameter (1-based) onto the stack
                        pos++;
                        Debug.Assert(format[pos] >= '0' && format[pos] <= '9');
                        stack.Push(args[format[pos] - '1']);
                        break;

                    case 'l':     // Pop a string and push its length
                        stack.Push(stack.Pop().String.Length);
                        break;

                    case '{':     // Push integer literal, enclosed between braces
                        pos++;
                        int intLit = 0;
                        while (format[pos] != '}')
                        {
                            Debug.Assert(format[pos] >= '0' && format[pos] <= '9');
                            intLit = (intLit * 10) + (format[pos] - '0');
                            pos++;
                        }
                        stack.Push(intLit);
                        break;

                    case '\'':     // Push literal character, enclosed between single quotes
                        stack.Push((int)format[pos + 1]);
                        Debug.Assert(format[pos + 2] == '\'');
                        pos += 2;
                        break;

                    // Storing and retrieving "static" and "dynamic" variables
                    case 'P':     // Pop a value and store it into either static or dynamic variables based on whether the a-z variable is capitalized
                        pos++;
                        int           setIndex;
                        FormatParam[] targetVars = GetDynamicOrStaticVariables(format[pos], ref dynamicVars, ref staticVars, out setIndex);
                        targetVars[setIndex] = stack.Pop();
                        break;

                    case 'g':     // Push a static or dynamic variable; which is based on whether the a-z variable is capitalized
                        pos++;
                        int           getIndex;
                        FormatParam[] sourceVars = GetDynamicOrStaticVariables(format[pos], ref dynamicVars, ref staticVars, out getIndex);
                        stack.Push(sourceVars[getIndex]);
                        break;

                    // Binary operations
                    case '+':
                    case '-':
                    case '*':
                    case '/':
                    case 'm':
                    case '^':     // arithmetic
                    case '&':
                    case '|':     // bitwise
                    case '=':
                    case '>':
                    case '<':                               // comparison
                    case 'A':
                    case 'O':                               // logical
                        int  second = stack.Pop().Int32;    // it's a stack... the second value was pushed last
                        int  first  = stack.Pop().Int32;
                        char c      = format[pos];
                        stack.Push(
                            c == '+' ? (first + second) :
                            c == '-' ? (first - second) :
                            c == '*' ? (first * second) :
                            c == '/' ? (first / second) :
                            c == 'm' ? (first % second) :
                            c == '^' ? (first ^ second) :
                            c == '&' ? (first & second) :
                            c == '|' ? (first | second) :
                            c == '=' ? AsInt(first == second) :
                            c == '>' ? AsInt(first > second) :
                            c == '<' ? AsInt(first < second) :
                            c == 'A' ? AsInt(AsBool(first) && AsBool(second)) :
                            c == 'O' ? AsInt(AsBool(first) || AsBool(second)) :
                            0);     // not possible; we just validated above
                        break;

                    // Unary operations
                    case '!':
                    case '~':
                        int value = stack.Pop().Int32;
                        stack.Push(
                            format[pos] == '!' ? AsInt(!AsBool(value)) :
                            ~value);
                        break;

                    // Some terminfo files appear to have a fairly liberal interpretation of %i. The spec states that %i increments the first two arguments,
                    // but some uses occur when there's only a single argument. To make sure we accommodate these files, we increment the values
                    // of up to (but not requiring) two arguments.
                    case 'i':
                        if (args.Length > 0)
                        {
                            args[0] = 1 + args[0].Int32;
                            if (args.Length > 1)
                            {
                                args[1] = 1 + args[1].Int32;
                            }
                        }
                        break;

                    // Conditional of the form %? if-part %t then-part %e else-part %;
                    // The "%e else-part" is optional.
                    case '?':
                        sawIfConditional = true;
                        break;

                    case 't':
                        // We hit the end of the if-part and are about to start the then-part.
                        // The if-part left its result on the stack; pop and evaluate.
                        bool conditionalResult = AsBool(stack.Pop().Int32);

                        // Regardless of whether it's true, run the then-part to get past it.
                        // If the conditional was true, output the then results.
                        pos++;
                        string thenResult = EvaluateInternal(format, ref pos, args, stack, ref dynamicVars, ref staticVars);
                        if (conditionalResult)
                        {
                            output.Append(thenResult);
                        }
                        Debug.Assert(format[pos] == 'e' || format[pos] == ';');

                        // We're past the then; the top of the stack should now be a Boolean
                        // indicating whether this conditional has more to be processed (an else clause).
                        if (!AsBool(stack.Pop().Int32))
                        {
                            // Process the else clause, and if the conditional was false, output the else results.
                            pos++;
                            string elseResult = EvaluateInternal(format, ref pos, args, stack, ref dynamicVars, ref staticVars);
                            if (!conditionalResult)
                            {
                                output.Append(elseResult);
                            }

                            // Now we should be done (any subsequent elseif logic will have been handled in the recursive call).
                            if (!AsBool(stack.Pop().Int32))
                            {
                                throw new InvalidOperationException(SR.IO_TermInfoInvalid);
                            }
                        }

                        // If we're in a nested processing, return to our parent.
                        if (!sawIfConditional)
                        {
                            stack.Push(1);
                            return(StringBuilderCache.GetStringAndRelease(output));
                        }

                        // Otherwise, we're done processing the conditional in its entirety.
                        sawIfConditional = false;
                        break;

                    case 'e':
                    case ';':
                        // Let our caller know why we're exiting, whether due to the end of the conditional or an else branch.
                        stack.Push(AsInt(format[pos] == ';'));
                        return(StringBuilderCache.GetStringAndRelease(output));

                    // Anything else is an error
                    default:
                        throw new InvalidOperationException(SR.IO_TermInfoInvalid);
                    }
                }

                stack.Push(1);
                return(StringBuilderCache.GetStringAndRelease(output));
            }
 public static string Evaluate(string format, params /* 0x00000001800D4E50-0x00000001800D4E60 */ FormatParam[] args) => default;                                                      // 0x000000018068F3F0-0x000000018068F570
 private static string EvaluateInternal(string format, ref int pos, FormatParam[] args, LowLevelStack stack, ref FormatParam[] dynamicVars, ref FormatParam[] staticVars) => default; // 0x000000018068E6E0-0x000000018068F3F0