diff --git a/src/stubser/cfile_if.h b/src/stubser/cfile_if.h index 8e92154..dcfcdf3 100644 --- a/src/stubser/cfile_if.h +++ b/src/stubser/cfile_if.h @@ -16,13 +16,20 @@ #include "cfunction_if.h" -/*! @brief Type of function definition */ +#define CVARIABLE_CHECK_TYPE(var, type) (type == (var & type)) +#define CVARIABLE_SET_TYPE(var, type) do{\ + var &= ~type; \ + var |= type; \ + } while(0) + +/*! @brief Type of function definition for bit field usage */ typedef enum _CFILE_VARIABLE_TYPE_T { CVARIABLE_TYPE_UNDEF = 0, /*!< @brief undefined */ CVARIABLE_TYPE_REGULAR = 1, /*!< @brief Regular C function definition */ CVARIABLE_TYPE_STATIC = 2, /*!< @brief Static C function definition */ CVARIABLE_TYPE_EXTERN = 4, /*!< @brief External C function definition */ + CVARIABLE_TYPE_FUPTR = 8, /*!< @brief Function pointer as parameter */ CVARIABLE_TYPE_LAST_ENUM } cfile_variable_type_t; diff --git a/src/stubser/cfile_parser.c b/src/stubser/cfile_parser.c index c9b380c..6a8aceb 100644 --- a/src/stubser/cfile_parser.c +++ b/src/stubser/cfile_parser.c @@ -78,7 +78,7 @@ int8_t cfile_parser_init() perror("Error regex\n"); return -1; } - if (0 > regcomp(®XfunctionPointer, CPARS_REGEX_PARAMETER_FUPTR, (REG_EXTENDED))) + if (0 > regcomp(®XfunctionPointer, CPARS_REGEX_FUNCTIONPOINTER, (REG_EXTENDED))) { perror("Error regex\n"); return -1; @@ -207,7 +207,7 @@ STATIC int8_t matchPrefix(void *aElement, celement_type_t aElementType, char *aS if (CELEMENT_TYPE_VARIABLE == aElementType) { - ((cfunction_t*) aElement)->type = CFUNCTION_TYPE_REGULAR; + ((cfile_variable_t*) aElement)->type = CVARIABLE_TYPE_REGULAR; } if (0 == regexec(®Xprefix, temp, CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS, matchGroup, 0)) @@ -219,11 +219,11 @@ STATIC int8_t matchPrefix(void *aElement, celement_type_t aElementType, char *aS { if (*prefix && NULL != strstr(*prefix, CPARS_PREFIX_EXTERN_S)) { - ((cfunction_t*) aElement)->type = CFUNCTION_TYPE_EXTERN; + ((cfile_variable_t*) aElement)->type = CVARIABLE_TYPE_EXTERN; } else if (*prefix && (NULL != strstr(*prefix, CPARS_PREFIX_STATIC_S) || NULL != strstr(*prefix, CPARS_PREFIX_STATIC2_S))) { - ((cfunction_t*) aElement)->type = CFUNCTION_TYPE_STATIC; + ((cfile_variable_t*) aElement)->type = CVARIABLE_TYPE_STATIC; } } } @@ -534,6 +534,7 @@ STATIC int8_t evaluateParameter(char *aParameter, cfunction_t *aFunction) { if (0 == regexec(®XfunctionPointer, token, CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS, matchGroup, 0)) { + // TODO only "1 dimensional" function pointer supported (e.g. void (**func)(void) NOT SUPPORTED) (void) revertFunctionPointer(token); tempParameter = cfunction_newParameter(&aFunction->parameter); @@ -645,6 +646,26 @@ STATIC int8_t cfile_parser_evaluateExpression(char *aExpression, cfile_t *aCfile } } } + else if (0 == regexec(®XfunctionPointer, aExpression, CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS, matchGroup, 0) // + && XREGEX_IS_MATCHGROUP(matchGroup, 1) // + && XREGEX_IS_MATCHGROUP(matchGroup, 2) // + && XREGEX_IS_MATCHGROUP(matchGroup, 3)) + { + // TODO only "1 dimensional" function pointer supported (e.g. void (**func)(void) NOT SUPPORTED) + printMatchGroup(aExpression, matchGroup); + variable = cfile_newVariable(&aCfile->variables); + if (variable) + { + (void) matchPrefix(variable, CELEMENT_TYPE_VARIABLE, &aExpression[matchGroup[1].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 1)); + CVARIABLE_SET_TYPE(variable->type, CVARIABLE_TYPE_FUPTR); + xmallocStrlcpy(&variable->name, &aExpression[matchGroup[2].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 2)); + // contains array information if available "[10]" + if (XREGEX_IS_MATCHGROUP(matchGroup, 3)) + { + xmallocStrlcpy(&variable->array, &aExpression[matchGroup[3].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 3)); + } + } + } return 0; } diff --git a/src/stubser/cfile_parser_loc.h b/src/stubser/cfile_parser_loc.h index 58890ec..66d12c3 100644 --- a/src/stubser/cfile_parser_loc.h +++ b/src/stubser/cfile_parser_loc.h @@ -27,13 +27,13 @@ #define CPARS_PREFIX_EXTERN_S "extern" #define CPARS_EXPRESSION_BASE "^[[:blank:]]*([ _\\*[:alnum:]]* +\\**)([_\\*[:alnum:]]+)" +#define CPARS_REGEX_FUNCTIONPOINTER "^[[:blank:]]*([ _\\*[:alnum:]]* +\\**)\\(([_\\*[:alnum:]]+)\\)(\\([^\\)]*\\))" #define FUNCTION_BASE CPARS_EXPRESSION_BASE "[[:blank:]]*\\([[:blank:]]*" #define CPARS_REGEX_FUNCTION FUNCTION_BASE "(.*)\\)[[:blank:]\\{\\};]+[[:blank:]]*" #define CPARS_REGEX_VARIABLE CPARS_EXPRESSION_BASE "[[:blank:]]*(\\[*[^;=]*)[[:blank:]]*[;=]" #define CPARS_REGEX_PARAMETER CPARS_EXPRESSION_BASE "[[:blank:]]*(\\[*[^;=]*)" -#define CPARS_REGEX_PARAMETER_FUPTR "^[[:blank:]]*([ _\\*[:alnum:]]* +\\**)\\(([_\\*[:alnum:]]+)\\)(\\([^\\)]*\\))" -#define CPARS_REGEX_PARAMETER_FUPTR_SEPA "\\([^\\,)]*(,)" +#define CPARS_REGEX_PARAMETER_FUPTR_SEPA "\\([^\\,)]*(,)" // function pointer parameter separation #define CPARS_REGEX_PREFIX "("CPARS_PREFIX_EXTERN_S"|EXTERN|"CPARS_PREFIX_STATIC_S"|STATIC|volatile|near|far)[[:blank:]]*(.*)" #define CPARS_EXPRESSION_START "^[[:blank:]]*([A-Za-z\\_][\\_\\*[:alnum:]]*)" diff --git a/src/stubser/stubser.c b/src/stubser/stubser.c index d4e0908..1af90bc 100644 --- a/src/stubser/stubser.c +++ b/src/stubser/stubser.c @@ -58,6 +58,8 @@ STATIC bool isDatatypeStandard(char *aDataType) STATIC void createVariableSpecificInit(const char* aVariableTemplate, FILE *aFile, cfile_variable_t *aVariable) { + char *tempChar = NULL; + if (NULL != strstr(aVariable->dataType, "const")) { return; @@ -65,7 +67,23 @@ STATIC void createVariableSpecificInit(const char* aVariableTemplate, FILE *aFil if (NULL != strstr(aVariable->dataType, "*") || aVariable->array) { - if (aVariable->array) + if (CVARIABLE_CHECK_TYPE(aVariable->type, CVARIABLE_TYPE_FUPTR)) + { + // removing all "*" for function pointer initialization + tempChar = strrchr(aVariable->name, '*'); + if (NULL != tempChar) + { + ++tempChar; // skip last '*' + } + else + { + tempChar = aVariable->name; + } + fprintf(aFile, "\t"); + fprintf(aFile, aVariableTemplate, tempChar); + fprintf(aFile, " = NULL;" NEWLINES); + } + else if (aVariable->array) { fprintf(aFile, "\t(void) memset("); fprintf(aFile, aVariableTemplate, aVariable->name); @@ -95,6 +113,8 @@ STATIC void createVariableSpecificInit(const char* aVariableTemplate, FILE *aFil STATIC void createVariableSpecificCheck(FILE *aFile, cfile_variable_t *aVariable) { + char *tempChar = NULL; + if (NULL != strstr(aVariable->dataType, "const")) { return; @@ -102,24 +122,38 @@ STATIC void createVariableSpecificCheck(FILE *aFile, cfile_variable_t *aVariable if (NULL != strstr(aVariable->dataType, "*") || aVariable->array) { - if (aVariable->array) + if (CVARIABLE_CHECK_TYPE(aVariable->type, CVARIABLE_TYPE_FUPTR)) { - fprintf(aFile, "\tCU_ASSERT_MEMORY_CHECK(\"%s\", %s, "STUBVARIABLE_EXTENDED_S1", sizeof(%s));"NEWLINES, aVariable->name, aVariable->name, + // removing all "*" for function pointer ASSERTs + tempChar = strrchr(aVariable->name, '*'); + if (NULL != tempChar) + { + ++tempChar; // skip last '*' + } + else + { + tempChar = aVariable->name; + } + fprintf(aFile, "\tCU_ASSERT_PTR_EQUAL(%s, "STUBVARIABLE_EXPECTED_S1");"NEWLINES, tempChar, tempChar); + } + else if (aVariable->array && !CVARIABLE_CHECK_TYPE(aVariable->type, CVARIABLE_TYPE_FUPTR)) + { + fprintf(aFile, "\tCU_ASSERT_MEMORY_CHECK(\"%s\", %s, "STUBVARIABLE_EXPECTED_S1", sizeof(%s));"NEWLINES, aVariable->name, aVariable->name, aVariable->name, aVariable->name); } else { - fprintf(aFile, "\tCU_ASSERT_PTR_EQUAL(%s, "STUBVARIABLE_EXTENDED_S1");"NEWLINES, aVariable->name, aVariable->name); + fprintf(aFile, "\tCU_ASSERT_PTR_EQUAL(%s, "STUBVARIABLE_EXPECTED_S1");"NEWLINES, aVariable->name, aVariable->name); } } else if (isDatatypeStandard(aVariable->dataType)) { - fprintf(aFile, "\tCU_ASSERT_EQUAL(%s, "STUBVARIABLE_EXTENDED_S1");"NEWLINES, aVariable->name, aVariable->name); + fprintf(aFile, "\tCU_ASSERT_EQUAL(%s, "STUBVARIABLE_EXPECTED_S1");"NEWLINES, aVariable->name, aVariable->name); } else { - fprintf(aFile, "\tCU_ASSERT_MEMORY_CHECK(\"%s\", &%s, &"STUBVARIABLE_EXTENDED_S1", sizeof(%s));"NEWLINES, aVariable->name, aVariable->name, + fprintf(aFile, "\tCU_ASSERT_MEMORY_CHECK(\"%s\", &%s, &"STUBVARIABLE_EXPECTED_S1", sizeof(%s));"NEWLINES, aVariable->name, aVariable->name, aVariable->name, aVariable->name); } } @@ -173,13 +207,21 @@ STATIC int8_t createStubExpected(char *aNoSuffix, FILE *aFile, FILE *aHeader, cf work = aList->head; while (work) { - if (CVARIABLE_TYPE_REGULAR != work->type || NULL != strstr(work->dataType, "const")) + if (!CVARIABLE_CHECK_TYPE(work->type, CVARIABLE_TYPE_REGULAR) || NULL != strstr(work->dataType, "const")) { work = work->next; continue; } - fprintf(aFile, "%s "STUBVARIABLE_EXTENDED_S1"%s;"NEWLINES, work->dataType, work->name, (work->array ? work->array : "")); - fprintf(aHeader, "extern %s "STUBVARIABLE_EXTENDED_S1"%s;"NEWLINES, work->dataType, work->name, (work->array ? work->array : "")); + if (CVARIABLE_CHECK_TYPE(work->type, CVARIABLE_TYPE_FUPTR)) + { + fprintf(aFile, "%s ("STUBVARIABLE_EXPECTED_S1")%s;"NEWLINES, work->dataType, work->name, (work->array ? work->array : "")); + fprintf(aHeader, "extern %s ("STUBVARIABLE_EXPECTED_S1")%s;"NEWLINES, work->dataType, work->name, (work->array ? work->array : "")); + } + else + { + fprintf(aFile, "%s "STUBVARIABLE_EXPECTED_S1"%s;"NEWLINES, work->dataType, work->name, (work->array ? work->array : "")); + fprintf(aHeader, "extern %s "STUBVARIABLE_EXPECTED_S1"%s;"NEWLINES, work->dataType, work->name, (work->array ? work->array : "")); + } work = work->next; } @@ -189,12 +231,12 @@ STATIC int8_t createStubExpected(char *aNoSuffix, FILE *aFile, FILE *aHeader, cf work = aList->head; while (work) { - if (CVARIABLE_TYPE_REGULAR != work->type) + if (!CVARIABLE_CHECK_TYPE(work->type, CVARIABLE_TYPE_REGULAR)) { work = work->next; continue; } - createVariableSpecificInit(STUBVARIABLE_EXTENDED_S1, aFile, work); + createVariableSpecificInit(STUBVARIABLE_EXPECTED_S1, aFile, work); work = work->next; } @@ -219,13 +261,22 @@ STATIC int8_t createStubGlobals(char *aNoSuffix, FILE *aFile, FILE *aHeader, cfi work = aList->head; while (work) { - if (CVARIABLE_TYPE_REGULAR != work->type) + if (!CVARIABLE_CHECK_TYPE(work->type, CVARIABLE_TYPE_REGULAR)) { work = work->next; continue; } - fprintf(aFile, "%s %s%s;"NEWLINES, work->dataType, work->name, (work->array ? work->array : "")); - fprintf(aHeader, "extern %s %s%s;"NEWLINES, work->dataType, work->name, (work->array ? work->array : "")); + if (CVARIABLE_CHECK_TYPE(work->type, CVARIABLE_TYPE_FUPTR)) + { + fprintf(aFile, "%s (%s)%s;"NEWLINES, work->dataType, work->name, (work->array ? work->array : "")); + fprintf(aHeader, "extern %s (%s)%s;"NEWLINES, work->dataType, work->name, (work->array ? work->array : "")); + } + else + { + fprintf(aFile, "%s %s%s;"NEWLINES, work->dataType, work->name, (work->array ? work->array : "")); + fprintf(aHeader, "extern %s %s%s;"NEWLINES, work->dataType, work->name, (work->array ? work->array : "")); + } + work = work->next; } @@ -234,7 +285,7 @@ STATIC int8_t createStubGlobals(char *aNoSuffix, FILE *aFile, FILE *aHeader, cfi work = aList->head; while (work) { - if (CVARIABLE_TYPE_REGULAR != work->type) + if (!CVARIABLE_CHECK_TYPE(work->type, CVARIABLE_TYPE_REGULAR)) { work = work->next; continue; @@ -273,7 +324,7 @@ STATIC int8_t createStubCheck(char *aNoSuffix, FILE *aFile, FILE *aHeader, cfile work = aList->head; while (work) { - if (CVARIABLE_TYPE_REGULAR != work->type) + if (!CVARIABLE_CHECK_TYPE(work->type, CVARIABLE_TYPE_REGULAR)) { work = work->next; continue; diff --git a/src/stubser/stubser_loc.h b/src/stubser/stubser_loc.h index 457e49e..e591bc5 100644 --- a/src/stubser/stubser_loc.h +++ b/src/stubser/stubser_loc.h @@ -42,7 +42,7 @@ #define STUBFUNCTION_INITGLOBALS_S1 "stub_%s_initGlobals" // stub_testfunction_initGlobals #define STUBFUNCTION_INIT_S1 "stub_%s_init" // stub_testfunction_init #define STUBFUNCTION_CHECK_S1 "stub_%s_checkGlobals" // stub_testfunction_checkGlobals -#define STUBVARIABLE_EXTENDED_S1 "%s_expected" // variable_expected +#define STUBVARIABLE_EXPECTED_S1 "%s_expected" // variable_expected #define STUB_CONSOLE_GOBACK "\033[2K\r" #define STUB_CONSOLE_RUN "[ ]" @@ -55,5 +55,5 @@ #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" -#define STUB_REGEX_STD_DATATYPE "(^|[^_[:alnum:]])([ui]+nt[0-9]{1,2}_t|char|uchar|word[12346]{2}|int[12346]{2}|byte)([^_[:alnum:]]|$)" +#define STUB_REGEX_STD_DATATYPE "(^|[^_[:alnum:]])([ui]+nt[0-9]{1,2}_t|char|uchar|word[12346]{2}|int[12346]{0,2}|byte)([^_[:alnum:]]|$)" #endif /* STUBSER_STUBSER_LOC_H_ */