Represents an opengl constant in C# format. Both the constant name and value can be retrieved or set. The value can be either a number, another constant or an alias to a constant
Пример #1
0
        /// <summary>
        /// Places a new constant in the specified enum, if it doesn't already exist.
        /// The existing constant is replaced iff the new has a numeric value and the old
        /// has a reference value (eg 0x5 is preferred over AttribMask.Foo)
        /// </summary>
        /// <param name="s"></param>
        /// <param name="t"></param>
        /// <returns></returns>
        internal static Bind.Structures.Enum Merge(Bind.Structures.Enum s, Bind.Structures.Constant t)
        {
            if (!s.ConstantCollection.ContainsKey(t.Name))
            {
                s.ConstantCollection.Add(t.Name, t);
            }
            else
            {
                // Tried to add a constant that already exists. If one constant
                // is like: 'Foo = 0x5' and the other like: 'Foo = Bar.Foo', then
                // keep the first one.
                if (!Char.IsDigit(((Constant)s.ConstantCollection[t.Name]).Value[0]))
                {
                    s.ConstantCollection.Remove(t.Name);
                    s.ConstantCollection.Add(t.Name, t);
                }
            }

            return(s);
        }
Пример #2
0
        /// <summary>
        /// Places a new constant in the specified enum, if it doesn't already exist.
        /// The existing constant is replaced iff the new has a numeric value and the old
        /// has a reference value (eg 0x5 is preferred over AttribMask.Foo)
        /// </summary>
        /// <param name="s"></param>
        /// <param name="t"></param>
        /// <returns></returns>
        internal static Enum Merge(Enum s, Constant t)
        {
            if (!s.ConstantCollection.ContainsKey(t.Name))
            {
                s.ConstantCollection.Add(t.Name, t);
            }
            else
            {
                // Tried to add a constant that already exists. If one constant
                // is like: 'Foo = 0x5' and the other like: 'Foo = Bar.Foo', then 
                // keep the first one.
                if (!String.IsNullOrEmpty(s.ConstantCollection[t.Name].Reference))
                {
                    s.ConstantCollection[t.Name] = t;
                }
            }

            return s;
        }
        /// <summary>
        /// Places a new constant in the specified enum, if it doesn't already exist.
        /// The existing constant is replaced iff the new has a numeric value and the old
        /// has a reference value (eg 0x5 is preferred over AttribMask.Foo)
        /// </summary>
        /// <param name="s"></param>
        /// <param name="t"></param>
        /// <returns></returns>
        internal static Enum Merge(Enum s, Constant t)
        {
            if (!s.ConstantCollection.ContainsKey(t.Name))
            {
                s.ConstantCollection.Add(t.Name, t);
            }
            else
            {
                // Tried to add a constant that already exists. If one constant
                // is like: 'Foo = 0x5' and the other like: 'Foo = Bar.Foo', then 
                // keep the first one.
                if (!Char.IsDigit(((Constant)s.ConstantCollection[t.Name]).Value[0]))
                {
                    s.ConstantCollection.Remove(t.Name);
                    s.ConstantCollection.Add(t.Name, t);
                }
            }

            return s;
        }
Пример #4
0
 // There are cases when a value is an aliased constant, with no enum specified.
 // (e.g. FOG_COORD_ARRAY_TYPE = GL_FOG_COORDINATE_ARRAY_TYPE)
 // In this case try searching all enums for the correct constant to alias (stupid opengl specs).
 // This turns every bare alias into a normal alias that is processed afterwards.
 static void ResolveBareAlias(Constant c, EnumCollection enums)
 {
     // Constants are considered bare aliases when they don't have a reference and
     // their values are non-numeric.
     if (String.IsNullOrEmpty(c.Reference) && !Char.IsDigit(c.Value[0]))
     {
         // Skip generic GLenum, as this doesn't help resolve references.
         foreach (Enum e in enums.Values.Where(e => e.Name != "GLenum"))
         {
             if (e.ConstantCollection.ContainsKey(c.Value))
             {
                 c.Reference = e.Name;
                 break;
             }
         }
     }
 }
