From f09a9997ba01a5a4d9cc564ffb30d2ddbf23dbc9 Mon Sep 17 00:00:00 2001 From: Martin Winkler Date: Thu, 30 Dec 2021 22:22:12 +0100 Subject: [PATCH] Normalize all the line endings --- .cproject | 244 ++-- .project | 52 +- .settings/org.eclipse.cdt.core.prefs | 22 +- src/ext/debug.h | 176 +-- src/ext/xmalloc.c | 158 +-- src/ext/xmalloc.h | 48 +- src/ext/xregex.h | 44 +- src/ext/xstring.c | 308 ++--- src/ext/xstring.h | 46 +- src/ext/xtime.h | 64 +- src/ext/xtypes.h | 82 +- src/main.c | 444 +++---- src/stubser/cfile.c | 326 ++--- src/stubser/cfile_if.h | 152 +-- src/stubser/cfile_parser.c | 1676 ++++++++++++------------- src/stubser/cfile_parser_if.h | 42 +- src/stubser/cfile_parser_loc.h | 114 +- src/stubser/cfile_parser_worker.c | 304 ++--- src/stubser/cfile_parser_worker_loc.h | 38 +- src/stubser/cfunction.c | 344 ++--- src/stubser/cfunction_if.h | 172 +-- src/stubser/stubser_if.h | 38 +- src/stubser/stubser_loc.h | 152 +-- 23 files changed, 2523 insertions(+), 2523 deletions(-) diff --git a/.cproject b/.cproject index cf72a82..45e69e3 100644 --- a/.cproject +++ b/.cproject @@ -1,123 +1,123 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.project b/.project index c8414af..1daad17 100644 --- a/.project +++ b/.project @@ -1,26 +1,26 @@ - - - stubser - - - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - + + + stubser + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/.settings/org.eclipse.cdt.core.prefs b/.settings/org.eclipse.cdt.core.prefs index f925dfa..1c39039 100644 --- a/.settings/org.eclipse.cdt.core.prefs +++ b/.settings/org.eclipse.cdt.core.prefs @@ -1,11 +1,11 @@ -eclipse.preferences.version=1 -environment/project/cdt.managedbuild.config.gnu.cygwin.exe.debug.384908978/CYGWIN_HOME/delimiter=; -environment/project/cdt.managedbuild.config.gnu.cygwin.exe.debug.384908978/CYGWIN_HOME/operation=replace -environment/project/cdt.managedbuild.config.gnu.cygwin.exe.debug.384908978/CYGWIN_HOME/value=C\:\\cygwin -environment/project/cdt.managedbuild.config.gnu.cygwin.exe.debug.384908978/append=true -environment/project/cdt.managedbuild.config.gnu.cygwin.exe.debug.384908978/appendContributed=true -environment/project/cdt.managedbuild.config.gnu.cygwin.exe.release.1204024233/CYGWIN_HOME/delimiter=; -environment/project/cdt.managedbuild.config.gnu.cygwin.exe.release.1204024233/CYGWIN_HOME/operation=replace -environment/project/cdt.managedbuild.config.gnu.cygwin.exe.release.1204024233/CYGWIN_HOME/value=C\:\\cygwin -environment/project/cdt.managedbuild.config.gnu.cygwin.exe.release.1204024233/append=true -environment/project/cdt.managedbuild.config.gnu.cygwin.exe.release.1204024233/appendContributed=true +eclipse.preferences.version=1 +environment/project/cdt.managedbuild.config.gnu.cygwin.exe.debug.384908978/CYGWIN_HOME/delimiter=; +environment/project/cdt.managedbuild.config.gnu.cygwin.exe.debug.384908978/CYGWIN_HOME/operation=replace +environment/project/cdt.managedbuild.config.gnu.cygwin.exe.debug.384908978/CYGWIN_HOME/value=C\:\\cygwin +environment/project/cdt.managedbuild.config.gnu.cygwin.exe.debug.384908978/append=true +environment/project/cdt.managedbuild.config.gnu.cygwin.exe.debug.384908978/appendContributed=true +environment/project/cdt.managedbuild.config.gnu.cygwin.exe.release.1204024233/CYGWIN_HOME/delimiter=; +environment/project/cdt.managedbuild.config.gnu.cygwin.exe.release.1204024233/CYGWIN_HOME/operation=replace +environment/project/cdt.managedbuild.config.gnu.cygwin.exe.release.1204024233/CYGWIN_HOME/value=C\:\\cygwin +environment/project/cdt.managedbuild.config.gnu.cygwin.exe.release.1204024233/append=true +environment/project/cdt.managedbuild.config.gnu.cygwin.exe.release.1204024233/appendContributed=true diff --git a/src/ext/debug.h b/src/ext/debug.h index 57b4d45..4f85f69 100644 --- a/src/ext/debug.h +++ b/src/ext/debug.h @@ -1,88 +1,88 @@ -/*! - * @file debug.h - * @brief Helper for debug output - * - * Project: \n - * Subsystem: \n - * Module: mst\n - * Code: GNU-C\n - * - * @date 08.06.2016 - * @author Martin Winkler - */ -#ifndef _DEBUG_H_INCLUDED -#define _DEBUG_H_INCLUDED - -#include -#include - -#define isDebugLevel(dflag) (_DEBUG_OUTPUT >= dflag) - -/*! - * @brief extract only filename from __FILE__ without base path - */ -#define _DEBUG_FILENAME (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__) - -/*! - * @brief Debug assert helper macro - * @param cond condition for output - * @param dflag eDebugLevel required to print output - * @param format format same as for printf - * @param args arguments for printf - * - * Condition as string is appended to the output.\n - * e.g. DEBUG_LOG_ASSERT(i >= 1, DEBUG_LEVEL_INFO, "Not allowed");\n - * New line must be appended manually - */ -#ifdef _DEBUG_OUTPUT -#define DEBUG_LOG_ASSERT(cond, dflag, format, args...) do { if(isDebugLevel(dflag) && (cond)) \ - printf("%s:%d:%s():(" #cond "): " format, \ - _DEBUG_FILENAME, __LINE__, __func__, ##args); } \ - while (0) -#else -#define DEBUG_LOG_ASSERT(cond, dflag, format, args...) do{/* nothing */}while(0) -#endif - -/*! - * @brief Debug output helper macro - * @param dflag eDebugLevel required to print output - * @param format format same as for printf - * @param args arguments for printf - * - * New line must be appended manually - */ -#ifdef _DEBUG_OUTPUT -#define DEBUG_LOG(dflag, format, args...) do { if(isDebugLevel(dflag)) \ - printf("%s:%d:%s(): " format, \ - _DEBUG_FILENAME, __LINE__, __func__, ##args); } \ - while (0) -#else -#define DEBUG_LOG(dflag, format, args...) do{/* nothing */}while(0) -#endif - -/*! - * @brief Debug output helper macro to append text without addition information - * @param dflag eDebugLevel required to print output - * @param format format same as for printf - * @param args arguments for printf - * - * New line must be appended manually - */ -#ifdef _DEBUG_OUTPUT -#define DEBUG_LOG_APPEND(dflag, format, args...) do { if(isDebugLevel(dflag)) \ - printf(format, ##args); } \ - while (0) -#else -#define DEBUG_LOG_APPEND(dflag, format, args...) do{/* nothing */}while(0) -#endif - -typedef enum _EDEBUGLEVEL -{ - DEBUG_LEVEL_ALWAYS = 0, /* DEBUG_LOGs are visible regardless of DEBUG_LEVEL */ - DEBUG_LEVEL_INFO = 1, /* Visible when application started with -v */ - DEBUG_LEVEL_WARNING = 2, /* Visible when application started with -vv */ - DEBUG_LEVEL_ERROR = 3, -/* Visible when application started with -vvv */ -} eDebugLevel; - -#endif /* #ifndef _DEBUG_H_INCLUDED */ +/*! + * @file debug.h + * @brief Helper for debug output + * + * Project: \n + * Subsystem: \n + * Module: mst\n + * Code: GNU-C\n + * + * @date 08.06.2016 + * @author Martin Winkler + */ +#ifndef _DEBUG_H_INCLUDED +#define _DEBUG_H_INCLUDED + +#include +#include + +#define isDebugLevel(dflag) (_DEBUG_OUTPUT >= dflag) + +/*! + * @brief extract only filename from __FILE__ without base path + */ +#define _DEBUG_FILENAME (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__) + +/*! + * @brief Debug assert helper macro + * @param cond condition for output + * @param dflag eDebugLevel required to print output + * @param format format same as for printf + * @param args arguments for printf + * + * Condition as string is appended to the output.\n + * e.g. DEBUG_LOG_ASSERT(i >= 1, DEBUG_LEVEL_INFO, "Not allowed");\n + * New line must be appended manually + */ +#ifdef _DEBUG_OUTPUT +#define DEBUG_LOG_ASSERT(cond, dflag, format, args...) do { if(isDebugLevel(dflag) && (cond)) \ + printf("%s:%d:%s():(" #cond "): " format, \ + _DEBUG_FILENAME, __LINE__, __func__, ##args); } \ + while (0) +#else +#define DEBUG_LOG_ASSERT(cond, dflag, format, args...) do{/* nothing */}while(0) +#endif + +/*! + * @brief Debug output helper macro + * @param dflag eDebugLevel required to print output + * @param format format same as for printf + * @param args arguments for printf + * + * New line must be appended manually + */ +#ifdef _DEBUG_OUTPUT +#define DEBUG_LOG(dflag, format, args...) do { if(isDebugLevel(dflag)) \ + printf("%s:%d:%s(): " format, \ + _DEBUG_FILENAME, __LINE__, __func__, ##args); } \ + while (0) +#else +#define DEBUG_LOG(dflag, format, args...) do{/* nothing */}while(0) +#endif + +/*! + * @brief Debug output helper macro to append text without addition information + * @param dflag eDebugLevel required to print output + * @param format format same as for printf + * @param args arguments for printf + * + * New line must be appended manually + */ +#ifdef _DEBUG_OUTPUT +#define DEBUG_LOG_APPEND(dflag, format, args...) do { if(isDebugLevel(dflag)) \ + printf(format, ##args); } \ + while (0) +#else +#define DEBUG_LOG_APPEND(dflag, format, args...) do{/* nothing */}while(0) +#endif + +typedef enum _EDEBUGLEVEL +{ + DEBUG_LEVEL_ALWAYS = 0, /* DEBUG_LOGs are visible regardless of DEBUG_LEVEL */ + DEBUG_LEVEL_INFO = 1, /* Visible when application started with -v */ + DEBUG_LEVEL_WARNING = 2, /* Visible when application started with -vv */ + DEBUG_LEVEL_ERROR = 3, +/* Visible when application started with -vvv */ +} eDebugLevel; + +#endif /* #ifndef _DEBUG_H_INCLUDED */ diff --git a/src/ext/xmalloc.c b/src/ext/xmalloc.c index 189327a..b0ff271 100644 --- a/src/ext/xmalloc.c +++ b/src/ext/xmalloc.c @@ -1,79 +1,79 @@ -/*! - * @file xmalloc.c - * @brief - * @details - * Project: \n - * Subsystem: \n - * Module: \n - * Code: GNU-C\n - * - * @date 28.02.2017 - * @author Martin Winkler - */ - -#include -#include -#include "xmalloc.h" -#include "xtypes.h" - -void* xmalloc(size_t size) -{ - void *value = malloc(size); - if (value == 0) - perror("virtual memory exhausted"); - else - memset(value, 0, size); - return value; -} - -char* xmallocStrlcpy(char **aDest, char *aSource, size_t aSize) -{ - if (NULL == aSource || 0 == aSize) - { - return NULL; - } - if (NULL != *aDest) - { - *aDest = (char*) realloc(*aDest, aSize + 1); - } - else - { - *aDest = (char*) xmalloc(aSize + 1); - } - if (NULL != *aDest) - { - (void) strlcpy(*aDest, aSource, aSize + 1); - } - return *aDest; -} - -char* xmallocStrlcat(char **aDest, char *aSource, size_t aSize) -{ - size_t newSize = 0; - if (NULL == aSource || 0 == aSize) - { - return NULL; - } - if (NULL != *aDest) - { - newSize = strlen(*aDest) + aSize + 1; - *aDest = (char*) realloc(*aDest, newSize); - } - else - { - newSize = aSize + 1; - *aDest = (char*) xmalloc(newSize); - } - if (NULL != *aDest) - { - (void) strlcat(*aDest, aSource, newSize); - } - return *aDest; -} - -void xfree(void **aDest) -{ - free(*aDest); - *aDest = NULL; -} - +/*! + * @file xmalloc.c + * @brief + * @details + * Project: \n + * Subsystem: \n + * Module: \n + * Code: GNU-C\n + * + * @date 28.02.2017 + * @author Martin Winkler + */ + +#include +#include +#include "xmalloc.h" +#include "xtypes.h" + +void* xmalloc(size_t size) +{ + void *value = malloc(size); + if (value == 0) + perror("virtual memory exhausted"); + else + memset(value, 0, size); + return value; +} + +char* xmallocStrlcpy(char **aDest, char *aSource, size_t aSize) +{ + if (NULL == aSource || 0 == aSize) + { + return NULL; + } + if (NULL != *aDest) + { + *aDest = (char*) realloc(*aDest, aSize + 1); + } + else + { + *aDest = (char*) xmalloc(aSize + 1); + } + if (NULL != *aDest) + { + (void) strlcpy(*aDest, aSource, aSize + 1); + } + return *aDest; +} + +char* xmallocStrlcat(char **aDest, char *aSource, size_t aSize) +{ + size_t newSize = 0; + if (NULL == aSource || 0 == aSize) + { + return NULL; + } + if (NULL != *aDest) + { + newSize = strlen(*aDest) + aSize + 1; + *aDest = (char*) realloc(*aDest, newSize); + } + else + { + newSize = aSize + 1; + *aDest = (char*) xmalloc(newSize); + } + if (NULL != *aDest) + { + (void) strlcat(*aDest, aSource, newSize); + } + return *aDest; +} + +void xfree(void **aDest) +{ + free(*aDest); + *aDest = NULL; +} + diff --git a/src/ext/xmalloc.h b/src/ext/xmalloc.h index 54f7380..f225af2 100644 --- a/src/ext/xmalloc.h +++ b/src/ext/xmalloc.h @@ -1,24 +1,24 @@ -/*! - * @file xmalloc.h - * @brief - * @details - * Project: \n - * Subsystem: \n - * Module: \n - * Code: GNU-C\n - * - * @date 28.02.2017 - * @author Martin Winkler - */ - -#ifndef EXT_XMALLOC_H_ -#define EXT_XMALLOC_H_ - -#include - -void *xmalloc(size_t size); -void xfree(void**); -char* xmallocStrlcpy(char **aDest, char *aSource, size_t aSize); -char* xmallocStrlcat(char **aDest, char *aSource, size_t aSize); - -#endif /* EXT_XMALLOC_H_ */ +/*! + * @file xmalloc.h + * @brief + * @details + * Project: \n + * Subsystem: \n + * Module: \n + * Code: GNU-C\n + * + * @date 28.02.2017 + * @author Martin Winkler + */ + +#ifndef EXT_XMALLOC_H_ +#define EXT_XMALLOC_H_ + +#include + +void *xmalloc(size_t size); +void xfree(void**); +char* xmallocStrlcpy(char **aDest, char *aSource, size_t aSize); +char* xmallocStrlcat(char **aDest, char *aSource, size_t aSize); + +#endif /* EXT_XMALLOC_H_ */ diff --git a/src/ext/xregex.h b/src/ext/xregex.h index 6d01817..81ee1dd 100644 --- a/src/ext/xregex.h +++ b/src/ext/xregex.h @@ -1,22 +1,22 @@ -/*! - * @file xregex.h - * @brief - * @details - * Project: \n - * Subsystem: \n - * Module: \n - * Code: GNU-C\n - * - * @date 01.03.2017 - * @author Martin Winkler - */ - -#ifndef EXT_XREGEX_H_ -#define EXT_XREGEX_H_ - -#include - -#define XREGEX_IS_MATCHGROUP(groupArray, groupIndex) (groupArray[groupIndex].rm_so < groupArray[groupIndex].rm_eo && 0 <= groupArray[groupIndex].rm_so) -#define XREGEX_SIZEOF_MATCHGROUP(groupArray, groupIndex) (size_t) (groupArray[groupIndex].rm_eo - groupArray[groupIndex].rm_so) - -#endif /* EXT_XREGEX_H_ */ +/*! + * @file xregex.h + * @brief + * @details + * Project: \n + * Subsystem: \n + * Module: \n + * Code: GNU-C\n + * + * @date 01.03.2017 + * @author Martin Winkler + */ + +#ifndef EXT_XREGEX_H_ +#define EXT_XREGEX_H_ + +#include + +#define XREGEX_IS_MATCHGROUP(groupArray, groupIndex) (groupArray[groupIndex].rm_so < groupArray[groupIndex].rm_eo && 0 <= groupArray[groupIndex].rm_so) +#define XREGEX_SIZEOF_MATCHGROUP(groupArray, groupIndex) (size_t) (groupArray[groupIndex].rm_eo - groupArray[groupIndex].rm_so) + +#endif /* EXT_XREGEX_H_ */ diff --git a/src/ext/xstring.c b/src/ext/xstring.c index 6816054..33e479f 100644 --- a/src/ext/xstring.c +++ b/src/ext/xstring.c @@ -1,154 +1,154 @@ -/*! - * @file xstring.c - * @brief - * @details - * Project: \n - * Subsystem: \n - * Module: \n - * Code: GNU-C\n - * - * @date 27.02.2017 - * @author Martin Winkler - */ -#include "xtypes.h" -#include "xstring.h" -#include "ctype.h" - -char* gnu_basename(char *path) -{ - char *baseWin = strrchr(path, '\\'); - char *base = strrchr(path, '/'); - if (baseWin > base) - { - base = baseWin; - } - return base ? base + 1 : path; -} - -uint32_t xStrCount(char *aStr, char aC) -{ - uint32_t count = 0; - char *temp = NULL; - - if (NULL == aStr) - { - return 0; - } - temp = aStr; - - while (*temp) - { - if (aC == *temp) - { - ++count; - } - temp++; - } - - return count; -} - -/*! - * @brief Trim leading and trailing whitespaces - * @param [in] *str Input string - * @retval char* pointer to the trimmed substring - * - * @details - * This function returns a pointer to a substring of the original string. - * If the given string was allocated dynamically, the caller must not overwrite - * that pointer with the returned value, since the original pointer must be - * deallocated using the same allocator with which it was allocated. The return - * value must NOT be deallocated using free() etc. - */ -char* strntrimStatic(char *aStr, size_t aMaxLength) -{ - char *end; - - // Trim leading space - while (isspace((unsigned char)*aStr) && 0 < aMaxLength) - { - if (--aMaxLength > 0) - { - ++aStr; - } - } - - // All spaces at termination or end of max length - if (*aStr == '\0' || 0 == aMaxLength) - { - return aStr; - } - - // Trim trailing space - if (strlen(aStr) >= aMaxLength) - { - end = aStr + aMaxLength - 1; - } - else - { - end = aStr + strlen(aStr) - 1; - } - - while (end > aStr && isspace((unsigned char )*end)) - { - end--; - } - - // Write new null terminator (if length is enough) - if (end < (aStr + aMaxLength - 1)) - { - *(end + 1) = '\0'; - } - - return aStr; -} - -void xStringTrim(char *aStr, size_t aMaxLength) -{ - char *start; - char *end; - - if (NULL == aStr) - { - return; - } - start = aStr; - // Trim leading space - while (isspace((unsigned char)*aStr) && 0 < aMaxLength) - { - if (--aMaxLength > 0) - { - ++aStr; - } - } - - // All spaces at termination or end of max length - if (*aStr == '\0' || 0 == aMaxLength) - { - start = '\0'; - return; - } - - (void) strlcpy(start, aStr, strlen(aStr) + 1); - - // Trim trailing space - if (strlen(start) >= aMaxLength) - { - end = start + aMaxLength - 1; - } - else - { - end = start + strlen(start) - 1; - } - - while (end > start && isspace((unsigned char )*end)) - { - end--; - } - - // Write new null terminator (if length is enough) - if (end < (start + aMaxLength - 1)) - { - *(end + 1) = '\0'; - } -} +/*! + * @file xstring.c + * @brief + * @details + * Project: \n + * Subsystem: \n + * Module: \n + * Code: GNU-C\n + * + * @date 27.02.2017 + * @author Martin Winkler + */ +#include "xtypes.h" +#include "xstring.h" +#include "ctype.h" + +char* gnu_basename(char *path) +{ + char *baseWin = strrchr(path, '\\'); + char *base = strrchr(path, '/'); + if (baseWin > base) + { + base = baseWin; + } + return base ? base + 1 : path; +} + +uint32_t xStrCount(char *aStr, char aC) +{ + uint32_t count = 0; + char *temp = NULL; + + if (NULL == aStr) + { + return 0; + } + temp = aStr; + + while (*temp) + { + if (aC == *temp) + { + ++count; + } + temp++; + } + + return count; +} + +/*! + * @brief Trim leading and trailing whitespaces + * @param [in] *str Input string + * @retval char* pointer to the trimmed substring + * + * @details + * This function returns a pointer to a substring of the original string. + * If the given string was allocated dynamically, the caller must not overwrite + * that pointer with the returned value, since the original pointer must be + * deallocated using the same allocator with which it was allocated. The return + * value must NOT be deallocated using free() etc. + */ +char* strntrimStatic(char *aStr, size_t aMaxLength) +{ + char *end; + + // Trim leading space + while (isspace((unsigned char)*aStr) && 0 < aMaxLength) + { + if (--aMaxLength > 0) + { + ++aStr; + } + } + + // All spaces at termination or end of max length + if (*aStr == '\0' || 0 == aMaxLength) + { + return aStr; + } + + // Trim trailing space + if (strlen(aStr) >= aMaxLength) + { + end = aStr + aMaxLength - 1; + } + else + { + end = aStr + strlen(aStr) - 1; + } + + while (end > aStr && isspace((unsigned char )*end)) + { + end--; + } + + // Write new null terminator (if length is enough) + if (end < (aStr + aMaxLength - 1)) + { + *(end + 1) = '\0'; + } + + return aStr; +} + +void xStringTrim(char *aStr, size_t aMaxLength) +{ + char *start; + char *end; + + if (NULL == aStr) + { + return; + } + start = aStr; + // Trim leading space + while (isspace((unsigned char)*aStr) && 0 < aMaxLength) + { + if (--aMaxLength > 0) + { + ++aStr; + } + } + + // All spaces at termination or end of max length + if (*aStr == '\0' || 0 == aMaxLength) + { + start = '\0'; + return; + } + + (void) strlcpy(start, aStr, strlen(aStr) + 1); + + // Trim trailing space + if (strlen(start) >= aMaxLength) + { + end = start + aMaxLength - 1; + } + else + { + end = start + strlen(start) - 1; + } + + while (end > start && isspace((unsigned char )*end)) + { + end--; + } + + // Write new null terminator (if length is enough) + if (end < (start + aMaxLength - 1)) + { + *(end + 1) = '\0'; + } +} diff --git a/src/ext/xstring.h b/src/ext/xstring.h index f3c8919..f7d2b71 100644 --- a/src/ext/xstring.h +++ b/src/ext/xstring.h @@ -1,23 +1,23 @@ -/*! - * @file xstring.h - * @brief - * @details - * Project: \n - * Subsystem: \n - * Module: \n - * Code: GNU-C\n - * - * @date 27.02.2017 - * @author Martin Winkler - */ -#ifndef XSTRING_H_ -#define XSTRING_H_ - -#include - -char* gnu_basename(char *path); -uint32_t xStrCount(char *aStr, char aC); -char* strntrimStatic(char *aStr, size_t aMaxLength); -void xStringTrim(char *aStr, size_t aMaxLength); - -#endif /* XSTRING_H_ */ +/*! + * @file xstring.h + * @brief + * @details + * Project: \n + * Subsystem: \n + * Module: \n + * Code: GNU-C\n + * + * @date 27.02.2017 + * @author Martin Winkler + */ +#ifndef XSTRING_H_ +#define XSTRING_H_ + +#include + +char* gnu_basename(char *path); +uint32_t xStrCount(char *aStr, char aC); +char* strntrimStatic(char *aStr, size_t aMaxLength); +void xStringTrim(char *aStr, size_t aMaxLength); + +#endif /* XSTRING_H_ */ diff --git a/src/ext/xtime.h b/src/ext/xtime.h index d881a39..9bcb970 100644 --- a/src/ext/xtime.h +++ b/src/ext/xtime.h @@ -1,32 +1,32 @@ -/*! - * @file xtime.h - * @brief Provides additional definitions for working with delays - * - * Project: \n - * Subsystem: \n - * Module: mst\n - * Code: GNU-C\n - * - * @date 08.06.2016 - * @author Martin Winkler - */ -#ifndef XTIME_H_ -#define XTIME_H_ - -#include - -/*! @brief Convert milliseconds to nanoseconds */ -#define XTIME_MSTONS(milliseconds) (milliseconds * 1000000L) -/*! @brief Convert microseconds to nanoseconds */ -#define XTIME_USTONS(microseconds) (microseconds * 1000L) -/*! @brief Convert nanoseconds to milliseconds*/ -#define XTIME_NSTOMS(nanoseconds) (nanoseconds / 1000000L) -/*! @brief Convert nanoseconds to microseconds*/ -#define XTIME_NSTOUS(nanoseconds) (nanoseconds / 1000L) - -/*! @brief Only microseconds up to 1000000 are supported */ -#define XTIME_TIMESPEC_US(seconds, microseconds) (const struct timespec[]){{seconds, XTIME_USTONS(microseconds)}} -/*! @brief Only milliseconds up to 1000 are supported */ -#define XTIME_TIMESPEC_MS(seconds, milliseconds) (const struct timespec[]){{seconds, XTIME_MSTONS(milliseconds)}} - -#endif /* XTIME_H_ */ +/*! + * @file xtime.h + * @brief Provides additional definitions for working with delays + * + * Project: \n + * Subsystem: \n + * Module: mst\n + * Code: GNU-C\n + * + * @date 08.06.2016 + * @author Martin Winkler + */ +#ifndef XTIME_H_ +#define XTIME_H_ + +#include + +/*! @brief Convert milliseconds to nanoseconds */ +#define XTIME_MSTONS(milliseconds) (milliseconds * 1000000L) +/*! @brief Convert microseconds to nanoseconds */ +#define XTIME_USTONS(microseconds) (microseconds * 1000L) +/*! @brief Convert nanoseconds to milliseconds*/ +#define XTIME_NSTOMS(nanoseconds) (nanoseconds / 1000000L) +/*! @brief Convert nanoseconds to microseconds*/ +#define XTIME_NSTOUS(nanoseconds) (nanoseconds / 1000L) + +/*! @brief Only microseconds up to 1000000 are supported */ +#define XTIME_TIMESPEC_US(seconds, microseconds) (const struct timespec[]){{seconds, XTIME_USTONS(microseconds)}} +/*! @brief Only milliseconds up to 1000 are supported */ +#define XTIME_TIMESPEC_MS(seconds, milliseconds) (const struct timespec[]){{seconds, XTIME_MSTONS(milliseconds)}} + +#endif /* XTIME_H_ */ diff --git a/src/ext/xtypes.h b/src/ext/xtypes.h index 6c21383..e5e9d15 100644 --- a/src/ext/xtypes.h +++ b/src/ext/xtypes.h @@ -1,41 +1,41 @@ -/*! - * @file xtypes.h - * @brief - * @details - * Project: \n - * Subsystem: \n - * Module: \n - * Code: GNU-C\n - * - * @date 27.02.2017 - * @author Martin Winkler - */ - -#ifndef XTYPES_H_ -#define XTYPES_H_ - -#include // definition of NULL -#include // fixed width types -#include // definition of bool - -#define STRINGIZE_2(s) #s -/*! - * @brief Stringify the content of a definition - * @details - * Usage example: - * @code - #define VERSION_MAJOR 4 - #define VERSION_MINOR 47 - - #define VERSION_STRING "v" STRINGIZE(VERSION_MAJOR) "." STRINGIZE(VERSION_MINOR) - @endcode - */ -#define STRINGIZE(s) STRINGIZE_2(s) - -#if defined(UNIT_TEST) || defined(_DEBUG) -#define STATIC -#else -#define STATIC static -#endif - -#endif /* XTYPES_H_ */ +/*! + * @file xtypes.h + * @brief + * @details + * Project: \n + * Subsystem: \n + * Module: \n + * Code: GNU-C\n + * + * @date 27.02.2017 + * @author Martin Winkler + */ + +#ifndef XTYPES_H_ +#define XTYPES_H_ + +#include // definition of NULL +#include // fixed width types +#include // definition of bool + +#define STRINGIZE_2(s) #s +/*! + * @brief Stringify the content of a definition + * @details + * Usage example: + * @code + #define VERSION_MAJOR 4 + #define VERSION_MINOR 47 + + #define VERSION_STRING "v" STRINGIZE(VERSION_MAJOR) "." STRINGIZE(VERSION_MINOR) + @endcode + */ +#define STRINGIZE(s) STRINGIZE_2(s) + +#if defined(UNIT_TEST) || defined(_DEBUG) +#define STATIC +#else +#define STATIC static +#endif + +#endif /* XTYPES_H_ */ diff --git a/src/main.c b/src/main.c index a36a13f..b5e0c82 100644 --- a/src/main.c +++ b/src/main.c @@ -1,222 +1,222 @@ -/*! - * @file main.c - * @brief - * @details - * Project: \n - * Subsystem: \n - * Module: \n - * Code: GNU-C\n - * - * @date 27.02.2017 - * @author Martin Winkler - */ -#include -#include -#include -#include - -#include "version.h" -#include "xmalloc.h" -#include "xregex.h" -#include "xtypes.h" -#include "xstring.h" -#include "stubser/stubser_if.h" - -/* POSIX.1 says each process has at least 20 file descriptors. - * Three of those belong to the standard streams. - * Here, we use a conservative estimate of 15 available; - * assuming we use at most two for other uses in this program, - * we should never run into any problems. - * Most trees are shallower than that, so it is efficient. - * Deeper trees are traversed fine, just a bit slower. - * (Linux allows typically hundreds to thousands of open files, - * so you'll probably never see any issues even if you used - * a much higher value, say a couple of hundred, but - * 15 is a safe, reasonable value.) - */ -#ifndef USE_FDS -#define USE_FDS 15 -#endif - -#define MAIN_MAX_MATCHGROUP_FILENAME 2 -#define MAIN_CFILE_PATTERN "^(.*)\\.+[cC]$" - -STATIC regex_t main_regXcFile; -STATIC bool main_recurse = false; -STATIC char* main_outputDir = NULL; - -/*! - * @brief Using regular expressions to scan for c files, extract filename without suffix and start stub creation - * @details - * @par Parameter - * See gnu libc documentation for details (Data Type: __nftw_func_t). - */ -int evaluateEntry(const char *filepath, const struct stat *info, const int typeflag, struct FTW *pathinfo) -{ - regmatch_t matchGroup[MAIN_MAX_MATCHGROUP_FILENAME]; - char *noSuffix = NULL; - if (!main_recurse && 1 < pathinfo->level) - { - return 0; - } - if (typeflag != FTW_F) - { - return 0; - } - - if (0 != regexec(&main_regXcFile, gnu_basename((char*) filepath), MAIN_MAX_MATCHGROUP_FILENAME, matchGroup, 0)) - { - return 0; - } - - if (XREGEX_IS_MATCHGROUP(matchGroup, 1)) - { - xmallocStrlcpy(&noSuffix, &gnu_basename((char*) filepath)[matchGroup[1].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 1)); - if (NULL != noSuffix) - { - stubser_createStub((char*) filepath, noSuffix, main_outputDir); - } - free(noSuffix); - } - - return 0; -} - -/*! - * @brief Scan given directory recursively - */ -int evaluateDirectoryTree(const char * const dirpath) -{ - int result; - - /* Invalid directory path? */ - if (dirpath == NULL || *dirpath == '\0') - return errno = EINVAL; - - result = nftw(dirpath, evaluateEntry, USE_FDS, FTW_PHYS); - if (result >= 0) - errno = result; - - return errno; -} - -void printUsage(char *aAppName) -{ - printf("%s version: %s\n", aAppName, GITVERSION); - printf("Create stub c-files and c-header from c files for CUnit.\n\n"); - printf("Usage:\n"); - printf(" %s [options] [source dir] \n", aAppName); - printf("\nOptions:\n"); - printf(" -h, --help \tShow usage\n"); - printf(" -r, --recurse\tSearch source Dir recursively\n"); - printf(" --version \tShow version\n"); -} - -/*! - * @brief Search (optionally recursive) for c file and create stubs - * @param [in] argc Amount of command line arguments - * @param [in] **argv Array of arguments - * @retval EXIT_SUCCESS stubs created successfully - * @retval EXIT_FAILURE error with arguments or input - */ -int main(int argc, char **argv) -{ - int i = 0; - int ret = EXIT_FAILURE; - int outputDirIndex = 0; - uint8_t dirs = 0; - - if (regcomp(&main_regXcFile, MAIN_CFILE_PATTERN, REG_EXTENDED | REG_NEWLINE)) - { - fprintf(stderr, "%s.\n", strerror(errno)); - ret = EXIT_FAILURE; - goto l_main_end; - } - - if (argc < 2) - { - printUsage(gnu_basename(argv[0])); - ret = EXIT_FAILURE; - goto l_main_end; - } - - // evaluate command line parameter - for (i = 1; i < argc && i < 4; ++i) - { - if (NULL != strstr(argv[i], "-r") || NULL != strstr(argv[i], "--recurse")) - { - main_recurse = true; - } - else if (NULL != strstr(argv[i], "--version")) - { - printf("%s version: %s", gnu_basename(argv[0]), GITVERSION); - goto l_main_end; - } - else if (NULL != strstr(argv[i], "-h") || NULL != strstr(argv[i], "--help")) - { - printUsage(gnu_basename(argv[0])); - goto l_main_end; - } - else - { - outputDirIndex = i; - ++dirs; - } - } - - if (0 == outputDirIndex) - { - // only options; no output directory provided - printUsage(gnu_basename(argv[0])); - ret = EXIT_FAILURE; - goto l_main_end; - } - - if (0 > mkdir(argv[outputDirIndex], S_IRWXU)) - { - // output directory not available - if (EEXIST != errno) - { - fprintf(stderr, "%s.\n", strerror(errno)); - ret = EXIT_FAILURE; - goto l_main_end; - } - } - - xmallocStrlcpy(&main_outputDir, argv[outputDirIndex], strlen(argv[outputDirIndex]) + 1); - if (NULL == main_outputDir) - { - fprintf(stderr, "%s.\n", strerror(errno)); - ret = EXIT_FAILURE; - goto l_main_end; - } - - if (1 == dirs) - { - // only output provided; input will be "." - if (evaluateDirectoryTree(".")) - { - fprintf(stderr, "%s.\n", strerror(errno)); - ret = EXIT_FAILURE; - goto l_main_end; - } - } - else - { - // take input directory from arguments - if (evaluateDirectoryTree(argv[outputDirIndex - 1])) - { - fprintf(stderr, "%s.\n", strerror(errno)); - ret = EXIT_FAILURE; - goto l_main_end; - } - } - - ret = EXIT_SUCCESS; - - l_main_end: // label for ending main - - free(main_outputDir); - - return ret; -} +/*! + * @file main.c + * @brief + * @details + * Project: \n + * Subsystem: \n + * Module: \n + * Code: GNU-C\n + * + * @date 27.02.2017 + * @author Martin Winkler + */ +#include +#include +#include +#include + +#include "version.h" +#include "xmalloc.h" +#include "xregex.h" +#include "xtypes.h" +#include "xstring.h" +#include "stubser/stubser_if.h" + +/* POSIX.1 says each process has at least 20 file descriptors. + * Three of those belong to the standard streams. + * Here, we use a conservative estimate of 15 available; + * assuming we use at most two for other uses in this program, + * we should never run into any problems. + * Most trees are shallower than that, so it is efficient. + * Deeper trees are traversed fine, just a bit slower. + * (Linux allows typically hundreds to thousands of open files, + * so you'll probably never see any issues even if you used + * a much higher value, say a couple of hundred, but + * 15 is a safe, reasonable value.) + */ +#ifndef USE_FDS +#define USE_FDS 15 +#endif + +#define MAIN_MAX_MATCHGROUP_FILENAME 2 +#define MAIN_CFILE_PATTERN "^(.*)\\.+[cC]$" + +STATIC regex_t main_regXcFile; +STATIC bool main_recurse = false; +STATIC char* main_outputDir = NULL; + +/*! + * @brief Using regular expressions to scan for c files, extract filename without suffix and start stub creation + * @details + * @par Parameter + * See gnu libc documentation for details (Data Type: __nftw_func_t). + */ +int evaluateEntry(const char *filepath, const struct stat *info, const int typeflag, struct FTW *pathinfo) +{ + regmatch_t matchGroup[MAIN_MAX_MATCHGROUP_FILENAME]; + char *noSuffix = NULL; + if (!main_recurse && 1 < pathinfo->level) + { + return 0; + } + if (typeflag != FTW_F) + { + return 0; + } + + if (0 != regexec(&main_regXcFile, gnu_basename((char*) filepath), MAIN_MAX_MATCHGROUP_FILENAME, matchGroup, 0)) + { + return 0; + } + + if (XREGEX_IS_MATCHGROUP(matchGroup, 1)) + { + xmallocStrlcpy(&noSuffix, &gnu_basename((char*) filepath)[matchGroup[1].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 1)); + if (NULL != noSuffix) + { + stubser_createStub((char*) filepath, noSuffix, main_outputDir); + } + free(noSuffix); + } + + return 0; +} + +/*! + * @brief Scan given directory recursively + */ +int evaluateDirectoryTree(const char * const dirpath) +{ + int result; + + /* Invalid directory path? */ + if (dirpath == NULL || *dirpath == '\0') + return errno = EINVAL; + + result = nftw(dirpath, evaluateEntry, USE_FDS, FTW_PHYS); + if (result >= 0) + errno = result; + + return errno; +} + +void printUsage(char *aAppName) +{ + printf("%s version: %s\n", aAppName, GITVERSION); + printf("Create stub c-files and c-header from c files for CUnit.\n\n"); + printf("Usage:\n"); + printf(" %s [options] [source dir] \n", aAppName); + printf("\nOptions:\n"); + printf(" -h, --help \tShow usage\n"); + printf(" -r, --recurse\tSearch source Dir recursively\n"); + printf(" --version \tShow version\n"); +} + +/*! + * @brief Search (optionally recursive) for c file and create stubs + * @param [in] argc Amount of command line arguments + * @param [in] **argv Array of arguments + * @retval EXIT_SUCCESS stubs created successfully + * @retval EXIT_FAILURE error with arguments or input + */ +int main(int argc, char **argv) +{ + int i = 0; + int ret = EXIT_FAILURE; + int outputDirIndex = 0; + uint8_t dirs = 0; + + if (regcomp(&main_regXcFile, MAIN_CFILE_PATTERN, REG_EXTENDED | REG_NEWLINE)) + { + fprintf(stderr, "%s.\n", strerror(errno)); + ret = EXIT_FAILURE; + goto l_main_end; + } + + if (argc < 2) + { + printUsage(gnu_basename(argv[0])); + ret = EXIT_FAILURE; + goto l_main_end; + } + + // evaluate command line parameter + for (i = 1; i < argc && i < 4; ++i) + { + if (NULL != strstr(argv[i], "-r") || NULL != strstr(argv[i], "--recurse")) + { + main_recurse = true; + } + else if (NULL != strstr(argv[i], "--version")) + { + printf("%s version: %s", gnu_basename(argv[0]), GITVERSION); + goto l_main_end; + } + else if (NULL != strstr(argv[i], "-h") || NULL != strstr(argv[i], "--help")) + { + printUsage(gnu_basename(argv[0])); + goto l_main_end; + } + else + { + outputDirIndex = i; + ++dirs; + } + } + + if (0 == outputDirIndex) + { + // only options; no output directory provided + printUsage(gnu_basename(argv[0])); + ret = EXIT_FAILURE; + goto l_main_end; + } + + if (0 > mkdir(argv[outputDirIndex], S_IRWXU)) + { + // output directory not available + if (EEXIST != errno) + { + fprintf(stderr, "%s.\n", strerror(errno)); + ret = EXIT_FAILURE; + goto l_main_end; + } + } + + xmallocStrlcpy(&main_outputDir, argv[outputDirIndex], strlen(argv[outputDirIndex]) + 1); + if (NULL == main_outputDir) + { + fprintf(stderr, "%s.\n", strerror(errno)); + ret = EXIT_FAILURE; + goto l_main_end; + } + + if (1 == dirs) + { + // only output provided; input will be "." + if (evaluateDirectoryTree(".")) + { + fprintf(stderr, "%s.\n", strerror(errno)); + ret = EXIT_FAILURE; + goto l_main_end; + } + } + else + { + // take input directory from arguments + if (evaluateDirectoryTree(argv[outputDirIndex - 1])) + { + fprintf(stderr, "%s.\n", strerror(errno)); + ret = EXIT_FAILURE; + goto l_main_end; + } + } + + ret = EXIT_SUCCESS; + + l_main_end: // label for ending main + + free(main_outputDir); + + return ret; +} diff --git a/src/stubser/cfile.c b/src/stubser/cfile.c index 8d3d657..e802bcb 100644 --- a/src/stubser/cfile.c +++ b/src/stubser/cfile.c @@ -1,163 +1,163 @@ -/*! - * @file cfile.c - * @brief - * @details - * Project: \n - * Subsystem: \n - * Module: \n - * Code: GNU-C\n - * - * @date 08.03.2017 - * @author Martin Winkler - */ -#include -#include -#include "xtypes.h" -#include "xmalloc.h" -#include "cfile_if.h" - -cfile_variable_t* cfile_newVariable(cfile_variableList_t *aList) -{ - cfile_variable_t *new = NULL; - - if (NULL == aList) - { - perror("Null pointer"); - return NULL; - } - - new = (cfile_variable_t*) xmalloc(sizeof(cfile_variable_t)); - memset(new, 0, sizeof(cfile_variable_t)); - - if (NULL == aList->head) - { - aList->head = new; - aList->current = new; - } - else - { - aList->current->next = new; - aList->current = new; - } - ++aList->amount; - return new; -} - -int8_t cfile_freeVariables(cfile_variableList_t *aVariable) -{ - cfile_variable_t *work = NULL; - cfile_variable_t *next = NULL; - - if (NULL == aVariable) - { - perror("Null pointer"); - return -1; - } - - work = aVariable->head; - - while (work) - { - next = work->next; - free(work->dataType); - free(work->name); - free(work); - work = next; - } - - aVariable->amount = 0; - aVariable->head = NULL; - aVariable->current = NULL; - - return 0; -} - -void cfile_free(cfile_t *aCfile) -{ - cfile_freeVariables(&aCfile->variables); - cfunction_freeList(&aCfile->functions); -} - -void cfile_print(cfile_t *aCfile) -{ - cfile_variable_t *work = NULL; - - if (NULL == aCfile) - { - return; - } - - work = aCfile->variables.head; - - while (work) - { - printf("[ cva]%d:<%s> (%s) %s %s\n", work->type, work->prefix, work->dataType, work->name, work->array); - work = work->next; - } - - cfunction_printList(&aCfile->functions); -} - -/*! - * @brief Checks if at least one function uses a variable parameter list - * @retval -2 Null pointer parameter - * @retval -1 Has no va_list - * @retval 0 At least on va_list - */ -int8_t cfile_hasVaList(cfile_t *aFile) -{ - cfunction_t *function = aFile->functions.head; - cfunction_parameterList_t *paraList = NULL; - cfunction_parameter_t *parameter; - if (NULL == aFile) - { - return -2; - } - while(function) - { - paraList = &function->parameter; - parameter = paraList->head; - while(parameter) - { - if (CPARAMETER_TYPE_VARIABLE == parameter->type) - { - return 0; - } - parameter = parameter->next; - } - function = function->next; - } - return -1; -} - -/*! - * @brief Checks if at least one variable or function parameter is a pointer - * @retval -2 Null pointer parameter - * @retval -1 Has no pointer - * @retval 0 At least on pointer - */ -int8_t cfile_hasPointerParameter(cfile_t *aFile) -{ - cfunction_t *function = aFile->functions.head; - cfunction_parameterList_t *paraList = NULL; - cfunction_parameter_t *parameter; - if (NULL == aFile) - { - return -2; - } - while(function) - { - paraList = &function->parameter; - parameter = paraList->head; - while(parameter) - { - if (NULL != strstr(parameter->dataType, "*") || NULL != parameter->array) - { - return 0; - } - parameter = parameter->next; - } - function = function->next; - } - return -1; -} +/*! + * @file cfile.c + * @brief + * @details + * Project: \n + * Subsystem: \n + * Module: \n + * Code: GNU-C\n + * + * @date 08.03.2017 + * @author Martin Winkler + */ +#include +#include +#include "xtypes.h" +#include "xmalloc.h" +#include "cfile_if.h" + +cfile_variable_t* cfile_newVariable(cfile_variableList_t *aList) +{ + cfile_variable_t *new = NULL; + + if (NULL == aList) + { + perror("Null pointer"); + return NULL; + } + + new = (cfile_variable_t*) xmalloc(sizeof(cfile_variable_t)); + memset(new, 0, sizeof(cfile_variable_t)); + + if (NULL == aList->head) + { + aList->head = new; + aList->current = new; + } + else + { + aList->current->next = new; + aList->current = new; + } + ++aList->amount; + return new; +} + +int8_t cfile_freeVariables(cfile_variableList_t *aVariable) +{ + cfile_variable_t *work = NULL; + cfile_variable_t *next = NULL; + + if (NULL == aVariable) + { + perror("Null pointer"); + return -1; + } + + work = aVariable->head; + + while (work) + { + next = work->next; + free(work->dataType); + free(work->name); + free(work); + work = next; + } + + aVariable->amount = 0; + aVariable->head = NULL; + aVariable->current = NULL; + + return 0; +} + +void cfile_free(cfile_t *aCfile) +{ + cfile_freeVariables(&aCfile->variables); + cfunction_freeList(&aCfile->functions); +} + +void cfile_print(cfile_t *aCfile) +{ + cfile_variable_t *work = NULL; + + if (NULL == aCfile) + { + return; + } + + work = aCfile->variables.head; + + while (work) + { + printf("[ cva]%d:<%s> (%s) %s %s\n", work->type, work->prefix, work->dataType, work->name, work->array); + work = work->next; + } + + cfunction_printList(&aCfile->functions); +} + +/*! + * @brief Checks if at least one function uses a variable parameter list + * @retval -2 Null pointer parameter + * @retval -1 Has no va_list + * @retval 0 At least on va_list + */ +int8_t cfile_hasVaList(cfile_t *aFile) +{ + cfunction_t *function = aFile->functions.head; + cfunction_parameterList_t *paraList = NULL; + cfunction_parameter_t *parameter; + if (NULL == aFile) + { + return -2; + } + while(function) + { + paraList = &function->parameter; + parameter = paraList->head; + while(parameter) + { + if (CPARAMETER_TYPE_VARIABLE == parameter->type) + { + return 0; + } + parameter = parameter->next; + } + function = function->next; + } + return -1; +} + +/*! + * @brief Checks if at least one variable or function parameter is a pointer + * @retval -2 Null pointer parameter + * @retval -1 Has no pointer + * @retval 0 At least on pointer + */ +int8_t cfile_hasPointerParameter(cfile_t *aFile) +{ + cfunction_t *function = aFile->functions.head; + cfunction_parameterList_t *paraList = NULL; + cfunction_parameter_t *parameter; + if (NULL == aFile) + { + return -2; + } + while(function) + { + paraList = &function->parameter; + parameter = paraList->head; + while(parameter) + { + if (NULL != strstr(parameter->dataType, "*") || NULL != parameter->array) + { + return 0; + } + parameter = parameter->next; + } + function = function->next; + } + return -1; +} diff --git a/src/stubser/cfile_if.h b/src/stubser/cfile_if.h index e8286c2..b635b92 100644 --- a/src/stubser/cfile_if.h +++ b/src/stubser/cfile_if.h @@ -1,76 +1,76 @@ -/*! - * @file cfile_if.h - * @brief - * @details - * Project: \n - * Subsystem: \n - * Module: \n - * Code: GNU-C\n - * - * @date 08.03.2017 - * @author Martin Winkler - */ - -#ifndef STUBSER_CFILE_IF_H_ -#define STUBSER_CFILE_IF_H_ - -#include "cfunction_if.h" - -#define CVARIABLE_CHECK_TYPE(var, type) (type == (var & type)) -#define CVARIABLE_SET_TYPE(var, type) do{\ - var &= ~type; \ - var |= type; \ - } while(0) - -/*! @brief Type of variable definition for bit field usage */ -typedef enum _CFILE_VARIABLE_TYPE_T -{ - CVARIABLE_TYPE_UNDEF = 0, /*!< @brief undefined */ - CVARIABLE_TYPE_REGULAR = 0x01, /*!< @brief Regular C variable definition */ - CVARIABLE_TYPE_STATIC = 0x02, /*!< @brief Static C variable definition */ - CVARIABLE_TYPE_EXTERN = 0x04, /*!< @brief External C variable definition */ - CVARIABLE_TYPE_FUPTR = 0x08, /*!< @brief Function pointer as variable */ - CVARIABLE_TYPE_CONST = 0x10, /*!< @brief Const C variable */ - CVARIABLE_TYPE_LAST_ENUM -} cfile_variable_type_t; - -/*! @brief Parameter list node */ -typedef struct _CFILE_VARIABLE_T -{ - cfile_variable_type_t type; - char* prefix; /*!< @brief variable prefix (e.g. static) */ - char* dataType; /*!< @brief data type */ - char* name; /*!< @brief name */ - char* array; /*!< @brief array information (e.g. [10] or [DEF_MAX]) */ - struct _CFILE_VARIABLE_T *next; -} cfile_variable_t; - -/*! @brief parameter array */ -typedef struct _CFILE_VARIABLE_LIST_T -{ - uint8_t amount; - cfile_variable_t *head; - cfile_variable_t *current; -} cfile_variableList_t; - -/*! @brief brief_description */ -typedef struct _CFILE_T -{ - cfile_variableList_t variables; /*! @brief C variables */ - cfunction_list_t functions; /*!< @brief C functions */ -} cfile_t; - -#define CFILE_T_DEFAULT {\ - .variables.amount = 0, \ - .variables.head = NULL, \ - .variables.current = NULL, \ - .functions = CFUNCTION_LIST_DEFAULT } - -cfile_variable_t* cfile_newVariable(cfile_variableList_t *aList); -int8_t cfile_freeVariables(cfile_variableList_t *aVariable); -void cfile_free(cfile_t *aCfile); -void cfile_print(cfile_t *aCfile); -int8_t cfile_hasVaList(cfile_t *aFile); -int8_t cfile_hasPointerParameter(cfile_t *aFile); - -#endif /* STUBSER_CFILE_IF_H_ */ +/*! + * @file cfile_if.h + * @brief + * @details + * Project: \n + * Subsystem: \n + * Module: \n + * Code: GNU-C\n + * + * @date 08.03.2017 + * @author Martin Winkler + */ + +#ifndef STUBSER_CFILE_IF_H_ +#define STUBSER_CFILE_IF_H_ + +#include "cfunction_if.h" + +#define CVARIABLE_CHECK_TYPE(var, type) (type == (var & type)) +#define CVARIABLE_SET_TYPE(var, type) do{\ + var &= ~type; \ + var |= type; \ + } while(0) + +/*! @brief Type of variable definition for bit field usage */ +typedef enum _CFILE_VARIABLE_TYPE_T +{ + CVARIABLE_TYPE_UNDEF = 0, /*!< @brief undefined */ + CVARIABLE_TYPE_REGULAR = 0x01, /*!< @brief Regular C variable definition */ + CVARIABLE_TYPE_STATIC = 0x02, /*!< @brief Static C variable definition */ + CVARIABLE_TYPE_EXTERN = 0x04, /*!< @brief External C variable definition */ + CVARIABLE_TYPE_FUPTR = 0x08, /*!< @brief Function pointer as variable */ + CVARIABLE_TYPE_CONST = 0x10, /*!< @brief Const C variable */ + CVARIABLE_TYPE_LAST_ENUM +} cfile_variable_type_t; + +/*! @brief Parameter list node */ +typedef struct _CFILE_VARIABLE_T +{ + cfile_variable_type_t type; + char* prefix; /*!< @brief variable prefix (e.g. static) */ + char* dataType; /*!< @brief data type */ + char* name; /*!< @brief name */ + char* array; /*!< @brief array information (e.g. [10] or [DEF_MAX]) */ + struct _CFILE_VARIABLE_T *next; +} cfile_variable_t; + +/*! @brief parameter array */ +typedef struct _CFILE_VARIABLE_LIST_T +{ + uint8_t amount; + cfile_variable_t *head; + cfile_variable_t *current; +} cfile_variableList_t; + +/*! @brief brief_description */ +typedef struct _CFILE_T +{ + cfile_variableList_t variables; /*! @brief C variables */ + cfunction_list_t functions; /*!< @brief C functions */ +} cfile_t; + +#define CFILE_T_DEFAULT {\ + .variables.amount = 0, \ + .variables.head = NULL, \ + .variables.current = NULL, \ + .functions = CFUNCTION_LIST_DEFAULT } + +cfile_variable_t* cfile_newVariable(cfile_variableList_t *aList); +int8_t cfile_freeVariables(cfile_variableList_t *aVariable); +void cfile_free(cfile_t *aCfile); +void cfile_print(cfile_t *aCfile); +int8_t cfile_hasVaList(cfile_t *aFile); +int8_t cfile_hasPointerParameter(cfile_t *aFile); + +#endif /* STUBSER_CFILE_IF_H_ */ diff --git a/src/stubser/cfile_parser.c b/src/stubser/cfile_parser.c index a7cbeaa..4c479b3 100644 --- a/src/stubser/cfile_parser.c +++ b/src/stubser/cfile_parser.c @@ -1,838 +1,838 @@ -/*! - * @file cfile_parser.c - * @brief - * @details - * Project: \n - * Subsystem: \n - * Module: \n - * Code: GNU-C\n - * - * @date 28.02.2017 - * @author Martin Winkler - */ -#include -#include -#include -#include "xregex.h" -#include "xtypes.h" -#include "xstring.h" -#include "xmalloc.h" -#include "cfile_if.h" -#include "cfile_parser_if.h" -#include "cfile_parser_loc.h" -#include "cfile_parser_worker_loc.h" -#include "debug.h" - -/*! @brief Block detection return values */ -typedef enum _CFILE_BLOCK_RETURN_T -{ - CFILE_BLOCK_DETECT_ERROR = -1, /*!< @brief description */ - CFILE_BLOCK_DETECT_NONE = 0, /*!< @brief description */ - CFILE_BLOCK_DETECT_START = 1, /*!< @brief description */ - CFILE_BLOCK_DETECT_END = 2, /*!< @brief description */ -} cfile_block_return_t; - -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; -STATIC regex_t regXExpressionEnd; - -// line evaluation related variables -STATIC uint32_t cfile_parser_removeCommentHelper = 0; -STATIC uint32_t cfile_parser_removeBraceHelper = 0; - -int8_t cfile_parser_init() -{ - if (0 > regcomp(®XExpressionStart, CPARS_EXPRESSION_START, (REG_EXTENDED | REG_NEWLINE))) - { - perror("Error regex\n"); - return -1; - } - if (0 > regcomp(®XExpressionEnd, CPARS_EXPRESSION_END, (REG_EXTENDED | REG_NEWLINE))) - { - perror("Error regex\n"); - return -1; - } - if (0 > regcomp(®Xfunction, CPARS_REGEX_FUNCTION, (REG_EXTENDED | REG_NEWLINE))) - { - perror("Error regex\n"); - return -1; - } - if (0 > regcomp(®Xprefix, CPARS_REGEX_PREFIX, (REG_EXTENDED))) - { - perror("Error regex\n"); - return -1; - } - if (0 > regcomp(®Xparameter, CPARS_REGEX_PARAMETER, (REG_EXTENDED))) - { - 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_FUNCTIONPOINTER, (REG_EXTENDED))) - { - perror("Error regex\n"); - return -1; - } - if (0 > regcomp(®Xvariable, CPARS_REGEX_VARIABLE, (REG_EXTENDED | REG_NEWLINE))) - { - perror("Error regex\n"); - return -1; - } - - cfile_parser_initialized = true; - return 0; -} - -#if isDebugLevel(1) -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) - { - DEBUG_LOG_APPEND(1, "[%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)); - DEBUG_LOG_APPEND(1, "%s", match); - DEBUG_LOG_APPEND(1, "\n"); - } - } -} -#else -#define printMatchGroup(aString, aMatchgroup) do { /*nothing*/ } while(0) -#endif - -STATIC void checkFunctionType(cfunction_t *aFunction, char *aExpression) -{ - char *tempChar = NULL; - - if (NULL == aFunction || NULL == aExpression) - { - return; - } - - aFunction->type = CFUNCTION_TYPE_REGULAR; - - tempChar = strrchr(aExpression, CPARS_PROTOTYPE_END_C); - if (tempChar) - { - aFunction->type = CFUNCTION_TYPE_PROTO; - } - - if (NULL == aFunction->prefix) - { - return; - } - if (NULL != strstr(aFunction->prefix, CPARS_PREFIX_EXTERN_S)) - { - aFunction->type = CFUNCTION_TYPE_EXTERN; - } - else if ((NULL != strstr(aFunction->prefix, CPARS_PREFIX_STATIC_S) || NULL != strstr(aFunction->prefix, CPARS_PREFIX_STATIC2_S)) - && CFUNCTION_TYPE_PROTO != aFunction->type) - { - aFunction->type = CFUNCTION_TYPE_STATIC; - } -} - -/*! - * @brief Extract C expression prefix and data type and removing trailing blanks - * @param [out] *aElement Pointer to C element structure - * @param [in] aElementType C element type (CELEMENT_TYPE_VARIABLE, CELEMENT_TYPE_FUNCTION supported) - * @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 matchPrefix(void *aElement, celement_type_t aElementType, char *aString, size_t aSize) -{ - regmatch_t matchGroup[CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS]; - char *temp = NULL; - char *end = NULL; - char **prefix = NULL; - char **type = NULL; - - if (NULL == aElement || NULL == aString || 0 == aSize) - { - return -1; - } - - switch (aElementType) - { - case CELEMENT_TYPE_VARIABLE: - { - prefix = &((cfile_variable_t*) aElement)->prefix; - type = &((cfile_variable_t*) aElement)->dataType; - break; - } - case CELEMENT_TYPE_FUNCTION: - { - prefix = &((cfunction_t*) aElement)->prefix; - type = &((cfunction_t*) aElement)->dataType; - break; - } - default: - { - 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 (CELEMENT_TYPE_VARIABLE == aElementType) - { - ((cfile_variable_t*) aElement)->type = CVARIABLE_TYPE_REGULAR; - } - - if (0 == regexec(®Xprefix, temp, CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS, matchGroup, 0)) - { - if (XREGEX_IS_MATCHGROUP(matchGroup, 1)) - { - xmallocStrlcpy(prefix, &temp[matchGroup[1].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 1)); - if (CELEMENT_TYPE_VARIABLE == aElementType) - { - if (*prefix && NULL != strstr(*prefix, CPARS_PREFIX_EXTERN_S)) - { - ((cfile_variable_t*) aElement)->type = CVARIABLE_TYPE_EXTERN; - } - else if (*prefix && (NULL != strstr(*prefix, CPARS_PREFIX_STATIC_S) || NULL != strstr(*prefix, CPARS_PREFIX_STATIC2_S))) - { - ((cfile_variable_t*) aElement)->type = CVARIABLE_TYPE_STATIC; - } - } - } - if (XREGEX_IS_MATCHGROUP(matchGroup, 2)) - { - xmallocStrlcpy(type, &temp[matchGroup[2].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 2)); - } - } - else - { - xmallocStrlcpy(type, temp, strlen(temp)); - } - - if (CELEMENT_TYPE_VARIABLE == aElementType) - { - if (*type && NULL != strstr(*type, CPARS_ELEMENT_CONST)) - { - CVARIABLE_SET_TYPE(((cfile_variable_t* ) aElement)->type, CVARIABLE_TYPE_CONST); - } - } - - free(temp); - return 0; -} - -/*! - * @brief Find first given "start" or "end" string and return position - * @param [in] *aBlockStart Terminated string defining the start of a block - * @param [in] *aBlockEnd Terminated string defining the end of a block - * @param [in] *aLine Terminated line (e.g. read from a file getline()) - * @param [out] **aPosition Pointing to found block string (related to \ref aRemove) / NULL for CFILE_BLOCK_DETECT_NONE or CFILE_BLOCK_DETECT_ERROR - * @param [in] aRemove false - remove only content of block; true - also remove block strings - * @return cfile_block_return_t - * @retval CFILE_BLOCK_DETECT_START Start found - * @retval CFILE_BLOCK_DETECT_END End found - * @retval CFILE_BLOCK_DETECT_NONE No start or end found - * @retval CFILE_BLOCK_DETECT_ERROR Null pointer detected - */ -STATIC cfile_block_return_t cBlockDetection(const char *aBlockStart, const char *aBlockEnd, char *aLine, char **aPosition, bool aRemove) -{ - char *blockStart = NULL; - char *blockEnd = NULL; - cfile_block_return_t ret = CFILE_BLOCK_DETECT_NONE; - - if ( NULL == aBlockStart || NULL == aBlockEnd || NULL == aLine || NULL == aPosition) - { - perror("Null pointer"); - return CFILE_BLOCK_DETECT_ERROR; - } - - blockStart = strstr(aLine, aBlockStart); - blockEnd = strstr(aLine, aBlockEnd); - - if (NULL == blockStart && NULL == blockEnd) - { - // no block element - ret = CFILE_BLOCK_DETECT_NONE; - } - else if (NULL == blockStart) - { - // last line of block - ret = CFILE_BLOCK_DETECT_END; - } - else if (NULL == blockEnd) - { - // first line of block - - ret = CFILE_BLOCK_DETECT_START; - } - else if (blockStart < blockEnd) - { - // inline block - ret = CFILE_BLOCK_DETECT_START; - } - else - { - // last line of multi line block with further blocks in line - ret = CFILE_BLOCK_DETECT_END; - } - - switch (ret) - { - case CFILE_BLOCK_DETECT_START: - { - *aPosition = (aRemove ? blockStart : blockStart + strlen(aBlockStart)); - break; - } - case CFILE_BLOCK_DETECT_END: - { - *aPosition = (aRemove ? blockEnd + strlen(aBlockEnd) : blockEnd); - break; - } - case CFILE_BLOCK_DETECT_NONE: - { - *aPosition = NULL; - break; - } - default: - { - ret = CFILE_BLOCK_DETECT_ERROR; - *aPosition = NULL; - break; - } - } - - return ret; -} - -/*! - * @brief Remove blocks defined by "start" and "end" - * @attention May be called multiple time (for a whole file). *aHelper must not be changed within the process. - * @param [in] *aLine Terminated line (e.g. read from a file getline()) - * @param [in] *aBlockStart Terminated string defining the start of a block - * @param [in] *aBlockEnd Terminated string defining the end of a block - * @param [in,out] *aHelper Storage for block traversal - * @param [in] aRemove false - remove only content of block; true - also remove block strings - * @retval 0 Blocks removed or none found - * @retval 1 Line only within block - * @retval -1 Invalid block ending ("end" without corresponding "start") - * @retval -2 Null pointer detected - */ -STATIC int8_t cBlockRemoval(char *aLine, const char *aBlockStart, const char *aBlockEnd, uint32_t *aHelper, bool aRemove, bool aIgnore) -{ - const uint8_t depth = 1; // preparation to support which depth should be removed for nested block - bool blockLine = false; - int8_t ret = -1; - bool whileRun = true; - char *blockWorker = NULL; - char *blockMatch = NULL; - char *blockStart = NULL; - cfile_block_return_t blockDetected = CFILE_BLOCK_DETECT_NONE; - - if (NULL == aLine || NULL == aBlockStart || NULL == aBlockEnd || NULL == aHelper) - { - perror("Null pointer"); - return -2; - } - - blockWorker = aLine; - if (depth <= *aHelper) - { - blockStart = aLine; - blockLine = true; - } - - while (whileRun && CFILE_BLOCK_DETECT_NONE <= (blockDetected = cBlockDetection(aBlockStart, aBlockEnd, blockWorker, &blockMatch, aRemove))) - { - switch (blockDetected) - { - case CFILE_BLOCK_DETECT_START: - { - // additional starts within depth are ignored if aIgnore is true - // e.g. C comments are not allowed to be nested - if (!(aIgnore && depth <= *aHelper)) - { - ++*aHelper; - if (NULL == blockStart && depth <= *aHelper) - { - blockStart = blockMatch; - } - } - else - { - printf(CPARS_WARNING_START"Nested block start \"%s\": %s", aBlockStart, aLine); - } - blockWorker = (aRemove ? blockMatch + strlen(aBlockStart) : blockMatch); - break; - } - case CFILE_BLOCK_DETECT_END: - { - if (NULL != blockStart) - { - // inline comment - if (depth < *aHelper) - { - // remove block elements within depth + n - blockMatch += (aRemove ? 0 : strlen(aBlockEnd)); - } - strlcpy(blockStart, blockMatch, strlen(blockMatch) + 1); - blockMatch = NULL; - if (depth >= *aHelper) - { - // block removed when last end is hit - blockWorker = (aRemove ? blockStart : blockStart + strlen(aBlockEnd)); - blockStart = NULL; - } - else - { - blockWorker = blockStart; - } - } - - if (depth == *aHelper) - { - blockLine = false; - } - if (0 < *aHelper) - { - --*aHelper; - } - else - { - // error closing brace without beginning - whileRun = false; - ret = -1; - } - break; - } - case CFILE_BLOCK_DETECT_NONE: - { - if (NULL != blockStart && depth <= *aHelper) - { - // lines within a block - strlcpy(blockStart, CPARS_LINE_ENDING, strlen(CPARS_LINE_ENDING) + 1); - } - whileRun = false; - if (blockLine) - { - ret = 1; - } - else - { - ret = 0; - } - break; - } - default: - { - perror("Fatal unknown case"); - whileRun = false; - ret = -1; - break; - } - } - } - - return ret; -} - -/*! - * @brief Remove comments from given line - * @param [in] *aLine terminated string - * @return see \ref cBlockRemoval() - * @retval -2 NULL pointer detected - */ -STATIC int8_t removeCcomments(char *aLine) -{ - char *comment = NULL; - - if (NULL == aLine) - { - perror("Null pointer"); - return -2; - } - - // remove basic inline comments - comment = strstr(aLine, CPARS_COMMENT_INLINE); - if (NULL != comment) - { - strlcpy(comment, CPARS_LINE_ENDING, strlen(CPARS_LINE_ENDING) + 1); - comment = NULL; - } - - 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; - regmatch_t matchGroup[CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS]; - cfunction_parameter_t *tempParameter = NULL; - - if (NULL == aParameter || NULL == aFunction) - { - return -1; - } - prepareFunctionPointer(aParameter); - token = strtok(aParameter, ","); - while (token) - { - if (0 == regexec(®XfunctionPointer, token, CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS, matchGroup, 0)) - { - // TODO only "1 dimensional" function pointer supported (e.g. void (**func)(void) NOT SUPPORTED) - (void) revertFunctionPointer(token); - - tempParameter = cfunction_newParameter(&aFunction->parameter); - tempParameter->type = CPARAMETER_TYPE_FUNCPTR; - - 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, 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)); - } - } - } - else if (0 == strncmp(token, CPARS_STRCMP_PARAMETER_VARIABLE, sizeof(CPARS_STRCMP_PARAMETER_VARIABLE))) - { - tempParameter = cfunction_newParameter (&aFunction->parameter); - tempParameter->type = CPARAMETER_TYPE_VARIABLE; - xmallocStrlcpy(&tempParameter->name, CPARS_STRCMP_PARAMETER_VARIABLE, sizeof(CPARS_STRCMP_PARAMETER_VARIABLE)); - } - token = strtok(NULL, ","); - } - return 0; -} - -STATIC int8_t cfile_parser_evaluateExpression(char *aExpression, cfile_t *aCfile) -{ - uint16_t tempInt16 = 0; - char *tempChar = NULL; - cfile_variable_t *variable = NULL; - cfunction_t *function = NULL; - regmatch_t matchGroup[CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS]; - - if (NULL == aExpression || NULL == aCfile) - { - return -1; - } - - if (0 == regexec(®Xfunction, aExpression, CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS, matchGroup, - REG_NOTEOL) && CFILE_PARSER_IS_MATCHGROUP_FUNCTION(matchGroup)) - { - printMatchGroup(aExpression, matchGroup); - function = cfunction_addNewFunction(&aCfile->functions); - (void) matchPrefix(function, CELEMENT_TYPE_FUNCTION, &aExpression[matchGroup[1].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 1)); - checkFunctionType(function, aExpression); - xmallocStrlcpy(&function->name, &aExpression[matchGroup[2].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 2)); - if (XREGEX_IS_MATCHGROUP(matchGroup, 3)) - { - xmallocStrlcat(&tempChar, &aExpression[matchGroup[3].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 3)); - if (NULL != tempChar) - { - evaluateParameter(tempChar, function); - } - xfree((void**) &tempChar); - } - } - else if (0 == regexec(®Xvariable, aExpression, CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS, matchGroup, - REG_NOTEOL) && XREGEX_IS_MATCHGROUP(matchGroup, 1)) - { - printMatchGroup(aExpression, matchGroup); - variable = cfile_newVariable(&aCfile->variables); - if (variable) - { - (void) matchPrefix(variable, CELEMENT_TYPE_VARIABLE, &aExpression[matchGroup[1].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 1)); - xmallocStrlcpy(&variable->name, &aExpression[matchGroup[2].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 2)); - - // group 3 contains array information, if available - if (XREGEX_IS_MATCHGROUP(matchGroup, 3)) - { - xmallocStrlcpy(&tempChar, &aExpression[matchGroup[3].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 3)); - if (NULL != tempChar) - { - xStringTrim(tempChar, strlen(tempChar)); - } - - if (2 == strlen(tempChar) - xStrCount(tempChar, ' ')) - { - // array without size definition - xmallocStrlcat(&variable->dataType, "*", 1); - } - else - { - xmallocStrlcpy(&variable->array, tempChar, strlen(tempChar)); - } - xfree((void**) &tempChar); - } - - // would contain more variables separated by ',' - if (XREGEX_IS_MATCHGROUP(matchGroup, 4)) - { - if (NULL != (tempChar = strstr(&aExpression[matchGroup[4].rm_so], ","))) - { - // remove leading , - tempInt16 = tempChar - &aExpression[matchGroup[4].rm_so]; - matchGroup[4].rm_so += tempInt16 + 1; - tempChar = NULL; - - DEBUG_LOG_APPEND(1, "Variable list: %s\n", &aExpression[matchGroup[4].rm_so]); - xmallocStrlcpy(&tempChar, aCfile->variables.head->dataType, strlen(aCfile->variables.head->dataType)); - xmallocStrlcat(&tempChar, &aExpression[matchGroup[4].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 4) + 1); - DEBUG_LOG_APPEND(1, "Result: %s\n", tempChar); - - cfile_parser_evaluateExpression(tempChar, aCfile); - } - } - xfree((void**) &tempChar); - } - } - else if (0 == regexec(®XfunctionPointer, aExpression, CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS, matchGroup, 0) // - && XREGEX_IS_MATCHGROUP(matchGroup, 1) // - && XREGEX_IS_MATCHGROUP(matchGroup, 2) // - && XREGEX_IS_MATCHGROUP(matchGroup, 3)) - { - // TODO only "1 dimensional" function pointer supported (e.g. void (**func)(void) NOT SUPPORTED) - printMatchGroup(aExpression, matchGroup); - variable = cfile_newVariable(&aCfile->variables); - if (variable) - { - (void) matchPrefix(variable, CELEMENT_TYPE_VARIABLE, &aExpression[matchGroup[1].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 1)); - CVARIABLE_SET_TYPE(variable->type, CVARIABLE_TYPE_FUPTR); - xmallocStrlcpy(&variable->name, &aExpression[matchGroup[2].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 2)); - // contains array information if available "[10]" - if (XREGEX_IS_MATCHGROUP(matchGroup, 3)) - { - xmallocStrlcpy(&variable->array, &aExpression[matchGroup[3].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 3)); - } - } - } - - return 0; -} - -STATIC uint32_t cfile_parser_evaluateLine(uint32_t aNumber, char *aLine, cfile_t *aCfile) -{ - char *position = aLine; - uint32_t warnings = 0; - static char *match = NULL; - static uint8_t depth = 0; - char *tempMatch = NULL; - char *tempChar = NULL; - int8_t ret = 0; - - regex_t *matchStart = ®XExpressionStart; - regex_t *matchEnd = ®XExpressionEnd; - - ret = removeCcomments(aLine); - if (-1 == ret) - { - ++warnings; - } - else if (0 != ret) - { - return 0; - } - ret = cBlockRemoval(aLine, "{", "}", &cfile_parser_removeBraceHelper, false, false); - if (-1 == ret) - { - ++warnings; - } - else if (0 != ret) - { - return 0; - } - DEBUG_LOG_APPEND(2, "[ Li %04u] %s\n", aNumber, aLine); - tempChar = strrchr(aLine, '\n'); - if (tempChar) - { - *tempChar = '\0'; - } - tempChar = strrchr(aLine, '\r'); - if (tempChar) - { - *tempChar = '\0'; - } - - while (position) - { - if (NULL != (tempMatch = strstr(position, "#include"))) - { - // TODO save include information - DEBUG_LOG_APPEND(1, "[ Re %04u][%zu] %s\n", aNumber, strlen(tempMatch), tempMatch); - position = NULL; - continue; - } - warnings += regExWorker(&match, &position, matchStart, matchEnd, &depth, false); - if (match && 0 == depth) - { - DEBUG_LOG_APPEND(1, "[ Re %04u][%zu] %s\n", aNumber, strlen(match), match); - // Evaluate C expression - (void) cfile_parser_evaluateExpression(match, aCfile); - xfree((void**) &match); - } - } - return warnings; -} - -uint32_t cfile_parser(char *aPath, cfile_t *aCfile) -{ - FILE *fdesc; - ssize_t charRead = 0; - size_t lineSize = 0; - uint32_t lineNumber = 0; - char *fileLine = NULL; // will be allocated by getline(); must be freed - uint32_t warningCounter = 0; - - if (false == cfile_parser_initialized) - { - cfile_parser_init(); - } - - fdesc = fopen(aPath, "r"); - if (NULL == fdesc) - { - perror("Error open file"); - return -1; - } - - do - { - charRead = getline(&fileLine, &lineSize, fdesc); - if (0 <= charRead) - { - lineNumber++; - warningCounter += cfile_parser_evaluateLine(lineNumber, fileLine, aCfile); - } - } while (0 <= charRead); - - free(fileLine); - (void) fclose(fdesc); - -// error detection for block removal - if (0 != cfile_parser_removeCommentHelper || 0 != cfile_parser_removeBraceHelper) - { - DEBUG_LOG_APPEND(1, "Helper (%d/%d) %s\n", cfile_parser_removeCommentHelper, cfile_parser_removeBraceHelper, gnu_basename(aPath)); - cfile_parser_removeCommentHelper = 0; - cfile_parser_removeBraceHelper = 0; - ++warningCounter; - } - -// if (warningCounter) -// { -// ret = -4; -// } - - return warningCounter; -} +/*! + * @file cfile_parser.c + * @brief + * @details + * Project: \n + * Subsystem: \n + * Module: \n + * Code: GNU-C\n + * + * @date 28.02.2017 + * @author Martin Winkler + */ +#include +#include +#include +#include "xregex.h" +#include "xtypes.h" +#include "xstring.h" +#include "xmalloc.h" +#include "cfile_if.h" +#include "cfile_parser_if.h" +#include "cfile_parser_loc.h" +#include "cfile_parser_worker_loc.h" +#include "debug.h" + +/*! @brief Block detection return values */ +typedef enum _CFILE_BLOCK_RETURN_T +{ + CFILE_BLOCK_DETECT_ERROR = -1, /*!< @brief description */ + CFILE_BLOCK_DETECT_NONE = 0, /*!< @brief description */ + CFILE_BLOCK_DETECT_START = 1, /*!< @brief description */ + CFILE_BLOCK_DETECT_END = 2, /*!< @brief description */ +} cfile_block_return_t; + +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; +STATIC regex_t regXExpressionEnd; + +// line evaluation related variables +STATIC uint32_t cfile_parser_removeCommentHelper = 0; +STATIC uint32_t cfile_parser_removeBraceHelper = 0; + +int8_t cfile_parser_init() +{ + if (0 > regcomp(®XExpressionStart, CPARS_EXPRESSION_START, (REG_EXTENDED | REG_NEWLINE))) + { + perror("Error regex\n"); + return -1; + } + if (0 > regcomp(®XExpressionEnd, CPARS_EXPRESSION_END, (REG_EXTENDED | REG_NEWLINE))) + { + perror("Error regex\n"); + return -1; + } + if (0 > regcomp(®Xfunction, CPARS_REGEX_FUNCTION, (REG_EXTENDED | REG_NEWLINE))) + { + perror("Error regex\n"); + return -1; + } + if (0 > regcomp(®Xprefix, CPARS_REGEX_PREFIX, (REG_EXTENDED))) + { + perror("Error regex\n"); + return -1; + } + if (0 > regcomp(®Xparameter, CPARS_REGEX_PARAMETER, (REG_EXTENDED))) + { + 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_FUNCTIONPOINTER, (REG_EXTENDED))) + { + perror("Error regex\n"); + return -1; + } + if (0 > regcomp(®Xvariable, CPARS_REGEX_VARIABLE, (REG_EXTENDED | REG_NEWLINE))) + { + perror("Error regex\n"); + return -1; + } + + cfile_parser_initialized = true; + return 0; +} + +#if isDebugLevel(1) +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) + { + DEBUG_LOG_APPEND(1, "[%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)); + DEBUG_LOG_APPEND(1, "%s", match); + DEBUG_LOG_APPEND(1, "\n"); + } + } +} +#else +#define printMatchGroup(aString, aMatchgroup) do { /*nothing*/ } while(0) +#endif + +STATIC void checkFunctionType(cfunction_t *aFunction, char *aExpression) +{ + char *tempChar = NULL; + + if (NULL == aFunction || NULL == aExpression) + { + return; + } + + aFunction->type = CFUNCTION_TYPE_REGULAR; + + tempChar = strrchr(aExpression, CPARS_PROTOTYPE_END_C); + if (tempChar) + { + aFunction->type = CFUNCTION_TYPE_PROTO; + } + + if (NULL == aFunction->prefix) + { + return; + } + if (NULL != strstr(aFunction->prefix, CPARS_PREFIX_EXTERN_S)) + { + aFunction->type = CFUNCTION_TYPE_EXTERN; + } + else if ((NULL != strstr(aFunction->prefix, CPARS_PREFIX_STATIC_S) || NULL != strstr(aFunction->prefix, CPARS_PREFIX_STATIC2_S)) + && CFUNCTION_TYPE_PROTO != aFunction->type) + { + aFunction->type = CFUNCTION_TYPE_STATIC; + } +} + +/*! + * @brief Extract C expression prefix and data type and removing trailing blanks + * @param [out] *aElement Pointer to C element structure + * @param [in] aElementType C element type (CELEMENT_TYPE_VARIABLE, CELEMENT_TYPE_FUNCTION supported) + * @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 matchPrefix(void *aElement, celement_type_t aElementType, char *aString, size_t aSize) +{ + regmatch_t matchGroup[CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS]; + char *temp = NULL; + char *end = NULL; + char **prefix = NULL; + char **type = NULL; + + if (NULL == aElement || NULL == aString || 0 == aSize) + { + return -1; + } + + switch (aElementType) + { + case CELEMENT_TYPE_VARIABLE: + { + prefix = &((cfile_variable_t*) aElement)->prefix; + type = &((cfile_variable_t*) aElement)->dataType; + break; + } + case CELEMENT_TYPE_FUNCTION: + { + prefix = &((cfunction_t*) aElement)->prefix; + type = &((cfunction_t*) aElement)->dataType; + break; + } + default: + { + 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 (CELEMENT_TYPE_VARIABLE == aElementType) + { + ((cfile_variable_t*) aElement)->type = CVARIABLE_TYPE_REGULAR; + } + + if (0 == regexec(®Xprefix, temp, CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS, matchGroup, 0)) + { + if (XREGEX_IS_MATCHGROUP(matchGroup, 1)) + { + xmallocStrlcpy(prefix, &temp[matchGroup[1].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 1)); + if (CELEMENT_TYPE_VARIABLE == aElementType) + { + if (*prefix && NULL != strstr(*prefix, CPARS_PREFIX_EXTERN_S)) + { + ((cfile_variable_t*) aElement)->type = CVARIABLE_TYPE_EXTERN; + } + else if (*prefix && (NULL != strstr(*prefix, CPARS_PREFIX_STATIC_S) || NULL != strstr(*prefix, CPARS_PREFIX_STATIC2_S))) + { + ((cfile_variable_t*) aElement)->type = CVARIABLE_TYPE_STATIC; + } + } + } + if (XREGEX_IS_MATCHGROUP(matchGroup, 2)) + { + xmallocStrlcpy(type, &temp[matchGroup[2].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 2)); + } + } + else + { + xmallocStrlcpy(type, temp, strlen(temp)); + } + + if (CELEMENT_TYPE_VARIABLE == aElementType) + { + if (*type && NULL != strstr(*type, CPARS_ELEMENT_CONST)) + { + CVARIABLE_SET_TYPE(((cfile_variable_t* ) aElement)->type, CVARIABLE_TYPE_CONST); + } + } + + free(temp); + return 0; +} + +/*! + * @brief Find first given "start" or "end" string and return position + * @param [in] *aBlockStart Terminated string defining the start of a block + * @param [in] *aBlockEnd Terminated string defining the end of a block + * @param [in] *aLine Terminated line (e.g. read from a file getline()) + * @param [out] **aPosition Pointing to found block string (related to \ref aRemove) / NULL for CFILE_BLOCK_DETECT_NONE or CFILE_BLOCK_DETECT_ERROR + * @param [in] aRemove false - remove only content of block; true - also remove block strings + * @return cfile_block_return_t + * @retval CFILE_BLOCK_DETECT_START Start found + * @retval CFILE_BLOCK_DETECT_END End found + * @retval CFILE_BLOCK_DETECT_NONE No start or end found + * @retval CFILE_BLOCK_DETECT_ERROR Null pointer detected + */ +STATIC cfile_block_return_t cBlockDetection(const char *aBlockStart, const char *aBlockEnd, char *aLine, char **aPosition, bool aRemove) +{ + char *blockStart = NULL; + char *blockEnd = NULL; + cfile_block_return_t ret = CFILE_BLOCK_DETECT_NONE; + + if ( NULL == aBlockStart || NULL == aBlockEnd || NULL == aLine || NULL == aPosition) + { + perror("Null pointer"); + return CFILE_BLOCK_DETECT_ERROR; + } + + blockStart = strstr(aLine, aBlockStart); + blockEnd = strstr(aLine, aBlockEnd); + + if (NULL == blockStart && NULL == blockEnd) + { + // no block element + ret = CFILE_BLOCK_DETECT_NONE; + } + else if (NULL == blockStart) + { + // last line of block + ret = CFILE_BLOCK_DETECT_END; + } + else if (NULL == blockEnd) + { + // first line of block + + ret = CFILE_BLOCK_DETECT_START; + } + else if (blockStart < blockEnd) + { + // inline block + ret = CFILE_BLOCK_DETECT_START; + } + else + { + // last line of multi line block with further blocks in line + ret = CFILE_BLOCK_DETECT_END; + } + + switch (ret) + { + case CFILE_BLOCK_DETECT_START: + { + *aPosition = (aRemove ? blockStart : blockStart + strlen(aBlockStart)); + break; + } + case CFILE_BLOCK_DETECT_END: + { + *aPosition = (aRemove ? blockEnd + strlen(aBlockEnd) : blockEnd); + break; + } + case CFILE_BLOCK_DETECT_NONE: + { + *aPosition = NULL; + break; + } + default: + { + ret = CFILE_BLOCK_DETECT_ERROR; + *aPosition = NULL; + break; + } + } + + return ret; +} + +/*! + * @brief Remove blocks defined by "start" and "end" + * @attention May be called multiple time (for a whole file). *aHelper must not be changed within the process. + * @param [in] *aLine Terminated line (e.g. read from a file getline()) + * @param [in] *aBlockStart Terminated string defining the start of a block + * @param [in] *aBlockEnd Terminated string defining the end of a block + * @param [in,out] *aHelper Storage for block traversal + * @param [in] aRemove false - remove only content of block; true - also remove block strings + * @retval 0 Blocks removed or none found + * @retval 1 Line only within block + * @retval -1 Invalid block ending ("end" without corresponding "start") + * @retval -2 Null pointer detected + */ +STATIC int8_t cBlockRemoval(char *aLine, const char *aBlockStart, const char *aBlockEnd, uint32_t *aHelper, bool aRemove, bool aIgnore) +{ + const uint8_t depth = 1; // preparation to support which depth should be removed for nested block + bool blockLine = false; + int8_t ret = -1; + bool whileRun = true; + char *blockWorker = NULL; + char *blockMatch = NULL; + char *blockStart = NULL; + cfile_block_return_t blockDetected = CFILE_BLOCK_DETECT_NONE; + + if (NULL == aLine || NULL == aBlockStart || NULL == aBlockEnd || NULL == aHelper) + { + perror("Null pointer"); + return -2; + } + + blockWorker = aLine; + if (depth <= *aHelper) + { + blockStart = aLine; + blockLine = true; + } + + while (whileRun && CFILE_BLOCK_DETECT_NONE <= (blockDetected = cBlockDetection(aBlockStart, aBlockEnd, blockWorker, &blockMatch, aRemove))) + { + switch (blockDetected) + { + case CFILE_BLOCK_DETECT_START: + { + // additional starts within depth are ignored if aIgnore is true + // e.g. C comments are not allowed to be nested + if (!(aIgnore && depth <= *aHelper)) + { + ++*aHelper; + if (NULL == blockStart && depth <= *aHelper) + { + blockStart = blockMatch; + } + } + else + { + printf(CPARS_WARNING_START"Nested block start \"%s\": %s", aBlockStart, aLine); + } + blockWorker = (aRemove ? blockMatch + strlen(aBlockStart) : blockMatch); + break; + } + case CFILE_BLOCK_DETECT_END: + { + if (NULL != blockStart) + { + // inline comment + if (depth < *aHelper) + { + // remove block elements within depth + n + blockMatch += (aRemove ? 0 : strlen(aBlockEnd)); + } + strlcpy(blockStart, blockMatch, strlen(blockMatch) + 1); + blockMatch = NULL; + if (depth >= *aHelper) + { + // block removed when last end is hit + blockWorker = (aRemove ? blockStart : blockStart + strlen(aBlockEnd)); + blockStart = NULL; + } + else + { + blockWorker = blockStart; + } + } + + if (depth == *aHelper) + { + blockLine = false; + } + if (0 < *aHelper) + { + --*aHelper; + } + else + { + // error closing brace without beginning + whileRun = false; + ret = -1; + } + break; + } + case CFILE_BLOCK_DETECT_NONE: + { + if (NULL != blockStart && depth <= *aHelper) + { + // lines within a block + strlcpy(blockStart, CPARS_LINE_ENDING, strlen(CPARS_LINE_ENDING) + 1); + } + whileRun = false; + if (blockLine) + { + ret = 1; + } + else + { + ret = 0; + } + break; + } + default: + { + perror("Fatal unknown case"); + whileRun = false; + ret = -1; + break; + } + } + } + + return ret; +} + +/*! + * @brief Remove comments from given line + * @param [in] *aLine terminated string + * @return see \ref cBlockRemoval() + * @retval -2 NULL pointer detected + */ +STATIC int8_t removeCcomments(char *aLine) +{ + char *comment = NULL; + + if (NULL == aLine) + { + perror("Null pointer"); + return -2; + } + + // remove basic inline comments + comment = strstr(aLine, CPARS_COMMENT_INLINE); + if (NULL != comment) + { + strlcpy(comment, CPARS_LINE_ENDING, strlen(CPARS_LINE_ENDING) + 1); + comment = NULL; + } + + 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; + regmatch_t matchGroup[CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS]; + cfunction_parameter_t *tempParameter = NULL; + + if (NULL == aParameter || NULL == aFunction) + { + return -1; + } + prepareFunctionPointer(aParameter); + token = strtok(aParameter, ","); + while (token) + { + if (0 == regexec(®XfunctionPointer, token, CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS, matchGroup, 0)) + { + // TODO only "1 dimensional" function pointer supported (e.g. void (**func)(void) NOT SUPPORTED) + (void) revertFunctionPointer(token); + + tempParameter = cfunction_newParameter(&aFunction->parameter); + tempParameter->type = CPARAMETER_TYPE_FUNCPTR; + + 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, 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)); + } + } + } + else if (0 == strncmp(token, CPARS_STRCMP_PARAMETER_VARIABLE, sizeof(CPARS_STRCMP_PARAMETER_VARIABLE))) + { + tempParameter = cfunction_newParameter (&aFunction->parameter); + tempParameter->type = CPARAMETER_TYPE_VARIABLE; + xmallocStrlcpy(&tempParameter->name, CPARS_STRCMP_PARAMETER_VARIABLE, sizeof(CPARS_STRCMP_PARAMETER_VARIABLE)); + } + token = strtok(NULL, ","); + } + return 0; +} + +STATIC int8_t cfile_parser_evaluateExpression(char *aExpression, cfile_t *aCfile) +{ + uint16_t tempInt16 = 0; + char *tempChar = NULL; + cfile_variable_t *variable = NULL; + cfunction_t *function = NULL; + regmatch_t matchGroup[CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS]; + + if (NULL == aExpression || NULL == aCfile) + { + return -1; + } + + if (0 == regexec(®Xfunction, aExpression, CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS, matchGroup, + REG_NOTEOL) && CFILE_PARSER_IS_MATCHGROUP_FUNCTION(matchGroup)) + { + printMatchGroup(aExpression, matchGroup); + function = cfunction_addNewFunction(&aCfile->functions); + (void) matchPrefix(function, CELEMENT_TYPE_FUNCTION, &aExpression[matchGroup[1].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 1)); + checkFunctionType(function, aExpression); + xmallocStrlcpy(&function->name, &aExpression[matchGroup[2].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 2)); + if (XREGEX_IS_MATCHGROUP(matchGroup, 3)) + { + xmallocStrlcat(&tempChar, &aExpression[matchGroup[3].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 3)); + if (NULL != tempChar) + { + evaluateParameter(tempChar, function); + } + xfree((void**) &tempChar); + } + } + else if (0 == regexec(®Xvariable, aExpression, CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS, matchGroup, + REG_NOTEOL) && XREGEX_IS_MATCHGROUP(matchGroup, 1)) + { + printMatchGroup(aExpression, matchGroup); + variable = cfile_newVariable(&aCfile->variables); + if (variable) + { + (void) matchPrefix(variable, CELEMENT_TYPE_VARIABLE, &aExpression[matchGroup[1].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 1)); + xmallocStrlcpy(&variable->name, &aExpression[matchGroup[2].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 2)); + + // group 3 contains array information, if available + if (XREGEX_IS_MATCHGROUP(matchGroup, 3)) + { + xmallocStrlcpy(&tempChar, &aExpression[matchGroup[3].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 3)); + if (NULL != tempChar) + { + xStringTrim(tempChar, strlen(tempChar)); + } + + if (2 == strlen(tempChar) - xStrCount(tempChar, ' ')) + { + // array without size definition + xmallocStrlcat(&variable->dataType, "*", 1); + } + else + { + xmallocStrlcpy(&variable->array, tempChar, strlen(tempChar)); + } + xfree((void**) &tempChar); + } + + // would contain more variables separated by ',' + if (XREGEX_IS_MATCHGROUP(matchGroup, 4)) + { + if (NULL != (tempChar = strstr(&aExpression[matchGroup[4].rm_so], ","))) + { + // remove leading , + tempInt16 = tempChar - &aExpression[matchGroup[4].rm_so]; + matchGroup[4].rm_so += tempInt16 + 1; + tempChar = NULL; + + DEBUG_LOG_APPEND(1, "Variable list: %s\n", &aExpression[matchGroup[4].rm_so]); + xmallocStrlcpy(&tempChar, aCfile->variables.head->dataType, strlen(aCfile->variables.head->dataType)); + xmallocStrlcat(&tempChar, &aExpression[matchGroup[4].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 4) + 1); + DEBUG_LOG_APPEND(1, "Result: %s\n", tempChar); + + cfile_parser_evaluateExpression(tempChar, aCfile); + } + } + xfree((void**) &tempChar); + } + } + else if (0 == regexec(®XfunctionPointer, aExpression, CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS, matchGroup, 0) // + && XREGEX_IS_MATCHGROUP(matchGroup, 1) // + && XREGEX_IS_MATCHGROUP(matchGroup, 2) // + && XREGEX_IS_MATCHGROUP(matchGroup, 3)) + { + // TODO only "1 dimensional" function pointer supported (e.g. void (**func)(void) NOT SUPPORTED) + printMatchGroup(aExpression, matchGroup); + variable = cfile_newVariable(&aCfile->variables); + if (variable) + { + (void) matchPrefix(variable, CELEMENT_TYPE_VARIABLE, &aExpression[matchGroup[1].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 1)); + CVARIABLE_SET_TYPE(variable->type, CVARIABLE_TYPE_FUPTR); + xmallocStrlcpy(&variable->name, &aExpression[matchGroup[2].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 2)); + // contains array information if available "[10]" + if (XREGEX_IS_MATCHGROUP(matchGroup, 3)) + { + xmallocStrlcpy(&variable->array, &aExpression[matchGroup[3].rm_so], XREGEX_SIZEOF_MATCHGROUP(matchGroup, 3)); + } + } + } + + return 0; +} + +STATIC uint32_t cfile_parser_evaluateLine(uint32_t aNumber, char *aLine, cfile_t *aCfile) +{ + char *position = aLine; + uint32_t warnings = 0; + static char *match = NULL; + static uint8_t depth = 0; + char *tempMatch = NULL; + char *tempChar = NULL; + int8_t ret = 0; + + regex_t *matchStart = ®XExpressionStart; + regex_t *matchEnd = ®XExpressionEnd; + + ret = removeCcomments(aLine); + if (-1 == ret) + { + ++warnings; + } + else if (0 != ret) + { + return 0; + } + ret = cBlockRemoval(aLine, "{", "}", &cfile_parser_removeBraceHelper, false, false); + if (-1 == ret) + { + ++warnings; + } + else if (0 != ret) + { + return 0; + } + DEBUG_LOG_APPEND(2, "[ Li %04u] %s\n", aNumber, aLine); + tempChar = strrchr(aLine, '\n'); + if (tempChar) + { + *tempChar = '\0'; + } + tempChar = strrchr(aLine, '\r'); + if (tempChar) + { + *tempChar = '\0'; + } + + while (position) + { + if (NULL != (tempMatch = strstr(position, "#include"))) + { + // TODO save include information + DEBUG_LOG_APPEND(1, "[ Re %04u][%zu] %s\n", aNumber, strlen(tempMatch), tempMatch); + position = NULL; + continue; + } + warnings += regExWorker(&match, &position, matchStart, matchEnd, &depth, false); + if (match && 0 == depth) + { + DEBUG_LOG_APPEND(1, "[ Re %04u][%zu] %s\n", aNumber, strlen(match), match); + // Evaluate C expression + (void) cfile_parser_evaluateExpression(match, aCfile); + xfree((void**) &match); + } + } + return warnings; +} + +uint32_t cfile_parser(char *aPath, cfile_t *aCfile) +{ + FILE *fdesc; + ssize_t charRead = 0; + size_t lineSize = 0; + uint32_t lineNumber = 0; + char *fileLine = NULL; // will be allocated by getline(); must be freed + uint32_t warningCounter = 0; + + if (false == cfile_parser_initialized) + { + cfile_parser_init(); + } + + fdesc = fopen(aPath, "r"); + if (NULL == fdesc) + { + perror("Error open file"); + return -1; + } + + do + { + charRead = getline(&fileLine, &lineSize, fdesc); + if (0 <= charRead) + { + lineNumber++; + warningCounter += cfile_parser_evaluateLine(lineNumber, fileLine, aCfile); + } + } while (0 <= charRead); + + free(fileLine); + (void) fclose(fdesc); + +// error detection for block removal + if (0 != cfile_parser_removeCommentHelper || 0 != cfile_parser_removeBraceHelper) + { + DEBUG_LOG_APPEND(1, "Helper (%d/%d) %s\n", cfile_parser_removeCommentHelper, cfile_parser_removeBraceHelper, gnu_basename(aPath)); + cfile_parser_removeCommentHelper = 0; + cfile_parser_removeBraceHelper = 0; + ++warningCounter; + } + +// if (warningCounter) +// { +// ret = -4; +// } + + return warningCounter; +} diff --git a/src/stubser/cfile_parser_if.h b/src/stubser/cfile_parser_if.h index d092ebf..85860f9 100644 --- a/src/stubser/cfile_parser_if.h +++ b/src/stubser/cfile_parser_if.h @@ -1,21 +1,21 @@ -/*! - * @file cfile_parser_if.h - * @brief - * @details - * Project: \n - * Subsystem: \n - * Module: \n - * Code: GNU-C\n - * - * @date 28.02.2017 - * @author Martin Winkler - */ - -#ifndef STUBSER_CFILE_PARSER_IF_H_ -#define STUBSER_CFILE_PARSER_IF_H_ - -#define CPARS_ELEMENT_CONST "const" - -uint32_t cfile_parser(char *aPath, cfile_t *aList); - -#endif /* STUBSER_CFILE_PARSER_IF_H_ */ +/*! + * @file cfile_parser_if.h + * @brief + * @details + * Project: \n + * Subsystem: \n + * Module: \n + * Code: GNU-C\n + * + * @date 28.02.2017 + * @author Martin Winkler + */ + +#ifndef STUBSER_CFILE_PARSER_IF_H_ +#define STUBSER_CFILE_PARSER_IF_H_ + +#define CPARS_ELEMENT_CONST "const" + +uint32_t cfile_parser(char *aPath, cfile_t *aList); + +#endif /* STUBSER_CFILE_PARSER_IF_H_ */ diff --git a/src/stubser/cfile_parser_loc.h b/src/stubser/cfile_parser_loc.h index eb0cdab..29fe9d6 100644 --- a/src/stubser/cfile_parser_loc.h +++ b/src/stubser/cfile_parser_loc.h @@ -1,57 +1,57 @@ -/*! - * @file cfile_parser_loc.h - * @brief - * @details - * Project: \n - * Subsystem: \n - * Module: \n - * Code: GNU-C\n - * - * @date 28.02.2017 - * @author Martin Winkler - */ -#ifndef STUBSER_CFILE_PARSER_LOC_H_ -#define STUBSER_CFILE_PARSER_LOC_H_ - -#define CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS 10 - -#define CPARS_LINE_ENDING "\r\n" -#define CPARS_COMMENT_INLINE "//" -#define CPARS_COMMENT_BLOCK_START "/*" -#define CPARS_COMMENT_BLOCK_END "*/" - -#define CPARS_PROTOTYPE_END_C ';' -#define CPARS_PREFIX_STATIC_S "static" -#define CPARS_PREFIX_STATIC2_S "STATIC" -#define CPARS_PREFIX_EXTERN_S "extern" - -#define CPARS_EXPRESSION_BASE "^[[:blank:]]*([ _\\*[:alnum:]]*[[:blank:]]+\\**)([_\\*[:alnum:]]+)" -#define CPARS_REGEX_FUNCTIONPOINTER "^[[:blank:]]*([ _\\*[:alnum:]]* +\\**)\\(([_\\*[:alnum:]]+)\\)(\\([^\\)]*\\))" - -#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 CPARS_EXPRESSION_BASE "[[:blank:]]*(\\[*[^;=]*)" -#define CPARS_STRCMP_PARAMETER_VARIABLE "..." -#define CPARS_REGEX_PARAMETER_FUPTR_SEPA "\\([^\\,)]*(,)" // function pointer parameter separation -#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_END "[[:blank:]]*([\\};]+)" - -#define CPARS_WARNING_START " W-> " - -#define CFILE_PARSER_IS_MATCHGROUP_FUNCTION(matchGroup) (XREGEX_IS_MATCHGROUP(matchGroup, 1) && XREGEX_IS_MATCHGROUP(matchGroup, 2)) - -/*! @brief Type of function definition */ -typedef enum _CELEMENT_TYPE_T -{ - CELEMENT_TYPE_UNDEF = 0, /*!< @brief undefined */ - CELEMENT_TYPE_INCLUDE = 1, /*!< @brief C #include */ - CELEMENT_TYPE_DEFINE = 2, /*!< @brief C #define */ - CELEMENT_TYPE_VARIABLE = 3, /*!< @brief Prototype C variable definition */ - CELEMENT_TYPE_FUNCTION = 4, /*!< @brief Prototype C function definition */ - CELEMENT_TYPE_LAST_ENUM -} celement_type_t; - -#endif /* STUBSER_CFILE_PARSER_LOC_H_ */ +/*! + * @file cfile_parser_loc.h + * @brief + * @details + * Project: \n + * Subsystem: \n + * Module: \n + * Code: GNU-C\n + * + * @date 28.02.2017 + * @author Martin Winkler + */ +#ifndef STUBSER_CFILE_PARSER_LOC_H_ +#define STUBSER_CFILE_PARSER_LOC_H_ + +#define CFILE_PARSER_MAX_REGEX_MATCHING_GROUPS 10 + +#define CPARS_LINE_ENDING "\r\n" +#define CPARS_COMMENT_INLINE "//" +#define CPARS_COMMENT_BLOCK_START "/*" +#define CPARS_COMMENT_BLOCK_END "*/" + +#define CPARS_PROTOTYPE_END_C ';' +#define CPARS_PREFIX_STATIC_S "static" +#define CPARS_PREFIX_STATIC2_S "STATIC" +#define CPARS_PREFIX_EXTERN_S "extern" + +#define CPARS_EXPRESSION_BASE "^[[:blank:]]*([ _\\*[:alnum:]]*[[:blank:]]+\\**)([_\\*[:alnum:]]+)" +#define CPARS_REGEX_FUNCTIONPOINTER "^[[:blank:]]*([ _\\*[:alnum:]]* +\\**)\\(([_\\*[:alnum:]]+)\\)(\\([^\\)]*\\))" + +#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 CPARS_EXPRESSION_BASE "[[:blank:]]*(\\[*[^;=]*)" +#define CPARS_STRCMP_PARAMETER_VARIABLE "..." +#define CPARS_REGEX_PARAMETER_FUPTR_SEPA "\\([^\\,)]*(,)" // function pointer parameter separation +#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_END "[[:blank:]]*([\\};]+)" + +#define CPARS_WARNING_START " W-> " + +#define CFILE_PARSER_IS_MATCHGROUP_FUNCTION(matchGroup) (XREGEX_IS_MATCHGROUP(matchGroup, 1) && XREGEX_IS_MATCHGROUP(matchGroup, 2)) + +/*! @brief Type of function definition */ +typedef enum _CELEMENT_TYPE_T +{ + CELEMENT_TYPE_UNDEF = 0, /*!< @brief undefined */ + CELEMENT_TYPE_INCLUDE = 1, /*!< @brief C #include */ + CELEMENT_TYPE_DEFINE = 2, /*!< @brief C #define */ + CELEMENT_TYPE_VARIABLE = 3, /*!< @brief Prototype C variable definition */ + CELEMENT_TYPE_FUNCTION = 4, /*!< @brief Prototype C function definition */ + CELEMENT_TYPE_LAST_ENUM +} celement_type_t; + +#endif /* STUBSER_CFILE_PARSER_LOC_H_ */ diff --git a/src/stubser/cfile_parser_worker.c b/src/stubser/cfile_parser_worker.c index f92917b..a54f684 100644 --- a/src/stubser/cfile_parser_worker.c +++ b/src/stubser/cfile_parser_worker.c @@ -1,152 +1,152 @@ -/*! - * @file cfile_parser_worker.c - * @brief - * @details - * Project: \n - * Subsystem: \n - * Module: \n - * Code: GNU-C\n - * - * @date 09.03.2017 - * @author Martin Winkler - */ - -#include "xtypes.h" -#include "xregex.h" -#include "xmalloc.h" -#include "debug.h" -#include "cfile_parser_loc.h" -#include "cfile_parser_worker_loc.h" - -/*! - * @brief String block detection using regular expressions - * @attention Recursive function (calls itself to find block end on same line) - * @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) - * @param [in] *aStart Regular expression defining block start - * @param [in] *aEnd Regular expression defining block end - * @param [out] *aBlockDepth Current depth of parsing - * @param [in] aMultiLevel false - starts within block are ignored - * @return Matched string and various information about the parsing - * @retval uint32_t amount of warnings during parser run - * - * @details - * - Parsing done when (match && 0 == aBlockDepth) - * - Orphan end markers are ignored and skipped. - */ -uint32_t regExWorker(char **aOutput, char **aInput, const regex_t *aStart, const regex_t *aEnd, uint8_t *aBlockDepth, bool aMultiLevel) -{ - uint32_t warningCounter = 0; - regmatch_t matchStart[2]; - regmatch_t matchEnd[2]; - regmatch_t *match = NULL; - char *begin = NULL; - size_t size = 0; - - if (!**aInput || NULL == *aInput) - { - if (*aBlockDepth) - { - xmallocStrlcat(aOutput, " ", 2); - } - *aInput = NULL; - goto regExWorker_end; - } - - // 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) - { - // complete line within block - *aInput += strlen(*aInput); - goto regExWorker_end; - } - } - else - { - begin = NULL; - // no findings - if (!match) - { - // skip remaining character within line without match - *aInput += strlen(*aInput); - goto regExWorker_end; - } - } - - 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 start marker in result - begin = *aInput + match[1].rm_so; // include start marker in result - *aInput += match[1].rm_eo; - } - else - { - // ignore starts within block - size = match->rm_eo; - *aInput += match->rm_eo; - } - goto regExWorker_end; - } - - if (match == matchEnd) - { - DEBUG_LOG_APPEND(2, "[ CEe]"); - //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; - if (0 < *aBlockDepth) - { - --*aBlockDepth; - } - // TODO orphan end markers - // must be evaluated depending on expression - // e.g. array[]={}; -> must have } and ; - // function{} -> must not have ; -// else -// { -// // orphan end marker -// ++warningCounter; -// } - goto regExWorker_end; - } - - regExWorker_end: - - if (begin) - { - xmallocStrlcat(aOutput, begin, size); - if (*aBlockDepth) - { - warningCounter += regExWorker(aOutput, aInput, aStart, aEnd, aBlockDepth, aMultiLevel); - } - } - - return warningCounter; -} +/*! + * @file cfile_parser_worker.c + * @brief + * @details + * Project: \n + * Subsystem: \n + * Module: \n + * Code: GNU-C\n + * + * @date 09.03.2017 + * @author Martin Winkler + */ + +#include "xtypes.h" +#include "xregex.h" +#include "xmalloc.h" +#include "debug.h" +#include "cfile_parser_loc.h" +#include "cfile_parser_worker_loc.h" + +/*! + * @brief String block detection using regular expressions + * @attention Recursive function (calls itself to find block end on same line) + * @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) + * @param [in] *aStart Regular expression defining block start + * @param [in] *aEnd Regular expression defining block end + * @param [out] *aBlockDepth Current depth of parsing + * @param [in] aMultiLevel false - starts within block are ignored + * @return Matched string and various information about the parsing + * @retval uint32_t amount of warnings during parser run + * + * @details + * - Parsing done when (match && 0 == aBlockDepth) + * - Orphan end markers are ignored and skipped. + */ +uint32_t regExWorker(char **aOutput, char **aInput, const regex_t *aStart, const regex_t *aEnd, uint8_t *aBlockDepth, bool aMultiLevel) +{ + uint32_t warningCounter = 0; + regmatch_t matchStart[2]; + regmatch_t matchEnd[2]; + regmatch_t *match = NULL; + char *begin = NULL; + size_t size = 0; + + if (!**aInput || NULL == *aInput) + { + if (*aBlockDepth) + { + xmallocStrlcat(aOutput, " ", 2); + } + *aInput = NULL; + goto regExWorker_end; + } + + // 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) + { + // complete line within block + *aInput += strlen(*aInput); + goto regExWorker_end; + } + } + else + { + begin = NULL; + // no findings + if (!match) + { + // skip remaining character within line without match + *aInput += strlen(*aInput); + goto regExWorker_end; + } + } + + 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 start marker in result + begin = *aInput + match[1].rm_so; // include start marker in result + *aInput += match[1].rm_eo; + } + else + { + // ignore starts within block + size = match->rm_eo; + *aInput += match->rm_eo; + } + goto regExWorker_end; + } + + if (match == matchEnd) + { + DEBUG_LOG_APPEND(2, "[ CEe]"); + //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; + if (0 < *aBlockDepth) + { + --*aBlockDepth; + } + // TODO orphan end markers + // must be evaluated depending on expression + // e.g. array[]={}; -> must have } and ; + // function{} -> must not have ; +// else +// { +// // orphan end marker +// ++warningCounter; +// } + goto regExWorker_end; + } + + regExWorker_end: + + if (begin) + { + xmallocStrlcat(aOutput, begin, size); + if (*aBlockDepth) + { + warningCounter += regExWorker(aOutput, aInput, aStart, aEnd, aBlockDepth, aMultiLevel); + } + } + + return warningCounter; +} diff --git a/src/stubser/cfile_parser_worker_loc.h b/src/stubser/cfile_parser_worker_loc.h index a34bf09..8f5b0f7 100644 --- a/src/stubser/cfile_parser_worker_loc.h +++ b/src/stubser/cfile_parser_worker_loc.h @@ -1,19 +1,19 @@ -/*! - * @file cfile_parser_worker_loc.h - * @brief - * @details - * Project: \n - * Subsystem: \n - * Module: \n - * Code: GNU-C\n - * - * @date 09.03.2017 - * @author Martin Winkler - */ - -#ifndef STUBSER_CFILE_PARSER_WORKER_LOC_H_ -#define STUBSER_CFILE_PARSER_WORKER_LOC_H_ - -uint32_t regExWorker(char **aOutput, char **aInput, const regex_t *aStart, const regex_t *aEnd, uint8_t *aBlockDepth, bool aMultiLevel); - -#endif /* STUBSER_CFILE_PARSER_WORKER_LOC_H_ */ +/*! + * @file cfile_parser_worker_loc.h + * @brief + * @details + * Project: \n + * Subsystem: \n + * Module: \n + * Code: GNU-C\n + * + * @date 09.03.2017 + * @author Martin Winkler + */ + +#ifndef STUBSER_CFILE_PARSER_WORKER_LOC_H_ +#define STUBSER_CFILE_PARSER_WORKER_LOC_H_ + +uint32_t regExWorker(char **aOutput, char **aInput, const regex_t *aStart, const regex_t *aEnd, uint8_t *aBlockDepth, bool aMultiLevel); + +#endif /* STUBSER_CFILE_PARSER_WORKER_LOC_H_ */ diff --git a/src/stubser/cfunction.c b/src/stubser/cfunction.c index 68711d3..c4ef599 100644 --- a/src/stubser/cfunction.c +++ b/src/stubser/cfunction.c @@ -1,172 +1,172 @@ -/*! - * @file cfunction.c - * @brief - * @details - * Project: \n - * Subsystem: \n - * Module: \n - * Code: GNU-C\n - * - * @date 28.02.2017 - * @author Martin Winkler - */ -#include -#include -#include "xtypes.h" -#include "xmalloc.h" -#include "cfunction_if.h" - -cfunction_t* cfunction_addNewFunction(cfunction_list_t *aList) -{ - cfunction_t *new = NULL; - - if (NULL == aList) - { - perror("Null pointer"); - return NULL; - } - - new = (cfunction_t*) xmalloc(sizeof(cfunction_t)); - memset(new, 0, sizeof(cfunction_t)); - - if (NULL == aList->head) - { - aList->amount = 0; - aList->head = new; - aList->current = new; - } - else - { - aList->current->next = new; - aList->current = new; - } - ++aList->amount; - return new; -} - -cfunction_parameter_t* cfunction_newParameter(cfunction_parameterList_t *aList) -{ - cfunction_parameter_t *new = NULL; - - if (NULL == aList) - { - perror("Null pointer"); - return NULL; - } - - new = (cfunction_parameter_t*) xmalloc(sizeof(cfunction_parameter_t)); - memset(new, 0, sizeof(cfunction_parameter_t)); - - if (NULL == aList->head) - { - aList->amount = 0; - aList->head = new; - aList->current = new; - } - else - { - aList->current->next = new; - aList->current = new; - } - ++aList->amount; - return new; -} - -STATIC int8_t cfunction_freeParameter(struct _CFUNCTION_PARAMETER_LIST_T *aParameter) -{ - cfunction_parameter_t *work = NULL; - cfunction_parameter_t *next = NULL; - - if (NULL == aParameter) - { - perror("Null pointer"); - return -1; - } - - work = aParameter->head; - - while (work) - { - next = work->next; - free(work->dataType); - free(work->name); - free(work); - work = next; - } - - aParameter->head = NULL; - aParameter->current = NULL; - - return 0; -} - -int8_t cfunction_freeFunction(cfunction_t **aFunction) -{ - cfunction_t *work = *aFunction; - - if (NULL == aFunction || NULL == *aFunction) - { - return -1; - } - - free(work->prefix); - free(work->dataType); - free(work->name); - cfunction_freeParameter(&work->parameter); - free(work); - - *aFunction = NULL; - - return 0; -} - -int8_t cfunction_freeList(cfunction_list_t *aList) -{ - cfunction_t *work = NULL; - cfunction_t *next = NULL; - - if (NULL == aList) - { - perror("Null pointer"); - return -1; - } - - work = aList->head; - - while (work) - { - next = work->next; - cfunction_freeFunction(&work); - work = next; - } - - aList->head = NULL; - aList->current = NULL; - - return 0; -} - -void cfunction_printList(cfunction_list_t *aList) -{ - cfunction_t *work = aList->head; - cfunction_parameter_t *param = NULL; - - if (NULL == aList) - { - return; - } - - while (work) - { - 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("%d(%s)%s%s%s", param->type, param->dataType, param->name, (param->array ? param->array : ""), (param->next ? "," : "")); - param = param->next; - } - printf("\n"); - work = work->next; - } - printf(" %d Functions\n", aList->amount); -} +/*! + * @file cfunction.c + * @brief + * @details + * Project: \n + * Subsystem: \n + * Module: \n + * Code: GNU-C\n + * + * @date 28.02.2017 + * @author Martin Winkler + */ +#include +#include +#include "xtypes.h" +#include "xmalloc.h" +#include "cfunction_if.h" + +cfunction_t* cfunction_addNewFunction(cfunction_list_t *aList) +{ + cfunction_t *new = NULL; + + if (NULL == aList) + { + perror("Null pointer"); + return NULL; + } + + new = (cfunction_t*) xmalloc(sizeof(cfunction_t)); + memset(new, 0, sizeof(cfunction_t)); + + if (NULL == aList->head) + { + aList->amount = 0; + aList->head = new; + aList->current = new; + } + else + { + aList->current->next = new; + aList->current = new; + } + ++aList->amount; + return new; +} + +cfunction_parameter_t* cfunction_newParameter(cfunction_parameterList_t *aList) +{ + cfunction_parameter_t *new = NULL; + + if (NULL == aList) + { + perror("Null pointer"); + return NULL; + } + + new = (cfunction_parameter_t*) xmalloc(sizeof(cfunction_parameter_t)); + memset(new, 0, sizeof(cfunction_parameter_t)); + + if (NULL == aList->head) + { + aList->amount = 0; + aList->head = new; + aList->current = new; + } + else + { + aList->current->next = new; + aList->current = new; + } + ++aList->amount; + return new; +} + +STATIC int8_t cfunction_freeParameter(struct _CFUNCTION_PARAMETER_LIST_T *aParameter) +{ + cfunction_parameter_t *work = NULL; + cfunction_parameter_t *next = NULL; + + if (NULL == aParameter) + { + perror("Null pointer"); + return -1; + } + + work = aParameter->head; + + while (work) + { + next = work->next; + free(work->dataType); + free(work->name); + free(work); + work = next; + } + + aParameter->head = NULL; + aParameter->current = NULL; + + return 0; +} + +int8_t cfunction_freeFunction(cfunction_t **aFunction) +{ + cfunction_t *work = *aFunction; + + if (NULL == aFunction || NULL == *aFunction) + { + return -1; + } + + free(work->prefix); + free(work->dataType); + free(work->name); + cfunction_freeParameter(&work->parameter); + free(work); + + *aFunction = NULL; + + return 0; +} + +int8_t cfunction_freeList(cfunction_list_t *aList) +{ + cfunction_t *work = NULL; + cfunction_t *next = NULL; + + if (NULL == aList) + { + perror("Null pointer"); + return -1; + } + + work = aList->head; + + while (work) + { + next = work->next; + cfunction_freeFunction(&work); + work = next; + } + + aList->head = NULL; + aList->current = NULL; + + return 0; +} + +void cfunction_printList(cfunction_list_t *aList) +{ + cfunction_t *work = aList->head; + cfunction_parameter_t *param = NULL; + + if (NULL == aList) + { + return; + } + + while (work) + { + 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("%d(%s)%s%s%s", param->type, param->dataType, param->name, (param->array ? param->array : ""), (param->next ? "," : "")); + param = param->next; + } + printf("\n"); + work = work->next; + } + printf(" %d Functions\n", aList->amount); +} diff --git a/src/stubser/cfunction_if.h b/src/stubser/cfunction_if.h index c17b2e7..0acf68c 100644 --- a/src/stubser/cfunction_if.h +++ b/src/stubser/cfunction_if.h @@ -1,86 +1,86 @@ -/*! - * @file cfunction_if.h - * @brief - * @details - * Project: \n - * Subsystem: \n - * Module: \n - * Code: GNU-C\n - * - * @date 28.02.2017 - * @author Martin Winkler - */ - -#ifndef STUBSER_CFUNCTION_IF_H_ -#define STUBSER_CFUNCTION_IF_H_ - -/*! @brief Type of function definition */ -typedef enum _CFUNCTION_TYPE_T -{ - CFUNCTION_TYPE_UNDEF = 0, /*!< @brief undefined */ - CFUNCTION_TYPE_REGULAR = 1, /*!< @brief Regular C function definition */ - CFUNCTION_TYPE_STATIC = 2, /*!< @brief Static C function definition */ - CFUNCTION_TYPE_PROTO = 3, /*!< @brief Prototype C function definition */ - CFUNCTION_TYPE_EXTERN = 4, /*!< @brief External C function definition */ - 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_VARIABLE = 3, /*!< @brief Variable parameter list */ - CPARAMETER_TYPE_LAST_ENUM -} cparameter_type_t; - -/*! @brief Parameter list node */ -typedef struct _CFUNCTION_PARAMETER_T -{ - 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; - -/*! @brief parameter array */ -typedef struct _CFUNCTION_PARAMETER_LIST_T -{ - uint8_t amount; - cfunction_parameter_t *head; - cfunction_parameter_t *current; -} cfunction_parameterList_t; - -/*! @brief brief_description */ -typedef struct _CFUNCTION_T -{ - cfunction_type_t type; - char *prefix; /*!< @brief prefix like static or extern */ - char *dataType; /*!< @brief return type */ - char *name; /*!< @brief name */ - cfunction_parameterList_t parameter;/*!< @brief parameter array */ - struct _CFUNCTION_T *next; -} cfunction_t; - -/*! @brief Dynamic function list */ -typedef struct _CFUNCTION_LIST_T -{ - uint16_t amount; - cfunction_t *head; - cfunction_t *current; -} cfunction_list_t; - -#define CFUNCTION_LIST_DEFAULT {\ - .amount = 0, \ - .head = NULL, \ - .current = NULL } - -cfunction_t* cfunction_addNewFunction(cfunction_list_t *aList); -cfunction_parameter_t* cfunction_newParameter(cfunction_parameterList_t *aList); -int8_t cfunction_freeFunction(cfunction_t **aFunction); -int8_t cfunction_freeList(cfunction_list_t *aList); -void cfunction_printList(cfunction_list_t *aList); - -#endif /* STUBSER_CFUNCTION_IF_H_ */ +/*! + * @file cfunction_if.h + * @brief + * @details + * Project: \n + * Subsystem: \n + * Module: \n + * Code: GNU-C\n + * + * @date 28.02.2017 + * @author Martin Winkler + */ + +#ifndef STUBSER_CFUNCTION_IF_H_ +#define STUBSER_CFUNCTION_IF_H_ + +/*! @brief Type of function definition */ +typedef enum _CFUNCTION_TYPE_T +{ + CFUNCTION_TYPE_UNDEF = 0, /*!< @brief undefined */ + CFUNCTION_TYPE_REGULAR = 1, /*!< @brief Regular C function definition */ + CFUNCTION_TYPE_STATIC = 2, /*!< @brief Static C function definition */ + CFUNCTION_TYPE_PROTO = 3, /*!< @brief Prototype C function definition */ + CFUNCTION_TYPE_EXTERN = 4, /*!< @brief External C function definition */ + 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_VARIABLE = 3, /*!< @brief Variable parameter list */ + CPARAMETER_TYPE_LAST_ENUM +} cparameter_type_t; + +/*! @brief Parameter list node */ +typedef struct _CFUNCTION_PARAMETER_T +{ + 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; + +/*! @brief parameter array */ +typedef struct _CFUNCTION_PARAMETER_LIST_T +{ + uint8_t amount; + cfunction_parameter_t *head; + cfunction_parameter_t *current; +} cfunction_parameterList_t; + +/*! @brief brief_description */ +typedef struct _CFUNCTION_T +{ + cfunction_type_t type; + char *prefix; /*!< @brief prefix like static or extern */ + char *dataType; /*!< @brief return type */ + char *name; /*!< @brief name */ + cfunction_parameterList_t parameter;/*!< @brief parameter array */ + struct _CFUNCTION_T *next; +} cfunction_t; + +/*! @brief Dynamic function list */ +typedef struct _CFUNCTION_LIST_T +{ + uint16_t amount; + cfunction_t *head; + cfunction_t *current; +} cfunction_list_t; + +#define CFUNCTION_LIST_DEFAULT {\ + .amount = 0, \ + .head = NULL, \ + .current = NULL } + +cfunction_t* cfunction_addNewFunction(cfunction_list_t *aList); +cfunction_parameter_t* cfunction_newParameter(cfunction_parameterList_t *aList); +int8_t cfunction_freeFunction(cfunction_t **aFunction); +int8_t cfunction_freeList(cfunction_list_t *aList); +void cfunction_printList(cfunction_list_t *aList); + +#endif /* STUBSER_CFUNCTION_IF_H_ */ diff --git a/src/stubser/stubser_if.h b/src/stubser/stubser_if.h index d8e3ccf..36f0cae 100644 --- a/src/stubser/stubser_if.h +++ b/src/stubser/stubser_if.h @@ -1,19 +1,19 @@ -/*! - * @file stubser_if.h - * @brief - * @details - * Project: \n - * Subsystem: \n - * Module: \n - * Code: GNU-C\n - * - * @date 27.02.2017 - * @author Martin Winkler - */ - -#ifndef STUBSER_STUBSER_IF_H_ -#define STUBSER_STUBSER_IF_H_ - -int stubser_createStub(char *path, char* aNoSuffix, char *aOutput); - -#endif /* STUBSER_STUBSER_IF_H_ */ +/*! + * @file stubser_if.h + * @brief + * @details + * Project: \n + * Subsystem: \n + * Module: \n + * Code: GNU-C\n + * + * @date 27.02.2017 + * @author Martin Winkler + */ + +#ifndef STUBSER_STUBSER_IF_H_ +#define STUBSER_STUBSER_IF_H_ + +int stubser_createStub(char *path, char* aNoSuffix, char *aOutput); + +#endif /* STUBSER_STUBSER_IF_H_ */ diff --git a/src/stubser/stubser_loc.h b/src/stubser/stubser_loc.h index a0a7871..c5f9f45 100644 --- a/src/stubser/stubser_loc.h +++ b/src/stubser/stubser_loc.h @@ -1,76 +1,76 @@ -/*! - * @file stubser_loc.h - * @brief - * @details - * Project: \n - * Subsystem: \n - * Module: \n - * Code: GNU-C\n - * - * @date 04.03.2017 - * @author Martin Winkler - */ - -#ifndef STUBSER_STUBSER_LOC_H_ -#define STUBSER_STUBSER_LOC_H_ - -#define NEWLINES "\r\n" -#define NEWLINE(output) fputs(NEWLINES, output) -#define NCHECK(string) (NULL == string ? "" : string) - -// Maximum amount of instances within test subject functions -#define STUB_INSTANCES_AMOUNT 32 - -#define STUB_START_S1 "// ---------------------------------------------->" NEWLINES \ - "/* Start of stub %s() */" -#define STUB_END_S1 "/* End of stub %s() */" NEWLINES \ - "// ----------------------------------------------<%s" - -#define STUBINSTANCE_AMOUNT_S1 "STUB_INSTANCES_AMOUNT_%s" //STUB_INSTANCES_AMOUNT_modulfunction_1 -#define STUBPARAMETER_TYPEDEF_S1 "stubparameter_t_%s" // stubparameter_t_modulfunction_1 -#define STUBPARAMETER_STRUCT_S1 "stubparameter_%s" // stubparameter_modulfunction_1 -#define STUBPARAMETER_PARAM_S1 "parameter_%c" // "stubparameter_modulfunction_1".parameter_a -#define STUBPARAMETER_CALLTEST_S "stubCallTest" -#define STUBPARAMETER_POINTERHANDLING_S "stubPointerHandling" -#define STUBPARAMETER_POINTERHANDLING_ENUM_S "stub_parameter_pointer_handling_t" -#define STUBPARAMETER_POINTERHANDLING_ADDRESS_S "STUB_PARAMETER_POINTER_HANDLING_ADDRESS" -#define STUBPARAMETER_POINTERHANDLING_CONTENT_S "STUB_PARAMETER_POINTER_HANDLING_CONTENT" -#define STUBPARAMETER_POINTERHANDLING_INJECT_S "STUB_PARAMETER_POINTER_HANDLING_INJECT" -#define STUBPARAMETER_RETURN_S "returnValue" // "stubparameter_modulfunction_1".returnValue -#define STUBINSTANCE_S1 "stubInstance_%s" // stubInstance_modulfunction_1 -#define STUBINSTANCE_DATATYPE_S "uint8_t" -#define STUBINIT_PARAM_INSTANCE_S "aInstance" -#define STUBINIT_PARAM_CALLTEST_S "aStubCallTest" -#define STUBINIT_PARAM_PARAMETER_S1 "aParameter_%c" // aParameter_a -#define STUBINIT_PARAM_RETURN_S "aReturnValue" -#define STUBINIT_PARAM_POINTERHANDLING_S "aPointerHandling" - -#define STUBDEFAULT_PARAMETER_INDEX_CHAR 'a' -#define STUBDEFAULT_VALUE_FUNCTIONPOINTER_S "0xAA" -#define STUBDEFAULT_VALUE_POINTER_S1 "%s_testData" // stubfilename_testData -#define STUBDEFAULT_VALUE_POINTERSIZE_S "1" -#define STUBDEFAULT_VALUE_VARIABLE_S "0xAA" - -#define STUBFUNCTION_USER_INITEXPECTED_S1 "stub_%s_user_initExpected" // stub_testfunction_initExpected -#define STUBFUNCTION_USER_INITGLOBALS_S1 "stub_%s_user_initGlobals" // stub_testfunction_initGlobals -#define STUBFUNCTION_USER_CHECK_S1 "stub_%s_user_checkGlobals" // stub_testfunction_checkGlobals - -#define STUBFUNCTION_INITEXPECTED_S1 "stub_%s_initExpected" // stub_testfunction_initExpected -#define STUBFUNCTION_INITGLOBALS_S1 "stub_%s_initGlobals" // stub_testfunction_initGlobals -#define STUBFUNCTION_CHECK_S1 "stub_%s_checkGlobals" // stub_testfunction_checkGlobals -#define STUBFUNCTION_INIT_S1 "stub_%s_init" // stub_testfunction_init -#define STUBVARIABLE_EXPECTED_S1 "%s_expected" // variable_expected - -#define STUB_CONSOLE_GOBACK "\033[2K\r" -#define STUB_CONSOLE_RUN "[ ]" -#define STUB_CONSOLE_OK "[ OK ]" -#define STUB_CONSOLE_WARN "[WARN]" -#define STUB_CONSOLE_FAIL "[FAIL]" -#define STUB_CONSOLE_PARSE_ERROR_S2 "\n" STUB_CONSOLE_WARN " %s parsing with %d warnings (check output manually)" -#define STUB_CONSOLE_PARSE_RUN_S1 STUB_CONSOLE_RUN " %s parsing..." -#define STUB_CONSOLE_PARSE_OK_S1 STUB_CONSOLE_GOBACK STUB_CONSOLE_OK " %s parsing..." -#define STUB_CONSOLE_CREATE_ERROR_S2 "...stub creation failed\n"STUB_CONSOLE_FAIL " %s creation failed (%d)\n" -#define STUB_CONSOLE_CREATE_OK_S1 "...stub created > %s\n" - -#define STUB_REGEX_STD_DATATYPE "(^|[^_[:alnum:]])([ui]+nt[0-9]{1,2}_t|char|uchar|word[12346]{2}|int[12346]{0,2}|byte)([^_[:alnum:]]|$)" -#endif /* STUBSER_STUBSER_LOC_H_ */ +/*! + * @file stubser_loc.h + * @brief + * @details + * Project: \n + * Subsystem: \n + * Module: \n + * Code: GNU-C\n + * + * @date 04.03.2017 + * @author Martin Winkler + */ + +#ifndef STUBSER_STUBSER_LOC_H_ +#define STUBSER_STUBSER_LOC_H_ + +#define NEWLINES "\r\n" +#define NEWLINE(output) fputs(NEWLINES, output) +#define NCHECK(string) (NULL == string ? "" : string) + +// Maximum amount of instances within test subject functions +#define STUB_INSTANCES_AMOUNT 32 + +#define STUB_START_S1 "// ---------------------------------------------->" NEWLINES \ + "/* Start of stub %s() */" +#define STUB_END_S1 "/* End of stub %s() */" NEWLINES \ + "// ----------------------------------------------<%s" + +#define STUBINSTANCE_AMOUNT_S1 "STUB_INSTANCES_AMOUNT_%s" //STUB_INSTANCES_AMOUNT_modulfunction_1 +#define STUBPARAMETER_TYPEDEF_S1 "stubparameter_t_%s" // stubparameter_t_modulfunction_1 +#define STUBPARAMETER_STRUCT_S1 "stubparameter_%s" // stubparameter_modulfunction_1 +#define STUBPARAMETER_PARAM_S1 "parameter_%c" // "stubparameter_modulfunction_1".parameter_a +#define STUBPARAMETER_CALLTEST_S "stubCallTest" +#define STUBPARAMETER_POINTERHANDLING_S "stubPointerHandling" +#define STUBPARAMETER_POINTERHANDLING_ENUM_S "stub_parameter_pointer_handling_t" +#define STUBPARAMETER_POINTERHANDLING_ADDRESS_S "STUB_PARAMETER_POINTER_HANDLING_ADDRESS" +#define STUBPARAMETER_POINTERHANDLING_CONTENT_S "STUB_PARAMETER_POINTER_HANDLING_CONTENT" +#define STUBPARAMETER_POINTERHANDLING_INJECT_S "STUB_PARAMETER_POINTER_HANDLING_INJECT" +#define STUBPARAMETER_RETURN_S "returnValue" // "stubparameter_modulfunction_1".returnValue +#define STUBINSTANCE_S1 "stubInstance_%s" // stubInstance_modulfunction_1 +#define STUBINSTANCE_DATATYPE_S "uint8_t" +#define STUBINIT_PARAM_INSTANCE_S "aInstance" +#define STUBINIT_PARAM_CALLTEST_S "aStubCallTest" +#define STUBINIT_PARAM_PARAMETER_S1 "aParameter_%c" // aParameter_a +#define STUBINIT_PARAM_RETURN_S "aReturnValue" +#define STUBINIT_PARAM_POINTERHANDLING_S "aPointerHandling" + +#define STUBDEFAULT_PARAMETER_INDEX_CHAR 'a' +#define STUBDEFAULT_VALUE_FUNCTIONPOINTER_S "0xAA" +#define STUBDEFAULT_VALUE_POINTER_S1 "%s_testData" // stubfilename_testData +#define STUBDEFAULT_VALUE_POINTERSIZE_S "1" +#define STUBDEFAULT_VALUE_VARIABLE_S "0xAA" + +#define STUBFUNCTION_USER_INITEXPECTED_S1 "stub_%s_user_initExpected" // stub_testfunction_initExpected +#define STUBFUNCTION_USER_INITGLOBALS_S1 "stub_%s_user_initGlobals" // stub_testfunction_initGlobals +#define STUBFUNCTION_USER_CHECK_S1 "stub_%s_user_checkGlobals" // stub_testfunction_checkGlobals + +#define STUBFUNCTION_INITEXPECTED_S1 "stub_%s_initExpected" // stub_testfunction_initExpected +#define STUBFUNCTION_INITGLOBALS_S1 "stub_%s_initGlobals" // stub_testfunction_initGlobals +#define STUBFUNCTION_CHECK_S1 "stub_%s_checkGlobals" // stub_testfunction_checkGlobals +#define STUBFUNCTION_INIT_S1 "stub_%s_init" // stub_testfunction_init +#define STUBVARIABLE_EXPECTED_S1 "%s_expected" // variable_expected + +#define STUB_CONSOLE_GOBACK "\033[2K\r" +#define STUB_CONSOLE_RUN "[ ]" +#define STUB_CONSOLE_OK "[ OK ]" +#define STUB_CONSOLE_WARN "[WARN]" +#define STUB_CONSOLE_FAIL "[FAIL]" +#define STUB_CONSOLE_PARSE_ERROR_S2 "\n" STUB_CONSOLE_WARN " %s parsing with %d warnings (check output manually)" +#define STUB_CONSOLE_PARSE_RUN_S1 STUB_CONSOLE_RUN " %s parsing..." +#define STUB_CONSOLE_PARSE_OK_S1 STUB_CONSOLE_GOBACK STUB_CONSOLE_OK " %s parsing..." +#define STUB_CONSOLE_CREATE_ERROR_S2 "...stub creation failed\n"STUB_CONSOLE_FAIL " %s creation failed (%d)\n" +#define STUB_CONSOLE_CREATE_OK_S1 "...stub created > %s\n" + +#define STUB_REGEX_STD_DATATYPE "(^|[^_[:alnum:]])([ui]+nt[0-9]{1,2}_t|char|uchar|word[12346]{2}|int[12346]{0,2}|byte)([^_[:alnum:]]|$)" +#endif /* STUBSER_STUBSER_LOC_H_ */