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
This commit is contained in:
2017-03-10 09:10:04 +00:00
parent 11d281fe75
commit 5e967dc12e
4 changed files with 151 additions and 88 deletions

View File

@@ -46,7 +46,6 @@ STATIC regex_t regXparameter;
STATIC regex_t regXvariable; STATIC regex_t regXvariable;
STATIC regex_t regXExpressionStart; STATIC regex_t regXExpressionStart;
STATIC regex_t regXExpressionAssign;
STATIC regex_t regXExpressionEnd; STATIC regex_t regXExpressionEnd;
// line evaluation related variables // line evaluation related variables
@@ -61,11 +60,6 @@ int8_t cfile_parser_init()
perror("Error regex\n"); perror("Error regex\n");
return -1; return -1;
} }
if (0 > regcomp(&regXExpressionAssign, CPARS_EXPRESSION_EXPEND, (REG_EXTENDED | REG_NEWLINE)))
{
perror("Error regex\n");
return -1;
}
if (0 > regcomp(&regXExpressionEnd, CPARS_EXPRESSION_END, (REG_EXTENDED | REG_NEWLINE))) if (0 > regcomp(&regXExpressionEnd, CPARS_EXPRESSION_END, (REG_EXTENDED | REG_NEWLINE)))
{ {
perror("Error regex\n"); perror("Error regex\n");
@@ -650,49 +644,30 @@ STATIC cfunction_t* cfile_parser_evaluateLine1(char *aLine)
} }
#endif #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) STATIC int8_t cfile_parser_evaluateLine(uint32_t aNumber, char *aLine, cfile_t *aCfile)
{ {
stringWorker *worker = (stringWorker*) cWorker;
char *position = aLine; char *position = aLine;
char *result = NULL; int8_t result = 0;
size_t cSize = 0; static char *match = NULL;
static uint8_t depth = 0;
regex_t *matchStart = &regXExpressionStart; regex_t *matchStart = &regXExpressionStart;
regex_t *matchEnd = &regXExpressionEnd; regex_t *matchEnd = &regXExpressionEnd;
DEBUG_LOG_APPEND(1, "[ Li %04u] %s\n", aNumber, aLine); while (position)
// start with variable worker
while (position && NULL != *worker)
{ {
result = (*worker)(&position, matchStart, matchEnd, &workerActive, &cSize); result = regExWorker(&match, &position, matchStart, matchEnd, &depth, false);
if (NULL == result) if (match && 0 == result && 0 == depth)
{ {
if (false == workerActive) DEBUG_LOG_APPEND(1, "[ Re %04u] Works %zu %s\n", aNumber, strlen(match), match);
{
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); xfree((void**) &match);
worker = (stringWorker*) cWorker;
} }
else if (0 > result)
{ {
// force space between findings if (-2 == result)
xmallocStrlcat(&match, " ", 2); DEBUG_LOG_APPEND(2, "[ PEr]");
position = NULL;
xfree((void**) &match);
} }
} }
return 0; return 0;
@@ -703,9 +678,11 @@ int8_t cfile_parser(char *aPath, cfile_t *aCfile)
FILE *fdesc; FILE *fdesc;
ssize_t charRead = 0; ssize_t charRead = 0;
size_t lineSize = 0; size_t lineSize = 0;
uint32_t lineNumber = 1; uint32_t lineNumber = 0;
char *cTemp = NULL; char *cTemp = NULL;
char *fileLine = NULL; // will be allocated by getline(); must be freed char *fileLine = NULL; // will be allocated by getline(); must be freed
int8_t ret = 0;
uint8_t warningCounter = 0;
if (false == cfile_parser_initialized) if (false == cfile_parser_initialized)
{ {
@@ -724,14 +701,26 @@ int8_t cfile_parser(char *aPath, cfile_t *aCfile)
charRead = getline(&fileLine, &lineSize, fdesc); charRead = getline(&fileLine, &lineSize, fdesc);
if (0 <= charRead) if (0 <= charRead)
{ {
if (0 != removeCcomments(fileLine)) lineNumber++;
ret = removeCcomments(fileLine);
if (-1 == ret)
{
++warningCounter;
}
else if (0 != ret)
{ {
continue; 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; continue;
} }
DEBUG_LOG_APPEND(2, "[ Li %04u] %s", lineNumber, fileLine);
cTemp = strrchr(fileLine, '\n'); cTemp = strrchr(fileLine, '\n');
if (cTemp) if (cTemp)
{ {
@@ -742,7 +731,7 @@ int8_t cfile_parser(char *aPath, cfile_t *aCfile)
{ {
*cTemp = '\0'; *cTemp = '\0';
} }
(void) cfile_parser_evaluateLine(lineNumber++, fileLine, aCfile); (void) cfile_parser_evaluateLine(lineNumber, fileLine, aCfile);
} }
} while (0 <= charRead); } while (0 <= charRead);
@@ -756,7 +745,7 @@ int8_t cfile_parser(char *aPath, cfile_t *aCfile)
cfile_parser_parameterStorage); cfile_parser_parameterStorage);
cfile_parser_removeCommentHelper = 0; cfile_parser_removeCommentHelper = 0;
cfile_parser_removeBraceHelper = 0; cfile_parser_removeBraceHelper = 0;
return -2; ret = -2;
} }
// error detection for function parameter detection // 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); DEBUG_LOG_APPEND(1, "Function parameter not free: %s\n", cfile_parser_parameterStorage);
free(cfile_parser_parameterStorage); free(cfile_parser_parameterStorage);
cfile_parser_parameterStorage = NULL; cfile_parser_parameterStorage = NULL;
return -3; ret = -3;
} }
return 0; if (warningCounter && 0 <= ret)
{
ret = -4;
}
return ret;
} }