Пример #5
0
 static void ReplaceConstant(XPathNavigator enum_override, Constant c)
 {
     if (enum_override != null)
     {
         XPathNavigator constant_override = enum_override.SelectSingleNode(String.Format("token[@name='{0}']", c.OriginalName)) ??
             enum_override.SelectSingleNode(String.Format("token[@name={0}]", c.Name));
         if (constant_override != null)
         {
             foreach (XPathNavigator node in constant_override.SelectChildren(XPathNodeType.Element))
             {
                 switch (node.Name)
                 {
                     case "name": c.Name = (string)node.TypedValue; break;
                     case "value": c.Value = (string)node.TypedValue; break;
                 }
             }
         }
     }
 }
Пример #6
0
        private EnumCollection ReadEnums(XPathNavigator nav)
        {
            EnumCollection enums = new EnumCollection();
            Enum all = new Enum() { Name = Settings.CompleteEnumName };

            if (nav != null)
            {
                foreach (XPathNavigator node in nav.SelectChildren("enum", String.Empty))
                {
                    Enum e = new Enum()
                    {
                        Name = node.GetAttribute("name", String.Empty),
                        Type = node.GetAttribute("type", String.Empty)
                    };
                    if (String.IsNullOrEmpty(e.Name))
                        throw new InvalidOperationException(String.Format("Empty name for enum element {0}", node.ToString()));

                    foreach (XPathNavigator param in node.SelectChildren(XPathNodeType.Element))
                    {
                        Constant c = null;
                        switch (param.Name)
                        {
                            case "token":
                                c = new Constant
                                {
                                    Name = param.GetAttribute("name", String.Empty),
                                    Value = param.GetAttribute("value", String.Empty)
                                };
                                break;

                            case "use":
                                c = new Constant
                                {
                                    Name = param.GetAttribute("token", String.Empty),
                                    Reference = param.GetAttribute("enum", String.Empty),
                                    Value = param.GetAttribute("token", String.Empty),
                                };
                                break;

                            default:
                                throw new NotSupportedException();
                        }
                        Utilities.Merge(all, c);
                        try
                        {
                            if (!e.ConstantCollection.ContainsKey(c.Name))
                            {
                                e.ConstantCollection.Add(c.Name, c);
                            }
                            else if (e.ConstantCollection[c.Name].Value != c.Value)
                            {
                                var existing = e.ConstantCollection[c.Name];
                                if (existing.Reference != null && c.Reference == null)
                                {
                                    e.ConstantCollection[c.Name] = c;
                                }
                                else if (existing.Reference == null && c.Reference != null)
                                {
                                    // Keep existing
                                }
                                else
                                {
                                    Console.WriteLine("[Warning] Conflicting token {0}.{1} with value {2} != {3}",
                                        e.Name, c.Name, e.ConstantCollection[c.Name].Value, c.Value);
                                }
                            }
                        }
                        catch (ArgumentException ex)
                        {
                            Console.WriteLine("[Warning] Failed to add constant {0} to enum {1}: {2}", c.Name, e.Name, ex.Message);
                        }
                    }

                    Utilities.Merge(enums, e);
                }
            }

            Utilities.Merge(enums, all);
            return enums;
        }
