Beispiel #1
0
        /// <summary>
        /// The GetBlockIndexes function will locate the opening and closing bracket of the block of code passed to the function.  This function will traverse
        /// through the multi-layers of nested code in the top-level code block passed to the function and identify the positions of where the start and
        /// ending brackets are located in the code block.  An integer array will be return that will contain the index of the starting and ending bracket
        /// of the code block, respectively.
        ///
        /// This version of the function will examine the top-level block of code in that starts at either the position in the header specified in
        /// CurPos paramter or the current parsing position of the header data string loaded in an instantiated HeaderDeclareParser object.
        /// </summary>
        /// <param name="iCurPos">The current position of the header data string to parse code block.  If the CurPos parameter is
        /// set to -1, then the current position parser set in the class will be used.</param>
        /// <returns></returns>
        public int[] GetBlockIndexes(int iCurPos = -1)
        {
            try
            {
                if (iCurPos == -1)
                {
                    iCurPos = CurrentPos;
                }

                int[] aryBlockIndexes = ParserUtils.GetBlockIndexes(ref m_strHeaderData, iCurPos);

                if (aryBlockIndexes == null || (aryBlockIndexes[0] == -1 || aryBlockIndexes[1] == -1))
                {
                    return(null);
                }

                return(aryBlockIndexes);
            }
            catch (Exception err)
            {
                ErrorHandler.ShowErrorMessage(err, "Error in GetBlockIndexes Overload 2 function of HeaderDeclareParser class.");
                return(null);
            }
        }
        /// <summary>
        /// Extracts the next detected field (or set of fields) contained within a structure/union block.  The fields will be extracted from the structure/union within the code block
        /// passed in the Struct parameter of the function.  The next field to be extracted in the structure block will be determined by the position marker passed by reference
        /// in the CurPos parameter.  In the case that a set of fields are declared in one line and separated by commas, a set of fields for the declared
        /// data type will be extracted and loaded into the FieldData array.  Once a field or set of fields are detected and extracted they will be loaded
        /// into a FieldData array that will be returned by the function and can be added to the associated StructData data object.  The function will also
        /// update the current position marker of the structure body, the current field index and byte offset.
        /// </summary>
        /// <param name="strStruct">Complete structure/union block of code to extract.  This will contain the beginning to the end of the structure/union
        /// declaration.</param>
        /// <param name="strStructName">The name of the structure whose fields are to be extracted.</param>
        /// <param name="structOrUnion">Indicates if the block of code represents a structure or union.</param>
        /// <param name="iCurPos">The current position in the structure/union code block.</param>
        /// <param name="iCurFieldIndex">The next available field index in the structure to be assigned to the next extracted field.</param>
        /// <param name="iFieldByteOffset">The current byte offset to be assigned to the next field in the structure to be extracted.</param>
        /// <param name="blBitDetected">Indicates if the previous field extracted from the structure was a field with a bit declaration that has not currently
        /// exceeded the boundary of its associated data type.</param>
        /// <param name="iBitFieldDataSize">If bit fields are currently being extracted from the structure, then this field must be set to size
        /// of the data type associated with the bit fields that are being extracted.  The BitFieldDataSize will be used to increment the byte offset
        /// of the structure after the end of the bit field declaration is detected.</param>
        /// <param name="iBitCount">The total number of bits that are currently calculated for the current set of bit fields being extracted from
        /// the structure.  If the bit count surpasses the data size, then it indicates the end of the current set of bit fields being extracted and
        /// the beginning of a new set of bit fields in the structure.</param>
        /// <param name="strBitFieldTypeName">If bit fields are currently being extracted from the structure, then this field must be set with the
        /// previous data type name associated with the bit field declaration being extracted.  Once a new field type is detected, the current bit field
        /// extraction will stop for that field declaration.</param>
        /// <returns></returns>
        private FieldData[] ExtractStructFieldData(string strStruct, string strStructName, StructUnionEnum structOrUnion,
                                                   ref int iCurPos, ref int iCurFieldIndex, ref int iFieldByteOffset, ref bool blBitDetected,
                                                   ref int iBitFieldDataSize, ref int iBitCount, ref string strBitFieldTypeName)
        {
            try
            {
                FieldData[] aryFields     = null;
                FieldData   fdFieldSchema = new FieldData();

                bool blIsStructDeclaration = false;

                if (strStruct.IndexOf("struct", iCurPos) == iCurPos || strStruct.IndexOf("union", iCurPos) == iCurPos)
                {
                    int iBracketIndex = strStruct.IndexOf('{', iCurPos);
                    if (iBracketIndex != -1)
                    {
                        if (iBracketIndex < strStruct.IndexOf(';', iCurPos))
                        {
                            blIsStructDeclaration = true;
                        }
                    } //end if
                }     //end if

                int    iFieldEndPos       = -1;
                string strFieldData       = "";
                bool   blIsEnum           = false;
                bool   blIsStruct         = false;
                bool   blIsPointer        = false;
                bool   blIsFunction       = false;
                bool   blNewFieldDetected = true;

                if (blBitDetected)
                {
                    blNewFieldDetected = false;
                }

                if (!blIsStructDeclaration)
                {
                    iFieldEndPos = strStruct.IndexOf(';', iCurPos);
                    strFieldData = strStruct.Substring(iCurPos, iFieldEndPos - iCurPos).Trim();
                }//end if

                if (strStruct.IndexOf("enum", iCurPos) == iCurPos)
                {
                    fdFieldSchema.FieldType = FieldTypeEnum.Enum;

                    iCurPos           += "enum".Length;
                    blIsEnum           = true;
                    blNewFieldDetected = true;
                }
                else if (strStruct.IndexOf("struct", iCurPos) == iCurPos)
                {
                    fdFieldSchema.FieldType = FieldTypeEnum.Structure;

                    if (!blIsStructDeclaration)
                    {
                        iCurPos += "struct".Length;
                    }

                    blIsStruct         = true;
                    blNewFieldDetected = true;
                }
                else if (strStruct.IndexOf("union", iCurPos) == iCurPos)
                {
                    fdFieldSchema.FieldType = FieldTypeEnum.Structure;

                    if (!blIsStructDeclaration)
                    {
                        iCurPos += "union".Length;
                    }

                    blIsStruct         = true;
                    blNewFieldDetected = true;
                }//end if

                if (strFieldData.Contains("*") || (strFieldData.Contains("(") && strFieldData.EndsWith(")")))
                {
                    if (blIsStruct)
                    {
                        blIsStruct = false;
                    }

                    fdFieldSchema.FieldType = FieldTypeEnum.Pointer;
                    fdFieldSchema.DataSize  = PointerSizeBytes;
                    blIsPointer             = true;
                    blNewFieldDetected      = true;

                    if (strFieldData.Contains("(") && strFieldData.EndsWith(")"))
                    {
                        blIsFunction = true;
                        fdFieldSchema.FieldTypeName = "function";
                    } //end if
                }     //end if


                if (!blIsStructDeclaration)
                {
                    strFieldData = strStruct.Substring(iCurPos, iFieldEndPos - iCurPos).Trim();

                    //int iFieldCurPos = 0;

                    if (!blIsFunction)
                    {
                        int           iFieldCount   = 0;
                        List <string> lstFieldNames = new List <string>();

                        string[] aryFieldSections     = null;
                        string   strFieldTypeName     = "";
                        int      iFieldNameStartIndex = 0;

                        //The field names will begin either at the last element in the split field sections array string or when the first element
                        //containing a comma (which indicates the beginning of a multiple single field type declaration) is located.
                        if (!strFieldData.Contains(','))
                        {
                            aryFieldSections     = strFieldData.Split(new char[] { ' ', '\n' }, StringSplitOptions.RemoveEmptyEntries);
                            iFieldNameStartIndex = aryFieldSections.Length - 1;

                            for (int i = 0; i < aryFieldSections.Length - 1; i++)
                            {
                                strFieldTypeName += aryFieldSections[i];
                            }//next i

                            iFieldNameStartIndex = aryFieldSections.Length - 1;
                            lstFieldNames.Add(aryFieldSections[iFieldNameStartIndex].Trim().Replace(";", ""));
                        }
                        else
                        {
                            string[] aryFieldCommaSections = strFieldData.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);

                            string strSection = aryFieldCommaSections[0];

                            if (strSection.IndexOf(':') == -1)
                            {
                                aryFieldSections = strSection.Split(new char[] { ' ', '\n' }, StringSplitOptions.RemoveEmptyEntries);
                            }
                            else
                            {
                                int    iColonIndex   = strSection.IndexOf(':');
                                string strSectionSub = strSection.Substring(iColonIndex, strSection.Length - iColonIndex);
                                strSection  = strSection.Remove(iColonIndex);
                                strSection += strSectionSub.Replace(" ", "");

                                aryFieldSections = strSection.Split(new char[] { ' ', '\n' }, StringSplitOptions.RemoveEmptyEntries);

                                for (int i = 1; i < aryFieldCommaSections.Length; i++)
                                {
                                    aryFieldCommaSections[i] = aryFieldCommaSections[i].Replace(" ", "").Replace("\n", "");
                                } //next i
                            }     //end if

                            for (int i = 0; i < aryFieldSections.Length - 1; i++)
                            {
                                strFieldTypeName += aryFieldSections[i];
                            }//next i

                            iFieldNameStartIndex = aryFieldSections.Length - 1;
                            lstFieldNames.Add(aryFieldSections[iFieldNameStartIndex].Trim().Replace(";", ""));

                            for (int i = 1; i < aryFieldCommaSections.Length; i++)
                            {
                                lstFieldNames.Add(aryFieldCommaSections[i].Trim().Replace(";", ""));
                            }
                        }//end if

                        fdFieldSchema.FieldTypeName = strFieldTypeName;

                        if (!blIsPointer && !blIsStruct && !blIsEnum)
                        {
                            fdFieldSchema.FieldType = GetVarFieldType(fdFieldSchema.FieldTypeName);
                        }


                        //If fields in the structure are declared with bit values, then a check will be made to determine if any of the bit fields
                        //in the bit field set are declared without field names.  Bit fields declared without field names indicate either unused
                        //bits in the field or the repositioning to a new byte in the bit declared field set.  If an empty bit field name is declared
                        //with a bit value of zero, it indicates that the new bit field declared in the set will be positioned at a beginning of a new
                        //byte.
                        if (lstFieldNames[0].Contains(":"))
                        {
                            int iCheckBitFieldCounter   = 0;
                            int iFieldNameCountBitCheck = lstFieldNames.Count;
                            int iCheckBitIndex          = 0;
                            int iFieldBits = 0;

                            while (iCheckBitFieldCounter < iFieldNameCountBitCheck)
                            {
                                string strFieldName = lstFieldNames[iCheckBitIndex].Replace(" ", "");
                                if (strFieldName.StartsWith(":"))
                                {
                                    iFieldBits = Convert.ToInt32(strFieldName.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries)[1]);

                                    if (iFieldBits == 0)
                                    {
                                        //If a blank field with a zero value is detected, then advance the bit field counter to the beginning position
                                        //of the next byte of the field.
                                        int iByteAlignedBits = Convert.ToInt32(Math.Truncate(iBitFieldDataSize / 8d));
                                        iBitCount = 8 + iByteAlignedBits;
                                    }
                                    else
                                    {
                                        //If a blank field with a bit value declaration is detected, then the bit field counter is advanced to the number
                                        //of bits specified in the field.
                                        iBitCount += iFieldBits;
                                    }//end if

                                    //Since blank name bit field declarations are used only for repositioning the bit fields, these fields will be removed
                                    //from the field data list and not added to the structure.
                                    lstFieldNames.RemoveAt(iCheckBitIndex);
                                }
                                else
                                {
                                    iCheckBitIndex++;
                                }

                                iCheckBitFieldCounter++;
                            }//end while

                            if (lstFieldNames.Count == 0)
                            {
                                return(null);
                            }
                        }//end if


                        iFieldCount = lstFieldNames.Count;
                        aryFields   = new FieldData[iFieldCount];

                        int iFieldTypeDataSize = 0;

                        if (!blIsPointer)
                        {
                            iFieldTypeDataSize = GetVarFieldDataSize(fdFieldSchema.FieldTypeName);
                        }
                        else
                        {
                            iFieldTypeDataSize = PointerSizeBytes;

                            if (!fdFieldSchema.FieldTypeName.Contains("*"))
                            {
                                fdFieldSchema.FieldTypeName += "*";
                            }
                        }//end if

                        for (int i = 0; i < lstFieldNames.Count; i++)
                        {
                            if (blBitDetected && i > 0)
                            {
                                blNewFieldDetected = false;
                            }

                            aryFields[i] = new FieldData();

                            string[] aryFieldNameRaw = lstFieldNames[i].Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
                            string   strFieldName    = aryFieldNameRaw[0].Trim();
                            int      iFieldBits      = 0;

                            //FOR DEBUGGING
                            //if (aryFieldNameRaw.Length > 1)
                            //    Debugger.Break();
                            //////////////

                            if (blBitDetected)
                            {
                                bool blBitFieldEndDetect = false;

                                //If a bit field declaration extraction is currently in progress in the structure, then a check will be made to see if
                                //another field of the same bit declaration is detected or if a new field outside the set of fields of the bit declaration
                                //is detected, which will signal an end to the extraction of the previous set of bit fields.
                                if (aryFieldNameRaw.Length == 1)
                                {
                                    if (blBitDetected)
                                    {
                                        blBitFieldEndDetect = true;
                                    }
                                }
                                else if (fdFieldSchema.FieldTypeName != strBitFieldTypeName)
                                {
                                    //A field with a new data type, even being the beginning of a new bit field declaration, will result in the ending
                                    //of the previous set of bit field declarations, thereby advancing the offset position to the boundary of the
                                    //previous bit field declaration's data type.
                                    blBitFieldEndDetect = true;
                                }
                                else if (iBitCount >= (iBitFieldDataSize * 8))
                                {
                                    //If the previous set of bit fields that were extracted have been calculated to equal the size of the data type
                                    //associated with the set of bit fields then it can be determine that the end of the declaration for the set of
                                    //bit fields has been reached.  If a new set of bit field declarations are detected, then a new extraction operation
                                    //will be performed for the new set of bit fields.  The offset position will be advanced to the boundary of the
                                    //previous bit fields declaration's data type.
                                    blBitFieldEndDetect = true;
                                }//end if

                                if (blBitFieldEndDetect)
                                {
                                    //Once a new field is detected in the structure, the byte offset will be advanced in the structure.  The byte offset
                                    //will be advanced to a position that is equal to the size of the previous data type associated with the bit field
                                    //declaration.
                                    blNewFieldDetected = true;
                                    iFieldByteOffset  += iBitFieldDataSize;
                                    blBitDetected      = false;
                                } //end if
                            }     //end if

                            if (blNewFieldDetected && aryFieldNameRaw.Length > 1)
                            {
                                //If a new bit field declaration is detected in the structure, then the appropriate variables will be set to indicate
                                //that the next set of fields being extracted in the structure are part of a bit field declaration, until the end of the
                                //bit field declaration (or structure declaration) is detected.
                                blBitDetected       = true;
                                iBitFieldDataSize   = iFieldTypeDataSize;
                                strBitFieldTypeName = strFieldTypeName;
                            }//end if

                            if (aryFieldNameRaw.Length > 1)
                            {
                                iFieldBits = Convert.ToInt32(aryFieldNameRaw[1].Trim());
                                iBitCount += iFieldBits;
                            }//end if

                            int iTotalElements = 1;

                            if (strFieldName.Contains("["))
                            {
                                iTotalElements = ExtractorUtils.CalculateFieldElements(strFieldName);
                                strFieldName   = strFieldName.Split('[')[0].Trim();
                            }//end if

                            if (strFieldName.Contains("*"))
                            {
                                strFieldName = strFieldName.Replace("*", "").Trim();
                            }

                            aryFields[i].FieldName = strFieldName;
                            aryFields[i].Elements  = iTotalElements;

                            if (blNewFieldDetected)
                            {
                                aryFields[i].DataSize = iFieldTypeDataSize * iTotalElements;
                            }
                            else
                            {
                                //Bit field declarations will only have their data size set to the field's data size for the first field of the bit
                                //declaration that is extracted.  This will also allow for the structure's total data size to be properly calculated.
                                aryFields[i].DataSize = 0;
                            }

                            if (blBitDetected)
                            {
                                aryFields[i].Bits = iFieldBits;
                            }
                        }//next strFieldName

                        foreach (FieldData fdField in aryFields)
                        {
                            fdField.FieldIndex = iCurFieldIndex;
                            iCurFieldIndex++;

                            fdField.FieldKey   = strStructName + "_" + fdField.FieldIndex;
                            fdField.ParentName = strStructName;

                            fdField.FieldType     = fdFieldSchema.FieldType;
                            fdField.FieldTypeName = fdFieldSchema.FieldTypeName;

                            fdField.FieldByteOffset = iFieldByteOffset;

                            //Field byte offsets will only be incremented during the extraction of fields if the fields are being extracted from a structure.  If a union
                            //block is having its fields, extracted, the byte offset of all fields will be the same (all fields occupy shared memory space within a union)
                            //and the field byte offset variable will be incremented only after the entire union's data is extracted.
                            if (structOrUnion == StructUnionEnum.Structure)
                            {
                                //Field byte offsets will only be advanced if the field being extracted is not part of a bit declaration.  Byte offsets will
                                //be the same for each bit declaration and each declared bit variable will be treated as a single field of its associated
                                //data type.
                                if (!blBitDetected)
                                {
                                    //Advances byte offset position in structure to next field after the total bytes of the current field are calculated.
                                    iFieldByteOffset += fdField.DataSize;
                                }
                            } //end if
                        }     //next fdField
                    }
                    else
                    {
                        //If the current field being extracted in the structure is a pointer to a function, then the function field will be extracted
                        //as a pointer.   In addition, to being identified as a pointer field, the function will have a field name set to the
                        //word "Function" concatenated with the index of the function field in the structure.  This way the function
                        //field can be identified in the structure.  All additional settings of the function, such as field type name will have been
                        //set previously in the code.
                        fdFieldSchema.FieldIndex = iCurFieldIndex;
                        iCurFieldIndex++;

                        fdFieldSchema.FieldName = "Function" + "_" + fdFieldSchema.FieldIndex.ToString();
                        fdFieldSchema.FieldKey  = strStructName + "_" + fdFieldSchema.FieldIndex.ToString();

                        fdFieldSchema.ParentName = strStructName;

                        fdFieldSchema.FieldByteOffset = iFieldByteOffset;

                        //Field byte offsets will only be incremented during the extraction of fields if the fields are being extracted from a structure.  If a union
                        //block is having its fields, extracted, the byte offset of all fields will be the same (all fields occupy shared memory space within a union)
                        //and the field byte offset variable will be incremented only after the entire union's data is extracted.
                        if (structOrUnion == StructUnionEnum.Structure)
                        {
                            //Advances byte offset position in structure to next field after the total bytes of the current field are calculated.
                            iFieldByteOffset += fdFieldSchema.DataSize;
                        }//end if

                        aryFields = new FieldData[] { fdFieldSchema };
                    }//end if

                    //Advances the cursor of the structure to the end of the current field data that was extracted and to the beginning of the
                    //next set of field data to be extracted or to the end of the structure, if it has been reached.
                    iCurPos = iFieldEndPos + 1;
                }
                else
                {
                    string strNestedStruct       = "";
                    int[]  aryNestedBlockIndexes = ParserUtils.GetBlockIndexes(ref strStruct, iCurPos);

                    if (aryNestedBlockIndexes == null)
                    {
                        return(null);
                    }

                    int iEndNestStructIndex = strStruct.IndexOf(';', aryNestedBlockIndexes[1]);
                    strNestedStruct = strStruct.Substring(iCurPos, iEndNestStructIndex + 1 - iCurPos);

                    StructData sdChild = ExtractStructData(strNestedStruct);

                    if (sdChild == null)
                    {
                        return(null);
                    }

                    FieldData fdField = new FieldData();
                    fdField.FieldType     = FieldTypeEnum.Structure;
                    fdField.FieldTypeName = sdChild.StructName;
                    fdField.FieldName     = sdChild.StructName;

                    if (fdField.FieldName.Trim() == "")
                    {
                        //If a nested structure or union is unnamed, then a field type name of "struct" or "union" will be set as the field type
                        //name of the field.
                        if (sdChild.StructUnion == StructUnionEnum.Structure)
                        {
                            fdField.FieldTypeName = "struct";
                        }
                        else
                        {
                            fdField.FieldTypeName = "union";
                        }

                        //If a nested structure or union is unnamed, then a generated field name of "Structure" or "Union" concatenated
                        //with the field index will be set as the name of the field in the structure.
                        if (sdChild.StructUnion == StructUnionEnum.Structure)
                        {
                            fdField.FieldName = "Structure_" + iCurFieldIndex.ToString();
                        }
                        else
                        {
                            fdField.FieldName = "Union_" + iCurFieldIndex.ToString();
                        }
                    }
                    else
                    {
                        //Since there will be no way of identifying if nested structures/unions contained within structures and unions are either
                        //a structure or union type (as of the current version), it will be neccessary to concatenate to the name of the
                        //field, whether it is a nested structure or union.
                        if (sdChild.StructUnion == StructUnionEnum.Structure)
                        {
                            fdField.FieldName += " <struct>";
                        }
                        else
                        {
                            fdField.FieldName += " <union>";
                        }
                    }//end if

                    fdField.Elements = sdChild.Elements;
                    fdField.DataSize = sdChild.DataSize;

                    fdField.FieldIndex = iCurFieldIndex;
                    iCurFieldIndex++;

                    fdField.FieldKey   = strStructName + "_" + fdField.FieldIndex;
                    fdField.ParentName = strStructName;

                    fdField.FieldByteOffset = iFieldByteOffset;

                    //Field byte offsets will only be incremented during the extraction of fields if the fields are being extracted from a structure.  If a union
                    //block is having its fields, extracted, the byte offset of all fields will be the same (all fields occupy shared memory space within a union)
                    //and the field byte offset variable will be incremented only after the entire union's data is extracted.
                    if (structOrUnion == StructUnionEnum.Structure)
                    {
                        //Advances byte offset position in structure to next field after the total bytes of the current field are calculated.
                        iFieldByteOffset += fdField.DataSize;
                    }//end if

                    aryFields = new FieldData[] { fdField };

                    //Advances the cursor of the structure to the end of the current field data that was extracted and to the beginning of the
                    //next set of field data to be extracted or to the end of the structure, if it has been reached.
                    iCurPos = iEndNestStructIndex + 1;
                }//end if

                return(aryFields);
            }
            catch (Exception err)
            {
                ErrorHandler.ShowErrorMessage(err, "Error in ExtractStructFieldData function of StructExtractor class.");
                return(null);
            }
        }