- support for function pointer as parameter
- todo: function pointer globals
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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:]]*)"
|
||||
|
@@ -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");
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user