Пример #7
0
        public virtual EnumCollection ReadEnums(StreamReader specFile)
        {
            Trace.WriteLine("Reading opengl enumerant specs.");
            Trace.Indent();

            EnumCollection enums = new EnumCollection();

            // complete_enum contains all opengl enumerants.
            Enum complete_enum = new Enum();
            complete_enum.Name = Settings.CompleteEnumName;

            do
            {
                string line = NextValidLine(specFile);
                if (String.IsNullOrEmpty(line))
                    break;

                line = line.Replace('\t', ' ');

                // We just encountered the start of a new enumerant:
                while (!String.IsNullOrEmpty(line) && line.Contains("enum"))
                {
                    string[] words = line.Split(Utilities.Separators, StringSplitOptions.RemoveEmptyEntries);
                    if (words.Length == 0)
                        continue;

                    // Declare a new enumerant
                    Enum e = new Enum();
                    e.Name = Char.IsDigit(words[0][0]) ? Settings.ConstantPrefix + words[0] : words[0];

                    // And fill in the values for this enumerant
                    do
                    {
                        line = NextValidLine(specFile);

                        if (String.IsNullOrEmpty(line) || line.StartsWith("#"))
                            continue;

                        if (line.Contains("enum:") || specFile.EndOfStream)
                            break;

                        line = line.Replace('\t', ' ');
                        words = line.Split(Utilities.Separators, StringSplitOptions.RemoveEmptyEntries);

                        if (words.Length == 0)
                            continue;

                        // If we reach this point, we have found a new value for the current enumerant
                        Constant c = new Constant();
                        if (line.Contains("="))
                        {
                            // Trim the name's prefix, but only if not in Tao compat mode.
                            if (Settings.Compatibility == Settings.Legacy.Tao)
                            {
                            }
                            else
                            {
                                if (words[0].StartsWith(Settings.ConstantPrefix))
                                    words[0] = words[0].Substring(Settings.ConstantPrefix.Length);

                                if (Char.IsDigit(words[0][0]))
                                    words[0] = Settings.ConstantPrefix + words[0];
                            }

                            c.Name = words[0];
                            c.Value = words[2];
                        }
                        else if (words[0] == "use")
                        {
                            // Trim the prefix.
                            if (words[2].StartsWith(Settings.ConstantPrefix))
                                words[2] = words[2].Substring(Settings.ConstantPrefix.Length);

                            // If the remaining string starts with a digit, we were wrong above.
                            // Re-add the "GL_"
                            if (Char.IsDigit(words[2][0]))
                                words[2] = Settings.ConstantPrefix + words[2];

                            c.Name = words[2];
                            c.Reference = words[1];
                            c.Value = words[2];
                        }
                        else
                        {
                            // Typical cause is hand-editing the specs and forgetting to add an '=' sign.
                            throw new InvalidOperationException(String.Format(
                                "[Error] Invalid constant definition: \"{0}\"", line));
                        }

                        //if (!String.IsNullOrEmpty(c.Name) && !e.Members.Contains.Contains(c))
                        //SpecTranslator.Merge(e.Members, c);
                        if (!e.ConstantCollection.ContainsKey(c.Name))
                            e.ConstantCollection.Add(c.Name, c);
                        else
                            Trace.WriteLine(String.Format(
                                "Spec error: Constant {0} defined twice in enum {1}, discarding last definition.",
                                c.Name, e.Name));

                        // Insert the current constant in the list of all constants.
                        //SpecTranslator.Merge(complete_enum.Members, c);
                        complete_enum = Utilities.Merge(complete_enum, c);
                    }
                    while (!specFile.EndOfStream);

                    // At this point, the complete value list for the current enumerant has been read, so add this
                    // enumerant to the list.
                    //e.StartDirectives.Add(new CodeRegionDirective(CodeRegionMode.Start, "public enum " + e.Name));
                    //e.EndDirectives.Add(new CodeRegionDirective(CodeRegionMode.End, "public enum " + e.Name));

                    // (disabled) Hack - discard Boolean enum, it fsucks up the fragile translation code ahead.
                    //if (!e.Name.Contains("Bool"))
                    //Utilities.Merge(enums, e);

                    //e.Translate();

                    if (!enums.ContainsKey(e.Name))
                        enums.Add(e.Name, e);
                    else
                    {
                        // The enum already exists, merge constants.
                        foreach (Constant t in e.ConstantCollection.Values)
                            Utilities.Merge(enums[e.Name], t);
                    }
                }
            }
            while (!specFile.EndOfStream);

            enums.Add(complete_enum.Name, complete_enum);

            Trace.Unindent();

            return enums;
        }
Пример #8
0
        string GetDeclarationString(Constant c)
        {
            if (String.IsNullOrEmpty(c.Name))
            {
                throw new InvalidOperationException("Invalid Constant: Name is empty");
            }

            return String.Format("{0} = {1}((int){2}{3})",
                c.Name,
                c.Unchecked ? "unchecked" : String.Empty,
                !String.IsNullOrEmpty(c.Reference) ?
                    c.Reference + Settings.NamespaceSeparator :
                    String.Empty,
                c.Value);
        }
