diff --git a/src/stubser/cfile_parser.c b/src/stubser/cfile_parser.c index fef509d..09089e0 100644 --- a/src/stubser/cfile_parser.c +++ b/src/stubser/cfile_parser.c @@ -43,7 +43,6 @@ STATIC regex_t regXExpressionEnd; // line evaluation related variables STATIC uint32_t cfile_parser_removeCommentHelper = 0; STATIC uint32_t cfile_parser_removeBraceHelper = 0; -STATIC char *cfile_parser_parameterStorage = NULL; int8_t cfile_parser_init() { @@ -367,7 +366,7 @@ STATIC int8_t cBlockRemoval(char *aLine, const char *aBlockStart, const char *aB } else { - printf("[WARN] Nested block start (see file below): %s", aLine); + printf(CPARS_WARNING_START"Nested block start \"%s\": %s", aBlockStart, aLine); } blockWorker = (aRemove ? blockMatch + strlen(aBlockStart) : blockMatch); break; @@ -556,17 +555,49 @@ STATIC int8_t cfile_parser_evaluateExpression(char *aExpression, cfile_t *aCfile return 0; } -STATIC int8_t cfile_parser_evaluateLine(uint32_t aNumber, char *aLine, cfile_t *aCfile) +STATIC uint32_t cfile_parser_evaluateLine(uint32_t aNumber, char *aLine, cfile_t *aCfile) { char *position = aLine; - int8_t result = 0; + uint32_t warnings = 0; static char *match = NULL; static uint8_t depth = 0; char *tempMatch = NULL; + char *tempChar = NULL; + int8_t ret = 0; regex_t *matchStart = ®XExpressionStart; regex_t *matchEnd = ®XExpressionEnd; + ret = removeCcomments(aLine); + if (-1 == ret) + { + ++warnings; + } + else if (0 != ret) + { + return 0; + } + ret = cBlockRemoval(aLine, "{", "}", &cfile_parser_removeBraceHelper, false, false); + if (-1 == ret) + { + ++warnings; + } + else if (0 != ret) + { + return 0; + } + DEBUG_LOG_APPEND(2, "[ Li %04u] %s", aNumber, aLine); + tempChar = strrchr(aLine, '\n'); + if (tempChar) + { + *tempChar = '\0'; + } + tempChar = strrchr(aLine, '\r'); + if (tempChar) + { + *tempChar = '\0'; + } + while (position) { if (NULL != (tempMatch = strstr(position, "#include"))) @@ -576,35 +607,26 @@ STATIC int8_t cfile_parser_evaluateLine(uint32_t aNumber, char *aLine, cfile_t * position = NULL; continue; } - result = regExWorker(&match, &position, matchStart, matchEnd, &depth, false); - if (match && 0 == result && 0 == depth) + warnings += regExWorker(&match, &position, matchStart, matchEnd, &depth, false); + if (match && 0 == depth) { DEBUG_LOG_APPEND(1, "[ Re %04u][%zu] %s\n", aNumber, strlen(match), match); // Evaluate C expression (void) cfile_parser_evaluateExpression(match, aCfile); xfree((void**) &match); } - if (0 > result) - { - if (-2 == result) - DEBUG_LOG_APPEND(2, "[ PEr]"); - position = NULL; - xfree((void**) &match); - } } - return 0; + return warnings; } -int8_t cfile_parser(char *aPath, cfile_t *aCfile) +uint32_t cfile_parser(char *aPath, cfile_t *aCfile) { FILE *fdesc; ssize_t charRead = 0; size_t lineSize = 0; uint32_t lineNumber = 0; - char *cTemp = NULL; char *fileLine = NULL; // will be allocated by getline(); must be freed - int8_t ret = 0; - uint8_t warningCounter = 0; + uint32_t warningCounter = 0; if (false == cfile_parser_initialized) { @@ -624,36 +646,7 @@ int8_t cfile_parser(char *aPath, cfile_t *aCfile) if (0 <= charRead) { lineNumber++; - ret = removeCcomments(fileLine); - if (-1 == ret) - { - ++warningCounter; - } - else if (0 != ret) - { - continue; - } - ret = cBlockRemoval(fileLine, "{", "}", &cfile_parser_removeBraceHelper, false, false); - if (-1 == ret) - { - ++warningCounter; - } - else if (0 != ret) - { - continue; - } - DEBUG_LOG_APPEND(2, "[ Li %04u] %s", lineNumber, fileLine); - cTemp = strrchr(fileLine, '\n'); - if (cTemp) - { - *cTemp = '\0'; - } - cTemp = strrchr(fileLine, '\r'); - if (cTemp) - { - *cTemp = '\0'; - } - (void) cfile_parser_evaluateLine(lineNumber, fileLine, aCfile); + warningCounter += cfile_parser_evaluateLine(lineNumber, fileLine, aCfile); } } while (0 <= charRead); @@ -663,26 +656,16 @@ int8_t cfile_parser(char *aPath, cfile_t *aCfile) // error detection for block removal if (0 != cfile_parser_removeCommentHelper || 0 != cfile_parser_removeBraceHelper) { - DEBUG_LOG_APPEND(1, "Helper (%d/%d) %s %s\n", cfile_parser_removeCommentHelper, cfile_parser_removeBraceHelper, gnu_basename(aPath), - cfile_parser_parameterStorage); + DEBUG_LOG_APPEND(1, "Helper (%d/%d) %s\n", cfile_parser_removeCommentHelper, cfile_parser_removeBraceHelper, gnu_basename(aPath)); cfile_parser_removeCommentHelper = 0; cfile_parser_removeBraceHelper = 0; - ret = -2; + ++warningCounter; } - // error detection for function parameter detection - if (NULL != cfile_parser_parameterStorage) - { - DEBUG_LOG_APPEND(1, "Function parameter not free: %s\n", cfile_parser_parameterStorage); - free(cfile_parser_parameterStorage); - cfile_parser_parameterStorage = NULL; - ret = -3; - } +// if (warningCounter) +// { +// ret = -4; +// } - if (warningCounter && 0 <= ret) - { - ret = -4; - } - - return ret; + return warningCounter; } diff --git a/src/stubser/cfile_parser_if.h b/src/stubser/cfile_parser_if.h index 4dcfb18..a74bbed 100644 --- a/src/stubser/cfile_parser_if.h +++ b/src/stubser/cfile_parser_if.h @@ -14,6 +14,6 @@ #ifndef STUBSER_CFILE_PARSER_IF_H_ #define STUBSER_CFILE_PARSER_IF_H_ -int8_t cfile_parser(char *aPath, cfile_t *aList); +uint32_t cfile_parser(char *aPath, cfile_t *aList); #endif /* STUBSER_CFILE_PARSER_IF_H_ */ diff --git a/src/stubser/cfile_parser_loc.h b/src/stubser/cfile_parser_loc.h index 2dfafd2..533b673 100644 --- a/src/stubser/cfile_parser_loc.h +++ b/src/stubser/cfile_parser_loc.h @@ -36,6 +36,8 @@ #define CPARS_EXPRESSION_START "^[[:blank:]]*([A-Za-z\\_][\\_\\*[:alnum:]]*)" #define CPARS_EXPRESSION_END "[[:blank:]]*([\\};]+)" +#define CPARS_WARNING_START " W-> " + #define CFILE_PARSER_IS_MATCHGROUP_FUNCTION(matchGroup) (XREGEX_IS_MATCHGROUP(matchGroup, 1) && XREGEX_IS_MATCHGROUP(matchGroup, 2)) /*! @brief Type of function definition */ diff --git a/src/stubser/cfile_parser_worker.c b/src/stubser/cfile_parser_worker.c index 1f40c9f..da8bb72 100644 --- a/src/stubser/cfile_parser_worker.c +++ b/src/stubser/cfile_parser_worker.c @@ -20,32 +20,34 @@ /*! * @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 0 parsing done (aBlockDepth = 0) or in progress (aBlockDepth > 0) - * @retval -1 parsing ended without result - * @retval -2 parsing error (end without start) + * @retval uint32_t amount of warnings during parser run + * + * @details + * - Parsing done when (match && 0 == aBlockDepth) + * - Orphan end markers are ignored and skipped. */ -int8_t regExWorker(char **aOutput, char **aInput, const regex_t *aStart, const regex_t *aEnd, uint8_t *aBlockDepth, bool aMultiLevel) +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; - int8_t ret = -1; if (!**aInput || NULL == *aInput) { if (*aBlockDepth) { xmallocStrlcat(aOutput, " ", 2); - ret = 0; - } - else - { - ret = -1; } *aInput = NULL; goto regExWorker_end; @@ -76,8 +78,8 @@ int8_t regExWorker(char **aOutput, char **aInput, const regex_t *aStart, const r size = strlen(*aInput); if (!match) { + // complete line within block *aInput += strlen(*aInput); - ret = 0; goto regExWorker_end; } } @@ -87,12 +89,12 @@ int8_t regExWorker(char **aOutput, char **aInput, const regex_t *aStart, const r // no findings if (!match) { - ret = -1; + // skip remaining character within line without match + *aInput += strlen(*aInput); goto regExWorker_end; } } - // start && aDepth > 0 -> ignore if (match == matchStart) { if ((*aBlockDepth && aMultiLevel) || 0 == *aBlockDepth) @@ -100,8 +102,8 @@ int8_t regExWorker(char **aOutput, char **aInput, const regex_t *aStart, const r DEBUG_LOG_APPEND(2, "[ CEs]"); ++*aBlockDepth; size = XREGEX_SIZEOF_MATCHGROUP(match, 1); - //begin = *aInput + match[1].rm_eo; // don't include end marker in result - begin = *aInput + match[1].rm_so; // include end marker in result + //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 @@ -110,19 +112,28 @@ int8_t regExWorker(char **aOutput, char **aInput, const regex_t *aStart, const r size = match->rm_eo; *aInput += match->rm_eo; } - ret = 0; goto regExWorker_end; } if (match == matchEnd) { DEBUG_LOG_APPEND(2, "[ CEe]"); - if (0 < *aBlockDepth) - --*aBlockDepth; //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; - ret = 0; + 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; } @@ -133,9 +144,9 @@ int8_t regExWorker(char **aOutput, char **aInput, const regex_t *aStart, const r xmallocStrlcat(aOutput, begin, size); if (*aBlockDepth) { - (void) regExWorker(aOutput, aInput, aStart, aEnd, aBlockDepth, aMultiLevel); + warningCounter += regExWorker(aOutput, aInput, aStart, aEnd, aBlockDepth, aMultiLevel); } } - return ret; + return warningCounter; } diff --git a/src/stubser/cfile_parser_worker_loc.h b/src/stubser/cfile_parser_worker_loc.h index 0039580..c3ba073 100644 --- a/src/stubser/cfile_parser_worker_loc.h +++ b/src/stubser/cfile_parser_worker_loc.h @@ -14,6 +14,6 @@ #ifndef STUBSER_CFILE_PARSER_WORKER_LOC_H_ #define STUBSER_CFILE_PARSER_WORKER_LOC_H_ -int8_t regExWorker(char **aOutput, char **aInput, const regex_t *aStart, const regex_t *aEnd, uint8_t *aBlockDepth, bool aMultiLevel); +uint32_t regExWorker(char **aOutput, char **aInput, const regex_t *aStart, const regex_t *aEnd, uint8_t *aBlockDepth, bool aMultiLevel); #endif /* STUBSER_CFILE_PARSER_WORKER_LOC_H_ */ diff --git a/src/stubser/stubser.c b/src/stubser/stubser.c index d9b5c46..dc8584a 100644 --- a/src/stubser/stubser.c +++ b/src/stubser/stubser.c @@ -446,34 +446,33 @@ int stubser_createStub(char *path, char* aNoSuffix, char *aOutput) int8_t ret = -1; cfile_t cFile = CFILE_T_DEFAULT; + uint32_t warnings = 0; char fileName[PATH_MAX] = { '\0' }; - ret = cfile_parser(path, &cFile); +#if isDebugLevel(1) + printf(STUB_CONSOLE_PARSE_RUN_S1, path); +#else + printf(STUB_CONSOLE_PARSE_RUN_S1, gnu_basename(path)); +#endif + warnings = cfile_parser(path, &cFile); DEBUG_LOG_APPEND(1, "\n"); - if (0 != ret) + if (0 != warnings) { #if isDebugLevel(1) - printf(STUB_CONSOLE_PARSE_ERROR_S2, path, ret); + printf(STUB_CONSOLE_PARSE_ERROR_S2, path, warnings); #else - printf(STUB_CONSOLE_PARSE_ERROR_S2, gnu_basename(path), ret); + printf(STUB_CONSOLE_PARSE_ERROR_S2, gnu_basename(path), warnings); #endif - if (-2 == ret) - { - printf(" Block removal error (likely nested comments).\n"); - } - else if (-3 == ret) - { - printf(" Function parameter detection error\n"); - } - ret = -1; - goto end_stubser_createStub; } + else + { #if isDebugLevel(1) - printf(STUB_CONSOLE_PARSE_OK_S1, path); + printf(STUB_CONSOLE_PARSE_OK_S1, path); #else - printf(STUB_CONSOLE_PARSE_OK_S1, gnu_basename(path)); + printf(STUB_CONSOLE_PARSE_OK_S1, gnu_basename(path)); #endif + } sprintf(fileName, "%s/stub_%s", aOutput, aNoSuffix); ret = createStub(fileName, aNoSuffix, &cFile); if (0 != ret) diff --git a/src/stubser/stubser_loc.h b/src/stubser/stubser_loc.h index 65096ea..2037700 100644 --- a/src/stubser/stubser_loc.h +++ b/src/stubser/stubser_loc.h @@ -44,10 +44,14 @@ #define STUBFUNCTION_CHECK_S1 "stub_%s_checkGlobals" // stub_testfunction_checkGlobals #define STUBVARIABLE_EXTENDED_S1 "%s_expected" // variable_expected +#define STUB_CONSOLE_GOBACK "\033[2K\r" +#define STUB_CONSOLE_RUN "[ ]" #define STUB_CONSOLE_OK "[ OK ]" +#define STUB_CONSOLE_WARN "[WARN]" #define STUB_CONSOLE_FAIL "[FAIL]" -#define STUB_CONSOLE_PARSE_ERROR_S2 STUB_CONSOLE_FAIL " %s parsing failed (%d)\n" -#define STUB_CONSOLE_PARSE_OK_S1 STUB_CONSOLE_OK " %s parsing..." -#define STUB_CONSOLE_CREATE_ERROR_S2 "fail\n"STUB_CONSOLE_FAIL " %s creation failed (%d)\n" -#define STUB_CONSOLE_CREATE_OK_S1 "ok > %s\n" +#define STUB_CONSOLE_PARSE_ERROR_S2 "\n" STUB_CONSOLE_WARN " %s parsing with %d warnings (check output manually)" +#define STUB_CONSOLE_PARSE_RUN_S1 STUB_CONSOLE_RUN " %s parsing..." +#define STUB_CONSOLE_PARSE_OK_S1 STUB_CONSOLE_GOBACK STUB_CONSOLE_OK " %s parsing..." +#define STUB_CONSOLE_CREATE_ERROR_S2 "...stub creation failed\n"STUB_CONSOLE_FAIL " %s creation failed (%d)\n" +#define STUB_CONSOLE_CREATE_OK_S1 "...stub created > %s\n" #endif /* STUBSER_STUBSER_LOC_H_ */