// this kicks off the processing of a type; see if it is decorated by
    // rules.triggers, and if so, then build an xml node and process the rest
    // of the rules object for this type
    private bool ProcessType(MetaDataTypeDefinition type,
                             ParseRules rules,
                             XmlNode parent,
                             ref int categoryIndex,
                             ref XmlNode categories)
    {
        if (type.CustomAttributes == null)
        {
            return(false);
        }


        foreach (MetaDataCustomAttribute attrib in type.CustomAttributes)
        {
            foreach (TriggerDefinition rule in rules.triggers)
            {
                if (attrib.Name == rule.attribute)
                {
                    // only process this entry if the ancestry is valid
                    if (MatchInheritance(rule.derivesFromClass, type))
                    {
                        if (categoryIndex == 0)
                        {
                            categories = AddElement(parent, "categories");
                        }
                        // create an xml node from (attrib, rule)
                        XmlNode node = CreateNode(attrib, rule);

                        AddAttribute(node, "id", (categoryIndex++).ToString());
                        if (rule.categoryName != null)
                        {
                            AddAttribute(node, "name", rule.categoryName);
                        }
                        AddAttribute(node, "class", type.FullName);

                        // then do the rules.classDefinitions work
                        ProcessClassAttributes(type, rules.classAttributes, node);

                        // then do the rules.fieldDefinitions work
                        ProcessFieldAttributes(type, rules.fieldAttributes, node);

                        // then append this xml node to the manifest root doc
                        if (categories == null)
                        {
                            Console.WriteLine(" categories is null at index {0}", categoryIndex);
                        }
                        else
                        {
                            categories.AppendChild(node);
                        }
                        // once we match once, we stop operating on this type
                        return(true);
                    }
                }
            }
        }
        return(false);
    }
        public ParseRules(ParseRules inheritFrom,
                          TriggerDefinition[] triggers,
                          ClassDefinition[] classAttributes,
                          FieldDefinition[] fieldAttributes)
        {
            this.triggers = triggers;

            if (inheritFrom != null)
            {
                this.classAttributes = Inherit(inheritFrom.classAttributes,
                                               classAttributes);
                this.fieldAttributes = Inherit(inheritFrom.fieldAttributes,
                                               fieldAttributes);
            }
            else
            {
                this.classAttributes = classAttributes;
                this.fieldAttributes = fieldAttributes;
            }
        }
    static ManifestBuilder()
    {
        ParseRules categoryRules = new ParseRules(
            null,

            // "triggers"
            new TriggerDefinition[] {
            new TriggerDefinition("category",
                                  null,
                                  "Microsoft.Singularity.Configuration.CategoryAttribute",
                                  "Microsoft.Singularity.Configuration.CategoryDeclaration",
                                  new string [] { "name" }),
        },

            // "class" attributes
            new ClassDefinition[] {},

            // "field" attributes
            new FieldDefinition[] {
            // NB: the constructor fields on these are handled specially, unlike
            // everything else in this tool.  This is indicated by the "true"
            // value for the last parameter to the constructor

            // TODO: is this correct?  Should Endpoint declarations in
            // ConsoleCategories and Configuration be given names so that they are more
            // human-configurable?  Will an app ever declare multiple Endpoints of
            // the same type and require the kernel to user to patch those identical
            // endpoints to different (and conflicting) apps?  Could this problem be
            // addressed via stronger typing?

            new EndpointDefinition("endpoints",
                                   "extension",
                                   "Microsoft.Singularity.Configuration.ExtensionEndpointAttribute",
                                   "Microsoft.Singularity.Channels.TRef_2"
                                   + "<Microsoft.Singularity.Extending."
                                   + "ExtensionContract+Exp,Microsoft.Singularity"
                                   + ".Extending.ExtensionContract+Start>"),
            new ServiceEndpointDefinition("endpoints",
                                          "serviceProvider",
                                          "Microsoft.Singularity.Configuration.ServiceEndpointAttribute",
                                          "Microsoft.Singularity.Channels.TRef_2"
                                          + "<Microsoft.Singularity.Directory."
                                          + "ServiceProviderContract+Exp,Microsoft."
                                          + "Singularity.Directory.ServiceProviderContract"
                                          + "+Start>"),
            // TODO: - the inheritance on this is not correct
            new EndpointDefinition("endpoints",
                                   "endpoint",
                                   "Microsoft.Singularity.Configuration.EndpointAttribute",
                                   null),
            new EndpointDefinition("endpoints",
                                   "customEndpoint",
                                   "Microsoft.Singularity.Configuration.CustomEndpointAttribute",
                                   null),

            new EndpointDefinition("endpoints",
                                   "inputPipe",
                                   "Microsoft.Singularity.Configuration.InputEndpointAttribute",
                                   null,
                                   new string [] { "Kind" }),
            new EndpointDefinition("endpoints",
                                   "outputPipe",
                                   "Microsoft.Singularity.Configuration.OutputEndpointAttribute",
                                   null,
                                   new string [] { "Kind" }),
            new ParameterDefinition("StringParameters",
                                    "StringParameter",
                                    "Microsoft.Singularity.Configuration.StringParameterAttribute",
                                    "STRING",
                                    new string [] { "Name" }),
            new ParameterDefinition("LongParameters",
                                    "LongParameter",
                                    "Microsoft.Singularity.Configuration.LongParameterAttribute",
                                    "I8",
                                    new string [] { "Name" }),
            new ParameterDefinition("BoolParameters",
                                    "BoolParameter",
                                    "Microsoft.Singularity.Configuration.BoolParameterAttribute",
                                    "BOOLEAN",
                                    new string [] { "Name" }),
            new ParameterDefinition("StringArrayParameters",
                                    "StringArrayParameter",
                                    "Microsoft.Singularity.Configuration.StringArrayParameterAttribute",
                                    "SZARRAY",
                                    new string [] { "Name" }),
        }
            );

        ParseRules driverCategoryRules = new ParseRules(
            categoryRules, // inherit "class" and "field" rules from category.

            // "triggers"
            new TriggerDefinition[] {
            new TriggerDefinition("category",
                                  "driver",
                                  "Microsoft.Singularity.Io.DriverCategoryAttribute",
                                  "Microsoft.Singularity.Io.DriverCategoryDeclaration"),
        },

            // "class" attributes
            new ClassDefinition[] {
            new ClassDefinition("device",
                                "Microsoft.Singularity.Io.SignatureAttribute",
                                new string [] { "signature" }),
            new ClassDefinition("enumerates",
                                "Microsoft.Singularity.Io.EnumeratesDeviceAttribute",
                                new string [] { "signature" }),
        },

            // "field" attributes
            new FieldDefinition[] {
            new FieldDefinition("dynamicHardware",
                                "ioPortRange",
                                "Microsoft.Singularity.Io.IoPortRangeAttribute",
                                "Microsoft.Singularity.Io.IoPortRange",
                                new string [] { "id" },
                                new string [] { "Default", "baseAddress",
                                                "Length", "rangeLength",
                                                "Shared", "shared" }),
            new FieldDefinition("fixedHardware",
                                "ioPortRange",
                                "Microsoft.Singularity.Io.IoFixedPortRangeAttribute",
                                "Microsoft.Singularity.Io.IoPortRange",
                                new string [] { "id" },
                                new string [] { "Base", "baseAddress",
                                                "Length", "rangeLength",
                                                "Shared", "shared" },
                                new string [] { "fixed", "true" }),
            new FieldDefinition("dynamicHardware",
                                "ioIrqRange",
                                "Microsoft.Singularity.Io.IoIrqRangeAttribute",
                                "Microsoft.Singularity.Io.IoIrqRange",
                                new string [] { "id" },
                                new string [] { "Default", "baseAddress",
                                                "Length", "rangeLength",
                                                "Shared", "shared" },
                                new string [] { "rangeLength", "1" }),
            new FieldDefinition("fixedHardware",
                                "ioIrqRange",
                                "Microsoft.Singularity.Io.IoFixedIrqRangeAttribute",
                                "Microsoft.Singularity.Io.IoIrqRange",
                                new string [] { "id" },
                                new string [] { "Base", "baseAddress",
                                                "Length", "rangeLength",
                                                "Shared", "shared" },
                                new string [] { "fixed", "true",
                                                "rangeLength", "1" }),
            new FieldDefinition("dynamicHardware",
                                "ioDmaRange",
                                "Microsoft.Singularity.Io.IoDmaRangeAttribute",
                                "Microsoft.Singularity.Io.IoDmaRange",
                                new string [] { "id" },
                                new string [] { "Default", "baseAddress",
                                                "Length", "rangeLength",
                                                "Shared", "shared" },
                                new string [] { "rangeLength", "1" }),
            new FieldDefinition("dynamicHardware",
                                "ioMemoryRange",
                                "Microsoft.Singularity.Io.IoMemoryRangeAttribute",
                                "Microsoft.Singularity.Io.IoMemoryRange",
                                new string [] { "id" },
                                new string [] { "Default", "baseAddress",
                                                "Length", "rangeLength",
                                                "Shared", "shared" }),
            new FieldDefinition("fixedHardware",
                                "ioMemoryRange",
                                "Microsoft.Singularity.Io.IoFixedMemoryRangeAttribute",
                                "Microsoft.Singularity.Io.IoMemoryRange",
                                new string [] { "id" },
                                new string [] { "Base", "baseAddress",
                                                "Length", "rangeLength",
                                                "Shared", "shared",
                                                "AddressBits", "addressBits",
                                                "Alignment", "alignment" },
                                new string [] { "fixed", "true" }),
        }
            );

        ParseRules consoleCategoryRules = new ParseRules(
            categoryRules, // inherit "class" and "field" rules from category.

            // "triggers"
            new TriggerDefinition[] {
            new TriggerDefinition("category",
                                  "console",
                                  "Microsoft.Singularity.Configuration.ConsoleCategoryAttribute",
                                  "Microsoft.Singularity.Configuration.ConsoleCategoryDeclaration"),
        },

            // "class" attributes
            new ClassDefinition[] {
        },

            // "field" attributes
            new FieldDefinition[] {
        }
            );

        rules = new ParseRules[3] {
            driverCategoryRules,
            categoryRules,
            consoleCategoryRules,
        };
    }