コード例 #1
0
ファイル: Preprocessor.cs プロジェクト: cmrazek/DkTools
        private void ProcessDefineUse(PreprocessorParams p, string name)
        {
            var rdr = p.reader;

            if (p.suppress)
            {
                rdr.Use(name.Length);
                return;
            }
            if (p.restrictedDefines != null && p.restrictedDefines.Contains(name))
            {
                rdr.Use(name.Length);
                return;
            }

            PreprocessorDefine define = null;

            if (p.args != null)
            {
                foreach (var arg in p.args)
                {
                    if (arg.Name == name)
                    {
                        define = arg;
                        break;
                    }
                }
            }
            if (define == null)
            {
                _defines.TryGetValue(name, out define);
            }
            if (define == null || define.Disabled)
            {
                rdr.Use(name.Length);
                return;
            }

            var nameFilePos = rdr.FilePosition;

            if (nameFilePos.IsInFile)
            {
                _refs.Add(new Reference(define.Definition, nameFilePos));
            }

            if (define.DataType != null && name == define.DataType.Name)
            {
                // Insert the data type name before the data type, so that it's available in the quick info and database.
                rdr.Insert(string.Format("@{0} ", DataType.NormalizeEnumOption(name)));
            }
            rdr.Ignore(name.Length);

            p.result.DocumentAltered = true;

            List <string> paramList = null;

            if (define.ParamNames != null)
            {
                // This is a parameterized macro
                rdr.IgnoreWhiteSpaceAndComments(false);
                if (rdr.Peek() != '(')
                {
                    return;
                }
                rdr.Ignore(1);

                char ch;
                var  sb = new StringBuilder();
                paramList = new List <string>();

                rdr.IgnoreWhiteSpaceAndComments(false);
                while (!rdr.EOF)
                {
                    if (rdr.IgnoreComments())
                    {
                        continue;
                    }

                    ch = rdr.Peek();
                    if (ch == ',')
                    {
                        rdr.Ignore(1);

                        var argText           = ApplySubstitutions(sb.ToString(), p.args);
                        var resolvedParamText = ResolveMacros(argText, p.restrictedDefines, null, p.fileContext, p.contentType);
                        paramList.Add(resolvedParamText.Trim());

                        sb.Clear();
                    }
                    else if (ch == ')')
                    {
                        rdr.Ignore(1);
                        break;
                    }
                    else if (ch == '(')
                    {
                        rdr.Ignore(1);
                        sb.Append('(');
                        sb.Append(rdr.ReadAndIgnoreNestableContent(")"));
                        sb.Append(')');
                    }
                    else if (ch == '{')
                    {
                        rdr.Ignore(1);
                        sb.Append('{');
                        sb.Append(rdr.ReadAndIgnoreNestableContent("}"));
                        sb.Append('}');
                    }
                    else if (ch == '[')
                    {
                        rdr.Ignore(1);
                        sb.Append('[');
                        sb.Append(rdr.ReadAndIgnoreNestableContent("]"));
                        sb.Append(']');
                    }
                    else if (ch == '\'' || ch == '\"')
                    {
                        sb.Append(rdr.ReadAndIgnoreStringLiteral());
                    }
                    else
                    {
                        rdr.Ignore(1);
                        sb.Append(ch);
                    }
                }

                if (sb.Length > 0)
                {
                    var argText           = ApplySubstitutions(sb.ToString(), p.args);
                    var resolvedParamText = ResolveMacros(argText, p.restrictedDefines, null, p.fileContext, p.contentType);
                    paramList.Add(resolvedParamText.Trim());
                }

                if (define.ParamNames.Count != paramList.Count)
                {
                    return;
                }
            }

            var oldArgs = p.args;

            List <PreprocessorDefine> args = null;

            if (paramList != null)
            {
                if (define.ParamNames == null || define.ParamNames.Count != paramList.Count)
                {
                    return;
                }
                if (args == null)
                {
                    args = new List <PreprocessorDefine>();
                }
                for (int i = 0, ii = paramList.Count; i < ii; i++)
                {
                    args.Add(new PreprocessorDefine(define.ParamNames[i], paramList[i], null, FilePosition.Empty));
                }
            }
            if (p.args != null && p.args.Any())
            {
                if (args == null)
                {
                    args = new List <PreprocessorDefine>();
                }
                args.AddRange(p.args);
            }

            string[] restrictedDefines = null;
            if (p.restrictedDefines != null)
            {
                restrictedDefines = p.restrictedDefines.Concat(new string[] { name }).ToArray();
            }
            else
            {
                restrictedDefines = new string[] { name }
            };

            var textToAdd = ApplySubstitutions(define.Content, args);

            textToAdd = ResolveMacros(textToAdd, restrictedDefines, null, p.fileContext, p.contentType);
            rdr.Insert(textToAdd);

            p.args = oldArgs;
        }