View File

@@ -33,8 +33,7 @@
#define CPARS_REGEX_PARAMETER "[[:blank:]]*([ _\\*[:alnum:]]* +\\**)([_\\*[:alnum:]]*)[[: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 "(extern|EXTERN|static|STATIC|volatile|near|far)[[:blank:]]+([^\\*]*\\**)"
#define CPARS_EXPRESSION_START "^[[:blank:]]*([A-Za-z][\\_\\*[:alnum:]]*)" #define CPARS_EXPRESSION_START "^[[:blank:]]*([A-Za-z\\_][\\_\\*[:alnum:]]*)"
#define CPARS_EXPRESSION_EXPEND "[[:blank:]]*([=\{])[[:blank:]]*"
#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)) #define CFILE_PARSER_IS_MATCHGROUP_FUNCTION(matchGroup) (XREGEX_IS_MATCHGROUP(matchGroup, 1) && XREGEX_IS_MATCHGROUP(matchGroup, 2))

View File

@@ -13,57 +13,129 @@
#include "xtypes.h" #include "xtypes.h"
#include "xregex.h" #include "xregex.h"
#include "xmalloc.h"
#include "debug.h" #include "debug.h"
#include "cfile_parser_loc.h" #include "cfile_parser_loc.h"
#include "cfile_parser_worker_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]; regmatch_t matchStart[2];
char *begin; 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; if (*aBlockDepth)
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]"); xmallocStrlcat(aOutput, " ", 2);
*aActive = false; ret = 0;
*aSize += matchGroup[1].rm_so; // don't include end marker in result
*aInput += matchGroup[1].rm_eo;
return begin;
} }
else else
{ {
DEBUG_LOG_APPEND(1, "[ CE+]"); ret = -1;
*aSize += strlen(*aInput);
*aInput += strlen(*aInput);
return begin;
} }
} *aInput = NULL;
else if (0 == regexec(aStart, *aInput, CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS, matchGroup, REG_NOTEOL) && XREGEX_IS_MATCHGROUP(matchGroup, 1)) goto regExWorker_end;
{
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; // 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;
} }

View File

@@ -14,8 +14,6 @@
#ifndef STUBSER_CFILE_PARSER_WORKER_LOC_H_ #ifndef STUBSER_CFILE_PARSER_WORKER_LOC_H_
#define 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*); int8_t regExWorker(char **aOutput, char **aInput, const regex_t *aStart, const regex_t *aEnd, uint8_t *aBlockDepth, bool aMultiLevel);
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_ */ #endif /* STUBSER_CFILE_PARSER_WORKER_LOC_H_ */