public bool Apply(ref RegisterID regId, string fullName, out string shortName)
            {
                if (Breakpoint)
                    Debugger.Break();

                shortName = null;
                Match mSet = null, mReg = null, mSubreg = null;
                if (_SetRegex != null)
                {
                    mSet = _SetRegex.Match(regId.SetName);
                    if (!mSet.Success)
                        return false;
                }
                if (_RegisterRegex != null)
                {
                    mReg = _RegisterRegex.Match(regId.RegName);
                    if (!mReg.Success)
                        return false;
                }

                    mSubreg = _SubregisterRegex.Match(fullName);
                if (!mSubreg.Success)
                    return false;

                shortName = ExpandString(NewSubregister, mSet, mReg, mSubreg);
                if (NewSet != null || NewRegister != null)
                {
                    string setName = NewSet == null ? regId.SetName : ExpandString(NewSet, mSet, mReg, mSubreg);
                    string regName = NewRegister == null ? regId.RegName : ExpandString(NewRegister, mSet, mReg, mSubreg);
                    regId = new RegisterID(setName, regName);
                }

                if (StripRegisterNameFromSubregister)
                {
                    if (!shortName.StartsWith(regId.RegName + "_", StringComparison.InvariantCultureIgnoreCase))
                        throw new Exception("Unexpected subregister name after transformation");
                    shortName = shortName.Substring(regId.RegName.Length + 1);
                }
                return true;
            }
 public bool ApplySubregisterRenameRules(ref RegisterID thisReg, string subreg_name, out string shortSubregName)
 {
     shortSubregName = null;
     foreach (var rule in SubregisterRenameRules)
         if (rule.Apply(ref thisReg, subreg_name, out shortSubregName))
             return true;
     return false;
 }
            public bool Apply(ref RegisterID register)
            {
                if (register.SetName != OriginalName)
                    return false;
                if (!_RegisterNames.Contains(register.RegName))
                    return false;

                register = new RegisterID(NewName == null ? register.SetName : NewName, NewRegisterName == null ? register.RegName : NewRegisterName);
                return true;
            }
        private static Dictionary<string, List<HardwareSubRegister>> ProcessSubregisters(string fileContents, string fileName, RegisterParserConfiguration cfg, RegisterParserErrors errors)
        {
            Dictionary<string, List<HardwareSubRegister>> result = new Dictionary<string, List<HardwareSubRegister>>();
            Dictionary<string, uint> aDefPosDict = new Dictionary<string, uint>();

            // Process subregisters
            Regex rgSubregisterList = new Regex(@"/\*[!]?[<]?[\*]+[ ]+Bit[s]? definition [genric ]*for ([^_ ]*)_([^ ]*)[ ]+register[ ]+[*]+/[ ]*");
            Regex rgSubregisterListWildcard = new Regex(@"/\*+ +Bit definition for ([A-Z0-9a-z]+)_([A-Z0-9a-z]+) \(x *=[^()]+\) +register +\*+/");
            Regex rgSubregisterListWildcard2 = new Regex(@"/\*+ +Bit definition for ([A-Z0-9a-z]+)_([A-Z0-9a-z]+) registers? +\(x *=[^()]+\) +\*+/");
            Regex rbSubregisterListEth = new Regex(@"/\*+[ ]+Bit definition for (.*) [Rr]egister[ ]+[1-9]*[ ]*\*+/");
            Regex rbSubregisterListUsb = new Regex(@"/\*+ +([^ ]+ .*) register bits? definitions +\*+/", RegexOptions.IgnoreCase);
            Regex bit_def_regex = new Regex(@"#define[ ]+([^ \(\)]*)[ \t]+[,]?[ ]*\(\(([^\(\)]*)\)([0-9A-Fa-fx]*)[U]?\)[ ]*(/\*)?(!<)?[ ]*([^\*/]*)(\*/)?");

            string[] lines = fileContents.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
            int nextLine = 0;
            bool insideIgnoredBlock = false;
            for (;;)
            {
                if (nextLine >= lines.Length)
                    break;
                string line = lines[nextLine++];

                foreach (var patch in cfg.LinePatches)
                    if (patch.Apply(ref line))
                        break;

                Match m;
                RegisterID thisReg;
                if ((m = rgSubregisterList.Match(line)).Success)
                    thisReg = new RegisterID(m.Groups[1].Value, m.Groups[2].Value);
                else if (((m = rgSubregisterListWildcard.Match(line)).Success) || ((m = rgSubregisterListWildcard2.Match(line)).Success))
                    thisReg = new RegisterID(m.Groups[1].Value, m.Groups[2].Value);
                else if (((m = rbSubregisterListEth.Match(line)).Success) || (m = rbSubregisterListUsb.Match(line)).Success)
                {
                    var m4 = bit_def_regex.Match(lines[nextLine]);
                    if (!m4.Success)
                        m4 = Regex.Match(lines[nextLine], @"#define[ \t]+([\w\d]+)[ \t]+([0-9A-Fa-fx]*)[U]?");
                    if (!m4.Success)
                        errors.AddError(new RegisterParserErrors.BadBitDefinition { LineContents = line, LineNumber = nextLine - 1, FileName = fileName });

                    string subreg_def = m4.Groups[1].Value;
                    int index = subreg_def.IndexOf("_");
                    if (index <= 0)
                    {
                        errors.AddError(new RegisterParserErrors.BadBitDefinition { LineContents = line, LineNumber = nextLine - 1, FileName = fileName });
                        continue;
                    }
                    string regSet = subreg_def.Substring(0, index);
                    subreg_def = subreg_def.Substring(index + 1);
                    index = subreg_def.IndexOf("_");
                    if (index <= 0)
                    {
                        errors.AddError(new RegisterParserErrors.BadBitDefinition { LineContents = line, LineNumber = nextLine - 1, FileName = fileName });
                        continue;
                    }

                    thisReg = new RegisterID(regSet, subreg_def.Substring(0, index));
                }
                else
                {
                    if (line.StartsWith("/**") && (line.Contains("Bit definition") || line.Contains("Bits definition")))
                    {
                        if (cfg.IsBlockDefinitionIgnored(line))
                            insideIgnoredBlock = true;
                        else
                            errors.AddError(new RegisterParserErrors.BadBitDefinition { LineContents = line, LineNumber = nextLine - 1, FileName = fileName });
                    }

                    if (line.StartsWith("#define")
                        && line.Contains("0x")
                        && !line.Contains("CLEAR_REG")
                        && !line.Contains("USB_EP")
                        && !line.Contains("FLASH_FKEY")
                        && !line.Contains("FLASH_KEY")
                        && !line.Contains("EXTI_EMR")
                        && !line.Contains("FLASH_OPTKEY")
                        && !line.Contains("(USB_BASE +")
                        && !line.Contains("RTC_BKP_NUMBER")
                        && !line.Contains("USB_ISTR")
                        && !line.Contains("USB_LPMCSR")
                        && !line.Contains("USB_DADDR")
                        && !line.Contains("USB_BASE")
                        && !line.Contains("USB_CNTR")
                        && !line.Contains("USB_BCDR")
                        && !line.Contains("USB_FNR")
                        && !line.Contains("USB_PMAADDR")
                        && !line.Contains("define HRTIM_")  //Not much formal system in comments to parse. Currently ignoring.
                        )
                    {
                        if (result.Count > 0 && !insideIgnoredBlock)
                            errors.AddError(new RegisterParserErrors.BadSubregisterDefinition { FileName = fileName, LineContents = line, LineNumber = nextLine - 1 });
                    }

                    continue;
                }

                if (thisReg.RegName.Contains("/"))
                {
                    int idx = thisReg.RegName.IndexOf('/');
                    thisReg = new RegisterID(thisReg.SetName, thisReg.RegName.Substring(0, idx).TrimEnd('1', '2', '3', '4'));
                }

                insideIgnoredBlock = false;

                //Apply name adjustment rules
                if ((thisReg.SetName == "DMA") && ((thisReg.RegName.Substring(0, thisReg.RegName.Length - 1) == "CCR") || (thisReg.RegName.Substring(0, thisReg.RegName.Length - 1) == "CNDTR") || (thisReg.RegName.Substring(0, thisReg.RegName.Length - 1) == "CPAR") || (thisReg.RegName.Substring(0, thisReg.RegName.Length - 1) == "CMAR")))// Header BUG: DMA_Channel defs not DMA defs
                    thisReg = new RegisterID("DMA_Channel", thisReg.RegName.Substring(0, thisReg.RegName.Length - 1));
                else
                {
                    foreach (var rule in cfg.RegisterSetRenameRules)
                    {
                        if (rule.Apply(ref thisReg))
                            break;
                    }
                }

                var subregisters = new List<HardwareSubRegister>();

                for (;;)
                {
                    if (nextLine >= lines.Length)
                        break;
                    line = lines[nextLine++];

                    foreach (var patch in cfg.SubregisterLinePatches)
                        if (patch.Apply(ref line))
                            break;
                    string subreg_name = "";
                    string reg_type = "";
                    string address_offset = "";
                    bool aParseOk = false;
                    m = bit_def_regex.Match(line);
                    if (!m.Success)
                    {
                        m = Regex.Match(line, @"#define[ \t]+([\w]+)[ \t]+[\(]?([\w]+)[\)]?");
                        if (m.Success && !m.Groups[1].Value.EndsWith("_Pos") && !m.Groups[1].Value.EndsWith("_Msk") && !line.Contains("<<"))
                        {
                            subreg_name = m.Groups[1].Value;
                            if (subreg_name == "RTC_BKP_NUMBER")
                                continue;

                            reg_type = "uint32_t";
                            if (m.Groups[2].Value.StartsWith("0x"))
                            {
                                address_offset = m.Groups[2].Value.Replace("U", "");//#define GPIO_OTYPER_OT_0                (0x00000001U)
                                aDefPosDict[m.Groups[1].Value] = UInt32.Parse(address_offset.Replace("x", ""), System.Globalization.NumberStyles.AllowHexSpecifier);
                            }
                            else
                            {
                                if (aDefPosDict.ContainsKey(m.Groups[2].Value))
                                {
                                    address_offset = FormatToHex(aDefPosDict[m.Groups[2].Value]);

                                    // for Legacy defines */
                                    aDefPosDict[m.Groups[1].Value] = aDefPosDict[m.Groups[2].Value];
                                } else
                                    if (Regex.IsMatch(m.Groups[2].Value, "(0x[0-9A-FU]+)"))
                                       aDefPosDict.Add(m.Groups[1].Value, (uint)ParseHex(m.Groups[2].Value));
                                    else {
                                            Console.WriteLine("No Hex value:{0}, : {1}", m.Groups[1].Value, m.Groups[2].Value);
                                           continue;
                                       }
                            }
                                aParseOk = true;
                            }
                    }
                    else
                    {
                         subreg_name = m.Groups[1].Value;
                         reg_type = m.Groups[2].Value;
                         address_offset = m.Groups[3].Value;
                        if (!aDefPosDict.ContainsKey(m.Groups[1].Value))
                            aDefPosDict.Add(m.Groups[1].Value, (uint)ParseHex(m.Groups[3].Value));
                         aParseOk = true;
                    }

                    if (aParseOk)
                    {
                        string shortSubregName;
                        if (cfg.IsSubregisterIgnored(subreg_name))
                            continue;

                        //Checks to see if any known values were missed from the above filters
                        if (subreg_name.EndsWith("_RST") ||
                            subreg_name.EndsWith("HSI") ||
                            subreg_name.EndsWith("HSE") ||
                            subreg_name.EndsWith("LSI") ||
                            subreg_name.EndsWith("MSI") ||
                            subreg_name.EndsWith("PLL") ||
                            subreg_name.EndsWith("_NOCLOCK") ||
                            subreg_name.EndsWith("_SYSCLK") ||
                            subreg_name.EndsWith("KEY")
                            )
                        {
                            if (subreg_name != "MACTMR_CR_EN" &&
                                subreg_name != "MACTMR_CR_RST" &&
                                subreg_name != "ADC_DMACR_RST" &&
                                subreg_name != "RTC_WPR_KEY" &&
                                subreg_name != "IWDG_KR_KEY" &&
                                subreg_name != "SCB_AIRCR_VECTKEY" &&
                                subreg_name != "HASH_CR_LKEY" &&
                                subreg_name != "WDG_KR_KEY" &&
                                !subreg_name.StartsWith("RCC_CFGR_") &&
                                subreg_name != "FLASH_OPTR_SRAM2_RST")
                            {
                                throw new Exception("Potential missed known subregister value!");
                            }
                        }

                        int offset, size;
                        try
                        {
                            ExtractFirstBitAndSize(ParseHex(address_offset), out size, out offset);
                        }
                        catch(Exception ex)
                        {
                            errors.AddError(new RegisterParserErrors.BitmaskNotSequential { FileName = fileName, LineContents = line, LineNumber = nextLine - 1 });
                            continue;
                        }

                        string desc = m.Groups[6].Value.TrimEnd();

                        if (subreg_name.StartsWith(thisReg.SubregisterPrefix))
                            shortSubregName = subreg_name.Substring(thisReg.SubregisterPrefix.Length);
                        else
                        {
                            if (cfg.IsMismatchingSubregisterIgnored(subreg_name))
                                continue;

                            if (!cfg.ApplySubregisterRenameRules(ref thisReg, subreg_name, out shortSubregName))
                            {
                                errors.AddError(new RegisterParserErrors.UnexpectedSubregisterName { FileName = fileName, LineContents = line, LineNumber = nextLine - 1, SubregName = subreg_name });
                                continue;
                            }
                        }

                        if (subregisters.Find(x => ((x.Name == shortSubregName) && (x.FirstBit == offset) && (x.SizeInBits == size))) != null)
                        {
                            Debug.WriteLine("Duplicate subregister not added: " + thisReg.SubregisterPrefix + shortSubregName);
                        }
                        else
                        {
                            subregisters.Add(new HardwareSubRegister
                            {
                                Name = shortSubregName,
                                SizeInBits = size,
                                FirstBit = offset,
                            });
                        }

                    }
                    else
                    {
                        //                        if (line.StartsWith("#define") && line.Contains("0x") && !line.Contains("CLEAR_REG"))
                        if (line.StartsWith("#define") && line.Contains("0x") && !line.Contains("CLEAR_REG") && !line.Contains("_Pos"))
                            errors.AddError(new RegisterParserErrors.BadSubregisterDefinition { FileName = fileName, LineContents = line, LineNumber = nextLine - 1 });
                        else if (line.Contains("/*                         USB Device General registers                       */"))
                            break;
                        else if (line.StartsWith("/*******") || line.Contains("Bit definition") || line.StartsWith("/*!<Common registers */"))
                            break;
                        else
                        {
                            var m1 = Regex.Match(line, @"#define[ \t]+([\w]+_Pos)[ \t]+\(([0-9A-Fa-f]+)U\)");
                            if (m1.Success)
                                aDefPosDict[m1.Groups[1].Value] = UInt32.Parse(m1.Groups[2].Value);
                            else
                            {
                                m1 = Regex.Match(line, @"#define[ \t]+([\w]+)[ \t]+\(0x([0-9A-Fa-fx]+)U << ([\w]+)\)");
                                if (m1.Success)
                                {
                                    UInt32 aValueMask = UInt32.Parse(m1.Groups[2].Value, System.Globalization.NumberStyles.AllowHexSpecifier);
                                    aValueMask = aValueMask << (int)aDefPosDict[m1.Groups[3].Value];
                                    aDefPosDict[m1.Groups[1].Value] = aValueMask;
                                }
                            }
                        }
                    }
                }

                result[thisReg.ToString()] = subregisters;
                subregisters = new List<HardwareSubRegister>();

                nextLine--;
            }

            //Remove useless subregisters that just define a numbered bit of another subregister value
            Regex numbered_name_regex = new Regex(@"(.*)_[0-9]+");
            foreach (var list in result.Values)
            {
                for (int i = 0; i < list.Count;i++ )
                {
                    var element = list[i];
                    var m = numbered_name_regex.Match(element.Name);
                    if (m.Success && (list.Find(x => (x.Name == m.Groups[1].Value)) != null) && (element.SizeInBits == 1))
                    {
                        //Debug.WriteLine("Removed bit definition " + element.Name);
                        list.Remove(element);
                        i--;
                    }
                }
            }

            return result;
        }