- 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 regXfunction;
STATIC regex_t regXprefix; STATIC regex_t regXprefix;
STATIC regex_t regXparameter; STATIC regex_t regXparameter;
STATIC regex_t regXfuPtrSeparator;
STATIC regex_t regXfunctionPointer;
STATIC regex_t regXvariable; STATIC regex_t regXvariable;
STATIC regex_t regXExpressionStart; STATIC regex_t regXExpressionStart;
@@ -71,6 +73,16 @@ int8_t cfile_parser_init()
perror("Error regex\n"); perror("Error regex\n");
return -1; 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))) if (0 > regcomp(&regXvariable, CPARS_REGEX_VARIABLE, (REG_EXTENDED | REG_NEWLINE)))
{ {
perror("Error regex\n"); 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); 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) STATIC int8_t evaluateParameter(char *aParameter, cfunction_t *aFunction)
{ {
char *token = NULL; char *token = NULL;
@@ -480,20 +528,23 @@ STATIC int8_t evaluateParameter(char *aParameter, cfunction_t *aFunction)
{ {
return -1; return -1;
} }
prepareFunctionPointer(aParameter);
token = strtok(aParameter, ","); token = strtok(aParameter, ",");
while (token) while (token)
{ {
// TODO special handling for function pointer as argument if (0 == regexec(&regXfunctionPointer, token, CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS, matchGroup, 0))
if (0 == regexec(&regXparameter, token, CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS, matchGroup, 0))
{ {
(void) revertFunctionPointer(token);
tempParameter = cfunction_newParameter(&aFunction->parameter); tempParameter = cfunction_newParameter(&aFunction->parameter);
tempParameter->type = CPARAMETER_TYPE_FUNCPTR;
if (XREGEX_IS_MATCHGROUP(matchGroup, 1)) if (XREGEX_IS_MATCHGROUP(matchGroup, 1))
{ {
xmallocStrlcpy(&tempParameter->type, &token[matchGroup[1].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 1)); xmallocStrlcpy(&tempParameter->dataType, &token[matchGroup[1].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 1));
if (NULL != tempParameter->type) 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)) 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)); 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, ","); token = strtok(NULL, ",");
} }
return 0; return 0;
} }

View File

@@ -31,7 +31,9 @@
#define FUNCTION_BASE CPARS_EXPRESSION_BASE "[[:blank:]]*\\([[:blank:]]*" #define FUNCTION_BASE CPARS_EXPRESSION_BASE "[[:blank:]]*\\([[:blank:]]*"
#define CPARS_REGEX_FUNCTION FUNCTION_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 "[[: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_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_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) while (work)
{ {
next = work->next; next = work->next;
free(work->type); free(work->dataType);
free(work->name); free(work->name);
free(work); free(work);
work = next; 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); printf("[ cfu]%d:<%s> (%s) %s [%d] ", work->type, work->prefix, work->dataType, work->name, work->parameter.amount);
while (param) 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; param = param->next;
} }
printf("\n"); printf("\n");

View File

@@ -25,11 +25,22 @@ typedef enum _CFUNCTION_TYPE_T
CFUNCTION_TYPE_LAST_ENUM CFUNCTION_TYPE_LAST_ENUM
} cfunction_type_t; } 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 */ /*! @brief Parameter list node */
typedef struct _CFUNCTION_PARAMETER_T 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* name; /*!< @brief name */
char* array; /*!< @brief array information (e.g. [10] or [DEF_MAX]) */
struct _CFUNCTION_PARAMETER_T *next; struct _CFUNCTION_PARAMETER_T *next;
} cfunction_parameter_t; } 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) 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, "\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, fprintf(aFile, STUBINIT_PARAM_PARAMETER_S1", "STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_PARAM_S1, aParameterIndex, aFunction->name,
aFunction->name, aParameterIndex); aFunction->name, aParameterIndex);
fprintf(aFile, ", strlen("STUBINIT_PARAM_PARAMETER_S1"));"NEWLINES, 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, "\tCU_ASSERT_PTR_EQUAL(");
fprintf(aFile, STUBINIT_PARAM_PARAMETER_S1", "STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_PARAM_S1, aParameterIndex, aFunction->name, fprintf(aFile, STUBINIT_PARAM_PARAMETER_S1", "STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_PARAM_S1, aParameterIndex, aFunction->name,
aFunction->name, aParameterIndex); aFunction->name, aParameterIndex);
fprintf(aFile, ");"NEWLINES); fprintf(aFile, ");"NEWLINES);
} }
else if (isDatatypeStandard(aParameter->type)) else if (isDatatypeStandard(aParameter->dataType))
{ {
fprintf(aFile, "\tCU_ASSERT_EQUAL("); fprintf(aFile, "\tCU_ASSERT_EQUAL(");
fprintf(aFile, STUBINIT_PARAM_PARAMETER_S1", "STUBPARAMETER_STRUCT_S1"["STUBINSTANCE_S1"]."STUBPARAMETER_PARAM_S1, aParameterIndex, aFunction->name, 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, "typedef struct _STUBPARAMETER_%s" NEWLINES, aFunction->name);
fprintf(aFile, "{" NEWLINES); 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);
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)) 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';
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); fprintf(aFile, "} "STUBPARAMETER_TYPEDEF_S1";" NEWLINES, aFunction->name);
NEWLINE(aFile); NEWLINE(aFile);
@@ -348,7 +362,14 @@ STATIC int8_t createStubFunctionBlock(FILE *aFile, FILE *aHeader, cfunction_t *a
parameterIndex = 'a'; parameterIndex = 'a';
while (parameter) 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; parameter = parameter->next;
} }
fprintf(aHeader, ");" NEWLINES); fprintf(aHeader, ");" NEWLINES);
@@ -363,7 +384,14 @@ STATIC int8_t createStubFunctionBlock(FILE *aFile, FILE *aHeader, cfunction_t *a
parameterIndex = 'a'; parameterIndex = 'a';
while (parameter) 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; parameter = parameter->next;
} }
fprintf(aFile, ")" NEWLINES); fprintf(aFile, ")" NEWLINES);
@@ -398,7 +426,17 @@ STATIC int8_t createStubFunctionBlock(FILE *aFile, FILE *aHeader, cfunction_t *a
parameterIndex = 'a'; parameterIndex = 'a';
while (parameter) 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; parameter = parameter->next;
} }
fprintf(aFile, ")" NEWLINES); fprintf(aFile, ")" NEWLINES);