Files
stubser/src/stubser/cfile_parser_worker.c
2019-04-04 15:45:29 +02:00

153 lines
4.0 KiB
C

/*!
* @file cfile_parser_worker.c
* @brief
* @details
* Project: \n
* Subsystem: \n
* Module: \n
* Code: GNU-C\n
*
* @date 09.03.2017
* @author Martin Winkler
*/
#include "xtypes.h"
#include "xregex.h"
#include "xmalloc.h"
#include "debug.h"
#include "cfile_parser_loc.h"
#include "cfile_parser_worker_loc.h"
/*!
* @brief String block detection using regular expressions
* @attention Recursive function (calls itself to find block end on same line)
* @param [out] **aOutput Matched group content across multiple calls (will be allocated as needed)
* @param [in,out] **aInput Char pointer to search string (will be moved to position after match)
* @param [in] *aStart Regular expression defining block start
* @param [in] *aEnd Regular expression defining block end
* @param [out] *aBlockDepth Current depth of parsing
* @param [in] aMultiLevel false - starts within block are ignored
* @return Matched string and various information about the parsing
* @retval uint32_t amount of warnings during parser run
*
* @details
* - Parsing done when (match && 0 == aBlockDepth)
* - Orphan end markers are ignored and skipped.
*/
uint32_t regExWorker(char **aOutput, char **aInput, const regex_t *aStart, const regex_t *aEnd, uint8_t *aBlockDepth, bool aMultiLevel)
{
uint32_t warningCounter = 0;
regmatch_t matchStart[2];
regmatch_t matchEnd[2];
regmatch_t *match = NULL;
char *begin = NULL;
size_t size = 0;
if (!**aInput || NULL == *aInput)
{
if (*aBlockDepth)
{
xmallocStrlcat(aOutput, " ", 2);
}
*aInput = NULL;
goto regExWorker_end;
}
// start
if (0 == regexec(aStart, *aInput, 2, matchStart, REG_NOTEOL) && XREGEX_IS_MATCHGROUP(matchStart, 1))
{
match = matchStart;
}
// end < start
if (0 == regexec(aEnd, *aInput, 2, matchEnd, REG_NOTEOL) && XREGEX_IS_MATCHGROUP(matchEnd, 1))
{
if (match && match->rm_so > matchEnd[1].rm_so)
{
match = matchEnd;
}
else if (!match)
{
match = matchEnd;
}
}
if (*aBlockDepth)
{
begin = *aInput;
size = strlen(*aInput);
if (!match)
{
// complete line within block
*aInput += strlen(*aInput);
goto regExWorker_end;
}
}
else
{
begin = NULL;
// no findings
if (!match)
{
// skip remaining character within line without match
*aInput += strlen(*aInput);
goto regExWorker_end;
}
}
if (match == matchStart)
{
if ((*aBlockDepth && aMultiLevel) || 0 == *aBlockDepth)
{
DEBUG_LOG_APPEND(2, "[ CEs]");
++*aBlockDepth;
size = XREGEX_SIZEOF_MATCHGROUP(match, 1);
//begin = *aInput + match[1].rm_eo; // don't include start marker in result
begin = *aInput + match[1].rm_so; // include start marker in result
*aInput += match[1].rm_eo;
}
else
{
// ignore starts within block
size = match->rm_eo;
*aInput += match->rm_eo;
}
goto regExWorker_end;
}
if (match == matchEnd)
{
DEBUG_LOG_APPEND(2, "[ CEe]");
//size = match[1].rm_so; // don't include end marker in result
size = match[1].rm_eo; // include end marker in result
*aInput += match[1].rm_eo;
if (0 < *aBlockDepth)
{
--*aBlockDepth;
}
// TODO orphan end markers
// must be evaluated depending on expression
// e.g. array[]={}; -> must have } and ;
// function{} -> must not have ;
// else
// {
// // orphan end marker
// ++warningCounter;
// }
goto regExWorker_end;
}
regExWorker_end:
if (begin)
{
xmallocStrlcat(aOutput, begin, size);
if (*aBlockDepth)
{
warningCounter += regExWorker(aOutput, aInput, aStart, aEnd, aBlockDepth, aMultiLevel);
}
}
return warningCounter;
}