- support for function pointer as parameter

- todo: function pointer globals
This commit is contained in:
2017-03-15 09:48:03 +00:00
parent f891492347
commit f39460e907
5 changed files with 163 additions and 24 deletions

View File

@@ -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(&regXfuPtrSeparator, CPARS_REGEX_PARAMETER_FUPTR_SEPA, (REG_EXTENDED)))
{
perror("Error regex\n");
return -1;
}
if (0 > regcomp(&regXfunctionPointer, CPARS_REGEX_PARAMETER_FUPTR, (REG_EXTENDED)))
{
perror("Error regex\n");
return -1;
}
if (0 > regcomp(&regXvariable, 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(&regXfuPtrSeparator, 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(&regXparameter, token, CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS, matchGroup, 0))
if (0 == regexec(&regXfunctionPointer, 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(&regXparameter, 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;
}

View File

@@ -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:]]*)"

View File

@@ -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");

View File

@@ -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;

View File

@@ -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);