Пример #9
0
        public virtual EnumCollection ReadEnums(StreamReader specFile)
        {
            Trace.WriteLine("Reading opengl enumerant specs.");
            Trace.Indent();

            EnumCollection enums = new EnumCollection();

            // complete_enum contains all opengl enumerants.
            Bind.Structures.Enum complete_enum = new Bind.Structures.Enum();
            complete_enum.Name = Settings.CompleteEnumName;

            do
            {
                string line = NextValidLine(specFile);
                if (String.IsNullOrEmpty(line))
                    break;

                line = line.Replace('\t', ' ');

                // We just encountered the start of a new enumerant:
                while (!String.IsNullOrEmpty(line) && line.Contains("enum"))
                {
                    string[] words = line.Split(Utilities.Separators, StringSplitOptions.RemoveEmptyEntries);
                    if (words.Length == 0)
                        continue;

                    // Declare a new enumerant
                    Bind.Structures.Enum e = new Bind.Structures.Enum();
                    e.Name = Char.IsDigit(words[0][0]) ? Settings.ConstantPrefix + words[0] : words[0];

                    // And fill in the values for this enumerant
                    do
                    {
                        line = NextValidLine(specFile);

                        if (String.IsNullOrEmpty(line) || line.StartsWith("#"))
                            continue;

                        if (line.Contains("enum:") || specFile.EndOfStream)
                            break;

                        line = line.Replace('\t', ' ');
                        words = line.Split(Utilities.Separators, StringSplitOptions.RemoveEmptyEntries);

                        if (words.Length == 0)
                            continue;

                        // If we reach this point, we have found a new value for the current enumerant
                        Constant c = new Constant();
                        if (line.Contains("="))
                        {
                            // Trim the name's prefix, but only if not in Tao compat mode.
                            if (Settings.Compatibility == Settings.Legacy.Tao)
                            {
                            }
                            else
                            {
                                if (words[0].StartsWith(Settings.ConstantPrefix))
                                    words[0] = words[0].Substring(Settings.ConstantPrefix.Length);

                                if (Char.IsDigit(words[0][0]))
                                    words[0] = Settings.ConstantPrefix + words[0];
                            }

                            c.Name = words[0];

                            uint number;
                            if (UInt32.TryParse(words[2].Replace("0x", String.Empty), System.Globalization.NumberStyles.AllowHexSpecifier, null, out number))
                            {
                                // The value is a number, check if it should be unchecked.
                                if (number > 0x7FFFFFFF)
                                {
                                    c.Unchecked = true;
                                }
                            }
                            else
                            {
                                // The value is not a number. Strip the prefix.
                                if (words[2].StartsWith(Settings.ConstantPrefix))
                                    words[2] = words[2].Substring(Settings.ConstantPrefix.Length);

                                // If the name now starts with a digit (doesn't matter whether we
                                // stripped "GL_" above), add a "GL_" prefix.
                                // (e.g. GL_4_BYTES).
                                if (Char.IsDigit(words[2][0]))
                                    words[2] = Settings.ConstantPrefix + words[2];
                            }

                            c.Value = words[2];
                        }
                        else if (words[0] == "use")
                        {
                            // Trim the prefix.
                            if (words[2].StartsWith(Settings.ConstantPrefix))
                                words[2] = words[2].Substring(Settings.ConstantPrefix.Length);

                            // If the remaining string starts with a digit, we were wrong above.
                            // Re-add the "GL_"
                            if (Char.IsDigit(words[2][0]))
                                words[2] = Settings.ConstantPrefix + words[2];

                            c.Name = words[2];
                            c.Reference = words[1];
                            c.Value = words[2];
                        }

                        //if (!String.IsNullOrEmpty(c.Name) && !e.Members.Contains.Contains(c))
                        //SpecTranslator.Merge(e.Members, c);
                        if (!e.ConstantCollection.ContainsKey(c.Name))
                            e.ConstantCollection.Add(c.Name, c);
                        else
                            Trace.WriteLine(String.Format(
                                "Spec error: Constant {0} defined twice in enum {1}, discarding last definition.",
                                c.Name, e.Name));

                        // Insert the current constant in the list of all constants.
                        //SpecTranslator.Merge(complete_enum.Members, c);
                        complete_enum = Utilities.Merge(complete_enum, c);
                    }
                    while (!specFile.EndOfStream);

                    // At this point, the complete value list for the current enumerant has been read, so add this
                    // enumerant to the list.
                    //e.StartDirectives.Add(new CodeRegionDirective(CodeRegionMode.Start, "public enum " + e.Name));
                    //e.EndDirectives.Add(new CodeRegionDirective(CodeRegionMode.End, "public enum " + e.Name));

                    // (disabled) Hack - discard Boolean enum, it fsucks up the fragile translation code ahead.
                    //if (!e.Name.Contains("Bool"))
                    //Utilities.Merge(enums, e);

                    //e.Translate();

                    if (!enums.ContainsKey(e.Name))
                    {
                        enums.Add(e.Name, e);
                    }
                    else
                    {
                        // The enum already exists, merge constants.
                        Trace.WriteLine(String.Format("Conflict: Enum {0} already exists, merging constants.", e.Name));
                        foreach (Constant t in e.ConstantCollection.Values)
                        {
                            Utilities.Merge(enums[e.Name], t);
                        }
                    }

                    //enums.Add(e);
                }
                //SpecTranslator.Merge(enums, complete_enum);
            }
            while (!specFile.EndOfStream);

            enums.Add(complete_enum.Name, complete_enum);

            Trace.Unindent();

            return enums;
        }
