Пример #1
0
        /// <summary>
        /// Called when a define token is hit
        /// </summary>
        /// <remarks></remarks>

        private void ProcessPoundDefine(PreprocessorLine line)
        {
            // Get the non whitespace tokens
            List <Token> list = line.GetValidTokens();

            ThrowIfFalse(list[0].TokenType == TokenType.PoundDefine);

            Macro macro = null;

            if (list.Count == 3 && list[1].TokenType == TokenType.Word)
            {
                string name = list[1].Value;
                macro = new Macro(name, list[2].Value);
            }
            else if (list.Count == 2 && list[1].TokenType == TokenType.Word)
            {
                string name = list[1].Value;
                macro = new Macro(name, string.Empty);
            }
            else if (list.Count == 1)
            {
                _scanner.AddWarning("Encountered an empty #define");
            }
            else if (list.Count > 3 && list[1].TokenType == TokenType.Word && list[2].TokenType == TokenType.ParenOpen)
            {
                macro = ProcessPoundDefineMethod(line);
            }
            else
            {
                macro = ProcessPoundDefineComplexMacro(line);
            }

            if (macro != null)
            {
                Macro oldMacro = null;
                if (_macroMap.TryGetValue(macro.Name, out oldMacro) && oldMacro.IsPermanent)
                {
                    TraceToStream("Kept: {0} -> {1} Attempted Value {2}", oldMacro.Name, oldMacro.Value, macro.Value);
                }
                else
                {
                    _macroMap[macro.Name] = macro;
                    if (macro.IsMethod)
                    {
                        MethodMacro method = (MethodMacro)macro;
                        TraceToStream("Defined: {0} -> {1}", macro.Name, method.MethodSignature);
                    }
                    else
                    {
                        TraceToStream("Defined: {0} -> {1}", macro.Name, macro.Value);
                    }
                }
            }
        }
Пример #2
0
        /// <summary>
        /// Called for a #undef line
        /// </summary>
        /// <param name="line"></param>
        /// <remarks></remarks>
        private void ProcessPoundUndefine(PreprocessorLine line)
        {
            // Get the none whitespace tokens
            List <Token> list = line.GetValidTokens();

            ThrowIfFalse(list[0].TokenType == TokenType.PoundUnDef);

            if (list.Count != 2 || list[1].TokenType != TokenType.Word)
            {
                _scanner.AddWarning("Error processing #undef");
            }
            else
            {
                string name = list[1].Value;
                if (_macroMap.ContainsKey(name))
                {
                    _macroMap.Remove(name);
                    TraceToStream("Undefined: {0}", name);
                }
            }
        }
Пример #3
0
        private void CollapseExpandedPreprocessorLines(ref PreprocessorLine line)
        {
            if (line.FirstValidToken != null && line.FirstValidToken.TokenType == TokenType.Pound)
            {
                List <Token> list          = line.GetValidTokens();
                Token        possibleToken = list[1];
                Token        poundToken    = null;

                if (list.Count >= 2 && TokenHelper.TryConvertToPoundToken(possibleToken.Value, out poundToken))
                {
                    // Strip out everything # -> define
                    List <Token> newList = new List <Token>(line.TokenList);
                    bool         done    = false;
                    while (!done)
                    {
                        if (newList.Count == 0)
                        {
                            Debug.Fail("Non-crititcal error reducing the preprocessor line");
                            return;
                        }
                        else if (object.ReferenceEquals(newList[0], possibleToken))
                        {
                            newList.RemoveAt(0);
                            newList.Insert(0, poundToken);
                            done = true;
                        }
                        else
                        {
                            newList.RemoveAt(0);
                        }
                    }

                    PreprocessorLine formattedLine = new PreprocessorLine();
                    formattedLine.FirstValidToken             = poundToken;
                    formattedLine.IsPreProcessorDirectiveLine = true;
                    formattedLine.TokenList = newList;
                    line = formattedLine;
                }
            }
        }
Пример #4
0
        /// <summary>
        /// Evaluate a preprocessor conditional statement and return whether or not it is true
        /// </summary>
        /// <param name="line"></param>
        /// <returns></returns>
        /// <remarks></remarks>
        private bool EvalauteConditional(PreprocessorLine line)
        {
            List <Token> list = line.GetValidTokens();

            // Remove the #pound token.  We don't care what type of conditional this is, this just serves
            // to evaluate it and let the caller interpret the result
            list.RemoveAt(0);

            // Make sure that all "defined" expressions wrap the next value in ()
            Int32 i = 0;

            while (i + 1 < list.Count)
            {
                Token cur = list[i];

                if (cur.TokenType == TokenType.Word && 0 == string.CompareOrdinal("defined", cur.Value) && list[i + 1].TokenType == TokenType.Word)
                {
                    list.Insert(i + 1, new Token(TokenType.ParenOpen, "("));
                    list.Insert(i + 3, new Token(TokenType.ParenClose, ")"));

                    i += 3;
                }

                i += 1;
            }

            ExpressionValue value = null;

            if (!_eval.TryEvaluate(list, out value))
            {
                _errorProvider.AddError("Could not evaluate expression {0}", line.ToString());
                return(false);
            }

            return(value.ConvertToBool());
        }