コード例 #2
0
ファイル: Preprocessor.cs プロジェクト: cmrazek/DkTools
        private PreprocessorResult Preprocess(PreprocessorParams p)
        {
            // This function assumes the source has already been merged.

            if (_defines == null)
            {
                _defines             = new Dictionary <string, PreprocessorDefine>();
                _defines["_WINDOWS"] = new PreprocessorDefine("_WINDOWS", string.Empty, null, FilePosition.Empty);
            }

            if (p.stdlibDefines != null)
            {
                foreach (var def in p.stdlibDefines)
                {
                    _defines[def.Name] = def;
                }
            }

            string str;
            var    sb  = new StringBuilder();
            var    rdr = p.reader;

            p.reader.SetWriter(p.writer);

            while (!rdr.EOF && !p.result.IncludeFileReached)
            {
                str = rdr.PeekToken(false);
                if (string.IsNullOrEmpty(str))
                {
                    continue;
                }

                if (str[0] == '#')
                {
                    ProcessDirective(p, str);
                    continue;
                }

                if (p.suppress)
                {
                    rdr.Ignore(str.Length);
                    continue;
                }

                if (str[0].IsWordChar(true))
                {
                    if (p.args != null && p.args.Any(x => x.Name == str))
                    {
                        ProcessDefineUse(p, str);
                    }
                    else if (_defines.ContainsKey(str))
                    {
                        ProcessDefineUse(p, str);
                    }
                    else if (str == "STRINGIZE")
                    {
                        rdr.Ignore(str.Length);
                        p.result.DocumentAltered = true;
                        ProcessStringizeKeyword(p);
                    }
                    else if (str == "defined" && p.contentType == ContentType.Condition)
                    {
                        rdr.Ignore(str.Length);
                        p.result.DocumentAltered = true;
                        ProcessDefinedKeyword(p);
                    }
                    else
                    {
                        rdr.Use(str.Length);
                    }
                    continue;
                }

                if (str == "@")
                {
                    // This is the start of the name portion of a data type definition.
                    rdr.Use(str.Length);
                    var name = rdr.PeekToken(true);
                    if (name.IsWord())
                    {
                        rdr.Use(name.Length);
                    }
                    continue;
                }

                rdr.Use(str.Length);
            }

            p.writer.Flush();

            return(p.result);
        }
コード例 #3
0
ファイル: Preprocessor.cs プロジェクト: cmrazek/DkTools
        private void ProcessDefine(PreprocessorParams p)
        {
            var    rdr = p.reader;
            char   ch;
            string str;

            // Get the define name
            rdr.IgnoreWhiteSpaceAndComments(true);
            var linkFilePos = rdr.FilePosition;
            var name        = rdr.PeekIdentifier();

            if (string.IsNullOrEmpty(name))
            {
                return;
            }
            var nameFilePos = rdr.FilePosition;

            rdr.Ignore(name.Length);

            // Check if this is parameterized
            List <string> paramNames = null;

            if (rdr.Peek() == '(')
            {
                rdr.Ignore(1);

                while (!rdr.EOF)
                {
                    rdr.IgnoreWhiteSpaceAndComments(true);

                    str = rdr.PeekToken(false);
                    if (string.IsNullOrEmpty(str))
                    {
                        return;
                    }
                    if (str == ",")
                    {
                        rdr.Ignore(str.Length);
                    }
                    else if (str[0].IsWordChar(true))
                    {
                        rdr.Ignore(str.Length);
                        if (!p.suppress)
                        {
                            if (paramNames == null)
                            {
                                paramNames = new List <string>();
                            }
                            paramNames.Add(str);
                        }
                    }
                    else if (str == ")")
                    {
                        rdr.Ignore(str.Length);
                        break;
                    }
                    else
                    {
                        return;
                    }
                }
            }

            // Read the define value
            rdr.IgnoreWhiteSpaceAndComments(true);
            var insideBlock = false;
            var braceLevel  = 0;

            ch = rdr.Peek();
            if (ch == '{')
            {
                insideBlock = true;
                braceLevel  = 1;
                rdr.Ignore(1);
            }

            var sb = new StringBuilder();

            while (!rdr.EOF)
            {
                if (rdr.IgnoreComments())
                {
                    continue;
                }

                str = rdr.PeekToken(true);
                if (str == null)
                {
                    // End of line found

                    char endCh;
                    int  index;
                    if (sb.GetLastNonWhiteChar(out endCh, out index))
                    {
                        if (endCh == '\\')
                        {
                            // define continues down to the next line, but don't include the slash in the resulting text.
                            sb.Remove(index, 1);
                            if (insideBlock)
                            {
                                sb.Append("\r\n");
                            }
                            //rdr.IgnoreUntil(c => c == '\r' || c == '\n');
                            rdr.IgnoreWhile(PreprocessorReaderExtensions.LineEndChars);
                            continue;
                        }
                        else if (insideBlock)
                        {
                            //rdr.IgnoreUntil(c => c == '\r' || c == '\n');
                            rdr.IgnoreWhile(PreprocessorReaderExtensions.LineEndChars);
                            sb.Append("\r\n");
                            continue;
                        }
                        else
                        {
                            break;
                        }
                    }
                    else
                    {
                        if (insideBlock)
                        {
                            //rdr.IgnoreUntil(c => c == '\r' || c == '\n');
                            rdr.IgnoreWhile(PreprocessorReaderExtensions.LineEndChars);
                            sb.Append("\r\n");
                            continue;
                        }
                        else
                        {
                            break;
                        }
                    }
                }

                if (str == "{" && insideBlock)
                {
                    braceLevel++;
                    rdr.Ignore(str.Length);
                    sb.Append('{');
                    continue;
                }

                if (str == "}" && insideBlock)
                {
                    rdr.Ignore(str.Length);
                    if (--braceLevel <= 0)
                    {
                        break;
                    }
                    else
                    {
                        sb.Append('}');
                        continue;
                    }
                }

                rdr.Ignore(str.Length);
                sb.Append(str);
            }

            if (!p.suppress)
            {
                var define = new PreprocessorDefine(name, sb.ToString().Trim(), paramNames, linkFilePos);
                _defines[name] = define;
                if (nameFilePos.IsInFile)
                {
                    _refs.Add(new Reference(define.Definition, nameFilePos));
                }
            }
        }