Пример #10
0
        public override EnumCollection ReadEnums(StreamReader specFile)
        {
            // First, read all enum definitions from spec and override file.
            // Afterwards, read all token/enum overrides from overrides file.
            // Every single enum is merged into

            EnumCollection enums = new EnumCollection();
            Enum all = new Enum() { Name = Settings.CompleteEnumName }; 
            XPathDocument specs = new XPathDocument(specFile);
            XPathDocument overrides = new XPathDocument(new StreamReader(Path.Combine(Settings.InputPath, functionOverridesFile)));

            foreach (XPathNavigator nav in new XPathNavigator[] {
                specs.CreateNavigator().SelectSingleNode("/signatures"),
                overrides.CreateNavigator().SelectSingleNode("/overrides/add") })
            {
                if (nav != null)
                {
                    foreach (XPathNavigator node in nav.SelectChildren("enum", String.Empty))
                    {
                        Enum e = new Enum()
                        {
                            Name = node.GetAttribute("name", String.Empty),
                            Type = node.GetAttribute("type", String.Empty)
                        };
                        if (String.IsNullOrEmpty(e.Name))
                            throw new InvalidOperationException(String.Format("Empty name for enum element {0}", node.ToString()));

                        foreach (XPathNavigator param in node.SelectChildren(XPathNodeType.Element))
                        {
                            Constant c = new Constant(param.GetAttribute("name", String.Empty), param.GetAttribute("value", String.Empty));
                            Utilities.Merge(all, c);
                            try { e.ConstantCollection.Add(c.Name, c); }
                            catch (ArgumentException ex) { Console.WriteLine("[Warning] Failed to add constant {0} to enum {1}: {2}", c.Name, e.Name, ex.Message); }
                        }

                        Utilities.Merge(enums, e);
                    }
                }
            }

            Utilities.Merge(enums, all);
            enums.Translate(overrides);
            return enums;
        }