Пример #5
0
        /// <summary>
        /// Process a #include line.  These take typically two forms
        ///   #include "foo.h"
        ///   #include &gt;foo.h&gt;
        ///
        /// </summary>
        /// <param name="line"></param>
        /// <remarks></remarks>

        private void ProcessPoundInclude(PreprocessorLine line)
        {
            if (!_options.FollowIncludes)
            {
                return;
            }

            // if the user did a <> include then there won't be any quotes around the string
            // so go ahead and redo the include to look like a "filename.h" include
            List <Token> list = new List <Token>(line.GetValidTokens());

            // Get rid of the #include
            ThrowIfFalse(list[1].TokenType == TokenType.PoundInclude);
            list.RemoveAt(0);

            string name = null;

            if (list[1].TokenType == TokenType.OpLessThan)
            {
                name = string.Empty;
                list.RemoveAt(0);
                while (list[1].TokenType != TokenType.OpGreaterThan)
                {
                    name += list[1].Value;
                    list.RemoveAt(0);
                }
                list.RemoveAt(0);
            }
            else if (list[1].IsQuotedString)
            {
                name = TokenHelper.ConvertToString(list[1]);
            }
            else
            {
                name = null;
            }

            if (name == null)
            {
                _scanner.AddWarning("Invalid #include statement");
                return;
            }

            // Now actually try and find the file.  First check the custom list
            bool found = false;

            if (File.Exists(name))
            {
                found = true;
                TraceToStream("include {0} followed -> {0}", name);
                TraceToStream("include {0} start", name);
                using (StreamReader reader = new StreamReader(name))
                {
                    ProcessCore(new TextReaderBag(name, reader));
                }
                TraceToStream("include {0} end", name);
            }
            else if (_options.IncludePathList.Count > 0)
            {
                // Search through the path list
                found = false;
                foreach (string prefix in _options.IncludePathList)
                {
                    string fullPath = Path.Combine(prefix, name);
                    if (File.Exists(fullPath))
                    {
                        found = true;
                        TraceToStream("include {0} followed -> {1}", name, fullPath);
                        TraceToStream("include {0} start", name);
                        using (StreamReader reader = new StreamReader(fullPath))
                        {
                            ProcessCore(new TextReaderBag(fullPath, reader));
                        }
                        TraceToStream("include {0} end", name);
                        break;
                    }
                }
            }
            else
            {
                found = false;
            }

            if (!found)
            {
                _scanner.AddWarning("Could not locate include file {0}", name);
                TraceToStream("include {0} not followed", name);
            }
        }
Пример #6
0
        /// <summary>
        /// Process a #define that is actually a function
        /// </summary>
        /// <param name="line"></param>
        /// <returns></returns>
        /// <remarks></remarks>
        private Macro ProcessPoundDefineMethod(PreprocessorLine line)
        {
            // First step is to parse out the name and parameters
            List <Token> list = line.GetValidTokens();
            string       name = list[1].Value;

            list.RemoveRange(0, 3);

            List <string> paramList = new List <string>();

            while ((list[0].TokenType != TokenType.ParenClose))
            {
                if (list[0].TokenType == TokenType.Word)
                {
                    paramList.Add(list[0].Value);
                }
                else if (list[0].TokenType == TokenType.ParenOpen)
                {
                    // ( is not legal inside a parameter list.  This is a simple macro
                    return(ProcessPoundDefineComplexMacro(line));
                }
                list.RemoveAt(0);
            }

            // Now get the fullBody.  We need the actual text for the fullBody so search through the true token list
            Int32 index = 0;

            while ((line.TokenList[index].TokenType != TokenType.ParenClose))
            {
                index += 1;
            }

            index += 1;
            List <Token> fullBody = line.TokenList.GetRange(index, line.TokenList.Count - index);

            // Strip the trailing and ending whitespace on the fullBody
            while (fullBody.Count > 0 && (fullBody[0].TokenType == TokenType.WhiteSpace || fullBody[0].TokenType == TokenType.NewLine))
            {
                fullBody.RemoveAt(0);
            }

            // Don't be fooled by a simple #define that simply wraps the entire fullBody inside a
            // set of ().
            if ((fullBody.Count == 0))
            {
                return(ProcessPoundDefineComplexMacro(line));
            }

            while (fullBody.Count > 0 && (fullBody[fullBody.Count - 1].TokenType == TokenType.WhiteSpace || fullBody[fullBody.Count - 1].TokenType == TokenType.NewLine))
            {
                fullBody.RemoveAt(fullBody.Count - 1);
            }

            // Coy the body token list since we are about to change the data
            List <Token> body = new List <Token>(fullBody);

            // Collapse the whitespace around ## entries
            int i = 0;

            while (i + 1 < body.Count)
            {
                Token left  = body[i];
                Token right = body[i + 1];

                if (left.TokenType == TokenType.Pound && right.TokenType == TokenType.Pound)
                {
                    // First look at the right
                    if (i + 2 < body.Count && body[i + 2].TokenType == TokenType.WhiteSpace)
                    {
                        body.RemoveAt(i + 2);
                    }

                    // Now look at the left
                    if (i > 0 && body[i - 1].TokenType == TokenType.WhiteSpace)
                    {
                        body.RemoveAt(i - 1);
                    }
                }

                i += 1;
            }

            index += 1;
            return(new MethodMacro(name, paramList, body, fullBody));
        }