/*! * @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; }