diff --git a/.cproject b/.cproject
index 7f2148c..242b6c7 100644
--- a/.cproject
+++ b/.cproject
@@ -30,6 +30,9 @@
+
@@ -109,4 +112,6 @@
+
+
diff --git a/src/ext/xstring.c b/src/ext/xstring.c
new file mode 100644
index 0000000..a78a7be
--- /dev/null
+++ b/src/ext/xstring.c
@@ -0,0 +1,75 @@
+/*!
+ * @file xstring.c
+ * @brief
+ * @details
+ * Project: \n
+ * Subsystem: \n
+ * Module: \n
+ * Code: GNU-C\n
+ *
+ * @date 27.02.2017
+ * @author SESA354004
+ */
+#include "xstring.h"
+#include "ctype.h"
+
+char* gnu_basename(char *path)
+{
+ char *base = strrchr(path, '/');
+ return base ? base + 1 : path;
+}
+
+/*!
+ * @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;
+}
diff --git a/src/ext/xstring.h b/src/ext/xstring.h
new file mode 100644
index 0000000..6d777cc
--- /dev/null
+++ b/src/ext/xstring.h
@@ -0,0 +1,21 @@
+/*!
+ * @file xstring.h
+ * @brief
+ * @details
+ * Project: \n
+ * Subsystem: \n
+ * Module: \n
+ * Code: GNU-C\n
+ *
+ * @date 27.02.2017
+ * @author SESA354004
+ */
+#ifndef XSTRING_H_
+#define XSTRING_H_
+
+#include
+
+char* gnu_basename(char *path);
+char* strntrimStatic(char *aStr, size_t aMaxLength);
+
+#endif /* XSTRING_H_ */
diff --git a/src/ext/xtime.h b/src/ext/xtime.h
new file mode 100644
index 0000000..7725efc
--- /dev/null
+++ b/src/ext/xtime.h
@@ -0,0 +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 SESA354004
+ */
+#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
new file mode 100644
index 0000000..39cb61b
--- /dev/null
+++ b/src/ext/xtypes.h
@@ -0,0 +1,41 @@
+/*!
+ * @file xtypes.h
+ * @brief
+ * @details
+ * Project: \n
+ * Subsystem: \n
+ * Module: \n
+ * Code: GNU-C\n
+ *
+ * @date 27.02.2017
+ * @author SESA354004
+ */
+
+#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
new file mode 100644
index 0000000..ffbe1cb
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,78 @@
+/*!
+ * @file main.c
+ * @brief
+ * @details
+ * Project: \n
+ * Subsystem: \n
+ * Module: \n
+ * Code: GNU-C\n
+ *
+ * @date 27.02.2017
+ * @author SESA354004
+ */
+#include
+#include
+#include
+#include
+#include "xtypes.h"
+#include "xstring.h"
+#include "stubser/stubser_if.h"
+
+static int one(const struct dirent *unused)
+{
+ return 1;
+}
+
+/*
+ * @brief Scan given folder for .c files
+ * @param argc amount of command line arguments
+ * @param **argv array of argments separated by spaces
+ * @retval -1 Directory not found or regex compilation error
+ * @retval 0 Direcotry scanned successfully
+ * @details
+ * see printf for usage
+ */
+int main(int argc, char **argv)
+{
+ struct dirent **eps;
+ int n;
+ regex_t regX;
+ char filePath[256] =
+ { 0 };
+ const char *pattern = "^.*\\.[cC]";
+
+ printf("%s %s\n\n", argv[1], argv[2]);
+
+ if (3 != argc)
+ {
+ printf("Usage:\n");
+ printf(" %s \n", gnu_basename(argv[0]));
+ return -1;
+ }
+
+ if (regcomp(®X, pattern, REG_NEWLINE))
+ {
+ fprintf(stderr, "bad pattern: '%s'\n", pattern);
+ return -1;
+ }
+
+ n = scandir(argv[1], &eps, one, alphasort);
+ if (n >= 0)
+ {
+ int cnt;
+ for (cnt = 0; cnt < n; ++cnt)
+ {
+ if (0 == regexec(®X, eps[cnt]->d_name, 0, NULL, 0) //
+ && DT_REG == eps[cnt]->d_type)
+ {
+ sprintf(filePath, "%s/%s", argv[1], eps[cnt]->d_name);
+ printf("%s (%d)\n", filePath, eps[cnt]->d_type);
+ scanFile(filePath);
+ }
+ }
+ }
+ else
+ perror("Couldn't open the directory");
+
+ return 0;
+}
diff --git a/src/stubi.c b/src/stubi.c
deleted file mode 100644
index 69e9c60..0000000
--- a/src/stubi.c
+++ /dev/null
@@ -1,271 +0,0 @@
-/*!
- Name : stubi.c
- Author : Martin Winkler
- Version :
- Copyright :
- Description : Scan a folder for .c files and generate stubs from function definitions
-
- @todo complete function dissection
- @todo output stub header and function
- @attention Using regular expressions to scan c files for function definitions. No 100%
- success rate and should be seen as helper. Result must be reviewed manually.
- */
-
-#include
-#include
-#include
-#include
-#include
-
-#define STUBI_FUNCTION_REGEX "^[ \\t]*([ _\\*[:alnum:]]*) ([_\\*[:alnum:]]*)[ \\t]*\\(([^\\)]*)"
-#define STUBI_FUNCTION_MULTI "[ \\t]*(.*)"
-#define STUBI_FUNCTION_MULTI_END "[ \\t]*(.*)\\)[ \\t\\{;]*"
-
-static int one(const struct dirent *unused)
-{
- return 1;
-}
-
-static char *gnu_basename(char *path)
-{
- char *base = strrchr(path, '/');
- return base ? base + 1 : path;
-}
-
-/*!
- * @brief Process a string (e.g. from getline()) if it is a single or multiple line function definition
- * @todo closing parenthesis within parameter list will break the detection
- * @retval -1 Invalid regula expressions
- * @retval -2 Given String not a function
- * @retval 0 function evaluated
- */
-static int matchFunction(char *aLine)
-{
- const size_t maxGroup = 10;
- regmatch_t matchGroup[maxGroup];
- const char *pattern =
- STUBI_FUNCTION_REGEX;
- const char *patternend =
- STUBI_FUNCTION_REGEX "\\)";
- regex_t regX;
- regex_t regXEnd;
- regex_t regXMulti;
- regex_t regXMultiEnd;
- uint8_t i = 0;
- char funPrefix[256] =
- { 0 };
- static uint8_t multiParamFlag = 0;
- uint8_t multiParamEndFlag = 0;
-
- if (0 > regcomp(®X, pattern, REG_EXTENDED | REG_NEWLINE))
- {
- perror("Error regex\n");
- return -1;
- }
-
- if (0 > regcomp(®XEnd, patternend, REG_EXTENDED | REG_NEWLINE))
- {
- perror("Error regexend\n");
- return -1;
- }
-
- if (0 > regcomp(®XMulti, STUBI_FUNCTION_MULTI, REG_EXTENDED | REG_NEWLINE))
- {
- perror("Error regXMulti\n");
- return -1;
- }
-
- if (0 > regcomp(®XMultiEnd, STUBI_FUNCTION_MULTI_END, REG_EXTENDED | REG_NEWLINE))
- {
- perror("Error regXMultiEnd\n");
- return -1;
- }
-
- if (multiParamFlag)
- {
- if (0 == regexec(®XMultiEnd, aLine, maxGroup, matchGroup, 0))
- {
- // end of multi line function
- ++multiParamFlag;
- multiParamEndFlag = 1;
- }
- else
- {
- // continuation of multi line function
- (void) regexec(®XMulti, aLine, maxGroup, matchGroup, 0);
- ++multiParamFlag;
- }
- }
- else if (0 == regexec(®XEnd, aLine, maxGroup, matchGroup, 0))
- {
- // single line function
- multiParamFlag = 0;
- }
- else if (0 == regexec(®X, aLine, maxGroup, matchGroup, 0))
- {
- // start of multi line function
- ++multiParamFlag;
- printf("[ mls][%d]:", multiParamFlag);
- }
- else
- {
- // no fit
- return -2;
- }
-
- switch (multiParamFlag)
- {
- case 0: // single line function definition
- case 1: // first line of multi line function definition
- {
- (void) strlcpy(funPrefix, &aLine[matchGroup[1].rm_so], (size_t) (matchGroup[1].rm_eo - matchGroup[1].rm_so) + 1);
-
- if ( //
- NULL == strstr(funPrefix, "extern") //
- && NULL == strstr(funPrefix, "EXTERN") //
- && NULL == strstr(funPrefix, "static") //
- && NULL == strstr(funPrefix, "STATIC") //
- && matchGroup[2].rm_so < matchGroup[2].rm_eo)
- {
- printf("[ sl ]:%s", funPrefix);
- for (i = 2; i < maxGroup && 0 <= matchGroup[i].rm_so; ++i)
- {
- printf(" (%.3ld - %.3ld): ", matchGroup[i].rm_so, matchGroup[i].rm_eo);
- printf("%.*s", (int) (matchGroup[i].rm_eo - matchGroup[i].rm_so), &aLine[matchGroup[i].rm_so]);
- }
- printf("\n");
- }
- // TODO special handling for static functions (as extern in stub header)
- else if (NULL != strstr(funPrefix, "static") || NULL != strstr(funPrefix, "STATIC"))
- {
- printf("[todo] %s %.*s\n", funPrefix, (int) (matchGroup[2].rm_eo - matchGroup[2].rm_so), &aLine[matchGroup[2].rm_so]);
- }
- // ignore functions declared as extern
- else if (NULL != strstr(funPrefix, "extern") || NULL != strstr(funPrefix, "EXTERN"))
- {
- printf("[ nu ] %s %.*s\n", funPrefix, (int) (matchGroup[2].rm_eo - matchGroup[2].rm_so), &aLine[matchGroup[2].rm_so]);
- }
- break;
- }
- default: // further lines
- {
- if (multiParamEndFlag)
- {
- printf("[ mle][%d]:", multiParamFlag);
- }
- else
- {
- printf("[ ml ][%d]:", multiParamFlag);
- }
-
- if (matchGroup[1].rm_so < matchGroup[1].rm_eo)
- {
- for (i = 1; i < maxGroup && 0 <= matchGroup[i].rm_so; ++i)
- {
- printf("(%.3ld-%.3ld):", matchGroup[i].rm_so, matchGroup[i].rm_eo);
- printf("%.*s", (int) (matchGroup[i].rm_eo - matchGroup[i].rm_so), &aLine[matchGroup[i].rm_so]);
- }
- printf("\n");
- }
-
- if (multiParamEndFlag)
- {
- multiParamFlag = 0;
- multiParamEndFlag = 0;
- }
-
- break;
- }
- }
-
- return 0;
-}
-
-/*
- * @brief Opens given file for line by line function matching
- * @param *path file path
- * @retval 0 matching complete
- * @retval -1 error opening file
- */
-static int scanFile(char *path)
-{
- FILE *fdesc;
- ssize_t charRead = 0;
- size_t lineSize = 0;
- char *fileLine = NULL; // will be allocated by getline(); must be freed
-
- fdesc = fopen(path, "r");
- if (NULL == fdesc)
- {
- perror("Error open file");
- return -1;
- }
-
- do
- {
- charRead = getline(&fileLine, &lineSize, fdesc);
- if (0 <= charRead)
- {
- (void) matchFunction(fileLine);
- }
- } while (0 <= charRead);
-
- free(fileLine);
- (void) fclose(fdesc);
- return 0;
-}
-
-/*
- * @brief Scan given folder for .c files
- * @param argc amount of command line arguments
- * @param **argv array of argments separated by spaces
- * @retval -1 Directory not found or regex compilation error
- * @retval 0 Direcotry scanned successfully
- * @details
- * see printf for usage
- */
-int main(int argc, char **argv)
-{
- struct dirent **eps;
- int n;
- regex_t regX;
- char filePath[256] =
- { 0 };
- const char *pattern = "^.*\\.[cC]";
-
- printf("%s %s\n\n", argv[1], argv[2]);
-
- if (3 != argc)
- {
- printf("Usage:\n");
- printf(" %s \n", gnu_basename(argv[0]));
- return -1;
- }
-
- if (regcomp(®X, pattern, REG_NEWLINE))
- {
- fprintf(stderr, "bad pattern: '%s'\n", pattern);
- return -1;
- }
-
- n = scandir(argv[1], &eps, one, alphasort);
- if (n >= 0)
- {
- int cnt;
- for (cnt = 0; cnt < n; ++cnt)
- {
- if (0 == regexec(®X, eps[cnt]->d_name, 0, NULL, 0) //
- && DT_REG == eps[cnt]->d_type)
- {
- sprintf(filePath, "%s/%s", argv[1], eps[cnt]->d_name);
- printf("%s (%d)\n", filePath, eps[cnt]->d_type);
- scanFile(filePath);
- }
- }
- }
- else
- perror("Couldn't open the directory");
-
- return 0;
-}
-
diff --git a/src/stubser/stubser.c b/src/stubser/stubser.c
new file mode 100644
index 0000000..5b99369
--- /dev/null
+++ b/src/stubser/stubser.c
@@ -0,0 +1,207 @@
+/*!
+ Name : stubi.c
+ Author : Martin Winkler
+ Version :
+ Copyright :
+ Description : Scan a folder for .c files and generate stubs from function definitions
+
+ @todo complete function dissection
+ @todo output stub header and function
+ @attention Using regular expressions to scan c files for function definitions. No 100%
+ success rate and should be seen as helper. Result must be reviewed manually.
+ */
+
+#include
+#include
+#include
+#include
+#include "xtypes.h"
+#include "xstring.h"
+
+#define STUBI_FUNCTION_REGEX "^[ \\t]*([ _\\*[:alnum:]]*) ([_\\*[:alnum:]]*)[ \\t]*\\(([^\\)]*)"
+#define STUBI_FUNCTION_MULTI "[ \\t]*(.*)"
+#define STUBI_FUNCTION_MULTI_END "[ \\t]*(.*)\\)[ \\t\\{;]*"
+
+/*!
+ * @brief Process a string (e.g. from getline()) if it is a single or multiple line function definition
+ * @todo closing parenthesis within parameter list will break the detection
+ * @retval -1 Invalid regula expressions
+ * @retval -2 Given String not a function
+ * @retval 0 function evaluated
+ */
+STATIC int matchFunction(char *aLine)
+{
+ const size_t maxGroup = 10;
+ regmatch_t matchGroup[maxGroup];
+ const char *pattern =
+ STUBI_FUNCTION_REGEX;
+ const char *patternend =
+ STUBI_FUNCTION_REGEX "\\)";
+ regex_t regX;
+ regex_t regXEnd;
+ regex_t regXMulti;
+ regex_t regXMultiEnd;
+ uint8_t i = 0;
+ char funPrefix[256] =
+ { 0 };
+ static uint8_t multiParamFlag = 0;
+ uint8_t multiParamEndFlag = 0;
+
+ if (0 > regcomp(®X, pattern, REG_EXTENDED | REG_NEWLINE))
+ {
+ perror("Error regex\n");
+ return -1;
+ }
+
+ if (0 > regcomp(®XEnd, patternend, REG_EXTENDED | REG_NEWLINE))
+ {
+ perror("Error regexend\n");
+ return -1;
+ }
+
+ if (0 > regcomp(®XMulti, STUBI_FUNCTION_MULTI, REG_EXTENDED | REG_NEWLINE))
+ {
+ perror("Error regXMulti\n");
+ return -1;
+ }
+
+ if (0 > regcomp(®XMultiEnd, STUBI_FUNCTION_MULTI_END, REG_EXTENDED | REG_NEWLINE))
+ {
+ perror("Error regXMultiEnd\n");
+ return -1;
+ }
+
+ if (multiParamFlag)
+ {
+ if (0 == regexec(®XMultiEnd, aLine, maxGroup, matchGroup, 0))
+ {
+ // end of multi line function
+ ++multiParamFlag;
+ multiParamEndFlag = 1;
+ }
+ else
+ {
+ // continuation of multi line function
+ (void) regexec(®XMulti, aLine, maxGroup, matchGroup, 0);
+ ++multiParamFlag;
+ }
+ }
+ else if (0 == regexec(®XEnd, aLine, maxGroup, matchGroup, 0))
+ {
+ // single line function
+ multiParamFlag = 0;
+ }
+ else if (0 == regexec(®X, aLine, maxGroup, matchGroup, 0))
+ {
+ // start of multi line function
+ ++multiParamFlag;
+ printf("[ mls][%d]:", multiParamFlag);
+ }
+ else
+ {
+ // no fit
+ return -2;
+ }
+
+ switch (multiParamFlag)
+ {
+ case 0: // single line function definition
+ case 1: // first line of multi line function definition
+ {
+ (void) strlcpy(funPrefix, &aLine[matchGroup[1].rm_so], (size_t) (matchGroup[1].rm_eo - matchGroup[1].rm_so) + 1);
+
+ if ( //
+ NULL == strstr(funPrefix, "extern") //
+ && NULL == strstr(funPrefix, "EXTERN") //
+ && NULL == strstr(funPrefix, "static") //
+ && NULL == strstr(funPrefix, "STATIC") //
+ && matchGroup[2].rm_so < matchGroup[2].rm_eo)
+ {
+ printf("[ sl ]:%s", funPrefix);
+ for (i = 2; i < maxGroup && 0 <= matchGroup[i].rm_so; ++i)
+ {
+ printf(" (%.3ld - %.3ld): ", matchGroup[i].rm_so, matchGroup[i].rm_eo);
+ printf("%.*s", (int) (matchGroup[i].rm_eo - matchGroup[i].rm_so), &aLine[matchGroup[i].rm_so]);
+ }
+ printf("\n");
+ }
+ // TODO special handling for static functions (as extern in stub header)
+ else if (NULL != strstr(funPrefix, "static") || NULL != strstr(funPrefix, "STATIC"))
+ {
+ printf("[todo] %s %.*s\n", funPrefix, (int) (matchGroup[2].rm_eo - matchGroup[2].rm_so), &aLine[matchGroup[2].rm_so]);
+ }
+ // ignore functions declared as extern
+ else if (NULL != strstr(funPrefix, "extern") || NULL != strstr(funPrefix, "EXTERN"))
+ {
+ printf("[ nu ] %s %.*s\n", funPrefix, (int) (matchGroup[2].rm_eo - matchGroup[2].rm_so), &aLine[matchGroup[2].rm_so]);
+ }
+ break;
+ }
+ default: // further lines
+ {
+ if (multiParamEndFlag)
+ {
+ printf("[ mle][%d]:", multiParamFlag);
+ }
+ else
+ {
+ printf("[ ml ][%d]:", multiParamFlag);
+ }
+
+ if (matchGroup[1].rm_so < matchGroup[1].rm_eo)
+ {
+ for (i = 1; i < maxGroup && 0 <= matchGroup[i].rm_so; ++i)
+ {
+ printf("(%.3ld-%.3ld):", matchGroup[i].rm_so, matchGroup[i].rm_eo);
+ printf("%.*s", (int) (matchGroup[i].rm_eo - matchGroup[i].rm_so), &aLine[matchGroup[i].rm_so]);
+ }
+ printf("\n");
+ }
+
+ if (multiParamEndFlag)
+ {
+ multiParamFlag = 0;
+ multiParamEndFlag = 0;
+ }
+
+ break;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * @brief Opens given file for line by line function matching
+ * @param *path file path
+ * @retval 0 matching complete
+ * @retval -1 error opening file
+ */
+int scanFile(char *path)
+{
+ FILE *fdesc;
+ ssize_t charRead = 0;
+ size_t lineSize = 0;
+ char *fileLine = NULL; // will be allocated by getline(); must be freed
+
+ fdesc = fopen(path, "r");
+ if (NULL == fdesc)
+ {
+ perror("Error open file");
+ return -1;
+ }
+
+ do
+ {
+ charRead = getline(&fileLine, &lineSize, fdesc);
+ if (0 <= charRead)
+ {
+ (void) matchFunction(fileLine);
+ }
+ } while (0 <= charRead);
+
+ free(fileLine);
+ (void) fclose(fdesc);
+ return 0;
+}
+
diff --git a/src/stubser/stubser_if.h b/src/stubser/stubser_if.h
new file mode 100644
index 0000000..e3aae09
--- /dev/null
+++ b/src/stubser/stubser_if.h
@@ -0,0 +1,19 @@
+/*!
+ * @file stubser_if.h
+ * @brief
+ * @details
+ * Project: \n
+ * Subsystem: \n
+ * Module: \n
+ * Code: GNU-C\n
+ *
+ * @date 27.02.2017
+ * @author SESA354004
+ */
+
+#ifndef STUBSER_STUBSER_IF_H_
+#define STUBSER_STUBSER_IF_H_
+
+int scanFile(char *path);
+
+#endif /* STUBSER_STUBSER_IF_H_ */