Пример #11
0
        EnumCollection ReadEnums(XPathNavigator nav)
        {
            EnumCollection enums = new EnumCollection();
            Enum all = new Enum() { Name = Settings.CompleteEnumName };

            if (nav != null)
            {
                var reuse_list = new List<KeyValuePair<Enum, string>>();

                // First pass: collect all available tokens and enums
                foreach (XPathNavigator node in nav.SelectChildren("enum", String.Empty))
                {
                    Enum e = new Enum()
                    {
                        Name = node.GetAttribute("name", String.Empty).Trim(),
                        Type = node.GetAttribute("type", String.Empty).Trim()
                    };

                    if (String.IsNullOrEmpty(e.Name))
                        throw new InvalidOperationException(String.Format("Empty name for enum element {0}", node.ToString()));

                    // It seems that all flag collections contain "Mask" in their names.
                    // This looks like a heuristic, but it holds 100% in practice
                    // (checked all enums to make sure).
                    e.IsFlagCollection = e.Name.ToLower().Contains("mask");

                    foreach (XPathNavigator param in node.SelectChildren(XPathNodeType.Element))
                    {
                        Constant c = null;
                        switch (param.Name)
                        {
                            case "token":
                                c = new Constant
                                {
                                    Name = param.GetAttribute("name", String.Empty).Trim(),
                                    Value = param.GetAttribute("value", String.Empty).Trim()
                                };
                                break;

                            case "use":
                                c = new Constant
                                {
                                    Name = param.GetAttribute("token", String.Empty).Trim(),
                                    Reference = param.GetAttribute("enum", String.Empty).Trim(),
                                    Value = param.GetAttribute("token", String.Empty).Trim(),
                                };
                                break;

                            case "reuse":
                                var reuse_enum = param.GetAttribute("enum", String.Empty).Trim();
                                reuse_list.Add(new KeyValuePair<Enum, string>(e, reuse_enum));
                                break;

                            default:
                                throw new NotSupportedException();
                        }

                        if (c != null)
                        {
                            Utilities.Merge(all, c);
                            try
                            {
                                if (!e.ConstantCollection.ContainsKey(c.Name))
                                {
                                    e.ConstantCollection.Add(c.Name, c);
                                }
                                else if (e.ConstantCollection[c.Name].Value != c.Value)
                                {
                                    var existing = e.ConstantCollection[c.Name];
                                    if (existing.Reference != null && c.Reference == null)
                                    {
                                        e.ConstantCollection[c.Name] = c;
                                    }
                                    else if (existing.Reference == null && c.Reference != null)
                                    {
                                        // Keep existing
                                    }
                                    else
                                    {
                                        Console.WriteLine("[Warning] Conflicting token {0}.{1} with value {2} != {3}",
                                            e.Name, c.Name, e.ConstantCollection[c.Name].Value, c.Value);
                                    }
                                }
                            }
                            catch (ArgumentException ex)
                            {
                                Console.WriteLine("[Warning] Failed to add constant {0} to enum {1}: {2}", c.Name, e.Name, ex.Message);
                            }
                        }
                    }

                    Utilities.Merge(enums, e);
                }

                // Second pass: resolve "reuse" directives
restart:
                foreach (var pair in reuse_list)
                {
                    var e = pair.Key;
                    var reuse = pair.Value;
                    var count = e.ConstantCollection.Count;

                    if (enums.ContainsKey(reuse))
                    {
                        var reuse_enum = enums[reuse];
                        foreach (var token in reuse_enum.ConstantCollection.Values)
                        {
                            Utilities.Merge(e, token);
                        }
                    }
                    else
                    {
                        Console.WriteLine("[Warning] Reuse token not found: {0}", reuse);
                    }

                    if (count != e.ConstantCollection.Count)
                    {
                        // Restart resolution of reuse directives whenever
                        // we modify an enum. This is the simplest (brute) way
                        // to resolve chains of reuse directives:
                        // e.g. enum A reuses B which reuses C
                        goto restart;
                    }
                }
            }

            Utilities.Merge(enums, all);
            return enums;
        }
