- still WIP for parsing of parameter
- new blockdetection and -removal functions (used for comments and function bodies)
This commit is contained in:
@@ -22,8 +22,16 @@
|
|||||||
|
|
||||||
#define CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS 10
|
#define CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS 10
|
||||||
|
|
||||||
|
/*! @brief Block detection return values */
|
||||||
|
typedef enum _CFILE_BLOCK_RETURN_T
|
||||||
|
{
|
||||||
|
CFILE_BLOCK_DETECT_ERROR = -1, /*!< @brief description */
|
||||||
|
CFILE_BLOCK_DETECT_NONE = 0, /*!< @brief description */
|
||||||
|
CFILE_BLOCK_DETECT_START = 1, /*!< @brief description */
|
||||||
|
CFILE_BLOCK_DETECT_END = 2, /*!< @brief description */
|
||||||
|
} cfile_block_return_t;
|
||||||
|
|
||||||
STATIC bool cfile_parser_initialized = false;
|
STATIC bool cfile_parser_initialized = false;
|
||||||
STATIC bool blockComment = false;
|
|
||||||
STATIC uint8_t cfile_parser_functionLine = 0;
|
STATIC uint8_t cfile_parser_functionLine = 0;
|
||||||
STATIC cfunction_t *cfile_parser_function = NULL;
|
STATIC cfunction_t *cfile_parser_function = NULL;
|
||||||
STATIC regex_t regX;
|
STATIC regex_t regX;
|
||||||
@@ -82,6 +90,7 @@ int8_t cfile_parser_init()
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if(0)
|
||||||
STATIC void printMatchGroup(char *aString, regmatch_t *aMatchGroup)
|
STATIC void printMatchGroup(char *aString, regmatch_t *aMatchGroup)
|
||||||
{
|
{
|
||||||
char match[1024] =
|
char match[1024] =
|
||||||
@@ -99,6 +108,7 @@ STATIC void printMatchGroup(char *aString, regmatch_t *aMatchGroup)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
STATIC void checkFunctionType(cfunction_t *aFunction)
|
STATIC void checkFunctionType(cfunction_t *aFunction)
|
||||||
{
|
{
|
||||||
@@ -168,24 +178,226 @@ STATIC int8_t matchFunctionStart(cfunction_t *aFunction, char *aString, size_t a
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Find first given "start" or "end" string and return position
|
||||||
|
* @param [in] *aBlockStart Terminated string defining the start of a block
|
||||||
|
* @param [in] *aBlockEnd Terminated string defining the end of a block
|
||||||
|
* @param [in] *aLine Terminated line (e.g. read from a file getline())
|
||||||
|
* @param [out] **aPosition Pointing to found block string (realted to \ref aRemove) / NULL for CFILE_BLOCK_DETECT_NONE or CFILE_BLOCK_DETECT_ERROR
|
||||||
|
* @param [in] aRemove false - remove only content of block; true - also remove block strings
|
||||||
|
* @return cfile_block_return_t
|
||||||
|
* @retval CFILE_BLOCK_DETECT_START Start found
|
||||||
|
* @retval CFILE_BLOCK_DETECT_END End found
|
||||||
|
* @retval CFILE_BLOCK_DETECT_NONE No start or end found
|
||||||
|
* @retval CFILE_BLOCK_DETECT_ERROR Null pointer detected
|
||||||
|
*/
|
||||||
|
STATIC cfile_block_return_t cBlockDetection(const char *aBlockStart, const char *aBlockEnd, char *aLine, char **aPosition, bool aRemove)
|
||||||
|
{
|
||||||
|
char *blockStart = NULL;
|
||||||
|
char *blockEnd = NULL;
|
||||||
|
cfile_block_return_t ret = CFILE_BLOCK_DETECT_NONE;
|
||||||
|
|
||||||
|
if ( NULL == aBlockStart || NULL == aBlockEnd || NULL == aLine || NULL == aPosition)
|
||||||
|
{
|
||||||
|
perror("Null pointer");
|
||||||
|
return CFILE_BLOCK_DETECT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockStart = strstr(aLine, aBlockStart);
|
||||||
|
blockEnd = strstr(aLine, aBlockEnd);
|
||||||
|
|
||||||
|
if (NULL == blockStart && NULL == blockEnd)
|
||||||
|
{
|
||||||
|
// no block element
|
||||||
|
ret = CFILE_BLOCK_DETECT_NONE;
|
||||||
|
}
|
||||||
|
else if (NULL == blockStart)
|
||||||
|
{
|
||||||
|
// last line of block
|
||||||
|
ret = CFILE_BLOCK_DETECT_END;
|
||||||
|
}
|
||||||
|
else if (NULL == blockEnd)
|
||||||
|
{
|
||||||
|
// first line of block
|
||||||
|
|
||||||
|
ret = CFILE_BLOCK_DETECT_START;
|
||||||
|
}
|
||||||
|
else if (blockStart < blockEnd)
|
||||||
|
{
|
||||||
|
// inline block
|
||||||
|
ret = CFILE_BLOCK_DETECT_START;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// last line of multi line block with further blocks in line
|
||||||
|
ret = CFILE_BLOCK_DETECT_END;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (ret)
|
||||||
|
{
|
||||||
|
case CFILE_BLOCK_DETECT_START:
|
||||||
|
{
|
||||||
|
*aPosition = (aRemove ? blockStart : blockStart + strlen(aBlockStart));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CFILE_BLOCK_DETECT_END:
|
||||||
|
{
|
||||||
|
*aPosition = (aRemove ? blockEnd + strlen(aBlockEnd) : blockEnd);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CFILE_BLOCK_DETECT_NONE:
|
||||||
|
{
|
||||||
|
*aPosition = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
ret = CFILE_BLOCK_DETECT_ERROR;
|
||||||
|
*aPosition = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Remove blocks defined by "start" and "end"
|
||||||
|
* @attention May be called multiple time (for a whole file). *aHelper must not be changed within the process.
|
||||||
|
* @param [in] *aLine Terminated line (e.g. read from a file getline())
|
||||||
|
* @param [in] *aBlockStart Terminated string defining the start of a block
|
||||||
|
* @param [in] *aBlockEnd Terminated string defining the end of a block
|
||||||
|
* @param [in,out] *aHelper Storage for block traversal
|
||||||
|
* @param [in] aRemove false - remove only content of block; true - also remove block strings
|
||||||
|
* @retval 0 Blocks removed or none found
|
||||||
|
* @retval 1 Line only within block
|
||||||
|
* @retval -1 Invalid block ending ("end" without corresponding "start")
|
||||||
|
* @retval -2 Null pointer detected
|
||||||
|
*/
|
||||||
|
STATIC int8_t cBlockRemoval(char *aLine, const char *aBlockStart, const char *aBlockEnd, uint32_t *aHelper, bool aRemove)
|
||||||
|
{
|
||||||
|
const uint8_t depth = 1; // preparation to support which depth should be removed for nested block
|
||||||
|
bool blockLine = false;
|
||||||
|
int8_t ret = -1;
|
||||||
|
bool whileRun = true;
|
||||||
|
char *blockWorker = NULL;
|
||||||
|
char *blockMatch = NULL;
|
||||||
|
char *blockStart = NULL;
|
||||||
|
cfile_block_return_t blockDetected = CFILE_BLOCK_DETECT_NONE;
|
||||||
|
|
||||||
|
if (NULL == aLine || NULL == aBlockStart || NULL == aBlockEnd || NULL == aHelper)
|
||||||
|
{
|
||||||
|
perror("Null pointer");
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockWorker = aLine;
|
||||||
|
if (depth <= *aHelper)
|
||||||
|
{
|
||||||
|
blockStart = aLine;
|
||||||
|
blockLine = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (whileRun && CFILE_BLOCK_DETECT_NONE <= (blockDetected = cBlockDetection(aBlockStart, aBlockEnd, blockWorker, &blockMatch, aRemove)))
|
||||||
|
{
|
||||||
|
switch (blockDetected)
|
||||||
|
{
|
||||||
|
case CFILE_BLOCK_DETECT_START:
|
||||||
|
{
|
||||||
|
++*aHelper;
|
||||||
|
if (NULL == blockStart && depth <= *aHelper)
|
||||||
|
{
|
||||||
|
blockStart = blockMatch;
|
||||||
|
}
|
||||||
|
blockWorker = (aRemove ? blockMatch + strlen(aBlockStart) : blockMatch);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CFILE_BLOCK_DETECT_END:
|
||||||
|
{
|
||||||
|
if (NULL != blockStart)
|
||||||
|
{
|
||||||
|
// inline comment
|
||||||
|
if (depth < *aHelper)
|
||||||
|
{
|
||||||
|
// remove block elements within depth + n
|
||||||
|
blockMatch += (aRemove ? 0 : strlen(aBlockEnd));
|
||||||
|
}
|
||||||
|
strlcpy(blockStart, blockMatch, strlen(blockMatch) + 1);
|
||||||
|
blockMatch = NULL;
|
||||||
|
if (depth >= *aHelper)
|
||||||
|
{
|
||||||
|
// block removed when last end is hit
|
||||||
|
blockWorker = (aRemove ? blockStart : blockStart + strlen(aBlockEnd));
|
||||||
|
blockStart = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
blockWorker = blockStart;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (depth == *aHelper)
|
||||||
|
{
|
||||||
|
blockLine = false;
|
||||||
|
}
|
||||||
|
if (0 < *aHelper)
|
||||||
|
{
|
||||||
|
--*aHelper;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// error closing brace without beginning
|
||||||
|
whileRun = false;
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CFILE_BLOCK_DETECT_NONE:
|
||||||
|
{
|
||||||
|
if (NULL != blockStart && depth <= *aHelper)
|
||||||
|
{
|
||||||
|
// lines within a block
|
||||||
|
strlcpy(blockStart, CPARS_LINE_ENDING, strlen(CPARS_LINE_ENDING) + 1);
|
||||||
|
}
|
||||||
|
whileRun = false;
|
||||||
|
if (blockLine)
|
||||||
|
{
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
perror("Fatal unknown case");
|
||||||
|
whileRun = false;
|
||||||
|
ret = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Remove comments from given line
|
* @brief Remove comments from given line
|
||||||
* @param [in] *aLine terminated string
|
* @param [in] *aLine terminated string
|
||||||
* @param [out] param1 paramdescription1
|
* @return see \ref cBlockRemoval()
|
||||||
* @retval 0 comments removed
|
* @retval -2 NULL pointer detected
|
||||||
* @retval 1 line within block comment (no c evaluation needed)
|
|
||||||
* @retval -1 NULL pointer detected
|
|
||||||
*/
|
*/
|
||||||
int8_t removeComments(char *aLine)
|
STATIC int8_t removeCcomments(char *aLine)
|
||||||
{
|
{
|
||||||
bool emptyLine = false;
|
static uint32_t helper = 0;
|
||||||
char *comment = NULL;
|
char *comment = NULL;
|
||||||
char *commentEnd = NULL;
|
|
||||||
|
|
||||||
if (NULL == aLine)
|
if (NULL == aLine)
|
||||||
{
|
{
|
||||||
perror("Null pointer");
|
perror("Null pointer");
|
||||||
return -1;
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove basic inline comments
|
// remove basic inline comments
|
||||||
@@ -196,54 +408,30 @@ int8_t removeComments(char *aLine)
|
|||||||
comment = NULL;
|
comment = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove block comments (also across multiple lines)
|
return cBlockRemoval(aLine, CPARS_COMMENT_BLOCK_START, CPARS_COMMENT_BLOCK_END, &helper, true);
|
||||||
if (blockComment)
|
|
||||||
{
|
|
||||||
emptyLine = true;
|
|
||||||
comment = aLine;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
comment = strstr(aLine, CPARS_COMMENT_BLOCK_START);
|
|
||||||
}
|
|
||||||
while (comment)
|
|
||||||
{
|
|
||||||
commentEnd = strstr(comment, CPARS_COMMENT_BLOCK_END);
|
|
||||||
if (NULL != commentEnd)
|
|
||||||
{
|
|
||||||
// copy character without block comment ending (strlen(CPARS_COMMENT_BLOCK_END))
|
|
||||||
strlcpy(comment, commentEnd + strlen(CPARS_COMMENT_BLOCK_END), strlen(commentEnd + strlen(CPARS_COMMENT_BLOCK_END)) + 1);
|
|
||||||
comment = strstr(aLine, "/*");
|
|
||||||
blockComment = false;
|
|
||||||
emptyLine = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
strlcpy(comment, CPARS_LINE_ENDING, strlen(CPARS_LINE_ENDING) + 1);
|
|
||||||
blockComment = true;
|
|
||||||
comment = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (int8_t) emptyLine;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Process a string (e.g. from getline()) if it is a single or multiple line function definition
|
* @brief Process a string (e.g. from getline()) if it is a single or multiple line function definition
|
||||||
* @todo closing parenthesis within parameter list will break the detection
|
* @todo closing parenthesis within parameter list will break the detection
|
||||||
* @retval -1 Invalid regula expressions
|
* @retval -1 Invalid regular expressions
|
||||||
* @retval -2 Given String not a function
|
* @retval -2 Given String not a function
|
||||||
* @retval 0 function evaluated
|
* @retval 0 function evaluated
|
||||||
*/
|
*/
|
||||||
STATIC cfunction_t* cfile_parser_evaluateLine(char *aLine)
|
STATIC cfunction_t* cfile_parser_evaluateLine(char *aLine)
|
||||||
{
|
{
|
||||||
|
static uint32_t braceHelper = 0;
|
||||||
const size_t maxGroup = CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS;
|
const size_t maxGroup = CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS;
|
||||||
regmatch_t matchGroup[maxGroup];
|
regmatch_t matchGroup[maxGroup];
|
||||||
bool functionEnd = false;
|
bool functionEnd = false;
|
||||||
cfunction_type_t tempFunctionType = CFUNCTION_TYPE_UNDEF;
|
cfunction_type_t tempFunctionType = CFUNCTION_TYPE_UNDEF;
|
||||||
cfunction_parameter_t *tempParameter = NULL;
|
cfunction_parameter_t *tempParameter = NULL;
|
||||||
|
|
||||||
if (0 != removeComments(aLine))
|
if (0 != removeCcomments(aLine))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (0 != cBlockRemoval(aLine, "{", "}", &braceHelper, false))
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -349,7 +537,6 @@ STATIC cfunction_t* cfile_parser_evaluateLine(char *aLine)
|
|||||||
}
|
}
|
||||||
if (functionEnd)
|
if (functionEnd)
|
||||||
{
|
{
|
||||||
// TODO clean function
|
|
||||||
if (CFUNCTION_TYPE_UNDEF == tempFunctionType)
|
if (CFUNCTION_TYPE_UNDEF == tempFunctionType)
|
||||||
{
|
{
|
||||||
cfunction_freeFunction(&cfile_parser_function);
|
cfunction_freeFunction(&cfile_parser_function);
|
||||||
|
Reference in New Issue
Block a user