From ea0939d74db51c7f2a1165a7fac1c389b96d1142 Mon Sep 17 00:00:00 2001 From: Martin Winkler Date: Wed, 1 Mar 2017 14:36:53 +0000 Subject: [PATCH] - WIP (dynamic function structure implementation; parameter parcing missing) --- src/ext/xmalloc.c | 2 +- src/ext/xregex.h | 1 + src/stubser/cfile_parser.c | 289 ++++++++++++++------------------- src/stubser/cfile_parser_loc.h | 6 +- src/stubser/cfunction.c | 20 ++- src/stubser/stubser.c | 9 +- 6 files changed, 153 insertions(+), 174 deletions(-) diff --git a/src/ext/xmalloc.c b/src/ext/xmalloc.c index d2bccdd..3859f32 100644 --- a/src/ext/xmalloc.c +++ b/src/ext/xmalloc.c @@ -16,7 +16,7 @@ #include "xmalloc.h" #include "xtypes.h" -void *xmalloc(size_t size) +void* xmalloc(size_t size) { void *value = malloc(size); if (value == 0) diff --git a/src/ext/xregex.h b/src/ext/xregex.h index 20647cf..7e1c75f 100644 --- a/src/ext/xregex.h +++ b/src/ext/xregex.h @@ -17,5 +17,6 @@ #include #define XREGEX_IS_MATCHGROUP(groupArray, groupIndex) (groupArray[groupIndex].rm_so < groupArray[groupIndex].rm_eo) +#define XREGEX_SIZEOF_MATCHGROUP(groupArray, groupIndex) (size_t) (groupArray[groupIndex].rm_eo - groupArray[groupIndex].rm_so) #endif /* EXT_XREGEX_H_ */ diff --git a/src/stubser/cfile_parser.c b/src/stubser/cfile_parser.c index 1f8e164..9815225 100644 --- a/src/stubser/cfile_parser.c +++ b/src/stubser/cfile_parser.c @@ -12,13 +12,15 @@ */ #include #include +#include #include "xregex.h" #include "xtypes.h" #include "xstring.h" +#include "xmalloc.h" #include "cfunction_if.h" #include "cfile_parser_loc.h" -#define CFILE_PARSTER_MAX_REGEX_MATCHING_GROUPS 10 +#define CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS 10 STATIC bool cfile_parser_initialized = false; STATIC uint8_t cfile_parser_functionLine = 0; @@ -30,6 +32,7 @@ STATIC regex_t regXmlPar; STATIC regex_t regXmlEnd; STATIC regex_t regXmlProto; STATIC regex_t regXproto; +STATIC regex_t regXprefix; int8_t cfile_parser_init() { @@ -68,12 +71,102 @@ int8_t cfile_parser_init() perror("Error regex\n"); return -1; } + if (0 > regcomp(®Xprefix, CPARS_REGEX_PREFIX, (REG_EXTENDED))) + { + perror("Error regex\n"); + return -1; + } cfile_parser_initialized = true; return 0; } -// TODO adapt in cfile_parser_evaluateLine() +STATIC void printMatchGroup(char *aString, regmatch_t *aMatchGroup) +{ + char match[1024] = + { 0 }; + uint8_t i = 0; + + for (i = 0; i < CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS && 0 <= aMatchGroup[i].rm_so; ++i) + { + if (aMatchGroup[i].rm_so < aMatchGroup[i].rm_eo) + { + printf("[%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)); + printf("%s", match); + printf("\n"); + } + } +} + +STATIC void checkFunctionType(cfunction_t *aFunction) +{ + if (NULL == aFunction->prefix) + { + return; + } + if ((NULL != strstr(aFunction->prefix, "static") || NULL != strstr(aFunction->prefix, "STATIC")) // + && 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 + * @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) +{ + regmatch_t matchGroup[CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS]; + char *temp = NULL; + char *end = NULL; + + if (NULL == aFunction || NULL == aString || 0 == aSize) + { + return -1; + } + + temp = (char*) xmalloc(aSize + 1); + if (NULL == temp) + { + return -1; + } + strlcpy(temp, aString, aSize + 1); + + // remove trailing spaces + end = temp + strlen(temp) - 1; + while (end > temp && isspace((uint8_t ) *end)) + { + end--; + } + *(end + 1) = '\0'; + + if (0 == regexec(®Xprefix, temp, CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS, matchGroup, 0)) + { + if (XREGEX_IS_MATCHGROUP(matchGroup, 1)) + { + cfunction_newDetail(&aFunction->prefix, &temp[matchGroup[1].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 1)); + checkFunctionType(aFunction); + } + if (XREGEX_IS_MATCHGROUP(matchGroup, 2)) + { + cfunction_newDetail(&aFunction->dataType, &temp[matchGroup[2].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 2)); + } + } + else + { + cfunction_newDetail(&aFunction->dataType, temp, strlen(temp)); + } + + free(temp); + return 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 @@ -81,156 +174,21 @@ int8_t cfile_parser_init() * @retval -2 Given String not a function * @retval 0 function evaluated */ -//STATIC int matchFunction(char *aLine) -//{ -// const size_t maxGroup = 10; -// regmatch_t matchGroup[maxGroup]; -// const char *pattern = STUBI_FUNCTION_REGEX; -// const char *patternend = STUBI_FUNCTION_REGEX -// "\\)"; -// regex_t regX; -// regex_t regXEnd; -// regex_t regXMulti; -// regex_t regXMultiEnd; -// uint8_t i = 0; -// char funPrefix[256] = -// { 0 }; -// static char funTest[2056] = -// { 0 }; -// static uint8_t multiParamFlag = 0; -// uint8_t multiParamEndFlag = 0; -// -// if (0 > regcomp(®X, pattern, REG_EXTENDED)) // | REG_NEWLINE)) -// { -// perror("Error regex\n"); -// return -1; -// } -// -// if (0 > regcomp(®XEnd, patternend, REG_EXTENDED)) // | REG_NEWLINE)) -// { -// perror("Error regexend\n"); -// return -1; -// } -// -// if (0 > regcomp(®XMulti, STUBI_FUNCTION_MULTI, REG_EXTENDED)) // | REG_NEWLINE)) -// { -// perror("Error regXMulti\n"); -// return -1; -// } -// -// if (0 > regcomp(®XMultiEnd, STUBI_FUNCTION_MULTI_END, REG_EXTENDED)) // | REG_NEWLINE)) -// { -// perror("Error regXMultiEnd\n"); -// return -1; -// } -// -// if (multiParamFlag) -// { -// if (0 == regexec(®XMultiEnd, aLine, maxGroup, matchGroup, 0)) -// { -// // end of multi line function -// ++multiParamFlag; -// multiParamEndFlag = 1; -// } -// else -// { -// // continuation of multi line function -// (void) regexec(®XMulti, aLine, maxGroup, matchGroup, 0); -// ++multiParamFlag; -// } -// } -// else if (0 == regexec(®XEnd, aLine, maxGroup, matchGroup, 0)) -// { -// // single line function -// multiParamFlag = 0; -// } -// else if (0 == regexec(®X, aLine, maxGroup, matchGroup, 0)) -// { -// // start of multi line function -// ++multiParamFlag; -// printf("[ mls][%d]:", multiParamFlag); -// } -// else -// { -// // no fit -// return -2; -// } -// -// switch (multiParamFlag) -// { -// case 0: // single line function definition -// case 1: // first line of multi line function definition -// { -// (void) strlcpy(funPrefix, &aLine[matchGroup[1].rm_so], (size_t) (matchGroup[1].rm_eo - matchGroup[1].rm_so) + 1); -// (void) strlcat(funTest, &aLine[matchGroup[1].rm_so], (size_t) (matchGroup[1].rm_eo - matchGroup[1].rm_so) + 1); -// -// if ( // -// NULL == strstr(funPrefix, "extern") // -// && NULL == strstr(funPrefix, "EXTERN") // -// && NULL == strstr(funPrefix, "static") // -// && NULL == strstr(funPrefix, "STATIC") // -// && matchGroup[2].rm_so < matchGroup[2].rm_eo) -// { -// printf("[ sl ]:%s", funPrefix); -// for (i = 2; i < maxGroup && 0 <= matchGroup[i].rm_so; ++i) -// { -// printf(" (%.3ld - %.3ld): ", matchGroup[i].rm_so, matchGroup[i].rm_eo); -// printf("%.*s", (int) (matchGroup[i].rm_eo - matchGroup[i].rm_so), &aLine[matchGroup[i].rm_so]); -// (void) strncat(funTest, &aLine[matchGroup[i].rm_so], (int) (matchGroup[i].rm_eo - matchGroup[i].rm_so) + 1); -// } -// printf("\n"); -// } -// // TODO special handling for static functions (as extern in stub header) -// else if (NULL != strstr(funPrefix, "static") || NULL != strstr(funPrefix, "STATIC")) -// { -// printf("[todo] %s %.*s\n", funPrefix, (int) (matchGroup[2].rm_eo - matchGroup[2].rm_so), &aLine[matchGroup[2].rm_so]); -// } -// // ignore functions declared as extern -// else if (NULL != strstr(funPrefix, "extern") || NULL != strstr(funPrefix, "EXTERN")) -// { -// printf("[ nu ] %s %.*s\n", funPrefix, (int) (matchGroup[2].rm_eo - matchGroup[2].rm_so), &aLine[matchGroup[2].rm_so]); -// } -// break; -// } -// default: // further lines -// { -// if (multiParamEndFlag) -// { -// printf("[ mle][%d]:", multiParamFlag); -// } -// else -// { -// printf("[ ml ][%d]:", multiParamFlag); -// } -// -// if (matchGroup[1].rm_so < matchGroup[1].rm_eo) -// { -// for (i = 1; i < maxGroup && 0 <= matchGroup[i].rm_so; ++i) -// { -// printf("(%.3ld-%.3ld):", matchGroup[i].rm_so, matchGroup[i].rm_eo); -// printf("%.*s", (int) (matchGroup[i].rm_eo - matchGroup[i].rm_so), &aLine[matchGroup[i].rm_so]); -// } -// printf("\n"); -// } -// -// if (multiParamEndFlag) -// { -// multiParamFlag = 0; -// multiParamEndFlag = 0; -// } -// -// break; -// } -// } -// -// return 0; -//} STATIC cfunction_t* cfile_parser_evaluateLine(char *aLine) { - const size_t maxGroup = CFILE_PARSTER_MAX_REGEX_MATCHING_GROUPS; + const size_t maxGroup = CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS; regmatch_t matchGroup[maxGroup]; bool functionEnd = false; cfunction_type_t tempFunctionType = CFUNCTION_TYPE_UNDEF; + cfunction_parameter_t *tempParameter = NULL; + char *tempChar = NULL; + + // remove basic inline comments + tempChar = strstr(aLine, "//"); + if (NULL != tempChar) + { + strlcpy(tempChar, "\r\n", 3); + } if (cfile_parser_functionLine) { @@ -238,29 +196,25 @@ STATIC cfunction_t* cfile_parser_evaluateLine(char *aLine) { tempFunctionType = CFUNCTION_TYPE_REGULAR; printf("[ mle]"); - ++cfile_parser_functionLine; functionEnd = true; } else if (0 == regexec(®XmlProto, aLine, maxGroup, matchGroup, REG_NOTEOL)) { tempFunctionType = CFUNCTION_TYPE_PROTO; printf("[ mlp]"); - ++cfile_parser_functionLine; functionEnd = true; } else if (0 == regexec(®XmlPar, aLine, maxGroup, matchGroup, REG_NOTEOL)) { printf("[ ml+]"); - ++cfile_parser_functionLine; } else { tempFunctionType = CFUNCTION_TYPE_UNDEF; - ++cfile_parser_functionLine; functionEnd = true; - // TODO fallback (free currently used memory) - return NULL; } + + ++cfile_parser_functionLine; } else if (0 == regexec(®Xsl, aLine, maxGroup, matchGroup, REG_NOTEOL) && CFILE_PARSER_IS_MATCHGROUP_FUNCTION(matchGroup)) { @@ -287,11 +241,9 @@ STATIC cfunction_t* cfile_parser_evaluateLine(char *aLine) { return NULL; } - #if (0) { uint8_t i = 0; - char *tempChar = NULL; char match[1024] = { 0}; @@ -302,20 +254,17 @@ STATIC cfunction_t* cfile_parser_evaluateLine(char *aLine) if (0 < i) printf(" "); printf("[%02d](%.3ld - %.3ld)[%03d]: ", i, matchGroup[i].rm_so, matchGroup[i].rm_eo, (int) (matchGroup[i].rm_eo - matchGroup[i].rm_so)); - //printf("%.*s", (int) (matchGroup[i].rm_eo - matchGroup[i].rm_so), &aLine[matchGroup[i].rm_so]); strlcpy(match, &aLine[matchGroup[i].rm_so], (size_t) (matchGroup[i].rm_eo - matchGroup[i].rm_so + 1)); - tempChar = strstr(match, "//"); - if (NULL != tempChar) - { - *tempChar = '\0'; - } printf("%s", match); printf("\n"); } } + if (functionEnd) + { + cfile_parser_functionLine = 0; + } } -#endif - +#else switch (cfile_parser_functionLine) { case 0: // single line function definition @@ -323,11 +272,23 @@ STATIC cfunction_t* cfile_parser_evaluateLine(char *aLine) { cfile_parser_function = cfunction_newFunction(); cfile_parser_function->type = tempFunctionType; + matchFunctionStart(cfile_parser_function, &aLine[matchGroup[1].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 1)); + cfunction_newDetail(&cfile_parser_function->name, &aLine[matchGroup[2].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 2)); + if (XREGEX_IS_MATCHGROUP(matchGroup, 3)) + { + tempParameter = cfunction_newParameter(&cfile_parser_function->parameter); + cfunction_newDetail(&tempParameter->type, &aLine[matchGroup[3].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 3)); + } break; } default: // further lines { // TODO process parameter + if (XREGEX_IS_MATCHGROUP(matchGroup, 1)) + { + tempParameter = cfunction_newParameter(&cfile_parser_function->parameter); + cfunction_newDetail(&tempParameter->type, &aLine[matchGroup[1].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 1)); + } if (functionEnd) { // TODO clean function @@ -338,6 +299,7 @@ STATIC cfunction_t* cfile_parser_evaluateLine(char *aLine) else { cfile_parser_function->type = tempFunctionType; + checkFunctionType(cfile_parser_function); } cfile_parser_functionLine = 0; } @@ -352,6 +314,7 @@ STATIC cfunction_t* cfile_parser_evaluateLine(char *aLine) cfile_parser_function = NULL; return funTemp; } +#endif return NULL; } diff --git a/src/stubser/cfile_parser_loc.h b/src/stubser/cfile_parser_loc.h index 9372a7d..775efbd 100644 --- a/src/stubser/cfile_parser_loc.h +++ b/src/stubser/cfile_parser_loc.h @@ -14,14 +14,16 @@ #ifndef STUBSER_CFILE_PARSER_LOC_H_ #define STUBSER_CFILE_PARSER_LOC_H_ -#define FUNCTION_BASE "^[[:blank:]]*([ _\\*[:alnum:]]*) +([_\\*[:alnum:]]*)[[:blank:]]*\\(([^\\)]*)" +#define FUNCTION_BASE "^[[:blank:]]*([ _\\*[:alnum:]]* +\\**)([_\\*[:alnum:]]*)[[:blank:]]*\\([[:blank:]]*([^\r\\)]*)" #define FUNCTION_SL FUNCTION_BASE "\\)[^;]*$" -#define FUNCTION_ML_SOF 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_REGEX_PREFIX "(extern|EXTERN|static|STATIC|volatile|near|far)[[:blank:]]+([^\\*]*\\**)" + #define CFILE_PARSER_IS_MATCHGROUP_FUNCTION(matchGroup) (XREGEX_IS_MATCHGROUP(matchGroup, 1) && XREGEX_IS_MATCHGROUP(matchGroup, 2)) #endif /* STUBSER_CFILE_PARSER_LOC_H_ */ diff --git a/src/stubser/cfunction.c b/src/stubser/cfunction.c index ac8a71a..808b5c1 100644 --- a/src/stubser/cfunction.c +++ b/src/stubser/cfunction.c @@ -64,11 +64,14 @@ cfunction_parameter_t* cfunction_newParameter(struct _CFUNCTION_PARAMETER_LIST_T if (NULL == aList->head) { aList->head = new; + aList->current = new; + } + else + { + aList->current->next = new; + aList->current = new; } - - aList->current = new; ++aList->amount; - return new; } @@ -166,6 +169,7 @@ int8_t cfunction_freeList(cfunction_list_t *aList) void cfunction_printList(cfunction_list_t *aList) { cfunction_t *work = aList->head; + cfunction_parameter_t *param = NULL; if (NULL == aList) { @@ -174,7 +178,15 @@ void cfunction_printList(cfunction_list_t *aList) while (work) { - printf("[ cfu]: %d\n", work->type); + param = work->parameter.head; + printf("[ cfu]%d:%s %s %s [%d] ", work->type, work->prefix, work->dataType, work->name, work->parameter.amount); + while (param) + { + printf("%s ", param->type); + param = param->next; + } + printf("\n"); work = work->next; + } } diff --git a/src/stubser/stubser.c b/src/stubser/stubser.c index a9f7743..d20d496 100644 --- a/src/stubser/stubser.c +++ b/src/stubser/stubser.c @@ -30,10 +30,11 @@ int stubser_createStub(char *path) { cfunction_list_t functionList = CFUNCTION_LIST_DEFAULT; - (void) cfile_parser(path, &functionList); - - cfunction_printList(&functionList); - + if (0 == cfile_parser(path, &functionList)) + { + printf("\n"); + cfunction_printList(&functionList); + } cfunction_freeList(&functionList); return 0; }