Пример #12
0
        /// <summary>
        /// Replces the Value of the given constant with the value referenced by the [c.Reference, c.Value] pair.
        /// </summary>
        /// <param name="c">The Constant to translate</param>
        /// <param name="enums">The list of enums to check.</param>
        /// <param name="auxEnums">The list of auxilliary enums to check.</param>
        /// <returns>True if the reference was found; false otherwise.</returns>
        public static bool TranslateConstantWithReference(Constant c, EnumCollection enums, EnumCollection auxEnums)
        {
            if (!String.IsNullOrEmpty(c.Reference))
            {
                Constant referenced_constant;

                if (enums.ContainsKey(c.Reference) && enums[c.Reference].ConstantCollection.ContainsKey(c.Value))
                {
                    TranslateConstantWithReference(enums[c.Reference].ConstantCollection[c.Value] as Constant, enums, auxEnums);
                    referenced_constant = (enums[c.Reference].ConstantCollection[c.Value] as Constant);
                }
                else if (auxEnums.ContainsKey(c.Reference) && auxEnums[c.Reference].ConstantCollection.ContainsKey(c.Value))
                {
                    TranslateConstantWithReference(auxEnums[c.Reference].ConstantCollection[c.Value] as Constant, enums, auxEnums);
                    referenced_constant = (auxEnums[c.Reference].ConstantCollection[c.Value] as Constant);
                }
                else
                {
                    Console.WriteLine("[Warning] Reference {0} not found for token {1}.", c.Reference, c);
                    return false;
                }
                //else throw new InvalidOperationException(String.Format("Unknown Enum \"{0}\" referenced by Constant \"{1}\"",
                //                                                       c.Reference, c.ToString()));

                c.Value = referenced_constant.Value;
                c.Reference = null;
                c.Unchecked = referenced_constant.Unchecked;
            }

            return true;
        }
Пример #13
0
        /// <summary>
        /// Replces the Value of the given constant with the value referenced by the [c.Reference, c.Value] pair.
        /// </summary>
        /// <param name="c">The Constant to translate</param>
        /// <param name="enums">The list of enums to check.</param>
        /// <param name="auxEnums">The list of auxilliary enums to check.</param>
        /// <returns>True if the reference was found; false otherwise.</returns>
        public static bool TranslateConstantWithReference(Constant c, EnumCollection enums, EnumCollection auxEnums)
        {
            if (c == null)
                throw new ArgumentNullException("c");
            if (enums == null)
                throw new ArgumentNullException("enums");

            if (++CurrentReferenceDepth >= MaxReferenceDepth)
                throw new InvalidOperationException("Enum specification contains cycle");

            if (!String.IsNullOrEmpty(c.Reference))
            {
                Constant referenced_constant;

                if (enums.ContainsKey(c.Reference) && enums[c.Reference].ConstantCollection.ContainsKey(c.Value))
                {
                    // Transitively translate the referenced token
                    // Todo: this may cause loops if two tokens reference each other.
                    // Add a max reference depth and bail out?
                    TranslateConstantWithReference(enums[c.Reference].ConstantCollection[c.Value], enums, auxEnums);
                    referenced_constant = (enums[c.Reference].ConstantCollection[c.Value]);
                }
                else if (auxEnums != null && auxEnums.ContainsKey(c.Reference) && auxEnums[c.Reference].ConstantCollection.ContainsKey(c.Value))
                {
                    // Legacy from previous generator incarnation.
                    // Todo: merge everything into enums and get rid of auxEnums.
                    TranslateConstantWithReference(auxEnums[c.Reference].ConstantCollection[c.Value], enums, auxEnums);
                    referenced_constant = (auxEnums[c.Reference].ConstantCollection[c.Value]);
                }
                else if (enums.ContainsKey(Settings.CompleteEnumName) &&
                    enums[Settings.CompleteEnumName].ConstantCollection.ContainsKey(c.Value))
                {
                    // Try the All enum
                    var reference = enums[Settings.CompleteEnumName].ConstantCollection[c.Value];
                    if (reference.Reference == null)
                        referenced_constant = (enums[Settings.CompleteEnumName].ConstantCollection[c.Value]);
                    else
                    {
                        --CurrentReferenceDepth;
                        return false;
                    }
                }
                else
                {
                    --CurrentReferenceDepth;
                    return false;
                }
                //else throw new InvalidOperationException(String.Format("Unknown Enum \"{0}\" referenced by Constant \"{1}\"",
                //                                                       c.Reference, c.ToString()));

                c.Value = referenced_constant.Value;
                c.Reference = null;
            }

            --CurrentReferenceDepth;
            return true;
        }