From 11d281fe751ee1653c3daf03109490610cdb9c50 Mon Sep 17 00:00:00 2001 From: Martin Winkler Date: Thu, 9 Mar 2017 08:04:29 +0000 Subject: [PATCH 02/38] WIP recursive line worker detects C variable and function definitions - todo: detect expressione type (function, variable, ...) --- src/ext/xmalloc.c | 6 ++ src/ext/xmalloc.h | 1 + src/stubser/cfile.c | 79 +++++++++++++++++++ src/stubser/cfile_if.h | 53 +++++++++++++ src/stubser/cfile_parser.c | 109 +++++++++++++++++++++++--- src/stubser/cfile_parser_if.h | 2 +- src/stubser/cfile_parser_loc.h | 19 ++++- src/stubser/cfile_parser_worker.c | 69 ++++++++++++++++ src/stubser/cfile_parser_worker_loc.h | 21 +++++ src/stubser/cfunction_if.h | 15 ++-- src/stubser/stubser.c | 18 ++--- 11 files changed, 365 insertions(+), 27 deletions(-) create mode 100644 src/stubser/cfile.c create mode 100644 src/stubser/cfile_if.h create mode 100644 src/stubser/cfile_parser_worker.c create mode 100644 src/stubser/cfile_parser_worker_loc.h diff --git a/src/ext/xmalloc.c b/src/ext/xmalloc.c index ea215dc..6ef87b1 100644 --- a/src/ext/xmalloc.c +++ b/src/ext/xmalloc.c @@ -71,3 +71,9 @@ char* xmallocStrlcat(char **aDest, char *aSource, size_t aSize) return *aDest; } +void xfree(void **aDest) +{ + free(*aDest); + *aDest = NULL; +} + diff --git a/src/ext/xmalloc.h b/src/ext/xmalloc.h index fe5e5c9..7a6653a 100644 --- a/src/ext/xmalloc.h +++ b/src/ext/xmalloc.h @@ -17,6 +17,7 @@ #include void *xmalloc(size_t size); +void xfree(void**); char* xmallocStrlcpy(char **aDest, char *aSource, size_t aSize); char* xmallocStrlcat(char **aDest, char *aSource, size_t aSize); diff --git a/src/stubser/cfile.c b/src/stubser/cfile.c new file mode 100644 index 0000000..e58dfab --- /dev/null +++ b/src/stubser/cfile.c @@ -0,0 +1,79 @@ +/*! + * @file cfile.c + * @brief + * @details + * Project: \n + * Subsystem: \n + * Module: \n + * Code: GNU-C\n + * + * @date 08.03.2017 + * @author SESA354004 + */ +#include +#include +#include "xtypes.h" +#include "xmalloc.h" +#include "cfile_if.h" + +cfile_variable_t* cfile_newVariable(cfile_variableList_t *aList) +{ + cfile_variable_t *new = NULL; + + if (NULL == aList) + { + perror("Null pointer"); + return NULL; + } + + new = (cfile_variable_t*) xmalloc(sizeof(cfile_variable_t)); + memset(new, 0, sizeof(cfile_variable_t)); + + if (NULL == aList->head) + { + aList->head = new; + aList->current = new; + } + else + { + aList->current->next = new; + aList->current = new; + } + ++aList->amount; + return new; +} + +int8_t cfile_freeVariables(cfile_variableList_t *aVariable) +{ + cfile_variable_t *work = NULL; + cfile_variable_t *next = NULL; + + if (NULL == aVariable) + { + perror("Null pointer"); + return -1; + } + + work = aVariable->head; + + while (work) + { + next = work->next; + free(work->type); + free(work->name); + free(work); + work = next; + } + + aVariable->amount = 0; + aVariable->head = NULL; + aVariable->current = NULL; + + return 0; +} + +void cfile_free(cfile_t *aCfile) +{ + cfile_freeVariables(&aCfile->variables); + cfunction_freeList(&aCfile->functions); +} diff --git a/src/stubser/cfile_if.h b/src/stubser/cfile_if.h new file mode 100644 index 0000000..fff067d --- /dev/null +++ b/src/stubser/cfile_if.h @@ -0,0 +1,53 @@ +/*! + * @file cfile_if.h + * @brief + * @details + * Project: \n + * Subsystem: \n + * Module: \n + * Code: GNU-C\n + * + * @date 08.03.2017 + * @author SESA354004 + */ + +#ifndef STUBSER_CFILE_IF_H_ +#define STUBSER_CFILE_IF_H_ + +#include "cfunction_if.h" + +/*! @brief Parameter list node */ +typedef struct _CFILE_VARIABLE_T +{ + char* prefix; /*!< @brief variable prefix (e.g. static) */ + char* type; /*!< @brief data type */ + char* name; /*!< @brief name */ + struct _CFILE_VARIABLE_T *next; +} cfile_variable_t; + +/*! @brief parameter array */ +typedef struct _CFILE_VARIABLE_LIST_T +{ + uint8_t amount; + cfile_variable_t *head; + cfile_variable_t *current; +} cfile_variableList_t; + +/*! @brief brief_description */ +typedef struct _CFILE_T +{ + cfile_variableList_t variables; /*! @brief C variables */ + cfunction_list_t functions; /*!< @brief C functions */ +} cfile_t; + +#define CFILE_T_DEFAULT {\ + .variables.amount = 0, \ + .variables.head = NULL, \ + .variables.current = NULL, \ + .functions = CFUNCTION_LIST_DEFAULT } + +cfile_variable_t* cfile_newVariable(cfile_variableList_t *aList); +int8_t cfile_freeVariables(cfile_variableList_t *aVariable); +void cfile_free(cfile_t *aCfile); + +#endif /* STUBSER_CFILE_IF_H_ */ diff --git a/src/stubser/cfile_parser.c b/src/stubser/cfile_parser.c index 2a3dbf0..7923294 100644 --- a/src/stubser/cfile_parser.c +++ b/src/stubser/cfile_parser.c @@ -17,12 +17,11 @@ #include "xtypes.h" #include "xstring.h" #include "xmalloc.h" -#include "cfunction_if.h" +#include "cfile_if.h" #include "cfile_parser_loc.h" +#include "cfile_parser_worker_loc.h" #include "debug.h" -#define CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS 10 - /*! @brief Block detection return values */ typedef enum _CFILE_BLOCK_RETURN_T { @@ -44,6 +43,11 @@ STATIC regex_t regXmlProto; STATIC regex_t regXproto; STATIC regex_t regXprefix; STATIC regex_t regXparameter; +STATIC regex_t regXvariable; + +STATIC regex_t regXExpressionStart; +STATIC regex_t regXExpressionAssign; +STATIC regex_t regXExpressionEnd; // line evaluation related variables STATIC uint32_t cfile_parser_removeCommentHelper = 0; @@ -52,6 +56,21 @@ STATIC char *cfile_parser_parameterStorage = NULL; int8_t cfile_parser_init() { + if (0 > regcomp(®XExpressionStart, CPARS_EXPRESSION_START, (REG_EXTENDED | REG_NEWLINE))) + { + perror("Error regex\n"); + return -1; + } + if (0 > regcomp(®XExpressionAssign, CPARS_EXPRESSION_EXPEND, (REG_EXTENDED | REG_NEWLINE))) + { + perror("Error regex\n"); + return -1; + } + if (0 > regcomp(®XExpressionEnd, CPARS_EXPRESSION_END, (REG_EXTENDED | REG_NEWLINE))) + { + perror("Error regex\n"); + return -1; + } if (0 > regcomp(®X, FUNCTION_BASE, (REG_EXTENDED | REG_NEWLINE))) { perror("Error regex\n"); @@ -97,6 +116,11 @@ int8_t cfile_parser_init() perror("Error regex\n"); return -1; } + if (0 > regcomp(®Xvariable, CPARS_REGEX_VARIABLE, (REG_EXTENDED | REG_NEWLINE))) + { + perror("Error regex\n"); + return -1; + } cfile_parser_initialized = true; return 0; @@ -471,6 +495,7 @@ STATIC int8_t evaluateParameter(char *aParameter, cfunction_t *aFunction) return 0; } +#if(0) /*! * @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 @@ -478,7 +503,7 @@ STATIC int8_t evaluateParameter(char *aParameter, cfunction_t *aFunction) * @retval -2 Given String not a function * @retval 0 function evaluated */ -STATIC cfunction_t* cfile_parser_evaluateLine(char *aLine) +STATIC cfunction_t* cfile_parser_evaluateLine1(char *aLine) { const size_t maxGroup = CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS; regmatch_t matchGroup[maxGroup]; @@ -573,7 +598,7 @@ STATIC cfunction_t* cfile_parser_evaluateLine(char *aLine) switch (cfile_parser_functionLine) { case 0: // single line function definition - case 1: // first line of multi line function definition + case 1:// first line of multi line function definition { // TODO multiple functions in one line cfile_parser_function = cfunction_newFunction(); @@ -623,12 +648,63 @@ STATIC cfunction_t* cfile_parser_evaluateLine(char *aLine) return NULL; } +#endif -int8_t cfile_parser(char *aPath, cfunction_list_t *aList) +STATIC bool workerActive = false; +const stringWorker cWorker[2] = +{ cfile_expWorker, // Parse for variables + NULL }; +STATIC char *match = NULL; +STATIC int8_t cfile_parser_evaluateLine(uint32_t aNumber, char *aLine, cfile_t *aCfile) +{ + stringWorker *worker = (stringWorker*) cWorker; + char *position = aLine; + char *result = NULL; + size_t cSize = 0; + + regex_t *matchStart = ®XExpressionStart; + regex_t *matchEnd = ®XExpressionEnd; + + DEBUG_LOG_APPEND(1, "[ Li %04u] %s\n", aNumber, aLine); + // start with variable worker + + while (position && NULL != *worker) + { + result = (*worker)(&position, matchStart, matchEnd, &workerActive, &cSize); + if (NULL == result) + { + if (false == workerActive) + { + xfree((void**) &match); + ++worker; + } + continue; + } + xmallocStrlcat(&match, result, cSize); + + if (false == workerActive) + { + DEBUG_LOG_APPEND(1, "Works %zu %s\n", cSize, match); + // TODO evaluate expression according to worker + xfree((void**) &match); + worker = (stringWorker*) cWorker; + } + else + { + // force space between findings + xmallocStrlcat(&match, " ", 2); + } + } + return 0; +} + +int8_t cfile_parser(char *aPath, cfile_t *aCfile) { FILE *fdesc; ssize_t charRead = 0; size_t lineSize = 0; + uint32_t lineNumber = 1; + char *cTemp = NULL; char *fileLine = NULL; // will be allocated by getline(); must be freed if (false == cfile_parser_initialized) @@ -648,12 +724,25 @@ int8_t cfile_parser(char *aPath, cfunction_list_t *aList) charRead = getline(&fileLine, &lineSize, fdesc); if (0 <= charRead) { - cfunction_t *function = NULL; - function = cfile_parser_evaluateLine(fileLine); - if (NULL != function) + if (0 != removeCcomments(fileLine)) { - (void) cfunction_addFunction(aList, function); + continue; } + if (0 != cBlockRemoval(fileLine, "{", "}", &cfile_parser_removeBraceHelper, false, false)) + { + continue; + } + cTemp = strrchr(fileLine, '\n'); + if (cTemp) + { + *cTemp = '\0'; + } + cTemp = strrchr(fileLine, '\r'); + if (cTemp) + { + *cTemp = '\0'; + } + (void) cfile_parser_evaluateLine(lineNumber++, fileLine, aCfile); } } while (0 <= charRead); diff --git a/src/stubser/cfile_parser_if.h b/src/stubser/cfile_parser_if.h index 0d93cf9..4dcfb18 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, cfunction_list_t *aList); +int8_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 8620025..393142b 100644 --- a/src/stubser/cfile_parser_loc.h +++ b/src/stubser/cfile_parser_loc.h @@ -14,6 +14,8 @@ #ifndef STUBSER_CFILE_PARSER_LOC_H_ #define STUBSER_CFILE_PARSER_LOC_H_ +#define CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS 10 + #define CPARS_LINE_ENDING "\r\n" #define CPARS_COMMENT_INLINE "//" #define CPARS_COMMENT_BLOCK_START "/*" @@ -27,10 +29,25 @@ #define FUNCTION_ML_PROTO FUNCTION_ML_PAR "\\).*[[:blank:]]*;" #define FUNCTION_PROTO FUNCTION_BASE "\\).*[[:blank:]]*;" +#define CPARS_REGEX_VARIABLE "^[[:blank:]]*([ _\\*[:alnum:]]*)[[:blank:]]*[;=]" #define CPARS_REGEX_PARAMETER "[[:blank:]]*([ _\\*[:alnum:]]* +\\**)([_\\*[:alnum:]]*)[[:blank:]]*" - #define CPARS_REGEX_PREFIX "(extern|EXTERN|static|STATIC|volatile|near|far)[[:blank:]]+([^\\*]*\\**)" +#define CPARS_EXPRESSION_START "^[[:blank:]]*([A-Za-z][\\_\\*[:alnum:]]*)" +#define CPARS_EXPRESSION_EXPEND "[[:blank:]]*([=\{])[[:blank:]]*" +#define CPARS_EXPRESSION_END "[[:blank:]]*([\\};]+)" + #define CFILE_PARSER_IS_MATCHGROUP_FUNCTION(matchGroup) (XREGEX_IS_MATCHGROUP(matchGroup, 1) && XREGEX_IS_MATCHGROUP(matchGroup, 2)) +/*! @brief Type of function definition */ +typedef enum _CELEMENT_TYPE_T +{ + CELEMENT_TYPE_UNDEF = 0, /*!< @brief undefined */ + CELEMENT_TYPE_INCLUDE = 1, /*!< @brief C #include */ + CELEMENT_TYPE_DEFINE = 2, /*!< @brief C #define */ + CELEMENT_TYPE_VARIABLE = 3, /*!< @brief Prototype C variable definition */ + CELEMENT_TYPE_FUNCTION = 4, /*!< @brief Prototype C function definition */ + CELEMENT_TYPE_LAST_ENUM +} celement_type_t; + #endif /* STUBSER_CFILE_PARSER_LOC_H_ */ diff --git a/src/stubser/cfile_parser_worker.c b/src/stubser/cfile_parser_worker.c new file mode 100644 index 0000000..0e7d4a4 --- /dev/null +++ b/src/stubser/cfile_parser_worker.c @@ -0,0 +1,69 @@ +/*! + * @file cfile_parser_worker.c + * @brief + * @details + * Project: \n + * Subsystem: \n + * Module: \n + * Code: GNU-C\n + * + * @date 09.03.2017 + * @author SESA354004 + */ + +#include "xtypes.h" +#include "xregex.h" +#include "debug.h" +#include "cfile_parser_loc.h" +#include "cfile_parser_worker_loc.h" + +char* cfile_expWorker(char **aInput, const regex_t *aStart, const regex_t *aEnd, bool *aActive, size_t *aSize) +{ + regmatch_t matchGroup[CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS]; + char *begin; + + if (!**aInput) + { + *aInput = NULL; + return NULL; + } + if (!*aActive) + { + *aSize = 0; + begin = NULL; + } + else + { + begin = *aInput; + } + + if (*aActive) + { + if (aEnd != NULL && 0 == regexec(aEnd, *aInput, CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS, matchGroup, REG_NOTEOL) && XREGEX_IS_MATCHGROUP(matchGroup, 1)) + { + DEBUG_LOG_APPEND(1, "[ CEe]"); + *aActive = false; + *aSize += matchGroup[1].rm_so; // don't include end marker in result + *aInput += matchGroup[1].rm_eo; + return begin; + } + else + { + DEBUG_LOG_APPEND(1, "[ CE+]"); + *aSize += strlen(*aInput); + *aInput += strlen(*aInput); + return begin; + } + } + else if (0 == regexec(aStart, *aInput, CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS, matchGroup, REG_NOTEOL) && XREGEX_IS_MATCHGROUP(matchGroup, 1)) + { + DEBUG_LOG_APPEND(1, "[ CEs]"); + *aActive = true; + *aSize += XREGEX_SIZEOF_MATCHGROUP(matchGroup, 1); + begin = *aInput + matchGroup[1].rm_so; + *aInput += matchGroup[1].rm_eo; + cfile_expWorker(aInput, aStart, aEnd, aActive, aSize); + } + + return begin; +} diff --git a/src/stubser/cfile_parser_worker_loc.h b/src/stubser/cfile_parser_worker_loc.h new file mode 100644 index 0000000..5a7d1b4 --- /dev/null +++ b/src/stubser/cfile_parser_worker_loc.h @@ -0,0 +1,21 @@ +/*! + * @file cfile_parser_worker_loc.h + * @brief + * @details + * Project: \n + * Subsystem: \n + * Module: \n + * Code: GNU-C\n + * + * @date 09.03.2017 + * @author SESA354004 + */ + +#ifndef STUBSER_CFILE_PARSER_WORKER_LOC_H_ +#define STUBSER_CFILE_PARSER_WORKER_LOC_H_ + +typedef char* (*stringWorker)(char**, const regex_t *, const regex_t *, bool*, size_t*); + +char* cfile_expWorker(char **aInput, const regex_t *aStart, const regex_t *aEnd, bool *aActive, size_t *aSize); + +#endif /* STUBSER_CFILE_PARSER_WORKER_LOC_H_ */ diff --git a/src/stubser/cfunction_if.h b/src/stubser/cfunction_if.h index 2a23859..0981656 100644 --- a/src/stubser/cfunction_if.h +++ b/src/stubser/cfunction_if.h @@ -32,6 +32,14 @@ typedef struct _CFUNCTION_PARAMETER_T struct _CFUNCTION_PARAMETER_T *next; } cfunction_parameter_t; +/*! @brief parameter array */ +typedef struct _CFUNCTION_PARAMETER_LIST_T +{ + uint8_t amount; + cfunction_parameter_t *head; + cfunction_parameter_t *current; +} cfunction_parameterList_t; + /*! @brief brief_description */ typedef struct _CFUNCTION_T { @@ -39,12 +47,7 @@ typedef struct _CFUNCTION_T char *prefix; /*!< @brief prefix like static or extern */ char *dataType; /*!< @brief return type */ char *name; /*!< @brief name */ - struct _CFUNCTION_PARAMETER_LIST_T - { - uint8_t amount; - cfunction_parameter_t *head; - cfunction_parameter_t *current; - } parameter;/*!< @brief parameter array */ + cfunction_parameterList_t parameter;/*!< @brief parameter array */ struct _CFUNCTION_T *next; } cfunction_t; diff --git a/src/stubser/stubser.c b/src/stubser/stubser.c index 9a22fe8..887bd4c 100644 --- a/src/stubser/stubser.c +++ b/src/stubser/stubser.c @@ -19,7 +19,7 @@ #include "xtypes.h" #include "xstring.h" #include "xmalloc.h" -#include "cfunction_if.h" +#include "cfile_if.h" #include "cfile_parser_if.h" #include "stubser_if.h" #include "stubser_loc.h" @@ -194,7 +194,7 @@ STATIC int8_t createStubFunctionBlock(FILE *aFile, FILE *aHeader, cfunction_t *a return 0; } -STATIC int8_t createStub(char *aOutput, char *aNoSuffix, cfunction_list_t *aFunctionList) +STATIC int8_t createStub(char *aOutput, char *aNoSuffix, cfile_t *aCfile) { FILE *cfile; FILE *cheader; @@ -202,7 +202,7 @@ STATIC int8_t createStub(char *aOutput, char *aNoSuffix, cfunction_list_t *aFunc char *cHeaderName = NULL; cfunction_t *function = NULL; - if (NULL == aOutput || NULL == aFunctionList) + if (NULL == aOutput || NULL == aCfile) { return -1; } @@ -246,7 +246,7 @@ STATIC int8_t createStub(char *aOutput, char *aNoSuffix, cfunction_list_t *aFunc fprintf(cheader, "#ifndef _STUB_%s_H"NEWLINES, aNoSuffix); fprintf(cheader, "#define _STUB_%s_H"NEWLINES NEWLINES, aNoSuffix); - function = aFunctionList->head; + function = aCfile->functions.head; while (function) { (void) createStubFunctionBlock(cfile, cheader, function); @@ -271,12 +271,12 @@ STATIC int8_t createStub(char *aOutput, char *aNoSuffix, cfunction_list_t *aFunc int stubser_createStub(char *path, char* aNoSuffix, char *aOutput) { int8_t ret = -1; - cfunction_list_t functionList = - CFUNCTION_LIST_DEFAULT; + cfile_t cFile = + CFILE_T_DEFAULT; char fileName[PATH_MAX] = { '\0' }; - ret = cfile_parser(path, &functionList); + ret = cfile_parser(path, &cFile); DEBUG_LOG_APPEND(1, "\n"); if (0 != ret) { @@ -302,7 +302,7 @@ int stubser_createStub(char *path, char* aNoSuffix, char *aOutput) printf(STUB_CONSOLE_PARSE_OK_S1, gnu_basename(path)); #endif sprintf(fileName, "%s/stub_%s", aOutput, aNoSuffix); - ret = createStub(fileName, aNoSuffix, &functionList); + ret = createStub(fileName, aNoSuffix, &cFile); if (0 != ret) { printf(STUB_CONSOLE_CREATE_ERROR_S2, gnu_basename(path), ret); @@ -313,7 +313,7 @@ int stubser_createStub(char *path, char* aNoSuffix, char *aOutput) end_stubser_createStub: // function end target - cfunction_freeList(&functionList); + cfile_free(&cFile); return ret; } From 5e967dc12ef36d9b17445cc867520c0f56d7ec60 Mon Sep 17 00:00:00 2001 From: Martin Winkler Date: Fri, 10 Mar 2017 09:10:04 +0000 Subject: [PATCH 03/38] WIP multiline parser running (detecting variables, function, prototypes as whole string) - TODO parsing result of first pass (detecting C elements) - TODO #include, #if, ... not included --- src/stubser/cfile_parser.c | 82 +++++++------- src/stubser/cfile_parser_loc.h | 3 +- src/stubser/cfile_parser_worker.c | 150 +++++++++++++++++++------- src/stubser/cfile_parser_worker_loc.h | 4 +- 4 files changed, 151 insertions(+), 88 deletions(-) diff --git a/src/stubser/cfile_parser.c b/src/stubser/cfile_parser.c index 7923294..826c501 100644 --- a/src/stubser/cfile_parser.c +++ b/src/stubser/cfile_parser.c @@ -46,7 +46,6 @@ STATIC regex_t regXparameter; STATIC regex_t regXvariable; STATIC regex_t regXExpressionStart; -STATIC regex_t regXExpressionAssign; STATIC regex_t regXExpressionEnd; // line evaluation related variables @@ -61,11 +60,6 @@ int8_t cfile_parser_init() perror("Error regex\n"); return -1; } - if (0 > regcomp(®XExpressionAssign, CPARS_EXPRESSION_EXPEND, (REG_EXTENDED | REG_NEWLINE))) - { - perror("Error regex\n"); - return -1; - } if (0 > regcomp(®XExpressionEnd, CPARS_EXPRESSION_END, (REG_EXTENDED | REG_NEWLINE))) { perror("Error regex\n"); @@ -650,49 +644,30 @@ STATIC cfunction_t* cfile_parser_evaluateLine1(char *aLine) } #endif -STATIC bool workerActive = false; -const stringWorker cWorker[2] = -{ cfile_expWorker, // Parse for variables - NULL }; -STATIC char *match = NULL; STATIC int8_t cfile_parser_evaluateLine(uint32_t aNumber, char *aLine, cfile_t *aCfile) { - stringWorker *worker = (stringWorker*) cWorker; char *position = aLine; - char *result = NULL; - size_t cSize = 0; + int8_t result = 0; + static char *match = NULL; + static uint8_t depth = 0; regex_t *matchStart = ®XExpressionStart; regex_t *matchEnd = ®XExpressionEnd; - DEBUG_LOG_APPEND(1, "[ Li %04u] %s\n", aNumber, aLine); - // start with variable worker - - while (position && NULL != *worker) + while (position) { - result = (*worker)(&position, matchStart, matchEnd, &workerActive, &cSize); - if (NULL == result) + result = regExWorker(&match, &position, matchStart, matchEnd, &depth, false); + if (match && 0 == result && 0 == depth) { - if (false == workerActive) - { - xfree((void**) &match); - ++worker; - } - continue; - } - xmallocStrlcat(&match, result, cSize); - - if (false == workerActive) - { - DEBUG_LOG_APPEND(1, "Works %zu %s\n", cSize, match); - // TODO evaluate expression according to worker + DEBUG_LOG_APPEND(1, "[ Re %04u] Works %zu %s\n", aNumber, strlen(match), match); xfree((void**) &match); - worker = (stringWorker*) cWorker; } - else + if (0 > result) { - // force space between findings - xmallocStrlcat(&match, " ", 2); + if (-2 == result) + DEBUG_LOG_APPEND(2, "[ PEr]"); + position = NULL; + xfree((void**) &match); } } return 0; @@ -703,9 +678,11 @@ int8_t cfile_parser(char *aPath, cfile_t *aCfile) FILE *fdesc; ssize_t charRead = 0; size_t lineSize = 0; - uint32_t lineNumber = 1; + 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; if (false == cfile_parser_initialized) { @@ -724,14 +701,26 @@ int8_t cfile_parser(char *aPath, cfile_t *aCfile) charRead = getline(&fileLine, &lineSize, fdesc); if (0 <= charRead) { - if (0 != removeCcomments(fileLine)) + lineNumber++; + ret = removeCcomments(fileLine); + if (-1 == ret) + { + ++warningCounter; + } + else if (0 != ret) { continue; } - if (0 != cBlockRemoval(fileLine, "{", "}", &cfile_parser_removeBraceHelper, false, false)) + 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) { @@ -742,7 +731,7 @@ int8_t cfile_parser(char *aPath, cfile_t *aCfile) { *cTemp = '\0'; } - (void) cfile_parser_evaluateLine(lineNumber++, fileLine, aCfile); + (void) cfile_parser_evaluateLine(lineNumber, fileLine, aCfile); } } while (0 <= charRead); @@ -756,7 +745,7 @@ int8_t cfile_parser(char *aPath, cfile_t *aCfile) cfile_parser_parameterStorage); cfile_parser_removeCommentHelper = 0; cfile_parser_removeBraceHelper = 0; - return -2; + ret = -2; } // error detection for function parameter detection @@ -765,8 +754,13 @@ int8_t cfile_parser(char *aPath, cfile_t *aCfile) DEBUG_LOG_APPEND(1, "Function parameter not free: %s\n", cfile_parser_parameterStorage); free(cfile_parser_parameterStorage); cfile_parser_parameterStorage = NULL; - return -3; + ret = -3; } - return 0; + if (warningCounter && 0 <= ret) + { + ret = -4; + } + + return ret; } diff --git a/src/stubser/cfile_parser_loc.h b/src/stubser/cfile_parser_loc.h index 393142b..c18226b 100644 --- a/src/stubser/cfile_parser_loc.h +++ b/src/stubser/cfile_parser_loc.h @@ -33,8 +33,7 @@ #define CPARS_REGEX_PARAMETER "[[:blank:]]*([ _\\*[:alnum:]]* +\\**)([_\\*[:alnum:]]*)[[:blank:]]*" #define CPARS_REGEX_PREFIX "(extern|EXTERN|static|STATIC|volatile|near|far)[[:blank:]]+([^\\*]*\\**)" -#define CPARS_EXPRESSION_START "^[[:blank:]]*([A-Za-z][\\_\\*[:alnum:]]*)" -#define CPARS_EXPRESSION_EXPEND "[[:blank:]]*([=\{])[[:blank:]]*" +#define CPARS_EXPRESSION_START "^[[:blank:]]*([A-Za-z\\_][\\_\\*[:alnum:]]*)" #define CPARS_EXPRESSION_END "[[:blank:]]*([\\};]+)" #define CFILE_PARSER_IS_MATCHGROUP_FUNCTION(matchGroup) (XREGEX_IS_MATCHGROUP(matchGroup, 1) && XREGEX_IS_MATCHGROUP(matchGroup, 2)) diff --git a/src/stubser/cfile_parser_worker.c b/src/stubser/cfile_parser_worker.c index 0e7d4a4..1f40c9f 100644 --- a/src/stubser/cfile_parser_worker.c +++ b/src/stubser/cfile_parser_worker.c @@ -13,57 +13,129 @@ #include "xtypes.h" #include "xregex.h" +#include "xmalloc.h" #include "debug.h" #include "cfile_parser_loc.h" #include "cfile_parser_worker_loc.h" -char* cfile_expWorker(char **aInput, const regex_t *aStart, const regex_t *aEnd, bool *aActive, size_t *aSize) +/*! + * @brief String block detection using regular expressions + * @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) + * @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) + */ +int8_t regExWorker(char **aOutput, char **aInput, const regex_t *aStart, const regex_t *aEnd, uint8_t *aBlockDepth, bool aMultiLevel) { - regmatch_t matchGroup[CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS]; - char *begin; + 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) + if (!**aInput || NULL == *aInput) { - *aInput = NULL; - return NULL; - } - if (!*aActive) - { - *aSize = 0; - begin = NULL; - } - else - { - begin = *aInput; - } - - if (*aActive) - { - if (aEnd != NULL && 0 == regexec(aEnd, *aInput, CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS, matchGroup, REG_NOTEOL) && XREGEX_IS_MATCHGROUP(matchGroup, 1)) + if (*aBlockDepth) { - DEBUG_LOG_APPEND(1, "[ CEe]"); - *aActive = false; - *aSize += matchGroup[1].rm_so; // don't include end marker in result - *aInput += matchGroup[1].rm_eo; - return begin; + xmallocStrlcat(aOutput, " ", 2); + ret = 0; } else { - DEBUG_LOG_APPEND(1, "[ CE+]"); - *aSize += strlen(*aInput); - *aInput += strlen(*aInput); - return begin; + ret = -1; } - } - else if (0 == regexec(aStart, *aInput, CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS, matchGroup, REG_NOTEOL) && XREGEX_IS_MATCHGROUP(matchGroup, 1)) - { - DEBUG_LOG_APPEND(1, "[ CEs]"); - *aActive = true; - *aSize += XREGEX_SIZEOF_MATCHGROUP(matchGroup, 1); - begin = *aInput + matchGroup[1].rm_so; - *aInput += matchGroup[1].rm_eo; - cfile_expWorker(aInput, aStart, aEnd, aActive, aSize); + *aInput = NULL; + goto regExWorker_end; } - return begin; + // 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) + { + *aInput += strlen(*aInput); + ret = 0; + goto regExWorker_end; + } + } + else + { + begin = NULL; + // no findings + if (!match) + { + ret = -1; + goto regExWorker_end; + } + } + + // start && aDepth > 0 -> ignore + 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 end marker in result + begin = *aInput + match[1].rm_so; // include end marker in result + *aInput += match[1].rm_eo; + } + else + { + // ignore starts within block + 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; + goto regExWorker_end; + } + + regExWorker_end: + + if (begin) + { + xmallocStrlcat(aOutput, begin, size); + if (*aBlockDepth) + { + (void) regExWorker(aOutput, aInput, aStart, aEnd, aBlockDepth, aMultiLevel); + } + } + + return ret; } diff --git a/src/stubser/cfile_parser_worker_loc.h b/src/stubser/cfile_parser_worker_loc.h index 5a7d1b4..0039580 100644 --- a/src/stubser/cfile_parser_worker_loc.h +++ b/src/stubser/cfile_parser_worker_loc.h @@ -14,8 +14,6 @@ #ifndef STUBSER_CFILE_PARSER_WORKER_LOC_H_ #define STUBSER_CFILE_PARSER_WORKER_LOC_H_ -typedef char* (*stringWorker)(char**, const regex_t *, const regex_t *, bool*, size_t*); - -char* cfile_expWorker(char **aInput, const regex_t *aStart, const regex_t *aEnd, bool *aActive, size_t *aSize); +int8_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_ */ From 726077eef424e716a38a8b1fefb52982f123b5be Mon Sep 17 00:00:00 2001 From: Martin Winkler Date: Fri, 10 Mar 2017 14:27:24 +0000 Subject: [PATCH 04/38] - WIP populated cfile structure with variables, functions and according element type - cleaned unused variable and function definitions - cleaned debug output calls - todo: create and include "user defined" header for including missing headers to stub.c (will not be overwritten if exists) - todo: include "includes" in cfile structure --- src/stubser/cfile.c | 22 ++- src/stubser/cfile_if.h | 14 +- src/stubser/cfile_parser.c | 301 ++++++++++++--------------------- src/stubser/cfile_parser_loc.h | 20 +-- src/stubser/cfunction.c | 39 ++--- src/stubser/cfunction_if.h | 14 +- src/stubser/stubser.c | 4 + 7 files changed, 185 insertions(+), 229 deletions(-) diff --git a/src/stubser/cfile.c b/src/stubser/cfile.c index e58dfab..bde9088 100644 --- a/src/stubser/cfile.c +++ b/src/stubser/cfile.c @@ -59,7 +59,7 @@ int8_t cfile_freeVariables(cfile_variableList_t *aVariable) while (work) { next = work->next; - free(work->type); + free(work->dataType); free(work->name); free(work); work = next; @@ -77,3 +77,23 @@ void cfile_free(cfile_t *aCfile) cfile_freeVariables(&aCfile->variables); cfunction_freeList(&aCfile->functions); } + +void cfile_print(cfile_t *aCfile) +{ + cfile_variable_t *work = NULL; + + if (NULL == aCfile) + { + return; + } + + work = aCfile->variables.head; + + while (work) + { + printf("[ cva]%d:<%s> (%s) %s\n", work->type, work->prefix, work->dataType, work->name); + work = work->next; + } + + cfunction_printList(&aCfile->functions); +} diff --git a/src/stubser/cfile_if.h b/src/stubser/cfile_if.h index fff067d..a53525f 100644 --- a/src/stubser/cfile_if.h +++ b/src/stubser/cfile_if.h @@ -16,11 +16,22 @@ #include "cfunction_if.h" +/*! @brief Type of function definition */ +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_LAST_ENUM +} cfile_variable_type_t; + /*! @brief Parameter list node */ typedef struct _CFILE_VARIABLE_T { + cfile_variable_type_t type; char* prefix; /*!< @brief variable prefix (e.g. static) */ - char* type; /*!< @brief data type */ + char* dataType; /*!< @brief data type */ char* name; /*!< @brief name */ struct _CFILE_VARIABLE_T *next; } cfile_variable_t; @@ -49,5 +60,6 @@ typedef struct _CFILE_T cfile_variable_t* cfile_newVariable(cfile_variableList_t *aList); int8_t cfile_freeVariables(cfile_variableList_t *aVariable); void cfile_free(cfile_t *aCfile); +void cfile_print(cfile_t *aCfile); #endif /* STUBSER_CFILE_IF_H_ */ diff --git a/src/stubser/cfile_parser.c b/src/stubser/cfile_parser.c index 826c501..89f870f 100644 --- a/src/stubser/cfile_parser.c +++ b/src/stubser/cfile_parser.c @@ -32,15 +32,7 @@ typedef enum _CFILE_BLOCK_RETURN_T } cfile_block_return_t; STATIC bool cfile_parser_initialized = false; -STATIC uint8_t cfile_parser_functionLine = 0; -STATIC cfunction_t *cfile_parser_function = NULL; -STATIC regex_t regX; -STATIC regex_t regXsl; -STATIC regex_t regXmlStart; -STATIC regex_t regXmlPar; -STATIC regex_t regXmlEnd; -STATIC regex_t regXmlProto; -STATIC regex_t regXproto; +STATIC regex_t regXfunction; STATIC regex_t regXprefix; STATIC regex_t regXparameter; STATIC regex_t regXvariable; @@ -65,37 +57,7 @@ int8_t cfile_parser_init() perror("Error regex\n"); return -1; } - if (0 > regcomp(®X, FUNCTION_BASE, (REG_EXTENDED | REG_NEWLINE))) - { - perror("Error regex\n"); - return -1; - } - if (0 > regcomp(®Xsl, FUNCTION_SL, (REG_EXTENDED | REG_NEWLINE))) - { - perror("Error regex\n"); - return -1; - } - if (0 > regcomp(®XmlStart, FUNCTION_ML_SOF, (REG_EXTENDED | REG_NEWLINE))) - { - perror("Error regex\n"); - return -1; - } - if (0 > regcomp(®XmlPar, FUNCTION_ML_PAR, (REG_EXTENDED | REG_NEWLINE))) - { - perror("Error regex\n"); - return -1; - } - if (0 > regcomp(®XmlEnd, FUNCTION_ML_END, (REG_EXTENDED | REG_NEWLINE))) - { - perror("Error regex\n"); - return -1; - } - if (0 > regcomp(®XmlProto, FUNCTION_ML_PROTO, (REG_EXTENDED | REG_NEWLINE))) - { - perror("Error regex\n"); - return -1; - } - if (0 > regcomp(®Xproto, FUNCTION_PROTO, (REG_EXTENDED | REG_NEWLINE))) + if (0 > regcomp(®Xfunction, CPARS_REGEX_FUNCTION, (REG_EXTENDED | REG_NEWLINE))) { perror("Error regex\n"); return -1; @@ -120,7 +82,7 @@ int8_t cfile_parser_init() return 0; } -#if(0) +#if isDebugLevel(1) STATIC void printMatchGroup(char *aString, regmatch_t *aMatchGroup) { char match[1024] = @@ -131,47 +93,91 @@ STATIC void printMatchGroup(char *aString, regmatch_t *aMatchGroup) { if (aMatchGroup[i].rm_so < aMatchGroup[i].rm_eo) { - DEBUG_LOG_APPEND(1, "[%02d](%.3ld - %.3ld)[%03d]:", i, aMatchGroup[i].rm_so, aMatchGroup[i].rm_eo, (int) (aMatchGroup[i].rm_eo - aMatchGroup[i].rm_so)); + DEBUG_LOG_APPEND(1, "[%02d](%.3ld - %.3ld)[%03d]:", i, aMatchGroup[i].rm_so, aMatchGroup[i].rm_eo, + (int ) (aMatchGroup[i].rm_eo - aMatchGroup[i].rm_so)); strlcpy(match, &aString[aMatchGroup[i].rm_so], (size_t) (aMatchGroup[i].rm_eo - aMatchGroup[i].rm_so + 1)); DEBUG_LOG_APPEND(1, "%s", match); DEBUG_LOG_APPEND(1, "\n"); } } } +#else +#define printMatchGroup(aString, aMatchgroup) do { /*nothing*/ } while(0) #endif -STATIC void checkFunctionType(cfunction_t *aFunction) +STATIC void checkFunctionType(cfunction_t *aFunction, char *aExpression) { + char *tempChar = NULL; + + if (NULL == aFunction || NULL == aExpression) + { + return; + } + + aFunction->type = CFUNCTION_TYPE_REGULAR; + + tempChar = strrchr(aExpression, CPARS_PROTOTYPE_END_C); + if (tempChar) + { + aFunction->type = CFUNCTION_TYPE_PROTO; + } + if (NULL == aFunction->prefix) { return; } - if ((NULL != strstr(aFunction->prefix, "static") || NULL != strstr(aFunction->prefix, "STATIC")) // - && CFUNCTION_TYPE_PROTO != aFunction->type) + if (NULL != strstr(aFunction->prefix, CPARS_PREFIX_EXTERN_S)) + { + aFunction->type = CFUNCTION_TYPE_EXTERN; + } + else if (NULL != strstr(aFunction->prefix, CPARS_PREFIX_STATIC_S) && CFUNCTION_TYPE_PROTO != aFunction->type) { aFunction->type = CFUNCTION_TYPE_STATIC; } } /*! - * @brief Extract function prefix and data type and removing trailing blanks - * @param [out] *aFunction Pointer to function structure + * @brief Extract C expression prefix and data type and removing trailing blanks + * @param [out] *aElement Pointer to C element structure + * @param [in] aElementType C element type (CELEMENT_TYPE_VARIABLE, CELEMENT_TYPE_FUNCTION supported) * @param [in] *aString Pointer to a substring containing data type and/or prefix * @param [in] aSize Length of string * @retval 0 processing successful * @retval -1 processing failed */ -STATIC int8_t matchFunctionStart(cfunction_t *aFunction, char *aString, size_t aSize) +STATIC int8_t matchPrefix(void *aElement, celement_type_t aElementType, char *aString, size_t aSize) { regmatch_t matchGroup[CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS]; char *temp = NULL; char *end = NULL; + char **prefix = NULL; + char **type = NULL; - if (NULL == aFunction || NULL == aString || 0 == aSize) + if (NULL == aElement || NULL == aString || 0 == aSize) { return -1; } + switch (aElementType) + { + case CELEMENT_TYPE_VARIABLE: + { + prefix = &((cfile_variable_t*) aElement)->prefix; + type = &((cfile_variable_t*) aElement)->dataType; + break; + } + case CELEMENT_TYPE_FUNCTION: + { + prefix = &((cfunction_t*) aElement)->prefix; + type = &((cfunction_t*) aElement)->dataType; + break; + } + default: + { + return -1; + } + } + temp = (char*) xmalloc(aSize + 1); if (NULL == temp) { @@ -187,21 +193,36 @@ STATIC int8_t matchFunctionStart(cfunction_t *aFunction, char *aString, size_t a } *(end + 1) = '\0'; + if (CELEMENT_TYPE_VARIABLE == aElementType) + { + ((cfunction_t*) aElement)->type = CFUNCTION_TYPE_REGULAR; + } + if (0 == regexec(®Xprefix, temp, CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS, matchGroup, 0)) { if (XREGEX_IS_MATCHGROUP(matchGroup, 1)) { - xmallocStrlcpy(&aFunction->prefix, &temp[matchGroup[1].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 1)); - checkFunctionType(aFunction); + xmallocStrlcpy(prefix, &temp[matchGroup[1].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 1)); + if (CELEMENT_TYPE_VARIABLE == aElementType) + { + if (*prefix && NULL != strstr(*prefix, CPARS_PREFIX_EXTERN_S)) + { + ((cfunction_t*) aElement)->type = CFUNCTION_TYPE_EXTERN; + } + else if (*prefix && NULL != strstr(*prefix, CPARS_PREFIX_STATIC_S)) + { + ((cfunction_t*) aElement)->type = CFUNCTION_TYPE_STATIC; + } + } } if (XREGEX_IS_MATCHGROUP(matchGroup, 2)) { - xmallocStrlcpy(&aFunction->dataType, &temp[matchGroup[2].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 2)); + xmallocStrlcpy(type, &temp[matchGroup[2].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 2)); } } else { - xmallocStrlcpy(&aFunction->dataType, temp, strlen(temp)); + xmallocStrlcpy(type, temp, strlen(temp)); } free(temp); @@ -489,160 +510,50 @@ STATIC int8_t evaluateParameter(char *aParameter, cfunction_t *aFunction) return 0; } -#if(0) -/*! - * @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 - * @retval -1 Invalid regular expressions - * @retval -2 Given String not a function - * @retval 0 function evaluated - */ -STATIC cfunction_t* cfile_parser_evaluateLine1(char *aLine) +STATIC int8_t cfile_parser_evaluateExpression(char *aExpression, cfile_t *aCfile) { - const size_t maxGroup = CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS; - regmatch_t matchGroup[maxGroup]; - bool functionEnd = false; - cfunction_type_t tempFunctionType = CFUNCTION_TYPE_UNDEF; + char *tempChar = NULL; + cfile_variable_t *variable = NULL; + cfunction_t *function = NULL; + regmatch_t matchGroup[CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS]; - if (0 != removeCcomments(aLine)) + if (NULL == aExpression || NULL == aCfile) { - return NULL; - } - if (0 != cBlockRemoval(aLine, "{", "}", &cfile_parser_removeBraceHelper, false, false)) - { - return NULL; + return -1; } - if (cfile_parser_functionLine) + if (0 == regexec(®Xfunction, aExpression, CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS, matchGroup, + REG_NOTEOL) && CFILE_PARSER_IS_MATCHGROUP_FUNCTION(matchGroup)) { - if (0 == regexec(®XmlEnd, aLine, maxGroup, matchGroup, REG_NOTEOL)) + printMatchGroup(aExpression, matchGroup); + function = cfunction_addNewFunction(&aCfile->functions); + (void) matchPrefix(function, CELEMENT_TYPE_FUNCTION, &aExpression[matchGroup[1].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 1)); + checkFunctionType(function, aExpression); + xmallocStrlcpy(&function->name, &aExpression[matchGroup[2].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 2)); + if (XREGEX_IS_MATCHGROUP(matchGroup, 3)) { - tempFunctionType = CFUNCTION_TYPE_REGULAR; - DEBUG_LOG_APPEND(1, "[ mle]"); - functionEnd = true; - } - else if (0 == regexec(®XmlProto, aLine, maxGroup, matchGroup, REG_NOTEOL)) - { - tempFunctionType = CFUNCTION_TYPE_PROTO; - DEBUG_LOG_APPEND(1, "[ mlp]"); - functionEnd = true; - } - else if (0 == regexec(®XmlPar, aLine, maxGroup, matchGroup, REG_NOTEOL)) - { - DEBUG_LOG_APPEND(1, "[ ml+]"); - } - else - { - DEBUG_LOG_APPEND(1, "[ na ]"); - tempFunctionType = CFUNCTION_TYPE_UNDEF; - functionEnd = true; - } - - ++cfile_parser_functionLine; - } - else if (0 == regexec(®Xsl, aLine, maxGroup, matchGroup, REG_NOTEOL) && CFILE_PARSER_IS_MATCHGROUP_FUNCTION(matchGroup)) - { - tempFunctionType = CFUNCTION_TYPE_REGULAR; - DEBUG_LOG_APPEND(1, "[ sl ]"); - } - else if (0 == regexec(®XmlStart, aLine, maxGroup, matchGroup, REG_NOTEOL) && CFILE_PARSER_IS_MATCHGROUP_FUNCTION(matchGroup)) - { - tempFunctionType = CFUNCTION_TYPE_REGULAR; - DEBUG_LOG_APPEND(1, "[ mls]"); - ++cfile_parser_functionLine; - } - else if (0 == regexec(®Xproto, aLine, maxGroup, matchGroup, REG_NOTEOL) && CFILE_PARSER_IS_MATCHGROUP_FUNCTION(matchGroup)) - { - tempFunctionType = CFUNCTION_TYPE_PROTO; - DEBUG_LOG_APPEND(1, "[prot]"); - } - else if (0 == regexec(®X, aLine, maxGroup, matchGroup, REG_NOTEOL) && CFILE_PARSER_IS_MATCHGROUP_FUNCTION(matchGroup)) - { - tempFunctionType = CFUNCTION_TYPE_UNDEF; - DEBUG_LOG_APPEND(1, "[ fuX]"); - } - else - { - return NULL; - } -#if (0) - { - uint8_t i = 0; - char match[1024] = - { 0}; - - for (i = 0; i < maxGroup && 0 <= matchGroup[i].rm_so; ++i) - { - if (matchGroup[i].rm_so < matchGroup[i].rm_eo) + xmallocStrlcat(&tempChar, &aExpression[matchGroup[3].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 3)); + if (NULL != tempChar) { - if (0 < i) - DEBUG_LOG_APPEND(1, " "); - DEBUG_LOG_APPEND(1, "[%02d](%.3ld - %.3ld)[%03d]: ", i, matchGroup[i].rm_so, matchGroup[i].rm_eo, (int) (matchGroup[i].rm_eo - matchGroup[i].rm_so)); - strlcpy(match, &aLine[matchGroup[i].rm_so], (size_t) (matchGroup[i].rm_eo - matchGroup[i].rm_so + 1)); - DEBUG_LOG_APPEND(1, "%s", match); - DEBUG_LOG_APPEND(1, "\n"); + evaluateParameter(tempChar, function); } - } - if (functionEnd) - { - cfile_parser_functionLine = 0; + xfree((void**) &tempChar); } } -#else - switch (cfile_parser_functionLine) + else if (0 == regexec(®Xvariable, aExpression, CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS, matchGroup, + REG_NOTEOL) && XREGEX_IS_MATCHGROUP(matchGroup, 1)) { - case 0: // single line function definition - case 1:// first line of multi line function definition + printMatchGroup(aExpression, matchGroup); + variable = cfile_newVariable(&aCfile->variables); + if (variable) { - // TODO multiple functions in one line - cfile_parser_function = cfunction_newFunction(); - cfile_parser_function->type = tempFunctionType; - matchFunctionStart(cfile_parser_function, &aLine[matchGroup[1].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 1)); - xmallocStrlcpy(&cfile_parser_function->name, &aLine[matchGroup[2].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 2)); - if (XREGEX_IS_MATCHGROUP(matchGroup, 3)) - { - xmallocStrlcat(&cfile_parser_parameterStorage, &aLine[matchGroup[3].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 3)); - } - break; - } - default: // further lines - { - if (XREGEX_IS_MATCHGROUP(matchGroup, 1)) - { - xmallocStrlcat(&cfile_parser_parameterStorage, &aLine[matchGroup[1].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 1)); - } - if (functionEnd) - { - if (CFUNCTION_TYPE_UNDEF == tempFunctionType) - { - cfunction_freeFunction(&cfile_parser_function); - } - else - { - cfile_parser_function->type = tempFunctionType; - checkFunctionType(cfile_parser_function); - } - cfile_parser_functionLine = 0; - } - break; + (void) matchPrefix(variable, CELEMENT_TYPE_VARIABLE, &aExpression[matchGroup[1].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 1)); + xmallocStrlcpy(&variable->name, &aExpression[matchGroup[2].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 2)); } } - // return evaluated function - if (0 == cfile_parser_functionLine) - { - evaluateParameter(cfile_parser_parameterStorage, cfile_parser_function); - free(cfile_parser_parameterStorage); - cfile_parser_parameterStorage = NULL; - cfunction_t *funTemp = cfile_parser_function; - cfile_parser_function = NULL; - return funTemp; - } -#endif - - return NULL; + return 0; } -#endif STATIC int8_t cfile_parser_evaluateLine(uint32_t aNumber, char *aLine, cfile_t *aCfile) { @@ -650,16 +561,26 @@ STATIC int8_t cfile_parser_evaluateLine(uint32_t aNumber, char *aLine, cfile_t * int8_t result = 0; static char *match = NULL; static uint8_t depth = 0; + char *tempMatch = NULL; regex_t *matchStart = ®XExpressionStart; regex_t *matchEnd = ®XExpressionEnd; while (position) { + if (NULL != (tempMatch = strstr(position, "#include"))) + { + // TODO save include information + DEBUG_LOG_APPEND(1, "[ Re %04u] Works %zu %s\n", aNumber, strlen(tempMatch), tempMatch); + position = NULL; + continue; + } result = regExWorker(&match, &position, matchStart, matchEnd, &depth, false); if (match && 0 == result && 0 == depth) { DEBUG_LOG_APPEND(1, "[ Re %04u] Works %zu %s\n", aNumber, strlen(match), match); + // Evaluate C expression + (void) cfile_parser_evaluateExpression(match, aCfile); xfree((void**) &match); } if (0 > result) diff --git a/src/stubser/cfile_parser_loc.h b/src/stubser/cfile_parser_loc.h index c18226b..26ca9c7 100644 --- a/src/stubser/cfile_parser_loc.h +++ b/src/stubser/cfile_parser_loc.h @@ -21,20 +21,20 @@ #define CPARS_COMMENT_BLOCK_START "/*" #define CPARS_COMMENT_BLOCK_END "*/" -#define FUNCTION_BASE "^[[:blank:]]*([ _\\*[:alnum:]]* +\\**)([_\\*[:alnum:]]*)[[:blank:]]*\\([[:blank:]]*([^\r\\)]*)" -#define FUNCTION_SL FUNCTION_BASE "\\)[^;]*$" -#define FUNCTION_ML_SOF FUNCTION_BASE "[\r]*$" -#define FUNCTION_ML_PAR "^[[:blank:]]*([^\r]*)" -#define FUNCTION_ML_END FUNCTION_ML_PAR "\\)[^;]*$" -#define FUNCTION_ML_PROTO FUNCTION_ML_PAR "\\).*[[:blank:]]*;" -#define FUNCTION_PROTO FUNCTION_BASE "\\).*[[:blank:]]*;" +#define CPARS_PROTOTYPE_END_C ';' +#define CPARS_PREFIX_STATIC_S "static" +#define CPARS_PREFIX_EXTERN_S "extern" -#define CPARS_REGEX_VARIABLE "^[[:blank:]]*([ _\\*[:alnum:]]*)[[:blank:]]*[;=]" +#define CPARS_EXPRESSION_BASE "^[[: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:]]*[;=]" #define CPARS_REGEX_PARAMETER "[[:blank:]]*([ _\\*[:alnum:]]* +\\**)([_\\*[:alnum:]]*)[[:blank:]]*" -#define CPARS_REGEX_PREFIX "(extern|EXTERN|static|STATIC|volatile|near|far)[[:blank:]]+([^\\*]*\\**)" +#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:]]*)" -#define CPARS_EXPRESSION_END "[[:blank:]]*([\\};]+)" +#define CPARS_EXPRESSION_END "[[:blank:]]*([\\};]+)" #define CFILE_PARSER_IS_MATCHGROUP_FUNCTION(matchGroup) (XREGEX_IS_MATCHGROUP(matchGroup, 1) && XREGEX_IS_MATCHGROUP(matchGroup, 2)) diff --git a/src/stubser/cfunction.c b/src/stubser/cfunction.c index 2f21d22..f1a2d5d 100644 --- a/src/stubser/cfunction.c +++ b/src/stubser/cfunction.c @@ -16,39 +16,35 @@ #include "xmalloc.h" #include "cfunction_if.h" -cfunction_t* cfunction_newFunction() +cfunction_t* cfunction_addNewFunction(cfunction_list_t *aList) { cfunction_t *new = NULL; + if (NULL == aList) + { + perror("Null pointer"); + return NULL; + } + new = (cfunction_t*) xmalloc(sizeof(cfunction_t)); memset(new, 0, sizeof(cfunction_t)); - return new; -} - -int8_t cfunction_addFunction(cfunction_list_t *aList, cfunction_t *aNew) -{ - if (NULL == aList || NULL == aNew) - { - perror("Null pointer"); - return -1; - } - if (NULL == aList->head) { - aList->head = aNew; - aList->current = aNew; + aList->amount = 0; + aList->head = new; + aList->current = new; } else { - aList->current->next = aNew; - aList->current = aNew; + aList->current->next = new; + aList->current = new; } - - return 0; + ++aList->amount; + return new; } -cfunction_parameter_t* cfunction_newParameter(struct _CFUNCTION_PARAMETER_LIST_T *aList) +cfunction_parameter_t* cfunction_newParameter(cfunction_parameterList_t *aList) { cfunction_parameter_t *new = NULL; @@ -63,6 +59,7 @@ cfunction_parameter_t* cfunction_newParameter(struct _CFUNCTION_PARAMETER_LIST_T if (NULL == aList->head) { + aList->amount = 0; aList->head = new; aList->current = new; } @@ -162,7 +159,7 @@ void cfunction_printList(cfunction_list_t *aList) while (work) { param = work->parameter.head; - printf("[ cfu]%d:%s %s %s [%d] ", work->type, work->prefix, work->dataType, work->name, work->parameter.amount); + printf("[ cfu]%d:<%s> (%s) %s [%d] ", work->type, work->prefix, work->dataType, work->name, work->parameter.amount); while (param) { printf("%s|%s,", param->type, param->name); @@ -170,6 +167,6 @@ void cfunction_printList(cfunction_list_t *aList) } printf("\n"); work = work->next; - } + printf(" %d Functions\n", aList->amount); } diff --git a/src/stubser/cfunction_if.h b/src/stubser/cfunction_if.h index 0981656..ec18ef6 100644 --- a/src/stubser/cfunction_if.h +++ b/src/stubser/cfunction_if.h @@ -18,9 +18,10 @@ typedef enum _CFUNCTION_TYPE_T { CFUNCTION_TYPE_UNDEF = 0, /*!< @brief undefined */ - CFUNCTION_TYPE_REGULAR = 1, /*!< @brief Regular c function definition */ - CFUNCTION_TYPE_STATIC = 2, /*!< @brief Static c function definition */ - CFUNCTION_TYPE_PROTO = 3, /*!< @brief Prototype c function definition */ + CFUNCTION_TYPE_REGULAR = 1, /*!< @brief Regular C function definition */ + CFUNCTION_TYPE_STATIC = 2, /*!< @brief Static C function definition */ + CFUNCTION_TYPE_PROTO = 3, /*!< @brief Prototype C function definition */ + CFUNCTION_TYPE_EXTERN = 4, /*!< @brief External C function definition */ CFUNCTION_TYPE_LAST_ENUM } cfunction_type_t; @@ -54,17 +55,18 @@ typedef struct _CFUNCTION_T /*! @brief Dynamic function list */ typedef struct _CFUNCTION_LIST_T { + uint16_t amount; cfunction_t *head; cfunction_t *current; } cfunction_list_t; #define CFUNCTION_LIST_DEFAULT {\ + .amount = 0, \ .head = NULL, \ .current = NULL } -cfunction_t* cfunction_newFunction(); -int8_t cfunction_addFunction(cfunction_list_t *aList, cfunction_t *aNew); -cfunction_parameter_t* cfunction_newParameter(struct _CFUNCTION_PARAMETER_LIST_T *aList); +cfunction_t* cfunction_addNewFunction(cfunction_list_t *aList); +cfunction_parameter_t* cfunction_newParameter(cfunction_parameterList_t *aList); int8_t cfunction_freeFunction(cfunction_t **aFunction); int8_t cfunction_freeList(cfunction_list_t *aList); void cfunction_printList(cfunction_list_t *aList); diff --git a/src/stubser/stubser.c b/src/stubser/stubser.c index 887bd4c..33fef9e 100644 --- a/src/stubser/stubser.c +++ b/src/stubser/stubser.c @@ -311,6 +311,10 @@ int stubser_createStub(char *path, char* aNoSuffix, char *aOutput) } printf(STUB_CONSOLE_CREATE_OK_S1, fileName); +#if isDebugLevel(1) + cfile_print(&cFile); +#endif + end_stubser_createStub: // function end target cfile_free(&cFile); From 8690c0845ac5fde2f1677279514cfa421453ded7 Mon Sep 17 00:00:00 2001 From: Martin Winkler Date: Fri, 10 Mar 2017 15:01:07 +0000 Subject: [PATCH 05/38] - WIP creating user header and including it stub.c - todo: write stubs even when there are warnings for some lines --- src/stubser/stubser.c | 51 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/src/stubser/stubser.c b/src/stubser/stubser.c index 33fef9e..fcc8c92 100644 --- a/src/stubser/stubser.c +++ b/src/stubser/stubser.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "xtypes.h" #include "xstring.h" #include "xmalloc.h" @@ -194,6 +195,53 @@ STATIC int8_t createStubFunctionBlock(FILE *aFile, FILE *aHeader, cfunction_t *a return 0; } +/*! + * @brief Check if file exists using stat + * @param [in] *filename Path to file + * @retval 0 file does not exist + * @retval 1 file exists + */ +int file_exist(const char *filename) +{ + struct stat buffer; + return (stat(filename, &buffer) == 0); +} + +STATIC void createUserHeader(char *aOutput, char *aNoSuffix) +{ + FILE *cheader; + char *cHeaderName = NULL; + xmallocStrlcpy(&cHeaderName, aOutput, strlen(aOutput)); + xmallocStrlcat(&cHeaderName, "_user.h", 8); + + if (file_exist(cHeaderName)) + { + free(cHeaderName); + return; + } + + // user header doesn't exist + cheader = fopen(cHeaderName, "w"); + if (NULL == cheader) + { + free(cHeaderName); + return; + } + + fprintf(cheader, "/* @file %s"NEWLINES, gnu_basename(cHeaderName)); + fprintf(cheader, " * @details"NEWLINES" * This is a user defined stub header.\\n"NEWLINES); + fprintf(cheader, " * Define subject header needed for compilation of stub (e.g. typedefs, structures, ...).\\n"NEWLINES); + fprintf(cheader, " * - generated by stubser -"NEWLINES" */" NEWLINES NEWLINES); + + fprintf(cheader, "#ifndef _STUB_%s_USER_H"NEWLINES, aNoSuffix); + fprintf(cheader, "#define _STUB_%s_USER_H"NEWLINES NEWLINES, aNoSuffix); + + fprintf(cheader, NEWLINES"#endif // _STUB_%s_USER_H"NEWLINES, aNoSuffix); + + free(cHeaderName); + fclose(cheader); +} + STATIC int8_t createStub(char *aOutput, char *aNoSuffix, cfile_t *aCfile) { FILE *cfile; @@ -231,12 +279,15 @@ STATIC int8_t createStub(char *aOutput, char *aNoSuffix, cfile_t *aCfile) return -1; } + createUserHeader(aOutput, aNoSuffix); + fprintf(cfile, "/* @file %s"NEWLINES, gnu_basename(cFileName)); fprintf(cfile, " * @details"NEWLINES" * This is a stub for CUnit.\\n"NEWLINES); fprintf(cfile, " * - generated by stubser -"NEWLINES" */" NEWLINES NEWLINES); fprintf(cfile, "#include "NEWLINES); fprintf(cfile, "#include \"xtypes.h\""NEWLINES); fprintf(cfile, "#include \"stub.h\""NEWLINES); + fprintf(cfile, "#include \"stub_%s_user.h\""NEWLINES, aNoSuffix); fprintf(cfile, "#include \"%s\""NEWLINES NEWLINES, gnu_basename(cHeaderName)); fprintf(cheader, "/* @file %s"NEWLINES, gnu_basename(cHeaderName)); From e421f8137580048ca1550341ad240fbd7486cd57 Mon Sep 17 00:00:00 2001 From: Martin Winkler Date: Fri, 10 Mar 2017 15:06:55 +0000 Subject: [PATCH 06/38] - added TODO: special handling for function pointer --- src/stubser/cfile_parser.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/stubser/cfile_parser.c b/src/stubser/cfile_parser.c index 89f870f..61a01f3 100644 --- a/src/stubser/cfile_parser.c +++ b/src/stubser/cfile_parser.c @@ -484,6 +484,7 @@ STATIC int8_t evaluateParameter(char *aParameter, cfunction_t *aFunction) token = strtok(aParameter, ","); while (token) { + // TODO special handling for function pointer as argument if (0 == regexec(®Xparameter, token, CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS, matchGroup, 0)) { tempParameter = cfunction_newParameter(&aFunction->parameter); From ad2deb3b32d8b698f54949752aeeef1cc85765f4 Mon Sep 17 00:00:00 2001 From: Martin Winkler Date: Fri, 10 Mar 2017 15:07:19 +0000 Subject: [PATCH 07/38] - fix: create stubs only for regular files (STATIC functions are treated as regular) --- src/stubser/stubser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stubser/stubser.c b/src/stubser/stubser.c index fcc8c92..168f844 100644 --- a/src/stubser/stubser.c +++ b/src/stubser/stubser.c @@ -48,7 +48,7 @@ STATIC int8_t createStubFunctionBlock(FILE *aFile, FILE *aHeader, cfunction_t *a return -1; } - if (CFUNCTION_TYPE_REGULAR != aFunction->type && CFUNCTION_TYPE_STATIC != aFunction->type) + if (CFUNCTION_TYPE_REGULAR != aFunction->type) { return 1; } From adf425bb1aad837dda9a1d889dcd7a1b1f6aee93 Mon Sep 17 00:00:00 2001 From: Martin Winkler Date: Fri, 10 Mar 2017 22:48:29 +0000 Subject: [PATCH 08/38] - added creating function to work with stub global variables (init expected, init globals, check globals) --- src/stubser/stubser.c | 105 ++++++++++++++++++++++++++++++++++++++ src/stubser/stubser_loc.h | 5 ++ 2 files changed, 110 insertions(+) diff --git a/src/stubser/stubser.c b/src/stubser/stubser.c index 168f844..5ce87e6 100644 --- a/src/stubser/stubser.c +++ b/src/stubser/stubser.c @@ -38,6 +38,107 @@ STATIC bool isDatatypeVoid(char *aType) return true; } +STATIC int8_t createStubExpected(char *aNoSuffix, FILE *aFile, FILE *aHeader, cfile_variableList_t *aList) +{ + cfile_variable_t *work = NULL; + if (NULL == aFile || NULL == aHeader || NULL == aList) + { + return -1; + } + + work = aList->head; + while (work) + { + if (CVARIABLE_TYPE_REGULAR != work->type) + { + work = work->next; + continue; + } + fprintf(aFile, "%s "STUBVARIABLE_EXTENDED_S1";"NEWLINES, work->dataType, work->name); + fprintf(aHeader, "extern %s "STUBVARIABLE_EXTENDED_S1";"NEWLINES, work->dataType, work->name); + work = work->next; + } + + fprintf(aHeader, "void "STUBFUNCTION_INITEXPECTED_S1"();"NEWLINES NEWLINES, aNoSuffix); + fprintf(aFile, NEWLINES"void "STUBFUNCTION_INITEXPECTED_S1"()"NEWLINES"{"NEWLINES, aNoSuffix); + + work = aList->head; + while (work) + { + if (CVARIABLE_TYPE_REGULAR != work->type) + { + work = work->next; + continue; + } + // TODO type specific initialization + fprintf(aFile, "\t"STUBVARIABLE_EXTENDED_S1" = 0x55;"NEWLINES, work->name); + work = work->next; + } + + fprintf(aFile, "}"NEWLINES); + + return 0; +} + +STATIC int8_t createStubGlobals(char *aNoSuffix, FILE *aFile, FILE *aHeader, cfile_variableList_t *aList) +{ + cfile_variable_t *work = NULL; + if (NULL == aFile || NULL == aHeader || NULL == aList) + { + return -1; + } + + fprintf(aFile, NEWLINES"void "STUBFUNCTION_INITGLOBALS_S1"()"NEWLINES"{"NEWLINES, aNoSuffix); + + work = aList->head; + while (work) + { + if (CVARIABLE_TYPE_REGULAR != work->type) + { + work = work->next; + continue; + } + // TODO type specific initialization + fprintf(aFile, "\t%s = 0x55;"NEWLINES, work->name); + fprintf(aHeader, "extern %s %s;"NEWLINES, work->dataType, work->name); + work = work->next; + } + + fprintf(aFile, "}"NEWLINES); + fprintf(aHeader, "void "STUBFUNCTION_INITGLOBALS_S1"();"NEWLINES NEWLINES, aNoSuffix); + + return 0; +} + +STATIC int8_t createStubCheck(char *aNoSuffix, FILE *aFile, FILE *aHeader, cfile_variableList_t *aList) +{ + cfile_variable_t *work = NULL; + if (NULL == aFile || NULL == aHeader || NULL == aList) + { + return -1; + } + + fprintf(aHeader, "void "STUBFUNCTION_CHECK_S1"();"NEWLINES NEWLINES, aNoSuffix); + fprintf(aFile, NEWLINES"void "STUBFUNCTION_CHECK_S1"()"NEWLINES"{"NEWLINES, aNoSuffix); + + work = aList->head; + while (work) + { + if (CVARIABLE_TYPE_REGULAR != work->type) + { + work = work->next; + continue; + } + // TODO type specific initialization + fprintf(aFile, "\tCU_ASSERT_EQUAL(%s, "STUBVARIABLE_EXTENDED_S1");"NEWLINES, work->name, work->name); + work = work->next; + } + + fprintf(aFile, "}"NEWLINES NEWLINES); + + return 0; +} + STATIC int8_t createStubFunctionBlock(FILE *aFile, FILE *aHeader, cfunction_t *aFunction) { cfunction_parameter_t *parameter = NULL; @@ -297,6 +398,10 @@ STATIC int8_t createStub(char *aOutput, char *aNoSuffix, cfile_t *aCfile) fprintf(cheader, "#ifndef _STUB_%s_H"NEWLINES, aNoSuffix); fprintf(cheader, "#define _STUB_%s_H"NEWLINES NEWLINES, aNoSuffix); + createStubExpected(aNoSuffix, cfile, cheader, &aCfile->variables); + createStubGlobals(aNoSuffix, cfile, cheader, &aCfile->variables); + createStubCheck(aNoSuffix, cfile, cheader, &aCfile->variables); + function = aCfile->functions.head; while (function) { diff --git a/src/stubser/stubser_loc.h b/src/stubser/stubser_loc.h index 78a77e4..63dc3b1 100644 --- a/src/stubser/stubser_loc.h +++ b/src/stubser/stubser_loc.h @@ -38,6 +38,11 @@ #define STUBINIT_PARAM_PARAMETER_S1 "aParameter_%c" // aParameter_a #define STUBINIT_PARAM_RETURN_S "aReturnValue" +#define STUBFUNCTION_INITEXPECTED_S1 "stub_%s_initExpected" // stub_testfunction_checkGlobals +#define STUBFUNCTION_INITGLOBALS_S1 "stub_%s_initGlobals" // stub_testfunction_checkGlobals +#define STUBFUNCTION_CHECK_S1 "stub_%s_checkGlobals" // stub_testfunction_checkGlobals +#define STUBVARIABLE_EXTENDED_S1 "%s_expected" // variable_expected + #define STUB_CONSOLE_OK "[ OK ]" #define STUB_CONSOLE_FAIL "[FAIL]" #define STUB_CONSOLE_PARSE_ERROR_S2 STUB_CONSOLE_FAIL " %s parsing failed (%d)\n" From 0a1f9a39cfe477d728fb182fdb20eb0efc4629b6 Mon Sep 17 00:00:00 2001 From: Martin Winkler Date: Sat, 11 Mar 2017 12:40:36 +0000 Subject: [PATCH 09/38] - fix: detecting pointer arguments --- src/stubser/cfile_parser_loc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stubser/cfile_parser_loc.h b/src/stubser/cfile_parser_loc.h index 26ca9c7..2dfafd2 100644 --- a/src/stubser/cfile_parser_loc.h +++ b/src/stubser/cfile_parser_loc.h @@ -30,7 +30,7 @@ #define FUNCTION_BASE CPARS_EXPRESSION_BASE "[[:blank:]]*\\([[:blank:]]*" #define CPARS_REGEX_FUNCTION FUNCTION_BASE "(.*)\\)[[:blank:]\\{\\};]+[[:blank:]]*" #define CPARS_REGEX_VARIABLE CPARS_EXPRESSION_BASE "[[:blank:]]*[;=]" -#define CPARS_REGEX_PARAMETER "[[:blank:]]*([ _\\*[:alnum:]]* +\\**)([_\\*[:alnum:]]*)[[:blank:]]*" +#define CPARS_REGEX_PARAMETER "[[:blank:]]*([ _\\*[:alnum:]]* +\\**)([_\\*[:alnum:]]+)[[:blank:]]*" #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:]]*)" From 4a4abfa46f2c0b4841365e5dfba844ec3dcb7b39 Mon Sep 17 00:00:00 2001 From: Martin Winkler Date: Sat, 11 Mar 2017 12:41:39 +0000 Subject: [PATCH 10/38] - added function to init both (globals and expected) - cleaning debug output --- src/stubser/stubser.c | 29 +++++++++++++++++++++++------ src/stubser/stubser_loc.h | 5 +++-- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/stubser/stubser.c b/src/stubser/stubser.c index 5ce87e6..d9b5c46 100644 --- a/src/stubser/stubser.c +++ b/src/stubser/stubser.c @@ -60,7 +60,7 @@ STATIC int8_t createStubExpected(char *aNoSuffix, FILE *aFile, FILE *aHeader, cf } fprintf(aHeader, "void "STUBFUNCTION_INITEXPECTED_S1"();"NEWLINES NEWLINES, aNoSuffix); - fprintf(aFile, NEWLINES"void "STUBFUNCTION_INITEXPECTED_S1"()"NEWLINES"{"NEWLINES, aNoSuffix); + fprintf(aFile, "void "STUBFUNCTION_INITEXPECTED_S1"()"NEWLINES"{"NEWLINES, aNoSuffix); work = aList->head; while (work) @@ -75,7 +75,7 @@ STATIC int8_t createStubExpected(char *aNoSuffix, FILE *aFile, FILE *aHeader, cf work = work->next; } - fprintf(aFile, "}"NEWLINES); + fprintf(aFile, "}"NEWLINES NEWLINES); return 0; } @@ -88,7 +88,20 @@ STATIC int8_t createStubGlobals(char *aNoSuffix, FILE *aFile, FILE *aHeader, cfi return -1; } - fprintf(aFile, NEWLINES"void "STUBFUNCTION_INITGLOBALS_S1"()"NEWLINES"{"NEWLINES, aNoSuffix); + work = aList->head; + while (work) + { + if (CVARIABLE_TYPE_REGULAR != work->type) + { + work = work->next; + continue; + } + fprintf(aFile, "%s %s;"NEWLINES, work->dataType, work->name); + fprintf(aHeader, "extern %s %s;"NEWLINES, work->dataType, work->name); + work = work->next; + } + + fprintf(aFile, "void "STUBFUNCTION_INITGLOBALS_S1"()"NEWLINES"{"NEWLINES, aNoSuffix); work = aList->head; while (work) @@ -100,13 +113,17 @@ STATIC int8_t createStubGlobals(char *aNoSuffix, FILE *aFile, FILE *aHeader, cfi } // TODO type specific initialization fprintf(aFile, "\t%s = 0x55;"NEWLINES, work->name); - fprintf(aHeader, "extern %s %s;"NEWLINES, work->dataType, work->name); work = work->next; } fprintf(aFile, "}"NEWLINES); - fprintf(aHeader, "void "STUBFUNCTION_INITGLOBALS_S1"();"NEWLINES NEWLINES, aNoSuffix); + fprintf(aHeader, "void "STUBFUNCTION_INITGLOBALS_S1"();"NEWLINES, aNoSuffix); + fprintf(aHeader, "void "STUBFUNCTION_INIT_S1"();"NEWLINES NEWLINES, aNoSuffix); + fprintf(aFile, NEWLINES"void "STUBFUNCTION_INIT_S1"()"NEWLINES"{"NEWLINES, aNoSuffix); + fprintf(aFile, "\t"STUBFUNCTION_INITEXPECTED_S1"();"NEWLINES, aNoSuffix); + fprintf(aFile, "\t"STUBFUNCTION_INITGLOBALS_S1"();"NEWLINES, aNoSuffix); + fprintf(aFile, "}"NEWLINES NEWLINES); return 0; } @@ -119,7 +136,7 @@ STATIC int8_t createStubCheck(char *aNoSuffix, FILE *aFile, FILE *aHeader, cfile } fprintf(aHeader, "void "STUBFUNCTION_CHECK_S1"();"NEWLINES NEWLINES, aNoSuffix); - fprintf(aFile, NEWLINES"void "STUBFUNCTION_CHECK_S1"()"NEWLINES"{"NEWLINES, aNoSuffix); + fprintf(aFile, "void "STUBFUNCTION_CHECK_S1"()"NEWLINES"{"NEWLINES, aNoSuffix); work = aList->head; while (work) diff --git a/src/stubser/stubser_loc.h b/src/stubser/stubser_loc.h index 63dc3b1..65096ea 100644 --- a/src/stubser/stubser_loc.h +++ b/src/stubser/stubser_loc.h @@ -38,8 +38,9 @@ #define STUBINIT_PARAM_PARAMETER_S1 "aParameter_%c" // aParameter_a #define STUBINIT_PARAM_RETURN_S "aReturnValue" -#define STUBFUNCTION_INITEXPECTED_S1 "stub_%s_initExpected" // stub_testfunction_checkGlobals -#define STUBFUNCTION_INITGLOBALS_S1 "stub_%s_initGlobals" // stub_testfunction_checkGlobals +#define STUBFUNCTION_INITEXPECTED_S1 "stub_%s_initExpected" // stub_testfunction_initExpected +#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 From 0e0addd8d2b7e855c7d01e171743275696344c22 Mon Sep 17 00:00:00 2001 From: Martin Winkler Date: Sat, 11 Mar 2017 12:42:05 +0000 Subject: [PATCH 11/38] - cleaning debug output --- src/stubser/cfile_parser.c | 4 ++-- src/stubser/cfunction.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/stubser/cfile_parser.c b/src/stubser/cfile_parser.c index 61a01f3..fef509d 100644 --- a/src/stubser/cfile_parser.c +++ b/src/stubser/cfile_parser.c @@ -572,14 +572,14 @@ STATIC int8_t cfile_parser_evaluateLine(uint32_t aNumber, char *aLine, cfile_t * if (NULL != (tempMatch = strstr(position, "#include"))) { // TODO save include information - DEBUG_LOG_APPEND(1, "[ Re %04u] Works %zu %s\n", aNumber, strlen(tempMatch), tempMatch); + DEBUG_LOG_APPEND(1, "[ Re %04u][%zu] %s\n", aNumber, strlen(tempMatch), tempMatch); position = NULL; continue; } result = regExWorker(&match, &position, matchStart, matchEnd, &depth, false); if (match && 0 == result && 0 == depth) { - DEBUG_LOG_APPEND(1, "[ Re %04u] Works %zu %s\n", aNumber, strlen(match), match); + 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); diff --git a/src/stubser/cfunction.c b/src/stubser/cfunction.c index f1a2d5d..4b1ac67 100644 --- a/src/stubser/cfunction.c +++ b/src/stubser/cfunction.c @@ -162,7 +162,7 @@ void cfunction_printList(cfunction_list_t *aList) printf("[ cfu]%d:<%s> (%s) %s [%d] ", work->type, work->prefix, work->dataType, work->name, work->parameter.amount); while (param) { - printf("%s|%s,", param->type, param->name); + printf("(%s)%s,", param->type, param->name); param = param->next; } printf("\n"); From c6231c40079cf4096094bd833fb79da22ca5b41e Mon Sep 17 00:00:00 2001 From: Martin Winkler Date: Mon, 13 Mar 2017 10:11:55 +0000 Subject: [PATCH 12/38] - work on warnings counting and console output --- src/stubser/cfile_parser.c | 113 +++++++++++--------------- src/stubser/cfile_parser_if.h | 2 +- src/stubser/cfile_parser_loc.h | 2 + src/stubser/cfile_parser_worker.c | 53 +++++++----- src/stubser/cfile_parser_worker_loc.h | 2 +- src/stubser/stubser.c | 31 ++++--- src/stubser/stubser_loc.h | 12 ++- 7 files changed, 107 insertions(+), 108 deletions(-) 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_ */ From 6b4f3f41379c7a56d8085dc2db1ff0d40aa63349 Mon Sep 17 00:00:00 2001 From: Martin Winkler Date: Mon, 13 Mar 2017 14:00:56 +0000 Subject: [PATCH 13/38] - stub variable specific initialization and check --- src/stubser/cfile_parser_loc.h | 2 +- src/stubser/stubser.c | 94 +++++++++++++++++++++++++++++++--- src/stubser/stubser_loc.h | 2 + 3 files changed, 89 insertions(+), 9 deletions(-) diff --git a/src/stubser/cfile_parser_loc.h b/src/stubser/cfile_parser_loc.h index 533b673..eb85ec9 100644 --- a/src/stubser/cfile_parser_loc.h +++ b/src/stubser/cfile_parser_loc.h @@ -25,7 +25,7 @@ #define CPARS_PREFIX_STATIC_S "static" #define CPARS_PREFIX_EXTERN_S "extern" -#define CPARS_EXPRESSION_BASE "^[[:blank:]]*([ _\\*[:alnum:]]* +\\**)([_\\*[:alnum:]]+)" +#define CPARS_EXPRESSION_BASE "^[[:blank:]]*([ _\\*[:alnum:]]* +\\**)([_\\*[:alnum:]\\[\\]]+)" #define FUNCTION_BASE CPARS_EXPRESSION_BASE "[[:blank:]]*\\([[:blank:]]*" #define CPARS_REGEX_FUNCTION FUNCTION_BASE "(.*)\\)[[:blank:]\\{\\};]+[[:blank:]]*" diff --git a/src/stubser/stubser.c b/src/stubser/stubser.c index dc8584a..384a545 100644 --- a/src/stubser/stubser.c +++ b/src/stubser/stubser.c @@ -38,6 +38,71 @@ STATIC bool isDatatypeVoid(char *aType) return true; } +STATIC bool isDatatypeStandard(cfile_variable_t *aVariable) +{ + regex_t regXvariable; + + if (0 > regcomp(®Xvariable, STUB_REGEX_STD_DATATYPE, (REG_EXTENDED))) + { + perror("Error regex\n"); + return false; + } + + if (0 == regexec(®Xvariable, aVariable->dataType, 0, NULL, 0)) + { + return true; + } + + return false; +} + +STATIC void createVariableSpecificInit(const char* aVariableTemplate, FILE *aFile, cfile_variable_t *aVariable) +{ + if (NULL != strstr(aVariable->dataType, "const")) + { + return; + } + + if (NULL != strstr(aVariable->dataType, "*")) + { + fprintf(aFile, aVariableTemplate, aVariable->name); + fprintf(aFile, " = NULL;" NEWLINES); + } + else if (isDatatypeStandard(aVariable)) + { + fprintf(aFile, aVariableTemplate, aVariable->name); + fprintf(aFile, " = 0x55;" NEWLINES); + } + else + { + fprintf(aFile, "\t(void) memset(&"); + fprintf(aFile, aVariableTemplate, aVariable->name); + fprintf(aFile, ",0x55,sizeof(%s)); /* %s */" NEWLINES, aVariable->name, aVariable->dataType); + } +} + +STATIC void createVariableSpecificCheck(FILE *aFile, cfile_variable_t *aVariable) +{ + if (NULL != strstr(aVariable->dataType, "const")) + { + return; + } + + if (NULL != strstr(aVariable->dataType, "*")) + { + fprintf(aFile, "\tCU_ASSERT_PTR_EQUAL(%s, "STUBVARIABLE_EXTENDED_S1");"NEWLINES, aVariable->name, aVariable->name); + } + else if (isDatatypeStandard(aVariable)) + { + fprintf(aFile, "\tCU_ASSERT_EQUAL(%s, "STUBVARIABLE_EXTENDED_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, aVariable->name, + aVariable->name); + } +} + STATIC int8_t createStubExpected(char *aNoSuffix, FILE *aFile, FILE *aHeader, cfile_variableList_t *aList) { cfile_variable_t *work = NULL; @@ -46,6 +111,11 @@ STATIC int8_t createStubExpected(char *aNoSuffix, FILE *aFile, FILE *aHeader, cf return -1; } + if (0 == aList->amount) + { + return 0; + } + work = aList->head; while (work) { @@ -70,8 +140,7 @@ STATIC int8_t createStubExpected(char *aNoSuffix, FILE *aFile, FILE *aHeader, cf work = work->next; continue; } - // TODO type specific initialization - fprintf(aFile, "\t"STUBVARIABLE_EXTENDED_S1" = 0x55;"NEWLINES, work->name); + createVariableSpecificInit("\t"STUBVARIABLE_EXTENDED_S1, aFile, work); work = work->next; } @@ -88,6 +157,11 @@ STATIC int8_t createStubGlobals(char *aNoSuffix, FILE *aFile, FILE *aHeader, cfi return -1; } + if (0 == aList->amount) + { + return 0; + } + work = aList->head; while (work) { @@ -111,8 +185,7 @@ STATIC int8_t createStubGlobals(char *aNoSuffix, FILE *aFile, FILE *aHeader, cfi work = work->next; continue; } - // TODO type specific initialization - fprintf(aFile, "\t%s = 0x55;"NEWLINES, work->name); + createVariableSpecificInit("\t%s", aFile, work); work = work->next; } @@ -135,6 +208,11 @@ STATIC int8_t createStubCheck(char *aNoSuffix, FILE *aFile, FILE *aHeader, cfile return -1; } + if (0 == aList->amount) + { + return 0; + } + fprintf(aHeader, "void "STUBFUNCTION_CHECK_S1"();"NEWLINES NEWLINES, aNoSuffix); fprintf(aFile, "void "STUBFUNCTION_CHECK_S1"()"NEWLINES"{"NEWLINES, aNoSuffix); @@ -146,8 +224,7 @@ STATIC int8_t createStubCheck(char *aNoSuffix, FILE *aFile, FILE *aHeader, cfile work = work->next; continue; } - // TODO type specific initialization - fprintf(aFile, "\tCU_ASSERT_EQUAL(%s, "STUBVARIABLE_EXTENDED_S1");"NEWLINES, work->name, work->name); + createVariableSpecificCheck(aFile, work); work = work->next; } @@ -208,7 +285,7 @@ STATIC int8_t createStubFunctionBlock(FILE *aFile, FILE *aHeader, cfunction_t *a aFunction->name); NEWLINE(aFile); - // stub function init header +// stub function init header fprintf(aHeader, "void init_%s(uint8_t "STUBINIT_PARAM_INSTANCE_S", uint8_t "STUBINIT_PARAM_CALLTEST_S, aFunction->name); if (!isDatatypeVoid(aFunction->dataType)) { @@ -338,7 +415,7 @@ STATIC void createUserHeader(char *aOutput, char *aNoSuffix) return; } - // user header doesn't exist +// user header doesn't exist cheader = fopen(cHeaderName, "w"); if (NULL == cheader) { @@ -403,6 +480,7 @@ STATIC int8_t createStub(char *aOutput, char *aNoSuffix, cfile_t *aCfile) fprintf(cfile, " * @details"NEWLINES" * This is a stub for CUnit.\\n"NEWLINES); fprintf(cfile, " * - generated by stubser -"NEWLINES" */" NEWLINES NEWLINES); fprintf(cfile, "#include "NEWLINES); + fprintf(cfile, "#include \"xasserts.h\""NEWLINES); fprintf(cfile, "#include \"xtypes.h\""NEWLINES); fprintf(cfile, "#include \"stub.h\""NEWLINES); fprintf(cfile, "#include \"stub_%s_user.h\""NEWLINES, aNoSuffix); diff --git a/src/stubser/stubser_loc.h b/src/stubser/stubser_loc.h index 2037700..81b3574 100644 --- a/src/stubser/stubser_loc.h +++ b/src/stubser/stubser_loc.h @@ -54,4 +54,6 @@ #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" + +#define STUB_REGEX_STD_DATATYPE "u*int[0-9]{1,2}_t|uchar" #endif /* STUBSER_STUBSER_LOC_H_ */ From 1fa51576e36ca76a46479e1df2ba3747379bb795 Mon Sep 17 00:00:00 2001 From: Martin Winkler Date: Mon, 13 Mar 2017 19:42:03 +0000 Subject: [PATCH 14/38] - detect arrays and save size in structure - static variables not in stub --- src/stubser/cfile.c | 2 +- src/stubser/cfile_if.h | 1 + src/stubser/cfile_parser.c | 10 ++++++++-- src/stubser/cfile_parser_loc.h | 5 +++-- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/stubser/cfile.c b/src/stubser/cfile.c index bde9088..63f57a5 100644 --- a/src/stubser/cfile.c +++ b/src/stubser/cfile.c @@ -91,7 +91,7 @@ void cfile_print(cfile_t *aCfile) while (work) { - printf("[ cva]%d:<%s> (%s) %s\n", work->type, work->prefix, work->dataType, work->name); + printf("[ cva]%d:<%s> (%s) %s %s\n", work->type, work->prefix, work->dataType, work->name, work->array); work = work->next; } diff --git a/src/stubser/cfile_if.h b/src/stubser/cfile_if.h index a53525f..8e92154 100644 --- a/src/stubser/cfile_if.h +++ b/src/stubser/cfile_if.h @@ -33,6 +33,7 @@ typedef struct _CFILE_VARIABLE_T char* prefix; /*!< @brief variable prefix (e.g. static) */ char* dataType; /*!< @brief data type */ char* name; /*!< @brief name */ + char* array; /*!< @brief array information (e.g. [10] or [DEF_MAX]) */ struct _CFILE_VARIABLE_T *next; } cfile_variable_t; diff --git a/src/stubser/cfile_parser.c b/src/stubser/cfile_parser.c index 09089e0..62c6ed5 100644 --- a/src/stubser/cfile_parser.c +++ b/src/stubser/cfile_parser.c @@ -129,7 +129,8 @@ STATIC void checkFunctionType(cfunction_t *aFunction, char *aExpression) { aFunction->type = CFUNCTION_TYPE_EXTERN; } - else if (NULL != strstr(aFunction->prefix, CPARS_PREFIX_STATIC_S) && CFUNCTION_TYPE_PROTO != aFunction->type) + else if ((NULL != strstr(aFunction->prefix, CPARS_PREFIX_STATIC_S) || NULL != strstr(aFunction->prefix, CPARS_PREFIX_STATIC2_S)) + && CFUNCTION_TYPE_PROTO != aFunction->type) { aFunction->type = CFUNCTION_TYPE_STATIC; } @@ -208,7 +209,7 @@ STATIC int8_t matchPrefix(void *aElement, celement_type_t aElementType, char *aS { ((cfunction_t*) aElement)->type = CFUNCTION_TYPE_EXTERN; } - else if (*prefix && NULL != strstr(*prefix, CPARS_PREFIX_STATIC_S)) + else if (*prefix && (NULL != strstr(*prefix, CPARS_PREFIX_STATIC_S) || NULL != strstr(*prefix, CPARS_PREFIX_STATIC2_S))) { ((cfunction_t*) aElement)->type = CFUNCTION_TYPE_STATIC; } @@ -549,6 +550,11 @@ STATIC int8_t cfile_parser_evaluateExpression(char *aExpression, cfile_t *aCfile { (void) matchPrefix(variable, CELEMENT_TYPE_VARIABLE, &aExpression[matchGroup[1].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 1)); 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)); + } } } diff --git a/src/stubser/cfile_parser_loc.h b/src/stubser/cfile_parser_loc.h index eb85ec9..1e59280 100644 --- a/src/stubser/cfile_parser_loc.h +++ b/src/stubser/cfile_parser_loc.h @@ -23,13 +23,14 @@ #define CPARS_PROTOTYPE_END_C ';' #define CPARS_PREFIX_STATIC_S "static" +#define CPARS_PREFIX_STATIC2_S "STATIC" #define CPARS_PREFIX_EXTERN_S "extern" -#define CPARS_EXPRESSION_BASE "^[[:blank:]]*([ _\\*[:alnum:]]* +\\**)([_\\*[:alnum:]\\[\\]]+)" +#define CPARS_EXPRESSION_BASE "^[[: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:]]*[;=]" +#define CPARS_REGEX_VARIABLE CPARS_EXPRESSION_BASE "[[:blank:]]*(\\[*[^;=]*)[[:blank:]]*[;=]" #define CPARS_REGEX_PARAMETER "[[:blank:]]*([ _\\*[:alnum:]]* +\\**)([_\\*[:alnum:]]+)[[:blank:]]*" #define CPARS_REGEX_PREFIX "("CPARS_PREFIX_EXTERN_S"|EXTERN|"CPARS_PREFIX_STATIC_S"|STATIC|volatile|near|far)[[:blank:]]*(.*)" From 506bb44c58a60e3369f066ffb6cb77f3239ea984 Mon Sep 17 00:00:00 2001 From: Martin Winkler Date: Mon, 13 Mar 2017 19:46:07 +0000 Subject: [PATCH 15/38] - improved globals and expected initializatian and testing --- src/stubser/stubser.c | 51 ++++++++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 15 deletions(-) diff --git a/src/stubser/stubser.c b/src/stubser/stubser.c index 384a545..1dc93be 100644 --- a/src/stubser/stubser.c +++ b/src/stubser/stubser.c @@ -63,13 +63,25 @@ STATIC void createVariableSpecificInit(const char* aVariableTemplate, FILE *aFil return; } - if (NULL != strstr(aVariable->dataType, "*")) + if (NULL != strstr(aVariable->dataType, "*") || aVariable->array) { - fprintf(aFile, aVariableTemplate, aVariable->name); - fprintf(aFile, " = NULL;" NEWLINES); + if (aVariable->array) + { + fprintf(aFile, "\t(void) memset("); + fprintf(aFile, aVariableTemplate, aVariable->name); + fprintf(aFile, ", 0x55, sizeof(%s)); /* %s */" NEWLINES, aVariable->name, aVariable->dataType); + } + else + { + fprintf(aFile, "\t"); + fprintf(aFile, aVariableTemplate, aVariable->name); + fprintf(aFile, " = NULL;" NEWLINES); + } + } else if (isDatatypeStandard(aVariable)) { + fprintf(aFile, "\t"); fprintf(aFile, aVariableTemplate, aVariable->name); fprintf(aFile, " = 0x55;" NEWLINES); } @@ -77,7 +89,7 @@ STATIC void createVariableSpecificInit(const char* aVariableTemplate, FILE *aFil { fprintf(aFile, "\t(void) memset(&"); fprintf(aFile, aVariableTemplate, aVariable->name); - fprintf(aFile, ",0x55,sizeof(%s)); /* %s */" NEWLINES, aVariable->name, aVariable->dataType); + fprintf(aFile, ", 0x55, sizeof(%s)); /* %s */" NEWLINES, aVariable->name, aVariable->dataType); } } @@ -88,9 +100,18 @@ STATIC void createVariableSpecificCheck(FILE *aFile, cfile_variable_t *aVariable return; } - if (NULL != strstr(aVariable->dataType, "*")) + if (NULL != strstr(aVariable->dataType, "*") || aVariable->array) { - fprintf(aFile, "\tCU_ASSERT_PTR_EQUAL(%s, "STUBVARIABLE_EXTENDED_S1");"NEWLINES, aVariable->name, aVariable->name); + if (aVariable->array) + { + fprintf(aFile, "\tCU_ASSERT_MEMORY_CHECK(\"%s\", %s, "STUBVARIABLE_EXTENDED_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); + } + } else if (isDatatypeStandard(aVariable)) { @@ -98,8 +119,8 @@ STATIC void createVariableSpecificCheck(FILE *aFile, cfile_variable_t *aVariable } else { - fprintf(aFile, "\tCU_ASSERT_MEMORY_CHECK(\"%s\", &%s, &"STUBVARIABLE_EXTENDED_S1", sizeof(%s));"NEWLINES, aVariable->name, aVariable->name, aVariable->name, - aVariable->name); + fprintf(aFile, "\tCU_ASSERT_MEMORY_CHECK(\"%s\", &%s, &"STUBVARIABLE_EXTENDED_S1", sizeof(%s));"NEWLINES, aVariable->name, aVariable->name, + aVariable->name, aVariable->name); } } @@ -119,13 +140,13 @@ STATIC int8_t createStubExpected(char *aNoSuffix, FILE *aFile, FILE *aHeader, cf work = aList->head; while (work) { - if (CVARIABLE_TYPE_REGULAR != work->type) + if (CVARIABLE_TYPE_REGULAR != work->type || NULL != strstr(work->dataType, "const")) { work = work->next; continue; } - fprintf(aFile, "%s "STUBVARIABLE_EXTENDED_S1";"NEWLINES, work->dataType, work->name); - fprintf(aHeader, "extern %s "STUBVARIABLE_EXTENDED_S1";"NEWLINES, work->dataType, work->name); + 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 : "")); work = work->next; } @@ -140,7 +161,7 @@ STATIC int8_t createStubExpected(char *aNoSuffix, FILE *aFile, FILE *aHeader, cf work = work->next; continue; } - createVariableSpecificInit("\t"STUBVARIABLE_EXTENDED_S1, aFile, work); + createVariableSpecificInit(STUBVARIABLE_EXTENDED_S1, aFile, work); work = work->next; } @@ -170,8 +191,8 @@ STATIC int8_t createStubGlobals(char *aNoSuffix, FILE *aFile, FILE *aHeader, cfi work = work->next; continue; } - fprintf(aFile, "%s %s;"NEWLINES, work->dataType, work->name); - fprintf(aHeader, "extern %s %s;"NEWLINES, work->dataType, work->name); + 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; } @@ -185,7 +206,7 @@ STATIC int8_t createStubGlobals(char *aNoSuffix, FILE *aFile, FILE *aHeader, cfi work = work->next; continue; } - createVariableSpecificInit("\t%s", aFile, work); + createVariableSpecificInit("%s", aFile, work); work = work->next; } From a2c91798c59dfae9d380afa6c4d06cbe13bed245 Mon Sep 17 00:00:00 2001 From: Martin Winkler Date: Wed, 15 Mar 2017 05:40:44 +0000 Subject: [PATCH 16/38] - fix: calltest was not initialized - create parameter type sepcific checks --- src/stubser/stubser.c | 53 +++++++++++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 14 deletions(-) diff --git a/src/stubser/stubser.c b/src/stubser/stubser.c index 1dc93be..785514d 100644 --- a/src/stubser/stubser.c +++ b/src/stubser/stubser.c @@ -38,7 +38,7 @@ STATIC bool isDatatypeVoid(char *aType) return true; } -STATIC bool isDatatypeStandard(cfile_variable_t *aVariable) +STATIC bool isDatatypeStandard(char *aDataType) { regex_t regXvariable; @@ -48,7 +48,7 @@ STATIC bool isDatatypeStandard(cfile_variable_t *aVariable) return false; } - if (0 == regexec(®Xvariable, aVariable->dataType, 0, NULL, 0)) + if (0 == regexec(®Xvariable, aDataType, 0, NULL, 0)) { return true; } @@ -79,7 +79,7 @@ STATIC void createVariableSpecificInit(const char* aVariableTemplate, FILE *aFil } } - else if (isDatatypeStandard(aVariable)) + else if (isDatatypeStandard(aVariable->dataType)) { fprintf(aFile, "\t"); fprintf(aFile, aVariableTemplate, aVariable->name); @@ -113,7 +113,7 @@ STATIC void createVariableSpecificCheck(FILE *aFile, cfile_variable_t *aVariable } } - else if (isDatatypeStandard(aVariable)) + else if (isDatatypeStandard(aVariable->dataType)) { fprintf(aFile, "\tCU_ASSERT_EQUAL(%s, "STUBVARIABLE_EXTENDED_S1");"NEWLINES, aVariable->name, aVariable->name); } @@ -124,6 +124,38 @@ STATIC void createVariableSpecificCheck(FILE *aFile, cfile_variable_t *aVariable } } +STATIC void createParameterSpecificCheck(FILE *aFile, cfunction_t *aFunction, cfunction_parameter_t *aParameter, char aParameterIndex) +{ + if (NULL != strstr(aParameter->type, "*") && NULL != strstr(aParameter->type, "char")) + { + fprintf(aFile, "\tCU_ASSERT_MEMORY_CHECK(\"%s(%s)\", ", aFunction->name, aParameter->name); + fprintf(aFile, STUBINIT_PARAM_PARAMETER_S1", "STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_PARAM_S1, aParameterIndex, aFunction->name, + aFunction->name, aParameterIndex); + fprintf(aFile, ", strlen("STUBINIT_PARAM_PARAMETER_S1"));"NEWLINES, aParameterIndex); + } + else if (NULL != strstr(aParameter->type, "*")) + { + fprintf(aFile, "\tCU_ASSERT_PTR_EQUAL("); + fprintf(aFile, STUBINIT_PARAM_PARAMETER_S1", "STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_PARAM_S1, aParameterIndex, aFunction->name, + aFunction->name, aParameterIndex); + fprintf(aFile, ");"NEWLINES); + } + else if (isDatatypeStandard(aParameter->type)) + { + fprintf(aFile, "\tCU_ASSERT_EQUAL("); + fprintf(aFile, STUBINIT_PARAM_PARAMETER_S1", "STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_PARAM_S1, aParameterIndex, aFunction->name, + aFunction->name, aParameterIndex); + fprintf(aFile, ");"NEWLINES); + } + else + { + fprintf(aFile, "\tCU_ASSERT_MEMORY_CHECK(\"%s(%s)\", ", aFunction->name, aParameter->name); + fprintf(aFile, "&"STUBINIT_PARAM_PARAMETER_S1", &"STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_PARAM_S1, aParameterIndex, aFunction->name, + aFunction->name, aParameterIndex); + fprintf(aFile, ", sizeof("STUBINIT_PARAM_PARAMETER_S1"));"NEWLINES, aParameterIndex); + } +} + STATIC int8_t createStubExpected(char *aNoSuffix, FILE *aFile, FILE *aHeader, cfile_variableList_t *aList) { cfile_variable_t *work = NULL; @@ -341,6 +373,8 @@ STATIC int8_t createStubFunctionBlock(FILE *aFile, FILE *aHeader, cfunction_t *a fprintf(aFile, "\t\tCU_FAIL_FATAL(\"init_%s() - "STUBINIT_PARAM_INSTANCE_S" out of bounce\");" NEWLINES, aFunction->name); fprintf(aFile, "\t}" NEWLINES); fprintf(aFile, "\t"STUBINSTANCE_S1" = 0;" NEWLINES, aFunction->name); + fprintf(aFile, "\t"STUBPARAMETER_STRUCT_S1"["STUBINIT_PARAM_INSTANCE_S"]."STUBPARAMETER_CALLTEST_S" = "STUBINIT_PARAM_CALLTEST_S";" NEWLINES, + aFunction->name); if (!isDatatypeVoid(aFunction->dataType)) { fprintf(aFile, "\t"STUBPARAMETER_STRUCT_S1"["STUBINIT_PARAM_INSTANCE_S"]."STUBPARAMETER_RETURN_S" = "STUBINIT_PARAM_RETURN_S";" NEWLINES, @@ -381,16 +415,7 @@ STATIC int8_t createStubFunctionBlock(FILE *aFile, FILE *aHeader, cfunction_t *a parameterIndex = 'a'; while (parameter) { - if (NULL != strstr(parameter->type, "*")) - { - fprintf(aFile, "\tCU_ASSERT_PTR_EQUAL("); - } - else - { - fprintf(aFile, "\tCU_ASSERT_EQUAL("); - } - fprintf(aFile, STUBINIT_PARAM_PARAMETER_S1", "STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_PARAM_S1");" NEWLINES, parameterIndex, - aFunction->name, aFunction->name, parameterIndex); + createParameterSpecificCheck(aFile, aFunction, parameter, parameterIndex); ++parameterIndex; parameter = parameter->next; } From f89149234724be41e01fd531bdd2e4945e22fdc4 Mon Sep 17 00:00:00 2001 From: Martin Winkler Date: Wed, 15 Mar 2017 05:41:03 +0000 Subject: [PATCH 17/38] - improved regex for standard data types --- src/stubser/stubser_loc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stubser/stubser_loc.h b/src/stubser/stubser_loc.h index 81b3574..457e49e 100644 --- a/src/stubser/stubser_loc.h +++ b/src/stubser/stubser_loc.h @@ -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 "u*int[0-9]{1,2}_t|uchar" +#define STUB_REGEX_STD_DATATYPE "(^|[^_[:alnum:]])([ui]+nt[0-9]{1,2}_t|char|uchar|word[12346]{2}|int[12346]{2}|byte)([^_[:alnum:]]|$)" #endif /* STUBSER_STUBSER_LOC_H_ */ From f39460e9076931f7542d84f00a386e7b5d0a35ad Mon Sep 17 00:00:00 2001 From: Martin Winkler Date: Wed, 15 Mar 2017 09:48:03 +0000 Subject: [PATCH 18/38] - support for function pointer as parameter - todo: function pointer globals --- src/stubser/cfile_parser.c | 102 ++++++++++++++++++++++++++++++--- src/stubser/cfile_parser_loc.h | 4 +- src/stubser/cfunction.c | 4 +- src/stubser/cfunction_if.h | 13 ++++- src/stubser/stubser.c | 64 ++++++++++++++++----- 5 files changed, 163 insertions(+), 24 deletions(-) diff --git a/src/stubser/cfile_parser.c b/src/stubser/cfile_parser.c index 62c6ed5..c9b380c 100644 --- a/src/stubser/cfile_parser.c +++ b/src/stubser/cfile_parser.c @@ -35,6 +35,8 @@ STATIC bool cfile_parser_initialized = false; STATIC regex_t regXfunction; STATIC regex_t regXprefix; STATIC regex_t regXparameter; +STATIC regex_t regXfuPtrSeparator; +STATIC regex_t regXfunctionPointer; STATIC regex_t regXvariable; STATIC regex_t regXExpressionStart; @@ -71,6 +73,16 @@ int8_t cfile_parser_init() perror("Error regex\n"); return -1; } + if (0 > regcomp(®XfuPtrSeparator, CPARS_REGEX_PARAMETER_FUPTR_SEPA, (REG_EXTENDED))) + { + perror("Error regex\n"); + return -1; + } + if (0 > regcomp(®XfunctionPointer, CPARS_REGEX_PARAMETER_FUPTR, (REG_EXTENDED))) + { + perror("Error regex\n"); + return -1; + } if (0 > regcomp(®Xvariable, CPARS_REGEX_VARIABLE, (REG_EXTENDED | REG_NEWLINE))) { perror("Error regex\n"); @@ -470,6 +482,42 @@ STATIC int8_t removeCcomments(char *aLine) return cBlockRemoval(aLine, CPARS_COMMENT_BLOCK_START, CPARS_COMMENT_BLOCK_END, &cfile_parser_removeCommentHelper, true, true); } +/*! + * @brief Replace ',' within function pointer parameter with '#' + * @attention must be reverted (\ref revertFunctionPointer) before usage + * @param [in,out] *aParameter String of parameter + * @retval uint32_t Amount of ',' replaced + */ +uint32_t prepareFunctionPointer(char *aParameter) +{ + uint32_t matches = 0; + char *worker = aParameter; + regmatch_t matchGroup[CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS]; + while (0 == regexec(®XfuPtrSeparator, worker, CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS, matchGroup, 0) && XREGEX_IS_MATCHGROUP(matchGroup, 1)) + { + ++matches; + worker[matchGroup[1].rm_so] = '#'; + } + return matches; +} + +/*! + * @brief Revert '#' within function pointer parameter to ',' + * @param [in,out] *aParameter String of parameter + * @retval uint32_t Amount of '#' replaced + */ +uint32_t revertFunctionPointer(char *aParameter) +{ + uint32_t matches = 0; + char *worker = aParameter; + while ((worker = strstr(worker, "#"))) + { + ++matches; + *worker = ','; + } + return matches; +} + STATIC int8_t evaluateParameter(char *aParameter, cfunction_t *aFunction) { char *token = NULL; @@ -480,20 +528,23 @@ STATIC int8_t evaluateParameter(char *aParameter, cfunction_t *aFunction) { return -1; } - + prepareFunctionPointer(aParameter); token = strtok(aParameter, ","); while (token) { - // TODO special handling for function pointer as argument - if (0 == regexec(®Xparameter, token, CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS, matchGroup, 0)) + if (0 == regexec(®XfunctionPointer, token, CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS, matchGroup, 0)) { + (void) revertFunctionPointer(token); + tempParameter = cfunction_newParameter(&aFunction->parameter); + tempParameter->type = CPARAMETER_TYPE_FUNCPTR; + if (XREGEX_IS_MATCHGROUP(matchGroup, 1)) { - xmallocStrlcpy(&tempParameter->type, &token[matchGroup[1].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 1)); - if (NULL != tempParameter->type) + xmallocStrlcpy(&tempParameter->dataType, &token[matchGroup[1].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 1)); + if (NULL != tempParameter->dataType) { - xStringTrim(tempParameter->type, XREGEX_SIZEOF_MATCHGROUP(matchGroup, 1)); + xStringTrim(tempParameter->dataType, XREGEX_SIZEOF_MATCHGROUP(matchGroup, 1)); } } if (XREGEX_IS_MATCHGROUP(matchGroup, 2)) @@ -504,10 +555,47 @@ STATIC int8_t evaluateParameter(char *aParameter, cfunction_t *aFunction) xStringTrim(tempParameter->name, XREGEX_SIZEOF_MATCHGROUP(matchGroup, 2)); } } + if (XREGEX_IS_MATCHGROUP(matchGroup, 3)) + { + xmallocStrlcpy(&tempParameter->array, &token[matchGroup[3].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 3)); + if (NULL != tempParameter->array) + { + xStringTrim(tempParameter->array, XREGEX_SIZEOF_MATCHGROUP(matchGroup, 3)); + } + } + + } + else if (0 == regexec(®Xparameter, token, CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS, matchGroup, 0)) + { + tempParameter = cfunction_newParameter(&aFunction->parameter); + tempParameter->type = CPARAMETER_TYPE_REGULAR; + if (XREGEX_IS_MATCHGROUP(matchGroup, 1)) + { + xmallocStrlcpy(&tempParameter->dataType, &token[matchGroup[1].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 1)); + if (NULL != tempParameter->dataType) + { + xStringTrim(tempParameter->dataType, XREGEX_SIZEOF_MATCHGROUP(matchGroup, 1)); + } + } + if (XREGEX_IS_MATCHGROUP(matchGroup, 2)) + { + xmallocStrlcpy(&tempParameter->name, &token[matchGroup[2].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 2)); + if (NULL != tempParameter->name) + { + xStringTrim(tempParameter->name, XREGEX_SIZEOF_MATCHGROUP(matchGroup, 2)); + } + } + if (XREGEX_IS_MATCHGROUP(matchGroup, 3)) + { + xmallocStrlcpy(&tempParameter->array, &token[matchGroup[3].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 3)); + if (NULL != tempParameter->array) + { + xStringTrim(tempParameter->array, XREGEX_SIZEOF_MATCHGROUP(matchGroup, 2)); + } + } } token = strtok(NULL, ","); } - return 0; } diff --git a/src/stubser/cfile_parser_loc.h b/src/stubser/cfile_parser_loc.h index 1e59280..58890ec 100644 --- a/src/stubser/cfile_parser_loc.h +++ b/src/stubser/cfile_parser_loc.h @@ -31,7 +31,9 @@ #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 "[[:blank:]]*([ _\\*[:alnum:]]* +\\**)([_\\*[:alnum:]]+)[[: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_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/cfunction.c b/src/stubser/cfunction.c index 4b1ac67..20e4611 100644 --- a/src/stubser/cfunction.c +++ b/src/stubser/cfunction.c @@ -88,7 +88,7 @@ STATIC int8_t cfunction_freeParameter(struct _CFUNCTION_PARAMETER_LIST_T *aParam while (work) { next = work->next; - free(work->type); + free(work->dataType); free(work->name); free(work); work = next; @@ -162,7 +162,7 @@ void cfunction_printList(cfunction_list_t *aList) printf("[ cfu]%d:<%s> (%s) %s [%d] ", work->type, work->prefix, work->dataType, work->name, work->parameter.amount); while (param) { - printf("(%s)%s,", param->type, param->name); + printf("%d(%s)%s%s%s", param->type, param->dataType, param->name, (param->array ? param->array : ""), (param->next ? "," : "")); param = param->next; } printf("\n"); diff --git a/src/stubser/cfunction_if.h b/src/stubser/cfunction_if.h index ec18ef6..e383772 100644 --- a/src/stubser/cfunction_if.h +++ b/src/stubser/cfunction_if.h @@ -25,11 +25,22 @@ typedef enum _CFUNCTION_TYPE_T CFUNCTION_TYPE_LAST_ENUM } cfunction_type_t; +/*! @brief Type of function definition */ +typedef enum _CPARAMETER_TYPE_T +{ + CPARAMETER_TYPE_UNDEF = 0, /*!< @brief undefined */ + CPARAMETER_TYPE_REGULAR = 1, /*!< @brief Regular C function parameter */ + CPARAMETER_TYPE_FUNCPTR = 2, /*!< @brief Function pointer as parameter */ + CPARAMETER_TYPE_LAST_ENUM +} cparameter_type_t; + /*! @brief Parameter list node */ typedef struct _CFUNCTION_PARAMETER_T { - char* type; /*!< @brief data type */ + cparameter_type_t type; /*!< @brief Parameter type */ + char* dataType; /*!< @brief data type */ char* name; /*!< @brief name */ + char* array; /*!< @brief array information (e.g. [10] or [DEF_MAX]) */ struct _CFUNCTION_PARAMETER_T *next; } cfunction_parameter_t; diff --git a/src/stubser/stubser.c b/src/stubser/stubser.c index 785514d..d4e0908 100644 --- a/src/stubser/stubser.c +++ b/src/stubser/stubser.c @@ -126,21 +126,22 @@ STATIC void createVariableSpecificCheck(FILE *aFile, cfile_variable_t *aVariable STATIC void createParameterSpecificCheck(FILE *aFile, cfunction_t *aFunction, cfunction_parameter_t *aParameter, char aParameterIndex) { - if (NULL != strstr(aParameter->type, "*") && NULL != strstr(aParameter->type, "char")) + if (NULL != strstr(aParameter->dataType, "*") && NULL != strstr(aParameter->dataType, "char")) { fprintf(aFile, "\tCU_ASSERT_MEMORY_CHECK(\"%s(%s)\", ", aFunction->name, aParameter->name); fprintf(aFile, STUBINIT_PARAM_PARAMETER_S1", "STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_PARAM_S1, aParameterIndex, aFunction->name, aFunction->name, aParameterIndex); fprintf(aFile, ", strlen("STUBINIT_PARAM_PARAMETER_S1"));"NEWLINES, aParameterIndex); } - else if (NULL != strstr(aParameter->type, "*")) + else if (NULL != strstr(aParameter->dataType, "*") || NULL != aParameter->array) { + // matches also function pointer (array containing function pointer parameter list) fprintf(aFile, "\tCU_ASSERT_PTR_EQUAL("); fprintf(aFile, STUBINIT_PARAM_PARAMETER_S1", "STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_PARAM_S1, aParameterIndex, aFunction->name, aFunction->name, aParameterIndex); fprintf(aFile, ");"NEWLINES); } - else if (isDatatypeStandard(aParameter->type)) + else if (isDatatypeStandard(aParameter->dataType)) { fprintf(aFile, "\tCU_ASSERT_EQUAL("); fprintf(aFile, STUBINIT_PARAM_PARAMETER_S1", "STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_PARAM_S1, aParameterIndex, aFunction->name, @@ -313,17 +314,30 @@ STATIC int8_t createStubFunctionBlock(FILE *aFile, FILE *aHeader, cfunction_t *a fprintf(aFile, "typedef struct _STUBPARAMETER_%s" NEWLINES, aFunction->name); fprintf(aFile, "{" NEWLINES); fprintf(aFile, "\tuint8_t "STUBPARAMETER_CALLTEST_S"; /**< @brief If stub call is a STUB_CALL_PASS or STUB_CALL_FAIL */" NEWLINES); - parameter = aFunction->parameter.head; - parameterIndex = 'a'; - while (parameter) - { - fprintf(aFile, "\t%s "STUBPARAMETER_PARAM_S1"; /*!< @brief %s */" NEWLINES, NCHECK(parameter->type), parameterIndex++, NCHECK(parameter->name)); - parameter = parameter->next; - } if (!isDatatypeVoid(aFunction->dataType)) { fprintf(aFile, "\t%s "STUBPARAMETER_RETURN_S"; /**< @brief return value */" NEWLINES, aFunction->dataType); } + parameter = aFunction->parameter.head; + parameterIndex = 'a'; + while (parameter) + { + if (CPARAMETER_TYPE_FUNCPTR == parameter->type) + { + fprintf(aFile, "\t%s (*"STUBPARAMETER_PARAM_S1")%s; /*!< @brief %s */" NEWLINES, NCHECK(parameter->dataType), parameterIndex++, + NCHECK(parameter->array), NCHECK(parameter->name)); + } + else if (parameter->array) + { + fprintf(aFile, "\t%s *"STUBPARAMETER_PARAM_S1"; /*!< @brief %s */" NEWLINES, NCHECK(parameter->dataType), parameterIndex++, NCHECK(parameter->name)); + } + else if (CPARAMETER_TYPE_REGULAR == parameter->type) + { + fprintf(aFile, "\t%s "STUBPARAMETER_PARAM_S1"; /*!< @brief %s */" NEWLINES, NCHECK(parameter->dataType), parameterIndex++, NCHECK(parameter->name)); + } + parameter = parameter->next; + } + fprintf(aFile, "} "STUBPARAMETER_TYPEDEF_S1";" NEWLINES, aFunction->name); NEWLINE(aFile); @@ -348,7 +362,14 @@ STATIC int8_t createStubFunctionBlock(FILE *aFile, FILE *aHeader, cfunction_t *a parameterIndex = 'a'; while (parameter) { - fprintf(aHeader, ", %s "STUBINIT_PARAM_PARAMETER_S1, NCHECK(parameter->type), parameterIndex++); + if (CPARAMETER_TYPE_FUNCPTR == parameter->type) + { + fprintf(aHeader, ", %s (*"STUBINIT_PARAM_PARAMETER_S1")%s", NCHECK(parameter->dataType), parameterIndex++, NCHECK(parameter->array)); + } + else + { + fprintf(aHeader, ", %s "STUBINIT_PARAM_PARAMETER_S1"%s", NCHECK(parameter->dataType), parameterIndex++, NCHECK(parameter->array)); + } parameter = parameter->next; } fprintf(aHeader, ");" NEWLINES); @@ -363,7 +384,14 @@ STATIC int8_t createStubFunctionBlock(FILE *aFile, FILE *aHeader, cfunction_t *a parameterIndex = 'a'; while (parameter) { - fprintf(aFile, ", %s "STUBINIT_PARAM_PARAMETER_S1, NCHECK(parameter->type), parameterIndex++); + if (CPARAMETER_TYPE_FUNCPTR == parameter->type) + { + fprintf(aFile, ", %s (*"STUBINIT_PARAM_PARAMETER_S1")%s", NCHECK(parameter->dataType), parameterIndex++, NCHECK(parameter->array)); + } + else + { + fprintf(aFile, ", %s "STUBINIT_PARAM_PARAMETER_S1"%s", NCHECK(parameter->dataType), parameterIndex++, NCHECK(parameter->array)); + } parameter = parameter->next; } fprintf(aFile, ")" NEWLINES); @@ -398,7 +426,17 @@ STATIC int8_t createStubFunctionBlock(FILE *aFile, FILE *aHeader, cfunction_t *a parameterIndex = 'a'; while (parameter) { - fprintf(aFile, "%s "STUBINIT_PARAM_PARAMETER_S1"%s", NCHECK(parameter->type), parameterIndex++, (NULL != parameter->next ? ", " : "")); + if (CPARAMETER_TYPE_FUNCPTR == parameter->type) + { + fprintf(aFile, "%s (*"STUBINIT_PARAM_PARAMETER_S1")%s%s", NCHECK(parameter->dataType), parameterIndex++, NCHECK(parameter->array), + (NULL != parameter->next ? ", " : "")); + } + else + { + fprintf(aFile, "%s "STUBINIT_PARAM_PARAMETER_S1"%s%s", NCHECK(parameter->dataType), parameterIndex++, NCHECK(parameter->array), + (NULL != parameter->next ? ", " : "")); + } + parameter = parameter->next; } fprintf(aFile, ")" NEWLINES); From 26f5a868e88b4ef796c17f1e85457c25f73ee6d6 Mon Sep 17 00:00:00 2001 From: Martin Winkler Date: Wed, 15 Mar 2017 12:13:50 +0000 Subject: [PATCH 19/38] - support function pointer globals --- src/stubser/cfile_if.h | 9 +++- src/stubser/cfile_parser.c | 29 ++++++++++-- src/stubser/cfile_parser_loc.h | 4 +- src/stubser/stubser.c | 83 +++++++++++++++++++++++++++------- src/stubser/stubser_loc.h | 4 +- 5 files changed, 104 insertions(+), 25 deletions(-) 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_ */ From 6291fa4b781d3102d5ee4ade5776ac0fd30d578f Mon Sep 17 00:00:00 2001 From: Martin Winkler Date: Wed, 15 Mar 2017 12:54:07 +0000 Subject: [PATCH 20/38] - detect empty array size for globals and initialize as pointer --- src/stubser/cfile_parser.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/stubser/cfile_parser.c b/src/stubser/cfile_parser.c index 6a8aceb..c159485 100644 --- a/src/stubser/cfile_parser.c +++ b/src/stubser/cfile_parser.c @@ -642,7 +642,23 @@ STATIC int8_t cfile_parser_evaluateExpression(char *aExpression, cfile_t *aCfile // 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)); + xmallocStrlcpy(&tempChar, &aExpression[matchGroup[3].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 3)); + if (NULL != tempChar) + { + xStringTrim(tempChar, strlen(tempChar)); + } + + if (2 == strlen(tempChar)) + { + // array without size definition + xmallocStrlcat(&variable->dataType, "*", 1); + } + else + { + xmallocStrlcpy(&variable->array, tempChar, strlen(tempChar)); + } + + xfree((void**) &tempChar); } } } From f392bb586d7f8662bab439b5dffbe9fbd124bc27 Mon Sep 17 00:00:00 2001 From: Martin Winkler Date: Wed, 15 Mar 2017 13:14:52 +0000 Subject: [PATCH 21/38] - detecting empty array size even when containing spaces --- src/ext/xstring.c | 24 ++++++++++++++++++++++++ src/ext/xstring.h | 1 + src/stubser/cfile_parser.c | 2 +- 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/ext/xstring.c b/src/ext/xstring.c index db96d1b..c4454d9 100644 --- a/src/ext/xstring.c +++ b/src/ext/xstring.c @@ -10,6 +10,7 @@ * @date 27.02.2017 * @author SESA354004 */ +#include "xtypes.h" #include "xstring.h" #include "ctype.h" @@ -24,6 +25,29 @@ char* gnu_basename(char *path) return base ? base + 1 : path; } +uint32_t xStrCount(char *aStr, char aC) +{ + uint32_t count = 0; + char *temp = NULL; + + if (NULL == aStr) + { + return 0; + } + temp = aStr; + + while (*temp) + { + if (aC == *temp) + { + ++count; + } + temp++; + } + + return count; +} + /*! * @brief Trim leading and trailing whitespaces * @param [in] *str Input string diff --git a/src/ext/xstring.h b/src/ext/xstring.h index 324bb76..49c0d7a 100644 --- a/src/ext/xstring.h +++ b/src/ext/xstring.h @@ -16,6 +16,7 @@ #include char* gnu_basename(char *path); +uint32_t xStrCount(char *aStr, char aC); char* strntrimStatic(char *aStr, size_t aMaxLength); void xStringTrim(char *aStr, size_t aMaxLength); diff --git a/src/stubser/cfile_parser.c b/src/stubser/cfile_parser.c index c159485..f01a8fc 100644 --- a/src/stubser/cfile_parser.c +++ b/src/stubser/cfile_parser.c @@ -648,7 +648,7 @@ STATIC int8_t cfile_parser_evaluateExpression(char *aExpression, cfile_t *aCfile xStringTrim(tempChar, strlen(tempChar)); } - if (2 == strlen(tempChar)) + if (2 == strlen(tempChar) - xStrCount(tempChar, ' ')) { // array without size definition xmallocStrlcat(&variable->dataType, "*", 1); From e100189aa9ff7ea0efbdb49ab97da5c47d01e070 Mon Sep 17 00:00:00 2001 From: Martin Winkler Date: Wed, 15 Mar 2017 16:18:47 +0000 Subject: [PATCH 22/38] - fix doxygen file header --- src/stubser/stubser.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/stubser/stubser.c b/src/stubser/stubser.c index 1af90bc..0207a3e 100644 --- a/src/stubser/stubser.c +++ b/src/stubser/stubser.c @@ -558,7 +558,7 @@ STATIC void createUserHeader(char *aOutput, char *aNoSuffix) return; } - fprintf(cheader, "/* @file %s"NEWLINES, gnu_basename(cHeaderName)); + fprintf(cheader, "/*! @file %s"NEWLINES, gnu_basename(cHeaderName)); fprintf(cheader, " * @details"NEWLINES" * This is a user defined stub header.\\n"NEWLINES); fprintf(cheader, " * Define subject header needed for compilation of stub (e.g. typedefs, structures, ...).\\n"NEWLINES); fprintf(cheader, " * - generated by stubser -"NEWLINES" */" NEWLINES NEWLINES); @@ -611,7 +611,7 @@ STATIC int8_t createStub(char *aOutput, char *aNoSuffix, cfile_t *aCfile) createUserHeader(aOutput, aNoSuffix); - fprintf(cfile, "/* @file %s"NEWLINES, gnu_basename(cFileName)); + fprintf(cfile, "/*! @file %s"NEWLINES, gnu_basename(cFileName)); fprintf(cfile, " * @details"NEWLINES" * This is a stub for CUnit.\\n"NEWLINES); fprintf(cfile, " * - generated by stubser -"NEWLINES" */" NEWLINES NEWLINES); fprintf(cfile, "#include "NEWLINES); @@ -621,7 +621,7 @@ STATIC int8_t createStub(char *aOutput, char *aNoSuffix, cfile_t *aCfile) fprintf(cfile, "#include \"stub_%s_user.h\""NEWLINES, aNoSuffix); fprintf(cfile, "#include \"%s\""NEWLINES NEWLINES, gnu_basename(cHeaderName)); - fprintf(cheader, "/* @file %s"NEWLINES, gnu_basename(cHeaderName)); + fprintf(cheader, "/*! @file %s"NEWLINES, gnu_basename(cHeaderName)); fprintf(cheader, " * @details"NEWLINES" * This is a stub header.\\n"NEWLINES); fprintf(cheader, " * - generated by stubser -"NEWLINES" */" NEWLINES NEWLINES); From 97603f9001fea1366a68b743f98d628e7e2f03dd Mon Sep 17 00:00:00 2001 From: Martin Winkler Date: Thu, 16 Mar 2017 08:50:54 +0000 Subject: [PATCH 23/38] - create also stub user c file (not overwritten if exist) - calling user functions in init and check --- src/stubser/stubser.c | 102 ++++++++++++++++++++++---------------- src/stubser/stubser_loc.h | 6 ++- 2 files changed, 65 insertions(+), 43 deletions(-) diff --git a/src/stubser/stubser.c b/src/stubser/stubser.c index 0207a3e..73efe6f 100644 --- a/src/stubser/stubser.c +++ b/src/stubser/stubser.c @@ -199,11 +199,6 @@ STATIC int8_t createStubExpected(char *aNoSuffix, FILE *aFile, FILE *aHeader, cf return -1; } - if (0 == aList->amount) - { - return 0; - } - work = aList->head; while (work) { @@ -227,7 +222,7 @@ STATIC int8_t createStubExpected(char *aNoSuffix, FILE *aFile, FILE *aHeader, cf fprintf(aHeader, "void "STUBFUNCTION_INITEXPECTED_S1"();"NEWLINES NEWLINES, aNoSuffix); fprintf(aFile, "void "STUBFUNCTION_INITEXPECTED_S1"()"NEWLINES"{"NEWLINES, aNoSuffix); - + fprintf(aFile, "\t"STUBFUNCTION_USER_INITEXPECTED_S1"();"NEWLINES, aNoSuffix); work = aList->head; while (work) { @@ -253,11 +248,6 @@ STATIC int8_t createStubGlobals(char *aNoSuffix, FILE *aFile, FILE *aHeader, cfi return -1; } - if (0 == aList->amount) - { - return 0; - } - work = aList->head; while (work) { @@ -281,7 +271,7 @@ STATIC int8_t createStubGlobals(char *aNoSuffix, FILE *aFile, FILE *aHeader, cfi } fprintf(aFile, "void "STUBFUNCTION_INITGLOBALS_S1"()"NEWLINES"{"NEWLINES, aNoSuffix); - + fprintf(aFile, "\t"STUBFUNCTION_USER_INITGLOBALS_S1"();"NEWLINES, aNoSuffix); work = aList->head; while (work) { @@ -313,14 +303,9 @@ STATIC int8_t createStubCheck(char *aNoSuffix, FILE *aFile, FILE *aHeader, cfile return -1; } - if (0 == aList->amount) - { - return 0; - } - fprintf(aHeader, "void "STUBFUNCTION_CHECK_S1"();"NEWLINES NEWLINES, aNoSuffix); fprintf(aFile, "void "STUBFUNCTION_CHECK_S1"()"NEWLINES"{"NEWLINES, aNoSuffix); - + fprintf(aFile, "\t"STUBFUNCTION_USER_CHECK_S1"();"NEWLINES, aNoSuffix); work = aList->head; while (work) { @@ -539,37 +524,70 @@ int file_exist(const char *filename) STATIC void createUserHeader(char *aOutput, char *aNoSuffix) { - FILE *cheader; + FILE *fileDesc = NULL; char *cHeaderName = NULL; + char *cFileName = NULL; xmallocStrlcpy(&cHeaderName, aOutput, strlen(aOutput)); xmallocStrlcat(&cHeaderName, "_user.h", 8); + xmallocStrlcpy(&cFileName, aOutput, strlen(aOutput)); + xmallocStrlcat(&cFileName, "_user.c", 8); - if (file_exist(cHeaderName)) + if (!file_exist(cHeaderName)) { - free(cHeaderName); - return; + // user header doesn't exist + fileDesc = fopen(cHeaderName, "w"); + if (NULL != fileDesc) + { + + fprintf(fileDesc, "/*! @file %s"NEWLINES, gnu_basename(cHeaderName)); + fprintf(fileDesc, " * @details"NEWLINES" * This is a user defined stub header.\\n"NEWLINES); + fprintf(fileDesc, " * Define subject header needed for compilation of stub (e.g. typedefs, structures, ...).\\n"NEWLINES); + fprintf(fileDesc, " * - generated by stubser -"NEWLINES" */" NEWLINES NEWLINES); + + fprintf(fileDesc, "#ifndef _STUB_%s_USER_H"NEWLINES, aNoSuffix); + fprintf(fileDesc, "#define _STUB_%s_USER_H"NEWLINES, aNoSuffix); + + fprintf(fileDesc, NEWLINES"// predefined stub user functions"NEWLINES); + fprintf(fileDesc, "void "STUBFUNCTION_USER_INITEXPECTED_S1"();"NEWLINES, aNoSuffix); + fprintf(fileDesc, "void "STUBFUNCTION_USER_INITGLOBALS_S1"();"NEWLINES, aNoSuffix); + fprintf(fileDesc, "void "STUBFUNCTION_USER_CHECK_S1"();"NEWLINES, aNoSuffix); + + fprintf(fileDesc, NEWLINES"#endif // _STUB_%s_USER_H"NEWLINES, aNoSuffix); + + fclose(fileDesc); + fileDesc = NULL; + } } - -// user header doesn't exist - cheader = fopen(cHeaderName, "w"); - if (NULL == cheader) - { - free(cHeaderName); - return; - } - - fprintf(cheader, "/*! @file %s"NEWLINES, gnu_basename(cHeaderName)); - fprintf(cheader, " * @details"NEWLINES" * This is a user defined stub header.\\n"NEWLINES); - fprintf(cheader, " * Define subject header needed for compilation of stub (e.g. typedefs, structures, ...).\\n"NEWLINES); - fprintf(cheader, " * - generated by stubser -"NEWLINES" */" NEWLINES NEWLINES); - - fprintf(cheader, "#ifndef _STUB_%s_USER_H"NEWLINES, aNoSuffix); - fprintf(cheader, "#define _STUB_%s_USER_H"NEWLINES NEWLINES, aNoSuffix); - - fprintf(cheader, NEWLINES"#endif // _STUB_%s_USER_H"NEWLINES, aNoSuffix); - free(cHeaderName); - fclose(cheader); + + // TODO user c file + if (!file_exist(cFileName)) + { + // user header doesn't exist + fileDesc = fopen(cFileName, "w"); + if (NULL != fileDesc) + { + + fprintf(fileDesc, "/*! @file %s"NEWLINES, gnu_basename(cFileName)); + fprintf(fileDesc, " * @details"NEWLINES" * This is a user defined stub.\\n"NEWLINES); + fprintf(fileDesc, " * Define additional elements which need to be tested, or helper functions.\\n"NEWLINES); + fprintf(fileDesc, " * - generated by stubser -"NEWLINES" */" NEWLINES NEWLINES); + + fprintf(fileDesc, "#include "NEWLINES); + fprintf(fileDesc, "#include \"xasserts.h\""NEWLINES); + fprintf(fileDesc, "#include \"xtypes.h\""NEWLINES); + fprintf(fileDesc, "#include \"stub.h\""NEWLINES); + fprintf(fileDesc, "#include \"stub_%s_user.h\""NEWLINES, aNoSuffix); + + fprintf(fileDesc, "// predefined stub user functions"NEWLINES); + fprintf(fileDesc, "void "STUBFUNCTION_USER_INITEXPECTED_S1"()"NEWLINES"{"NEWLINES"\t"NEWLINES"}"NEWLINES NEWLINES, aNoSuffix); + fprintf(fileDesc, "void "STUBFUNCTION_USER_INITGLOBALS_S1"()"NEWLINES"{"NEWLINES"\t"NEWLINES"}"NEWLINES NEWLINES, aNoSuffix); + fprintf(fileDesc, "void "STUBFUNCTION_USER_CHECK_S1"()"NEWLINES"{"NEWLINES"\t"NEWLINES"}"NEWLINES NEWLINES, aNoSuffix); + + fclose(fileDesc); + } + } + free(cFileName); } STATIC int8_t createStub(char *aOutput, char *aNoSuffix, cfile_t *aCfile) diff --git a/src/stubser/stubser_loc.h b/src/stubser/stubser_loc.h index e591bc5..7389934 100644 --- a/src/stubser/stubser_loc.h +++ b/src/stubser/stubser_loc.h @@ -38,10 +38,14 @@ #define STUBINIT_PARAM_PARAMETER_S1 "aParameter_%c" // aParameter_a #define STUBINIT_PARAM_RETURN_S "aReturnValue" +#define STUBFUNCTION_USER_INITEXPECTED_S1 "stub_%s_user_initExpected" // stub_testfunction_initExpected +#define STUBFUNCTION_USER_INITGLOBALS_S1 "stub_%s_user_initGlobals" // stub_testfunction_initGlobals +#define STUBFUNCTION_USER_CHECK_S1 "stub_%s_user_checkGlobals" // stub_testfunction_checkGlobals + #define STUBFUNCTION_INITEXPECTED_S1 "stub_%s_initExpected" // stub_testfunction_initExpected #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 STUBFUNCTION_INIT_S1 "stub_%s_init" // stub_testfunction_init #define STUBVARIABLE_EXPECTED_S1 "%s_expected" // variable_expected #define STUB_CONSOLE_GOBACK "\033[2K\r" From cd9838808fb59be32d2a535393fb8a0d9a881f40 Mon Sep 17 00:00:00 2001 From: Martin Winkler Date: Thu, 16 Mar 2017 13:46:29 +0000 Subject: [PATCH 24/38] - calling user init functions after standard init functions (globals and expected) --- src/stubser/stubser.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/stubser/stubser.c b/src/stubser/stubser.c index 73efe6f..b776355 100644 --- a/src/stubser/stubser.c +++ b/src/stubser/stubser.c @@ -60,7 +60,7 @@ STATIC void createVariableSpecificInit(const char* aVariableTemplate, FILE *aFil { char *tempChar = NULL; - if (NULL != strstr(aVariable->dataType, "const")) + if (NULL != strstr(aVariable->dataType, CPARS_ELEMENT_CONST)) { return; } @@ -222,7 +222,7 @@ STATIC int8_t createStubExpected(char *aNoSuffix, FILE *aFile, FILE *aHeader, cf fprintf(aHeader, "void "STUBFUNCTION_INITEXPECTED_S1"();"NEWLINES NEWLINES, aNoSuffix); fprintf(aFile, "void "STUBFUNCTION_INITEXPECTED_S1"()"NEWLINES"{"NEWLINES, aNoSuffix); - fprintf(aFile, "\t"STUBFUNCTION_USER_INITEXPECTED_S1"();"NEWLINES, aNoSuffix); + work = aList->head; while (work) { @@ -234,7 +234,7 @@ STATIC int8_t createStubExpected(char *aNoSuffix, FILE *aFile, FILE *aHeader, cf createVariableSpecificInit(STUBVARIABLE_EXPECTED_S1, aFile, work); work = work->next; } - + fprintf(aFile, "\t"STUBFUNCTION_USER_INITEXPECTED_S1"();"NEWLINES, aNoSuffix); fprintf(aFile, "}"NEWLINES NEWLINES); return 0; @@ -271,7 +271,7 @@ STATIC int8_t createStubGlobals(char *aNoSuffix, FILE *aFile, FILE *aHeader, cfi } fprintf(aFile, "void "STUBFUNCTION_INITGLOBALS_S1"()"NEWLINES"{"NEWLINES, aNoSuffix); - fprintf(aFile, "\t"STUBFUNCTION_USER_INITGLOBALS_S1"();"NEWLINES, aNoSuffix); + work = aList->head; while (work) { @@ -283,7 +283,7 @@ STATIC int8_t createStubGlobals(char *aNoSuffix, FILE *aFile, FILE *aHeader, cfi createVariableSpecificInit("%s", aFile, work); work = work->next; } - + fprintf(aFile, "\t"STUBFUNCTION_USER_INITGLOBALS_S1"();"NEWLINES, aNoSuffix); fprintf(aFile, "}"NEWLINES); fprintf(aHeader, "void "STUBFUNCTION_INITGLOBALS_S1"();"NEWLINES, aNoSuffix); fprintf(aHeader, "void "STUBFUNCTION_INIT_S1"();"NEWLINES NEWLINES, aNoSuffix); @@ -305,7 +305,7 @@ STATIC int8_t createStubCheck(char *aNoSuffix, FILE *aFile, FILE *aHeader, cfile fprintf(aHeader, "void "STUBFUNCTION_CHECK_S1"();"NEWLINES NEWLINES, aNoSuffix); fprintf(aFile, "void "STUBFUNCTION_CHECK_S1"()"NEWLINES"{"NEWLINES, aNoSuffix); - fprintf(aFile, "\t"STUBFUNCTION_USER_CHECK_S1"();"NEWLINES, aNoSuffix); + work = aList->head; while (work) { @@ -317,7 +317,7 @@ STATIC int8_t createStubCheck(char *aNoSuffix, FILE *aFile, FILE *aHeader, cfile createVariableSpecificCheck(aFile, work); work = work->next; } - + fprintf(aFile, "\t"STUBFUNCTION_USER_CHECK_S1"();"NEWLINES, aNoSuffix); fprintf(aFile, "}"NEWLINES NEWLINES); return 0; From 106c030fa78edd11fddae1f615dd8a46975523eb Mon Sep 17 00:00:00 2001 From: Martin Winkler Date: Thu, 16 Mar 2017 13:46:57 +0000 Subject: [PATCH 25/38] - detect "const" for variables --- src/stubser/cfile_if.h | 9 +++++---- src/stubser/cfile_parser.c | 9 +++++++++ src/stubser/cfile_parser_if.h | 2 ++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/stubser/cfile_if.h b/src/stubser/cfile_if.h index dcfcdf3..9ecb0a4 100644 --- a/src/stubser/cfile_if.h +++ b/src/stubser/cfile_if.h @@ -26,10 +26,11 @@ 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_REGULAR = 0x01, /*!< @brief Regular C variable definition */ + CVARIABLE_TYPE_STATIC = 0x02, /*!< @brief Static C variable definition */ + CVARIABLE_TYPE_EXTERN = 0x04, /*!< @brief External C variable definition */ + CVARIABLE_TYPE_FUPTR = 0x08, /*!< @brief Function pointer as variable */ + CVARIABLE_TYPE_CONST = 0x10, /*!< @brief Const C variable */ CVARIABLE_TYPE_LAST_ENUM } cfile_variable_type_t; diff --git a/src/stubser/cfile_parser.c b/src/stubser/cfile_parser.c index f01a8fc..5ff7a2c 100644 --- a/src/stubser/cfile_parser.c +++ b/src/stubser/cfile_parser.c @@ -18,6 +18,7 @@ #include "xstring.h" #include "xmalloc.h" #include "cfile_if.h" +#include "cfile_parser_if.h" #include "cfile_parser_loc.h" #include "cfile_parser_worker_loc.h" #include "debug.h" @@ -237,6 +238,14 @@ STATIC int8_t matchPrefix(void *aElement, celement_type_t aElementType, char *aS xmallocStrlcpy(type, temp, strlen(temp)); } + if (CELEMENT_TYPE_VARIABLE == aElementType) + { + if (*type && NULL != strstr(*type, CPARS_ELEMENT_CONST)) + { + CVARIABLE_SET_TYPE(((cfile_variable_t* ) aElement)->type, CVARIABLE_TYPE_CONST); + } + } + free(temp); return 0; } diff --git a/src/stubser/cfile_parser_if.h b/src/stubser/cfile_parser_if.h index a74bbed..30bbb16 100644 --- a/src/stubser/cfile_parser_if.h +++ b/src/stubser/cfile_parser_if.h @@ -14,6 +14,8 @@ #ifndef STUBSER_CFILE_PARSER_IF_H_ #define STUBSER_CFILE_PARSER_IF_H_ +#define CPARS_ELEMENT_CONST "const" + uint32_t cfile_parser(char *aPath, cfile_t *aList); #endif /* STUBSER_CFILE_PARSER_IF_H_ */ From b1488841852f38318475959adf5b27c82179afaa Mon Sep 17 00:00:00 2001 From: Martin Winkler Date: Thu, 23 Mar 2017 06:52:10 +0000 Subject: [PATCH 26/38] - update project name --- .project | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.project b/.project index f649d94..c8414af 100644 --- a/.project +++ b/.project @@ -1,6 +1,6 @@ - stubi + stubser From 335b74a844d7f0e42da8c9698f302781b34a8024 Mon Sep 17 00:00:00 2001 From: Martin Winkler Date: Thu, 30 Aug 2018 09:14:34 +0000 Subject: [PATCH 27/38] Adding means to inject values via stub function pointer to test subject. Resulting stubs are not backward compatible. If stubbed functions contain pointer as parameter the tests need to be addapted. --- src/stubser/stubser.c | 146 ++++++++++++++++++++++++++++++++++---- src/stubser/stubser_loc.h | 6 ++ 2 files changed, 137 insertions(+), 15 deletions(-) diff --git a/src/stubser/stubser.c b/src/stubser/stubser.c index b776355..9343e07 100644 --- a/src/stubser/stubser.c +++ b/src/stubser/stubser.c @@ -14,6 +14,7 @@ */ #include #include +#include #include #include #include @@ -160,21 +161,55 @@ STATIC void createVariableSpecificCheck(FILE *aFile, cfile_variable_t *aVariable STATIC void createParameterSpecificCheck(FILE *aFile, cfunction_t *aFunction, cfunction_parameter_t *aParameter, char aParameterIndex) { - if (NULL != strstr(aParameter->dataType, "*") && NULL != strstr(aParameter->dataType, "char")) + if (CPARAMETER_TYPE_FUNCPTR == aParameter->type) { - fprintf(aFile, "\tCU_ASSERT_MEMORY_CHECK(\"%s(%s)\", ", aFunction->name, aParameter->name); - fprintf(aFile, STUBINIT_PARAM_PARAMETER_S1", "STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_PARAM_S1, aParameterIndex, aFunction->name, - aFunction->name, aParameterIndex); - fprintf(aFile, ", strlen("STUBINIT_PARAM_PARAMETER_S1"));"NEWLINES, aParameterIndex); - } - else if (NULL != strstr(aParameter->dataType, "*") || NULL != aParameter->array) - { - // matches also function pointer (array containing function pointer parameter list) + // function pointer fprintf(aFile, "\tCU_ASSERT_PTR_EQUAL("); fprintf(aFile, STUBINIT_PARAM_PARAMETER_S1", "STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_PARAM_S1, aParameterIndex, aFunction->name, aFunction->name, aParameterIndex); fprintf(aFile, ");"NEWLINES); } + else if (NULL != strstr(aParameter->dataType, "*") && NULL != strstr(aParameter->dataType, "char")) + { + fprintf(aFile, + "\tif ("STUBPARAMETER_POINTERHANDLING_ADDRESS_S " == " STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_POINTERHANDLING_S")" NEWLINES "\t{" NEWLINES, + aFunction->name, aFunction->name); + fprintf(aFile, "\t\tCU_ASSERT_MEMORY_CHECK(\"%s(%s)\", ", aFunction->name, aParameter->name); + fprintf(aFile, STUBINIT_PARAM_PARAMETER_S1", "STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_PARAM_S1, aParameterIndex, aFunction->name, + aFunction->name, aParameterIndex); + fprintf(aFile, ", strlen("STUBINIT_PARAM_PARAMETER_S1"));"NEWLINES, aParameterIndex); + fprintf(aFile, "\t}" NEWLINES); + if (NULL == strstr(aParameter->dataType, "const")) + { + fprintf(aFile, "\telse" NEWLINES "\t{" NEWLINES); + fprintf(aFile, "\t\tmemcpy(" STUBINIT_PARAM_PARAMETER_S1 ", "STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_PARAM_S1", " // + STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_PARAM_S1"_size",// + aParameterIndex, aFunction->name, aFunction->name, aParameterIndex, aFunction->name, aFunction->name, aParameterIndex); + fprintf(aFile, ");" NEWLINES); + fprintf(aFile, "\t}" NEWLINES); + } + } + else if (NULL != strstr(aParameter->dataType, "*") || NULL != aParameter->array) + { + // pointer + fprintf(aFile, + "\tif ("STUBPARAMETER_POINTERHANDLING_ADDRESS_S " == " STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_POINTERHANDLING_S")" NEWLINES "\t{" NEWLINES, + aFunction->name, aFunction->name); + fprintf(aFile, "\t\tCU_ASSERT_PTR_EQUAL("); + fprintf(aFile, STUBINIT_PARAM_PARAMETER_S1", "STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_PARAM_S1, aParameterIndex, aFunction->name, + aFunction->name, aParameterIndex); + fprintf(aFile, ");" NEWLINES); + fprintf(aFile, "\t}" NEWLINES); + if (NULL == strstr(aParameter->dataType, "const")) + { + fprintf(aFile, "\telse" NEWLINES "\t{" NEWLINES); + fprintf(aFile, "\t\tmemcpy(" STUBINIT_PARAM_PARAMETER_S1 ", "STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_PARAM_S1", " // + STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_PARAM_S1"_size",// + aParameterIndex, aFunction->name, aFunction->name, aParameterIndex, aFunction->name, aFunction->name, aParameterIndex); + fprintf(aFile, ");" NEWLINES); + fprintf(aFile, "\t}" NEWLINES); + } + } else if (isDatatypeStandard(aParameter->dataType)) { fprintf(aFile, "\tCU_ASSERT_EQUAL("); @@ -327,6 +362,18 @@ STATIC int8_t createStubFunctionBlock(FILE *aFile, FILE *aHeader, cfunction_t *a { cfunction_parameter_t *parameter = NULL; char parameterIndex = 'a'; + bool pointerAvailable = false; + + parameter = aFunction->parameter.head; + while (parameter) + { + if (NULL != strstr(parameter->dataType, "*") || parameter->array) + { + pointerAvailable = true; + break; + } + parameter = parameter->next; + } if (NULL == aFile || NULL == aHeader || NULL == aFunction) { @@ -349,10 +396,14 @@ STATIC int8_t createStubFunctionBlock(FILE *aFile, FILE *aHeader, cfunction_t *a fprintf(aFile, "// Expected parameter and return value structures" NEWLINES); fprintf(aFile, "typedef struct _STUBPARAMETER_%s" NEWLINES, aFunction->name); fprintf(aFile, "{" NEWLINES); - fprintf(aFile, "\tuint8_t "STUBPARAMETER_CALLTEST_S"; /**< @brief If stub call is a STUB_CALL_PASS or STUB_CALL_FAIL */" NEWLINES); + fprintf(aFile, "\tuint8_t "STUBPARAMETER_CALLTEST_S"; /*!< @brief If stub call is a STUB_CALL_PASS or STUB_CALL_FAIL */" NEWLINES); + if (pointerAvailable) + { + fprintf(aFile, "\t%s "STUBPARAMETER_POINTERHANDLING_S"; /*!< @brief pointer handling */" NEWLINES, STUBPARAMETER_POINTERHANDLING_ENUM_S); + } if (!isDatatypeVoid(aFunction->dataType)) { - fprintf(aFile, "\t%s "STUBPARAMETER_RETURN_S"; /**< @brief return value */" NEWLINES, aFunction->dataType); + fprintf(aFile, "\t%s "STUBPARAMETER_RETURN_S"; /*!< @brief return value */" NEWLINES, aFunction->dataType); } parameter = aFunction->parameter.head; parameterIndex = 'a'; @@ -365,7 +416,15 @@ STATIC int8_t createStubFunctionBlock(FILE *aFile, FILE *aHeader, cfunction_t *a } else if (parameter->array) { - fprintf(aFile, "\t%s *"STUBPARAMETER_PARAM_S1"; /*!< @brief %s */" NEWLINES, NCHECK(parameter->dataType), parameterIndex++, NCHECK(parameter->name)); + fprintf(aFile, "\t%s *"STUBPARAMETER_PARAM_S1"; /*!< @brief %s */" NEWLINES, NCHECK(parameter->dataType), parameterIndex, NCHECK(parameter->name)); + fprintf(aFile, "\tuint32_t "STUBPARAMETER_PARAM_S1"_size; /*!< @brief %s size to copy in case of parameter injection */" NEWLINES, parameterIndex++, + NCHECK(parameter->name)); + } + else if (NULL != strstr(parameter->dataType, "*")) + { + fprintf(aFile, "\t%s "STUBPARAMETER_PARAM_S1"; /*!< @brief %s */" NEWLINES, NCHECK(parameter->dataType), parameterIndex, NCHECK(parameter->name)); + fprintf(aFile, "\tuint32_t "STUBPARAMETER_PARAM_S1"_size; /*!< @brief %s size to copy in case of parameter injection */" NEWLINES, parameterIndex++, + NCHECK(parameter->name)); } else if (CPARAMETER_TYPE_REGULAR == parameter->type) { @@ -379,7 +438,7 @@ STATIC int8_t createStubFunctionBlock(FILE *aFile, FILE *aHeader, cfunction_t *a // Instance counter fprintf(aFile, "// Instance counter for stub functions" NEWLINES); - fprintf(aFile, "uint8_t "STUBINSTANCE_S1" = 0;" NEWLINES, aFunction->name); + fprintf(aFile, STUBINSTANCE_DATATYPE_S" "STUBINSTANCE_S1" = 0;" NEWLINES, aFunction->name); NEWLINE(aFile); // expected parameter @@ -388,8 +447,40 @@ STATIC int8_t createStubFunctionBlock(FILE *aFile, FILE *aHeader, cfunction_t *a aFunction->name); NEWLINE(aFile); +// stub function init header; function comment + fprintf(aHeader, "/*! @brief Stub initialization of init_%s" NEWLINES, aFunction->name); + fprintf(aHeader, " * @param " STUBINIT_PARAM_INSTANCE_S " Which stub call to initialize" NEWLINES); + fprintf(aHeader, " * @param " STUBINIT_PARAM_CALLTEST_S " Is stub call allowed (STUB_CALL_FAIL, STUB_CALL_PASS)" NEWLINES); + if (pointerAvailable) + { + fprintf(aHeader, + " * @param " STUBINIT_PARAM_POINTERHANDLING_S " How to handle pointer to data (STUB_PARAMETER_POINTER_HANDLING_ADDRESS, STUB_PARAMETER_POINTER_HANDLING_INJECT" NEWLINES); + } + if (!isDatatypeVoid(aFunction->dataType)) + { + fprintf(aHeader, " * @param " STUBINIT_PARAM_RETURN_S " Return value to inject" NEWLINES); + } + parameter = aFunction->parameter.head; + parameterIndex = 'a'; + while (parameter) + { + if (NULL != strstr(parameter->dataType, "*") || parameter->array) + { + fprintf(aHeader, + " * @param " STUBINIT_PARAM_PARAMETER_S1 "_size Use injection size 0 to ignore pointer (e.g. test subject references to internal variables)" NEWLINES, + parameterIndex); + } + parameterIndex++; + parameter = parameter->next; + } + fprintf(aHeader, " */" NEWLINES); + // stub function init header - fprintf(aHeader, "void init_%s(uint8_t "STUBINIT_PARAM_INSTANCE_S", uint8_t "STUBINIT_PARAM_CALLTEST_S, aFunction->name); + fprintf(aHeader, "void init_%s("STUBINSTANCE_DATATYPE_S " " STUBINIT_PARAM_INSTANCE_S", uint8_t "STUBINIT_PARAM_CALLTEST_S, aFunction->name); + if (pointerAvailable) + { + fprintf(aHeader, ", %s "STUBINIT_PARAM_POINTERHANDLING_S, STUBPARAMETER_POINTERHANDLING_ENUM_S); + } if (!isDatatypeVoid(aFunction->dataType)) { fprintf(aHeader, ", %s "STUBINIT_PARAM_RETURN_S, aFunction->dataType); @@ -402,6 +493,11 @@ STATIC int8_t createStubFunctionBlock(FILE *aFile, FILE *aHeader, cfunction_t *a { fprintf(aHeader, ", %s (*"STUBINIT_PARAM_PARAMETER_S1")%s", NCHECK(parameter->dataType), parameterIndex++, NCHECK(parameter->array)); } + else if (NULL != strstr(parameter->dataType, "*") || parameter->array) + { + fprintf(aHeader, ", %s "STUBINIT_PARAM_PARAMETER_S1"%s", NCHECK(parameter->dataType), parameterIndex, NCHECK(parameter->array)); + fprintf(aHeader, ", uint32_t "STUBINIT_PARAM_PARAMETER_S1"_size", parameterIndex++); + } else { fprintf(aHeader, ", %s "STUBINIT_PARAM_PARAMETER_S1"%s", NCHECK(parameter->dataType), parameterIndex++, NCHECK(parameter->array)); @@ -411,7 +507,11 @@ STATIC int8_t createStubFunctionBlock(FILE *aFile, FILE *aHeader, cfunction_t *a fprintf(aHeader, ");" NEWLINES); // stub function init - fprintf(aFile, "void init_%s(uint8_t "STUBINIT_PARAM_INSTANCE_S", uint8_t "STUBINIT_PARAM_CALLTEST_S, aFunction->name); + fprintf(aFile, "void init_%s("STUBINSTANCE_DATATYPE_S " " STUBINIT_PARAM_INSTANCE_S", uint8_t "STUBINIT_PARAM_CALLTEST_S, aFunction->name); + if (pointerAvailable) + { + fprintf(aFile, ", %s "STUBINIT_PARAM_POINTERHANDLING_S, STUBPARAMETER_POINTERHANDLING_ENUM_S); + } if (!isDatatypeVoid(aFunction->dataType)) { fprintf(aFile, ", %s "STUBINIT_PARAM_RETURN_S, aFunction->dataType); @@ -424,6 +524,11 @@ STATIC int8_t createStubFunctionBlock(FILE *aFile, FILE *aHeader, cfunction_t *a { fprintf(aFile, ", %s (*"STUBINIT_PARAM_PARAMETER_S1")%s", NCHECK(parameter->dataType), parameterIndex++, NCHECK(parameter->array)); } + else if (NULL != strstr(parameter->dataType, "*") || parameter->array) + { + fprintf(aFile, ", %s "STUBINIT_PARAM_PARAMETER_S1"%s", NCHECK(parameter->dataType), parameterIndex, NCHECK(parameter->array)); + fprintf(aFile, ", uint32_t "STUBINIT_PARAM_PARAMETER_S1"_size", parameterIndex++); + } else { fprintf(aFile, ", %s "STUBINIT_PARAM_PARAMETER_S1"%s", NCHECK(parameter->dataType), parameterIndex++, NCHECK(parameter->array)); @@ -439,6 +544,12 @@ STATIC int8_t createStubFunctionBlock(FILE *aFile, FILE *aHeader, cfunction_t *a fprintf(aFile, "\t"STUBINSTANCE_S1" = 0;" NEWLINES, aFunction->name); fprintf(aFile, "\t"STUBPARAMETER_STRUCT_S1"["STUBINIT_PARAM_INSTANCE_S"]."STUBPARAMETER_CALLTEST_S" = "STUBINIT_PARAM_CALLTEST_S";" NEWLINES, aFunction->name); + if (pointerAvailable) + { + fprintf(aFile, + "\t"STUBPARAMETER_STRUCT_S1"["STUBINIT_PARAM_INSTANCE_S"]."STUBPARAMETER_POINTERHANDLING_S" = "STUBINIT_PARAM_POINTERHANDLING_S";" NEWLINES, + aFunction->name); + } if (!isDatatypeVoid(aFunction->dataType)) { fprintf(aFile, "\t"STUBPARAMETER_STRUCT_S1"["STUBINIT_PARAM_INSTANCE_S"]."STUBPARAMETER_RETURN_S" = "STUBINIT_PARAM_RETURN_S";" NEWLINES, @@ -450,6 +561,11 @@ STATIC int8_t createStubFunctionBlock(FILE *aFile, FILE *aHeader, cfunction_t *a { fprintf(aFile, "\t"STUBPARAMETER_STRUCT_S1"["STUBINIT_PARAM_INSTANCE_S"]."STUBPARAMETER_PARAM_S1" = "STUBINIT_PARAM_PARAMETER_S1";" NEWLINES, aFunction->name, parameterIndex, parameterIndex); + if ((NULL != strstr(parameter->dataType, "*") || parameter->array) && CPARAMETER_TYPE_FUNCPTR != parameter->type) + { + fprintf(aFile, "\t"STUBPARAMETER_STRUCT_S1"["STUBINIT_PARAM_INSTANCE_S"]."STUBPARAMETER_PARAM_S1"_size = "STUBINIT_PARAM_PARAMETER_S1"_size;" NEWLINES, + aFunction->name, parameterIndex, parameterIndex); + } ++parameterIndex; parameter = parameter->next; } diff --git a/src/stubser/stubser_loc.h b/src/stubser/stubser_loc.h index 7389934..306e780 100644 --- a/src/stubser/stubser_loc.h +++ b/src/stubser/stubser_loc.h @@ -31,12 +31,18 @@ #define STUBPARAMETER_STRUCT_S1 "stubparameter_%s" // stubparameter_modulfunction_1 #define STUBPARAMETER_PARAM_S1 "parameter_%c" // "stubparameter_modulfunction_1".parameter_a #define STUBPARAMETER_CALLTEST_S "stubCallTest" +#define STUBPARAMETER_POINTERHANDLING_S "stubPointerHandling" +#define STUBPARAMETER_POINTERHANDLING_ENUM_S "stub_parameter_pointer_handling_t" +#define STUBPARAMETER_POINTERHANDLING_ADDRESS_S "STUB_PARAMETER_POINTER_HANDLING_ADDRESS" +#define STUBPARAMETER_POINTERHANDLING_INJECT_S "STUB_PARAMETER_POINTER_HANDLING_INJECT" #define STUBPARAMETER_RETURN_S "returnValue" // "stubparameter_modulfunction_1".returnValue #define STUBINSTANCE_S1 "stubInstance_%s" // stubInstance_modulfunction_1 +#define STUBINSTANCE_DATATYPE_S "uint8_t" #define STUBINIT_PARAM_INSTANCE_S "aInstance" #define STUBINIT_PARAM_CALLTEST_S "aStubCallTest" #define STUBINIT_PARAM_PARAMETER_S1 "aParameter_%c" // aParameter_a #define STUBINIT_PARAM_RETURN_S "aReturnValue" +#define STUBINIT_PARAM_POINTERHANDLING_S "aPointerHandling" #define STUBFUNCTION_USER_INITEXPECTED_S1 "stub_%s_user_initExpected" // stub_testfunction_initExpected #define STUBFUNCTION_USER_INITGLOBALS_S1 "stub_%s_user_initGlobals" // stub_testfunction_initGlobals From f313252d793436af898e6bbd72b97699b59b77b3 Mon Sep 17 00:00:00 2001 From: Martin Winkler Date: Fri, 31 Aug 2018 12:19:01 +0000 Subject: [PATCH 28/38] Supporting comma separated variable definition (int8_t varA, varB, varC[], *varD, varE[12];) --- src/stubser/cfile_parser.c | 29 +++++++++++++++++++++++++---- src/stubser/cfile_parser_loc.h | 3 +-- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/stubser/cfile_parser.c b/src/stubser/cfile_parser.c index 5ff7a2c..26adc65 100644 --- a/src/stubser/cfile_parser.c +++ b/src/stubser/cfile_parser.c @@ -611,6 +611,7 @@ STATIC int8_t evaluateParameter(char *aParameter, cfunction_t *aFunction) STATIC int8_t cfile_parser_evaluateExpression(char *aExpression, cfile_t *aCfile) { + uint16_t tempInt16 = 0; char *tempChar = NULL; cfile_variable_t *variable = NULL; cfunction_t *function = NULL; @@ -648,7 +649,8 @@ STATIC int8_t cfile_parser_evaluateExpression(char *aExpression, cfile_t *aCfile { (void) matchPrefix(variable, CELEMENT_TYPE_VARIABLE, &aExpression[matchGroup[1].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 1)); xmallocStrlcpy(&variable->name, &aExpression[matchGroup[2].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 2)); - // contains array information if available "[10]" + + // group 3 contains array information, if available if (XREGEX_IS_MATCHGROUP(matchGroup, 3)) { xmallocStrlcpy(&tempChar, &aExpression[matchGroup[3].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 3)); @@ -666,9 +668,28 @@ STATIC int8_t cfile_parser_evaluateExpression(char *aExpression, cfile_t *aCfile { xmallocStrlcpy(&variable->array, tempChar, strlen(tempChar)); } - xfree((void**) &tempChar); } + + // would contain more variables separated by ',' + if (XREGEX_IS_MATCHGROUP(matchGroup, 4)) + { + if (NULL != (tempChar = strstr(&aExpression[matchGroup[4].rm_so], ","))) + { + // remove leading , + tempInt16 = tempChar - &aExpression[matchGroup[4].rm_so]; + matchGroup[4].rm_so += tempInt16 + 1; + tempChar = NULL; + + DEBUG_LOG_APPEND(1, "Variable list: %s\n", &aExpression[matchGroup[4].rm_so]); + xmallocStrlcpy(&tempChar, aCfile->variables.head->dataType, strlen(aCfile->variables.head->dataType)); + xmallocStrlcat(&tempChar, &aExpression[matchGroup[4].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 4) + 1); + DEBUG_LOG_APPEND(1, "Result: %s\n", tempChar); + + cfile_parser_evaluateExpression(tempChar, aCfile); + } + } + xfree((void**) &tempChar); } } else if (0 == regexec(®XfunctionPointer, aExpression, CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS, matchGroup, 0) // @@ -726,7 +747,7 @@ STATIC uint32_t cfile_parser_evaluateLine(uint32_t aNumber, char *aLine, cfile_t { return 0; } - DEBUG_LOG_APPEND(2, "[ Li %04u] %s", aNumber, aLine); + DEBUG_LOG_APPEND(2, "[ Li %04u] %s\n", aNumber, aLine); tempChar = strrchr(aLine, '\n'); if (tempChar) { @@ -793,7 +814,7 @@ uint32_t cfile_parser(char *aPath, cfile_t *aCfile) free(fileLine); (void) fclose(fdesc); - // error detection for block removal +// error detection for block removal if (0 != cfile_parser_removeCommentHelper || 0 != cfile_parser_removeBraceHelper) { DEBUG_LOG_APPEND(1, "Helper (%d/%d) %s\n", cfile_parser_removeCommentHelper, cfile_parser_removeBraceHelper, gnu_basename(aPath)); diff --git a/src/stubser/cfile_parser_loc.h b/src/stubser/cfile_parser_loc.h index 66d12c3..509c81e 100644 --- a/src/stubser/cfile_parser_loc.h +++ b/src/stubser/cfile_parser_loc.h @@ -10,7 +10,6 @@ * @date 28.02.2017 * @author SESA354004 */ - #ifndef STUBSER_CFILE_PARSER_LOC_H_ #define STUBSER_CFILE_PARSER_LOC_H_ @@ -31,7 +30,7 @@ #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_VARIABLE CPARS_EXPRESSION_BASE "[[:blank:]]*(\\[*[^;=,]*)[[:blank:]]*(\\[*[^;=]*[;=])" #define CPARS_REGEX_PARAMETER CPARS_EXPRESSION_BASE "[[:blank:]]*(\\[*[^;=]*)" #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:]]*(.*)" From 66cdebd7c16bfe94922c3171976ac7b8f3dd2397 Mon Sep 17 00:00:00 2001 From: Martin Winkler Date: Tue, 4 Sep 2018 11:46:58 +0000 Subject: [PATCH 29/38] Using _size parameter = 0 to also disable address detection selectively Code comment enhancements for stubser and resulting stubs --- src/stubser/cfile_parser.c | 2 +- src/stubser/stubser.c | 37 +++++++++++++++++++++++++------------ 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/src/stubser/cfile_parser.c b/src/stubser/cfile_parser.c index 26adc65..c5cd672 100644 --- a/src/stubser/cfile_parser.c +++ b/src/stubser/cfile_parser.c @@ -255,7 +255,7 @@ STATIC int8_t matchPrefix(void *aElement, celement_type_t aElementType, char *aS * @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 [out] **aPosition Pointing to found block string (related 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 diff --git a/src/stubser/stubser.c b/src/stubser/stubser.c index 9343e07..9f60c79 100644 --- a/src/stubser/stubser.c +++ b/src/stubser/stubser.c @@ -171,14 +171,19 @@ STATIC void createParameterSpecificCheck(FILE *aFile, cfunction_t *aFunction, cf } else if (NULL != strstr(aParameter->dataType, "*") && NULL != strstr(aParameter->dataType, "char")) { - fprintf(aFile, - "\tif ("STUBPARAMETER_POINTERHANDLING_ADDRESS_S " == " STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_POINTERHANDLING_S")" NEWLINES "\t{" NEWLINES, - aFunction->name, aFunction->name); - fprintf(aFile, "\t\tCU_ASSERT_MEMORY_CHECK(\"%s(%s)\", ", aFunction->name, aParameter->name); + // char array with string comparison + fprintf(aFile, "\tif (" // + STUBPARAMETER_POINTERHANDLING_ADDRESS_S " == " STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_POINTERHANDLING_S// + ")" NEWLINES "\t{" NEWLINES, aFunction->name, aFunction->name); + // only assert if result should not be ignored (_size parameter) + fprintf(aFile, "\t\tif ("STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_PARAM_S1"_size)" NEWLINES, aFunction->name, aFunction->name, + aParameterIndex); + fprintf(aFile, "\t\t\tCU_ASSERT_MEMORY_CHECK(\"%s(%s)\", ", aFunction->name, aParameter->name); fprintf(aFile, STUBINIT_PARAM_PARAMETER_S1", "STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_PARAM_S1, aParameterIndex, aFunction->name, aFunction->name, aParameterIndex); fprintf(aFile, ", strlen("STUBINIT_PARAM_PARAMETER_S1"));"NEWLINES, aParameterIndex); fprintf(aFile, "\t}" NEWLINES); + // injection only for non constant parameter if (NULL == strstr(aParameter->dataType, "const")) { fprintf(aFile, "\telse" NEWLINES "\t{" NEWLINES); @@ -192,14 +197,18 @@ STATIC void createParameterSpecificCheck(FILE *aFile, cfunction_t *aFunction, cf else if (NULL != strstr(aParameter->dataType, "*") || NULL != aParameter->array) { // pointer - fprintf(aFile, - "\tif ("STUBPARAMETER_POINTERHANDLING_ADDRESS_S " == " STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_POINTERHANDLING_S")" NEWLINES "\t{" NEWLINES, - aFunction->name, aFunction->name); - fprintf(aFile, "\t\tCU_ASSERT_PTR_EQUAL("); + fprintf(aFile, "\tif (" // + STUBPARAMETER_POINTERHANDLING_ADDRESS_S " == " STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_POINTERHANDLING_S// + ")" NEWLINES "\t{" NEWLINES, aFunction->name, aFunction->name); + // only assert if result should not be ignored (_size parameter) + fprintf(aFile, "\t\tif ("STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_PARAM_S1"_size)" NEWLINES, aFunction->name, aFunction->name, + aParameterIndex); + fprintf(aFile, "\t\t\tCU_ASSERT_PTR_EQUAL("); fprintf(aFile, STUBINIT_PARAM_PARAMETER_S1", "STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_PARAM_S1, aParameterIndex, aFunction->name, aFunction->name, aParameterIndex); fprintf(aFile, ");" NEWLINES); fprintf(aFile, "\t}" NEWLINES); + // injection only for non constant parameter if (NULL == strstr(aParameter->dataType, "const")) { fprintf(aFile, "\telse" NEWLINES "\t{" NEWLINES); @@ -396,7 +405,7 @@ STATIC int8_t createStubFunctionBlock(FILE *aFile, FILE *aHeader, cfunction_t *a fprintf(aFile, "// Expected parameter and return value structures" NEWLINES); fprintf(aFile, "typedef struct _STUBPARAMETER_%s" NEWLINES, aFunction->name); fprintf(aFile, "{" NEWLINES); - fprintf(aFile, "\tuint8_t "STUBPARAMETER_CALLTEST_S"; /*!< @brief If stub call is a STUB_CALL_PASS or STUB_CALL_FAIL */" NEWLINES); + fprintf(aFile, "\tuint8_t "STUBPARAMETER_CALLTEST_S"; /*!< @brief Stub call is a STUB_CALL_PASS or STUB_CALL_FAIL */" NEWLINES); if (pointerAvailable) { fprintf(aFile, "\t%s "STUBPARAMETER_POINTERHANDLING_S"; /*!< @brief pointer handling */" NEWLINES, STUBPARAMETER_POINTERHANDLING_ENUM_S); @@ -449,6 +458,11 @@ STATIC int8_t createStubFunctionBlock(FILE *aFile, FILE *aHeader, cfunction_t *a // stub function init header; function comment fprintf(aHeader, "/*! @brief Stub initialization of init_%s" NEWLINES, aFunction->name); + if (pointerAvailable) + { + fprintf(aHeader, + " * @attention In case of address comparison, ..._size parameter = 0 ignores result (@ref " STUBINIT_PARAM_POINTERHANDLING_S ")." NEWLINES); + } fprintf(aHeader, " * @param " STUBINIT_PARAM_INSTANCE_S " Which stub call to initialize" NEWLINES); fprintf(aHeader, " * @param " STUBINIT_PARAM_CALLTEST_S " Is stub call allowed (STUB_CALL_FAIL, STUB_CALL_PASS)" NEWLINES); if (pointerAvailable) @@ -467,7 +481,7 @@ STATIC int8_t createStubFunctionBlock(FILE *aFile, FILE *aHeader, cfunction_t *a if (NULL != strstr(parameter->dataType, "*") || parameter->array) { fprintf(aHeader, - " * @param " STUBINIT_PARAM_PARAMETER_S1 "_size Use injection size 0 to ignore pointer (e.g. test subject references to internal variables)" NEWLINES, + " * @param " STUBINIT_PARAM_PARAMETER_S1 "_size 0 to ignore pointer for address comparison and injection (e.g. test subject references to internal variables)" NEWLINES, parameterIndex); } parameterIndex++; @@ -676,10 +690,9 @@ STATIC void createUserHeader(char *aOutput, char *aNoSuffix) } free(cHeaderName); - // TODO user c file if (!file_exist(cFileName)) { - // user header doesn't exist + // user code doesn't exist fileDesc = fopen(cFileName, "w"); if (NULL != fileDesc) { From 6d894b634ed772525e9c43bf3a955c3b89ada9e7 Mon Sep 17 00:00:00 2001 From: Martin Winkler Date: Tue, 4 Sep 2018 13:21:02 +0000 Subject: [PATCH 30/38] NULL pointer check for memcpy stub structure default initialization for pointer check --- src/stubser/stubser.c | 52 +++++++++++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 14 deletions(-) diff --git a/src/stubser/stubser.c b/src/stubser/stubser.c index 9f60c79..6935636 100644 --- a/src/stubser/stubser.c +++ b/src/stubser/stubser.c @@ -183,10 +183,10 @@ STATIC void createParameterSpecificCheck(FILE *aFile, cfunction_t *aFunction, cf aFunction->name, aParameterIndex); fprintf(aFile, ", strlen("STUBINIT_PARAM_PARAMETER_S1"));"NEWLINES, aParameterIndex); fprintf(aFile, "\t}" NEWLINES); - // injection only for non constant parameter + // injection only for non constant and non NULL parameter if (NULL == strstr(aParameter->dataType, "const")) { - fprintf(aFile, "\telse" NEWLINES "\t{" NEWLINES); + fprintf(aFile, "\telse if (NULL != " STUBINIT_PARAM_PARAMETER_S1 ")" NEWLINES "\t{" NEWLINES, aParameterIndex); fprintf(aFile, "\t\tmemcpy(" STUBINIT_PARAM_PARAMETER_S1 ", "STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_PARAM_S1", " // STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_PARAM_S1"_size",// aParameterIndex, aFunction->name, aFunction->name, aParameterIndex, aFunction->name, aFunction->name, aParameterIndex); @@ -208,10 +208,10 @@ STATIC void createParameterSpecificCheck(FILE *aFile, cfunction_t *aFunction, cf aFunction->name, aParameterIndex); fprintf(aFile, ");" NEWLINES); fprintf(aFile, "\t}" NEWLINES); - // injection only for non constant parameter + // injection only for non constant and non NULL parameter if (NULL == strstr(aParameter->dataType, "const")) { - fprintf(aFile, "\telse" NEWLINES "\t{" NEWLINES); + fprintf(aFile, "\telse if (NULL != " STUBINIT_PARAM_PARAMETER_S1 ")" NEWLINES "\t{" NEWLINES, aParameterIndex); fprintf(aFile, "\t\tmemcpy(" STUBINIT_PARAM_PARAMETER_S1 ", "STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_PARAM_S1", " // STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_PARAM_S1"_size",// aParameterIndex, aFunction->name, aFunction->name, aParameterIndex, aFunction->name, aFunction->name, aParameterIndex); @@ -420,24 +420,25 @@ STATIC int8_t createStubFunctionBlock(FILE *aFile, FILE *aHeader, cfunction_t *a { if (CPARAMETER_TYPE_FUNCPTR == parameter->type) { - fprintf(aFile, "\t%s (*"STUBPARAMETER_PARAM_S1")%s; /*!< @brief %s */" NEWLINES, NCHECK(parameter->dataType), parameterIndex++, + fprintf(aFile, "\t%s (*"STUBPARAMETER_PARAM_S1")%s; /*!< @brief \"%s\" */" NEWLINES, NCHECK(parameter->dataType), parameterIndex++, NCHECK(parameter->array), NCHECK(parameter->name)); } else if (parameter->array) { - fprintf(aFile, "\t%s *"STUBPARAMETER_PARAM_S1"; /*!< @brief %s */" NEWLINES, NCHECK(parameter->dataType), parameterIndex, NCHECK(parameter->name)); - fprintf(aFile, "\tuint32_t "STUBPARAMETER_PARAM_S1"_size; /*!< @brief %s size to copy in case of parameter injection */" NEWLINES, parameterIndex++, - NCHECK(parameter->name)); + fprintf(aFile, "\t%s *"STUBPARAMETER_PARAM_S1"; /*!< @brief \"%s\" */" NEWLINES, NCHECK(parameter->dataType), parameterIndex, NCHECK(parameter->name)); + fprintf(aFile, "\tuint32_t "STUBPARAMETER_PARAM_S1"_size; /*!< @brief \"%s\" size to copy in case of parameter injection */" NEWLINES, + parameterIndex++, NCHECK(parameter->name)); } else if (NULL != strstr(parameter->dataType, "*")) { - fprintf(aFile, "\t%s "STUBPARAMETER_PARAM_S1"; /*!< @brief %s */" NEWLINES, NCHECK(parameter->dataType), parameterIndex, NCHECK(parameter->name)); - fprintf(aFile, "\tuint32_t "STUBPARAMETER_PARAM_S1"_size; /*!< @brief %s size to copy in case of parameter injection */" NEWLINES, parameterIndex++, - NCHECK(parameter->name)); + fprintf(aFile, "\t%s "STUBPARAMETER_PARAM_S1"; /*!< @brief \"%s\" */" NEWLINES, NCHECK(parameter->dataType), parameterIndex, NCHECK(parameter->name)); + fprintf(aFile, "\tuint32_t "STUBPARAMETER_PARAM_S1"_size; /*!< @brief \"%s\" size to copy in case of parameter injection */" NEWLINES, + parameterIndex++, NCHECK(parameter->name)); } else if (CPARAMETER_TYPE_REGULAR == parameter->type) { - fprintf(aFile, "\t%s "STUBPARAMETER_PARAM_S1"; /*!< @brief %s */" NEWLINES, NCHECK(parameter->dataType), parameterIndex++, NCHECK(parameter->name)); + fprintf(aFile, "\t%s "STUBPARAMETER_PARAM_S1"; /*!< @brief \"%s\" */" NEWLINES, NCHECK(parameter->dataType), parameterIndex++, + NCHECK(parameter->name)); } parameter = parameter->next; } @@ -452,8 +453,31 @@ STATIC int8_t createStubFunctionBlock(FILE *aFile, FILE *aHeader, cfunction_t *a // expected parameter fprintf(aFile, "// Expected parameter and return value arrays for in-stub tests" NEWLINES); - fprintf(aFile, STUBPARAMETER_TYPEDEF_S1 " " STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_AMOUNT_S1"];" NEWLINES, aFunction->name, aFunction->name, - aFunction->name); + fprintf(aFile, STUBPARAMETER_TYPEDEF_S1 " " STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_AMOUNT_S1"]", aFunction->name, aFunction->name, aFunction->name); + if (pointerAvailable) + { + fprintf(aFile, " = {" NEWLINES); + // pointer address check by default + + parameter = aFunction->parameter.head; + parameterIndex = 'a'; + while (parameter) + { + // initialize _size parameter to 1 (default to check addresses) + if (CPARAMETER_TYPE_FUNCPTR != parameter->type && (parameter->array || NULL != strstr(parameter->dataType, "*"))) + { + fprintf(aFile, "\t[0 ... %u]."STUBPARAMETER_PARAM_S1" = (%s) 0x55," NEWLINES, STUB_INSTANCES_AMOUNT - 1, parameterIndex, parameter->dataType); + fprintf(aFile, "\t[0 ... %u]."STUBPARAMETER_PARAM_S1"_size = 1," NEWLINES, STUB_INSTANCES_AMOUNT - 1, parameterIndex); + } + ++parameterIndex; + parameter = parameter->next; + } + fprintf(aFile, "};" NEWLINES); + } + else + { + fprintf(aFile, ";" NEWLINES); + } NEWLINE(aFile); // stub function init header; function comment From f64696daacfcfe992a3c2aa15ce4594a66618529 Mon Sep 17 00:00:00 2001 From: Martin Winkler Date: Wed, 5 Sep 2018 08:24:30 +0000 Subject: [PATCH 31/38] Initializing expected parameter in declaration and after each instance run to ensure reproducibility. Assert for invalid STUB_PASS values --- src/stubser/stubser.c | 40 ++++++++++++++++++++++++++++++++++----- src/stubser/stubser_loc.h | 5 +++++ 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/src/stubser/stubser.c b/src/stubser/stubser.c index 6935636..504fb52 100644 --- a/src/stubser/stubser.c +++ b/src/stubser/stubser.c @@ -88,7 +88,7 @@ STATIC void createVariableSpecificInit(const char* aVariableTemplate, FILE *aFil { fprintf(aFile, "\t(void) memset("); fprintf(aFile, aVariableTemplate, aVariable->name); - fprintf(aFile, ", 0x55, sizeof(%s)); /* %s */" NEWLINES, aVariable->name, aVariable->dataType); + fprintf(aFile, ", "STUBDEFAULT_VALUE_VARIABLE_S", sizeof(%s)); /* %s */" NEWLINES, aVariable->name, aVariable->dataType); } else { @@ -102,13 +102,13 @@ STATIC void createVariableSpecificInit(const char* aVariableTemplate, FILE *aFil { fprintf(aFile, "\t"); fprintf(aFile, aVariableTemplate, aVariable->name); - fprintf(aFile, " = 0x55;" NEWLINES); + fprintf(aFile, " = "STUBDEFAULT_VALUE_VARIABLE_S";" NEWLINES); } else { fprintf(aFile, "\t(void) memset(&"); fprintf(aFile, aVariableTemplate, aVariable->name); - fprintf(aFile, ", 0x55, sizeof(%s)); /* %s */" NEWLINES, aVariable->name, aVariable->dataType); + fprintf(aFile, ", "STUBDEFAULT_VALUE_VARIABLE_S", sizeof(%s)); /* %s */" NEWLINES, aVariable->name, aVariable->dataType); } } @@ -168,6 +168,8 @@ STATIC void createParameterSpecificCheck(FILE *aFile, cfunction_t *aFunction, cf fprintf(aFile, STUBINIT_PARAM_PARAMETER_S1", "STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_PARAM_S1, aParameterIndex, aFunction->name, aFunction->name, aParameterIndex); fprintf(aFile, ");"NEWLINES); + fprintf(aFile, "\t"STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_PARAM_S1" = (%s) "STUBDEFAULT_VALUE_POINTER_S";" NEWLINES, aFunction->name, + aFunction->name, aParameterIndex, aParameter->dataType); } else if (NULL != strstr(aParameter->dataType, "*") && NULL != strstr(aParameter->dataType, "char")) { @@ -193,6 +195,10 @@ STATIC void createParameterSpecificCheck(FILE *aFile, cfunction_t *aFunction, cf fprintf(aFile, ");" NEWLINES); fprintf(aFile, "\t}" NEWLINES); } + fprintf(aFile, "\t"STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_PARAM_S1" = (%s) "STUBDEFAULT_VALUE_POINTER_S";" NEWLINES, aFunction->name, + aFunction->name, aParameterIndex, aParameter->dataType); + fprintf(aFile, "\t"STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_PARAM_S1"_size = "STUBDEFAULT_VALUE_POINTERSIZE_S";" NEWLINES, + aFunction->name, aFunction->name, aParameterIndex); } else if (NULL != strstr(aParameter->dataType, "*") || NULL != aParameter->array) { @@ -218,6 +224,10 @@ STATIC void createParameterSpecificCheck(FILE *aFile, cfunction_t *aFunction, cf fprintf(aFile, ");" NEWLINES); fprintf(aFile, "\t}" NEWLINES); } + fprintf(aFile, "\t"STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_PARAM_S1" = (%s) "STUBDEFAULT_VALUE_POINTER_S";" NEWLINES, aFunction->name, + aFunction->name, aParameterIndex, aParameter->dataType); + fprintf(aFile, "\t"STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_PARAM_S1"_size = "STUBDEFAULT_VALUE_POINTERSIZE_S";" NEWLINES, + aFunction->name, aFunction->name, aParameterIndex); } else if (isDatatypeStandard(aParameter->dataType)) { @@ -225,6 +235,8 @@ STATIC void createParameterSpecificCheck(FILE *aFile, cfunction_t *aFunction, cf fprintf(aFile, STUBINIT_PARAM_PARAMETER_S1", "STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_PARAM_S1, aParameterIndex, aFunction->name, aFunction->name, aParameterIndex); fprintf(aFile, ");"NEWLINES); + fprintf(aFile, "\t"STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_PARAM_S1" = (%s) "STUBDEFAULT_VALUE_VARIABLE_S";" NEWLINES, aFunction->name, + aFunction->name, aParameterIndex, aParameter->dataType); } else { @@ -232,6 +244,8 @@ STATIC void createParameterSpecificCheck(FILE *aFile, cfunction_t *aFunction, cf fprintf(aFile, "&"STUBINIT_PARAM_PARAMETER_S1", &"STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_PARAM_S1, aParameterIndex, aFunction->name, aFunction->name, aParameterIndex); fprintf(aFile, ", sizeof("STUBINIT_PARAM_PARAMETER_S1"));"NEWLINES, aParameterIndex); + fprintf(aFile, "\t"STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_PARAM_S1" = (%s) "STUBDEFAULT_VALUE_VARIABLE_S";" NEWLINES, aFunction->name, + aFunction->name, aParameterIndex, aParameter->dataType); } } @@ -466,9 +480,16 @@ STATIC int8_t createStubFunctionBlock(FILE *aFile, FILE *aHeader, cfunction_t *a // initialize _size parameter to 1 (default to check addresses) if (CPARAMETER_TYPE_FUNCPTR != parameter->type && (parameter->array || NULL != strstr(parameter->dataType, "*"))) { - fprintf(aFile, "\t[0 ... %u]."STUBPARAMETER_PARAM_S1" = (%s) 0x55," NEWLINES, STUB_INSTANCES_AMOUNT - 1, parameterIndex, parameter->dataType); + fprintf(aFile, "\t[0 ... %u]."STUBPARAMETER_PARAM_S1" = (%s) "STUBDEFAULT_VALUE_POINTER_S"," NEWLINES, STUB_INSTANCES_AMOUNT - 1, parameterIndex, + parameter->dataType); fprintf(aFile, "\t[0 ... %u]."STUBPARAMETER_PARAM_S1"_size = 1," NEWLINES, STUB_INSTANCES_AMOUNT - 1, parameterIndex); } + else + { + fprintf(aFile, "\t[0 ... %u]."STUBPARAMETER_PARAM_S1" = (%s) "STUBDEFAULT_VALUE_VARIABLE_S"," NEWLINES, STUB_INSTANCES_AMOUNT - 1, parameterIndex, + parameter->dataType); + } + ++parameterIndex; parameter = parameter->next; } @@ -636,8 +657,12 @@ STATIC int8_t createStubFunctionBlock(FILE *aFile, FILE *aHeader, cfunction_t *a fprintf(aFile, "\t\tCU_FAIL(\"Inadvertent %s() call.\");"NEWLINES"\t\tbreak;"NEWLINES, aFunction->name); fprintf(aFile, "\tcase STUB_CALL_PASS:" NEWLINES); fprintf(aFile, "\t\tCU_PASS(\"%s() called.\");"NEWLINES"\t\tbreak;"NEWLINES, aFunction->name); - fprintf(aFile, "\tdefault:"NEWLINES"\t\tbreak;"NEWLINES); + fprintf(aFile, "\tdefault:"NEWLINES); + fprintf(aFile, "\t\tCU_FAIL_OUTPUT_LESS(\"Invalid STUB_CALL test value: \","STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_CALLTEST_S", \"%%u\");"NEWLINES, + aFunction->name, aFunction->name); + fprintf(aFile, "\t\tbreak;"NEWLINES); fprintf(aFile, "\t}" NEWLINES); + fprintf(aFile, "\t"STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_CALLTEST_S" = STUB_CALL_FAIL;" NEWLINES, aFunction->name, aFunction->name); parameter = aFunction->parameter.head; parameterIndex = 'a'; @@ -647,6 +672,11 @@ STATIC int8_t createStubFunctionBlock(FILE *aFile, FILE *aHeader, cfunction_t *a ++parameterIndex; parameter = parameter->next; } + if (pointerAvailable) + { + fprintf(aFile, "\t"STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_POINTERHANDLING_S" = " STUBPARAMETER_POINTERHANDLING_ADDRESS_S ";" NEWLINES, + aFunction->name, aFunction->name); + } if (!isDatatypeVoid(aFunction->dataType)) { diff --git a/src/stubser/stubser_loc.h b/src/stubser/stubser_loc.h index 306e780..0809cbe 100644 --- a/src/stubser/stubser_loc.h +++ b/src/stubser/stubser_loc.h @@ -44,6 +44,11 @@ #define STUBINIT_PARAM_RETURN_S "aReturnValue" #define STUBINIT_PARAM_POINTERHANDLING_S "aPointerHandling" +#define STUBDEFAULT_VALUE_FUNCTIONPOINTER_S "0x55" +#define STUBDEFAULT_VALUE_POINTER_S "0x55" +#define STUBDEFAULT_VALUE_POINTERSIZE_S "1" +#define STUBDEFAULT_VALUE_VARIABLE_S "0x55" + #define STUBFUNCTION_USER_INITEXPECTED_S1 "stub_%s_user_initExpected" // stub_testfunction_initExpected #define STUBFUNCTION_USER_INITGLOBALS_S1 "stub_%s_user_initGlobals" // stub_testfunction_initGlobals #define STUBFUNCTION_USER_CHECK_S1 "stub_%s_user_checkGlobals" // stub_testfunction_checkGlobals From c26b8dc13ab148cad1210817e8e9b3ba99951508 Mon Sep 17 00:00:00 2001 From: Martin Winkler Date: Wed, 5 Sep 2018 13:51:38 +0000 Subject: [PATCH 32/38] post build step to copy exe directly to cygwin/bin --- .cproject | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.cproject b/.cproject index ce988b9..e7b8a07 100644 --- a/.cproject +++ b/.cproject @@ -67,7 +67,7 @@ - + From c90f479de99cd8779bdd73ec9c87ea54314887a0 Mon Sep 17 00:00:00 2001 From: Martin Winkler Date: Wed, 5 Sep 2018 13:52:36 +0000 Subject: [PATCH 33/38] stub init with fail condition initializes expected parameter with default, keeping structure array clean for further tests --- src/stubser/stubser.c | 49 +++++++++++++++++++++++++++++++++++---- src/stubser/stubser_loc.h | 6 ++--- 2 files changed, 47 insertions(+), 8 deletions(-) diff --git a/src/stubser/stubser.c b/src/stubser/stubser.c index 504fb52..4d1a7a3 100644 --- a/src/stubser/stubser.c +++ b/src/stubser/stubser.c @@ -600,34 +600,72 @@ STATIC int8_t createStubFunctionBlock(FILE *aFile, FILE *aHeader, cfunction_t *a fprintf(aFile, "\t{" NEWLINES); fprintf(aFile, "\t\tCU_FAIL_FATAL(\"init_%s() - "STUBINIT_PARAM_INSTANCE_S" out of bounce\");" NEWLINES, aFunction->name); fprintf(aFile, "\t}" NEWLINES); + // setting parameter fprintf(aFile, "\t"STUBINSTANCE_S1" = 0;" NEWLINES, aFunction->name); fprintf(aFile, "\t"STUBPARAMETER_STRUCT_S1"["STUBINIT_PARAM_INSTANCE_S"]."STUBPARAMETER_CALLTEST_S" = "STUBINIT_PARAM_CALLTEST_S";" NEWLINES, aFunction->name); + + // if STUB_CALL_PASS is requested init with parameter + fprintf(aFile, "\tif ( STUB_CALL_PASS == " STUBINIT_PARAM_CALLTEST_S ")" NEWLINES "\t{" NEWLINES); if (pointerAvailable) { fprintf(aFile, - "\t"STUBPARAMETER_STRUCT_S1"["STUBINIT_PARAM_INSTANCE_S"]."STUBPARAMETER_POINTERHANDLING_S" = "STUBINIT_PARAM_POINTERHANDLING_S";" NEWLINES, + "\t\t"STUBPARAMETER_STRUCT_S1"["STUBINIT_PARAM_INSTANCE_S"]."STUBPARAMETER_POINTERHANDLING_S" = "STUBINIT_PARAM_POINTERHANDLING_S";" NEWLINES, aFunction->name); } if (!isDatatypeVoid(aFunction->dataType)) { - fprintf(aFile, "\t"STUBPARAMETER_STRUCT_S1"["STUBINIT_PARAM_INSTANCE_S"]."STUBPARAMETER_RETURN_S" = "STUBINIT_PARAM_RETURN_S";" NEWLINES, + fprintf(aFile, "\t\t"STUBPARAMETER_STRUCT_S1"["STUBINIT_PARAM_INSTANCE_S"]."STUBPARAMETER_RETURN_S" = "STUBINIT_PARAM_RETURN_S";" NEWLINES, aFunction->name); } parameter = aFunction->parameter.head; parameterIndex = 'a'; while (parameter) { - fprintf(aFile, "\t"STUBPARAMETER_STRUCT_S1"["STUBINIT_PARAM_INSTANCE_S"]."STUBPARAMETER_PARAM_S1" = "STUBINIT_PARAM_PARAMETER_S1";" NEWLINES, + fprintf(aFile, "\t\t"STUBPARAMETER_STRUCT_S1"["STUBINIT_PARAM_INSTANCE_S"]."STUBPARAMETER_PARAM_S1" = "STUBINIT_PARAM_PARAMETER_S1";" NEWLINES, aFunction->name, parameterIndex, parameterIndex); if ((NULL != strstr(parameter->dataType, "*") || parameter->array) && CPARAMETER_TYPE_FUNCPTR != parameter->type) { - fprintf(aFile, "\t"STUBPARAMETER_STRUCT_S1"["STUBINIT_PARAM_INSTANCE_S"]."STUBPARAMETER_PARAM_S1"_size = "STUBINIT_PARAM_PARAMETER_S1"_size;" NEWLINES, + fprintf(aFile, + "\t\t"STUBPARAMETER_STRUCT_S1"["STUBINIT_PARAM_INSTANCE_S"]."STUBPARAMETER_PARAM_S1"_size = "STUBINIT_PARAM_PARAMETER_S1"_size;" NEWLINES, aFunction->name, parameterIndex, parameterIndex); } ++parameterIndex; parameter = parameter->next; } + fprintf(aFile, "\t}" NEWLINES); + // if STUB_CALL_FAIL is requested init with default parameter + fprintf(aFile, "\telse" NEWLINES "\t{" NEWLINES); + if (pointerAvailable) + { + fprintf(aFile, + "\t\t"STUBPARAMETER_STRUCT_S1"["STUBINIT_PARAM_INSTANCE_S"]."STUBPARAMETER_POINTERHANDLING_S" = "STUBPARAMETER_POINTERHANDLING_ADDRESS_S";" NEWLINES, + aFunction->name); + } + parameter = aFunction->parameter.head; + parameterIndex = 'a'; + while (parameter) + { + // initialize _size parameter to 1 (default to check addresses) + if (CPARAMETER_TYPE_FUNCPTR != parameter->type && (parameter->array || NULL != strstr(parameter->dataType, "*"))) + { + fprintf(aFile, "\t\t"STUBPARAMETER_STRUCT_S1"["STUBINIT_PARAM_INSTANCE_S"]."STUBPARAMETER_PARAM_S1" = (%s) "STUBDEFAULT_VALUE_POINTER_S";" NEWLINES, + aFunction->name, parameterIndex, parameter->dataType); + fprintf(aFile, + "\t\t"STUBPARAMETER_STRUCT_S1"["STUBINIT_PARAM_INSTANCE_S"]."STUBPARAMETER_PARAM_S1"_size = "STUBDEFAULT_VALUE_POINTERSIZE_S";" NEWLINES, + aFunction->name, parameterIndex); + } + else + { + fprintf(aFile, "\t\t"STUBPARAMETER_STRUCT_S1"["STUBINIT_PARAM_INSTANCE_S"]."STUBPARAMETER_PARAM_S1" = (%s) "STUBDEFAULT_VALUE_VARIABLE_S";" NEWLINES, + aFunction->name, parameterIndex, parameter->dataType); + } + + ++parameterIndex; + parameter = parameter->next; + } + fprintf(aFile, "\t}" NEWLINES); + fprintf(aFile, "}" NEWLINES); NEWLINE(aFile); @@ -658,7 +696,8 @@ STATIC int8_t createStubFunctionBlock(FILE *aFile, FILE *aHeader, cfunction_t *a fprintf(aFile, "\tcase STUB_CALL_PASS:" NEWLINES); fprintf(aFile, "\t\tCU_PASS(\"%s() called.\");"NEWLINES"\t\tbreak;"NEWLINES, aFunction->name); fprintf(aFile, "\tdefault:"NEWLINES); - fprintf(aFile, "\t\tCU_FAIL_OUTPUT_LESS(\"Invalid STUB_CALL test value: \","STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_CALLTEST_S", \"%%u\");"NEWLINES, + fprintf(aFile, + "\t\tCU_FAIL_OUTPUT_LESS(\"Invalid STUB_CALL test value: \","STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_CALLTEST_S", \"%%u\");"NEWLINES, aFunction->name, aFunction->name); fprintf(aFile, "\t\tbreak;"NEWLINES); fprintf(aFile, "\t}" NEWLINES); diff --git a/src/stubser/stubser_loc.h b/src/stubser/stubser_loc.h index 0809cbe..1d7d678 100644 --- a/src/stubser/stubser_loc.h +++ b/src/stubser/stubser_loc.h @@ -44,10 +44,10 @@ #define STUBINIT_PARAM_RETURN_S "aReturnValue" #define STUBINIT_PARAM_POINTERHANDLING_S "aPointerHandling" -#define STUBDEFAULT_VALUE_FUNCTIONPOINTER_S "0x55" -#define STUBDEFAULT_VALUE_POINTER_S "0x55" +#define STUBDEFAULT_VALUE_FUNCTIONPOINTER_S "0xAA" +#define STUBDEFAULT_VALUE_POINTER_S "0xAA" #define STUBDEFAULT_VALUE_POINTERSIZE_S "1" -#define STUBDEFAULT_VALUE_VARIABLE_S "0x55" +#define STUBDEFAULT_VALUE_VARIABLE_S "0xAA" #define STUBFUNCTION_USER_INITEXPECTED_S1 "stub_%s_user_initExpected" // stub_testfunction_initExpected #define STUBFUNCTION_USER_INITGLOBALS_S1 "stub_%s_user_initGlobals" // stub_testfunction_initGlobals From 47e79f04dce9109ae497c09f53eef70dfb9cb038 Mon Sep 17 00:00:00 2001 From: Martin Winkler Date: Fri, 7 Sep 2018 05:50:58 +0000 Subject: [PATCH 34/38] output with value for CU_ASSERT_EQUAL_OUTPUT --- src/stubser/stubser.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/src/stubser/stubser.c b/src/stubser/stubser.c index 4d1a7a3..27ef9fe 100644 --- a/src/stubser/stubser.c +++ b/src/stubser/stubser.c @@ -57,6 +57,26 @@ STATIC bool isDatatypeStandard(char *aDataType) return false; } +STATIC void addPrintfFormat(FILE *aFile, const char* aType) +{ + if (NULL != strstr(aType, "double")) + { + fprintf(aFile, ("\"%%e\"")); + } + else if (NULL != strstr(aType, "int32_t")) + { + fprintf(aFile, ("\"%%d\"")); + } + else if (NULL != strstr(aType, "32") || NULL != strstr(aType, "long")) + { + fprintf(aFile, ("\"%%ld\"")); + } + else + { + fprintf(aFile, ("\"%%d\"")); + } +} + STATIC void createVariableSpecificInit(const char* aVariableTemplate, FILE *aFile, cfile_variable_t *aVariable) { char *tempChar = NULL; @@ -150,7 +170,9 @@ STATIC void createVariableSpecificCheck(FILE *aFile, cfile_variable_t *aVariable } else if (isDatatypeStandard(aVariable->dataType)) { - fprintf(aFile, "\tCU_ASSERT_EQUAL(%s, "STUBVARIABLE_EXPECTED_S1");"NEWLINES, aVariable->name, aVariable->name); + fprintf(aFile, "\tCU_ASSERT_EQUAL_OUTPUT(%s, "STUBVARIABLE_EXPECTED_S1", ", aVariable->name, aVariable->name); + addPrintfFormat(aFile, aVariable->dataType); + fprintf(aFile, ");" NEWLINES); } else { @@ -231,9 +253,10 @@ STATIC void createParameterSpecificCheck(FILE *aFile, cfunction_t *aFunction, cf } else if (isDatatypeStandard(aParameter->dataType)) { - fprintf(aFile, "\tCU_ASSERT_EQUAL("); - fprintf(aFile, STUBINIT_PARAM_PARAMETER_S1", "STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_PARAM_S1, aParameterIndex, aFunction->name, + fprintf(aFile, "\tCU_ASSERT_EQUAL_OUTPUT("); + fprintf(aFile, STUBINIT_PARAM_PARAMETER_S1", "STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_PARAM_S1", ", aParameterIndex, aFunction->name, aFunction->name, aParameterIndex); + addPrintfFormat(aFile, aParameter->dataType); fprintf(aFile, ");"NEWLINES); fprintf(aFile, "\t"STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_PARAM_S1" = (%s) "STUBDEFAULT_VALUE_VARIABLE_S";" NEWLINES, aFunction->name, aFunction->name, aParameterIndex, aParameter->dataType); From fc12aa8bb2347d8a19d213247ffce7f4d0266daf Mon Sep 17 00:00:00 2001 From: Martin Winkler Date: Thu, 4 Apr 2019 14:00:40 +0100 Subject: [PATCH 35/38] Convert svn:ignore to .gitignore --- .gitignore | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..590eb55 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ + +# / +/Debug +/Release +/*.stackdump + +# /.settings/ +/.settings/*.xml From 9350133b2cfc3b438435a1aee79dc1ce988b754c Mon Sep 17 00:00:00 2001 From: Martin Winkler Date: Thu, 4 Apr 2019 14:11:20 +0100 Subject: [PATCH 36/38] Adding readme for gitea --- README.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 From 7928bb420954554b5e59454c03ba3c650d393654 Mon Sep 17 00:00:00 2001 From: Martin Winkler Date: Thu, 4 Apr 2019 15:31:36 +0200 Subject: [PATCH 37/38] Fix binary name in eclipse project settings --- .cproject | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.cproject b/.cproject index e7b8a07..5d41863 100644 --- a/.cproject +++ b/.cproject @@ -14,7 +14,7 @@ - + From 1699b336ec5d0602d0ccb36be97fbedcec87b1ee Mon Sep 17 00:00:00 2001 From: Martin Winkler Date: Thu, 4 Apr 2019 15:45:29 +0200 Subject: [PATCH 38/38] Replacing pseudonym --- src/ext/xmalloc.c | 2 +- src/ext/xmalloc.h | 2 +- src/ext/xregex.h | 2 +- src/ext/xstring.c | 2 +- src/ext/xstring.h | 2 +- src/ext/xtime.h | 2 +- src/ext/xtypes.h | 2 +- src/main.c | 2 +- src/stubser/cfile.c | 2 +- src/stubser/cfile_if.h | 2 +- src/stubser/cfile_parser.c | 2 +- src/stubser/cfile_parser_if.h | 2 +- src/stubser/cfile_parser_loc.h | 2 +- src/stubser/cfile_parser_worker.c | 2 +- src/stubser/cfile_parser_worker_loc.h | 2 +- src/stubser/cfunction.c | 2 +- src/stubser/cfunction_if.h | 2 +- src/stubser/stubser.c | 2 +- src/stubser/stubser_if.h | 2 +- src/stubser/stubser_loc.h | 2 +- 20 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/ext/xmalloc.c b/src/ext/xmalloc.c index 6ef87b1..189327a 100644 --- a/src/ext/xmalloc.c +++ b/src/ext/xmalloc.c @@ -8,7 +8,7 @@ * Code: GNU-C\n * * @date 28.02.2017 - * @author SESA354004 + * @author Martin Winkler */ #include diff --git a/src/ext/xmalloc.h b/src/ext/xmalloc.h index 7a6653a..54f7380 100644 --- a/src/ext/xmalloc.h +++ b/src/ext/xmalloc.h @@ -8,7 +8,7 @@ * Code: GNU-C\n * * @date 28.02.2017 - * @author SESA354004 + * @author Martin Winkler */ #ifndef EXT_XMALLOC_H_ diff --git a/src/ext/xregex.h b/src/ext/xregex.h index ac734ec..6d01817 100644 --- a/src/ext/xregex.h +++ b/src/ext/xregex.h @@ -8,7 +8,7 @@ * Code: GNU-C\n * * @date 01.03.2017 - * @author SESA354004 + * @author Martin Winkler */ #ifndef EXT_XREGEX_H_ diff --git a/src/ext/xstring.c b/src/ext/xstring.c index c4454d9..6816054 100644 --- a/src/ext/xstring.c +++ b/src/ext/xstring.c @@ -8,7 +8,7 @@ * Code: GNU-C\n * * @date 27.02.2017 - * @author SESA354004 + * @author Martin Winkler */ #include "xtypes.h" #include "xstring.h" diff --git a/src/ext/xstring.h b/src/ext/xstring.h index 49c0d7a..f3c8919 100644 --- a/src/ext/xstring.h +++ b/src/ext/xstring.h @@ -8,7 +8,7 @@ * Code: GNU-C\n * * @date 27.02.2017 - * @author SESA354004 + * @author Martin Winkler */ #ifndef XSTRING_H_ #define XSTRING_H_ diff --git a/src/ext/xtime.h b/src/ext/xtime.h index 7725efc..d881a39 100644 --- a/src/ext/xtime.h +++ b/src/ext/xtime.h @@ -8,7 +8,7 @@ * Code: GNU-C\n * * @date 08.06.2016 - * @author SESA354004 + * @author Martin Winkler */ #ifndef XTIME_H_ #define XTIME_H_ diff --git a/src/ext/xtypes.h b/src/ext/xtypes.h index 39cb61b..6c21383 100644 --- a/src/ext/xtypes.h +++ b/src/ext/xtypes.h @@ -8,7 +8,7 @@ * Code: GNU-C\n * * @date 27.02.2017 - * @author SESA354004 + * @author Martin Winkler */ #ifndef XTYPES_H_ diff --git a/src/main.c b/src/main.c index 0fc9bf2..3a132bb 100644 --- a/src/main.c +++ b/src/main.c @@ -8,7 +8,7 @@ * Code: GNU-C\n * * @date 27.02.2017 - * @author SESA354004 + * @author Martin Winkler */ #include #include diff --git a/src/stubser/cfile.c b/src/stubser/cfile.c index 63f57a5..b04ecb3 100644 --- a/src/stubser/cfile.c +++ b/src/stubser/cfile.c @@ -8,7 +8,7 @@ * Code: GNU-C\n * * @date 08.03.2017 - * @author SESA354004 + * @author Martin Winkler */ #include #include diff --git a/src/stubser/cfile_if.h b/src/stubser/cfile_if.h index 9ecb0a4..676a565 100644 --- a/src/stubser/cfile_if.h +++ b/src/stubser/cfile_if.h @@ -8,7 +8,7 @@ * Code: GNU-C\n * * @date 08.03.2017 - * @author SESA354004 + * @author Martin Winkler */ #ifndef STUBSER_CFILE_IF_H_ diff --git a/src/stubser/cfile_parser.c b/src/stubser/cfile_parser.c index c5cd672..391b00f 100644 --- a/src/stubser/cfile_parser.c +++ b/src/stubser/cfile_parser.c @@ -8,7 +8,7 @@ * Code: GNU-C\n * * @date 28.02.2017 - * @author SESA354004 + * @author Martin Winkler */ #include #include diff --git a/src/stubser/cfile_parser_if.h b/src/stubser/cfile_parser_if.h index 30bbb16..d092ebf 100644 --- a/src/stubser/cfile_parser_if.h +++ b/src/stubser/cfile_parser_if.h @@ -8,7 +8,7 @@ * Code: GNU-C\n * * @date 28.02.2017 - * @author SESA354004 + * @author Martin Winkler */ #ifndef STUBSER_CFILE_PARSER_IF_H_ diff --git a/src/stubser/cfile_parser_loc.h b/src/stubser/cfile_parser_loc.h index 509c81e..467d7d1 100644 --- a/src/stubser/cfile_parser_loc.h +++ b/src/stubser/cfile_parser_loc.h @@ -8,7 +8,7 @@ * Code: GNU-C\n * * @date 28.02.2017 - * @author SESA354004 + * @author Martin Winkler */ #ifndef STUBSER_CFILE_PARSER_LOC_H_ #define STUBSER_CFILE_PARSER_LOC_H_ diff --git a/src/stubser/cfile_parser_worker.c b/src/stubser/cfile_parser_worker.c index da8bb72..f92917b 100644 --- a/src/stubser/cfile_parser_worker.c +++ b/src/stubser/cfile_parser_worker.c @@ -8,7 +8,7 @@ * Code: GNU-C\n * * @date 09.03.2017 - * @author SESA354004 + * @author Martin Winkler */ #include "xtypes.h" diff --git a/src/stubser/cfile_parser_worker_loc.h b/src/stubser/cfile_parser_worker_loc.h index c3ba073..a34bf09 100644 --- a/src/stubser/cfile_parser_worker_loc.h +++ b/src/stubser/cfile_parser_worker_loc.h @@ -8,7 +8,7 @@ * Code: GNU-C\n * * @date 09.03.2017 - * @author SESA354004 + * @author Martin Winkler */ #ifndef STUBSER_CFILE_PARSER_WORKER_LOC_H_ diff --git a/src/stubser/cfunction.c b/src/stubser/cfunction.c index 20e4611..68711d3 100644 --- a/src/stubser/cfunction.c +++ b/src/stubser/cfunction.c @@ -8,7 +8,7 @@ * Code: GNU-C\n * * @date 28.02.2017 - * @author SESA354004 + * @author Martin Winkler */ #include #include diff --git a/src/stubser/cfunction_if.h b/src/stubser/cfunction_if.h index e383772..5403c39 100644 --- a/src/stubser/cfunction_if.h +++ b/src/stubser/cfunction_if.h @@ -8,7 +8,7 @@ * Code: GNU-C\n * * @date 28.02.2017 - * @author SESA354004 + * @author Martin Winkler */ #ifndef STUBSER_CFUNCTION_IF_H_ diff --git a/src/stubser/stubser.c b/src/stubser/stubser.c index 27ef9fe..325f714 100644 --- a/src/stubser/stubser.c +++ b/src/stubser/stubser.c @@ -10,7 +10,7 @@ * Code: GNU-C\n * * @date 06.03.2017 - * @author SESA354004 + * @author Martin Winkler */ #include #include diff --git a/src/stubser/stubser_if.h b/src/stubser/stubser_if.h index 0234ab8..d8e3ccf 100644 --- a/src/stubser/stubser_if.h +++ b/src/stubser/stubser_if.h @@ -8,7 +8,7 @@ * Code: GNU-C\n * * @date 27.02.2017 - * @author SESA354004 + * @author Martin Winkler */ #ifndef STUBSER_STUBSER_IF_H_ diff --git a/src/stubser/stubser_loc.h b/src/stubser/stubser_loc.h index 1d7d678..bb1731f 100644 --- a/src/stubser/stubser_loc.h +++ b/src/stubser/stubser_loc.h @@ -8,7 +8,7 @@ * Code: GNU-C\n * * @date 04.03.2017 - * @author SESA354004 + * @author Martin Winkler */ #ifndef STUBSER_STUBSER_LOC_H_