- refactored to modular structure
This commit is contained in:
@@ -30,6 +30,9 @@
|
|||||||
<tool id="cdt.managedbuild.tool.gnu.c.compiler.cygwin.exe.debug.75372444" name="Cygwin C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.cygwin.exe.debug">
|
<tool id="cdt.managedbuild.tool.gnu.c.compiler.cygwin.exe.debug.75372444" name="Cygwin C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.cygwin.exe.debug">
|
||||||
<option defaultValue="gnu.c.optimization.level.none" id="gnu.c.compiler.cygwin.exe.debug.option.optimization.level.1758127696" name="Optimization Level" superClass="gnu.c.compiler.cygwin.exe.debug.option.optimization.level" useByScannerDiscovery="false" valueType="enumerated"/>
|
<option defaultValue="gnu.c.optimization.level.none" id="gnu.c.compiler.cygwin.exe.debug.option.optimization.level.1758127696" name="Optimization Level" superClass="gnu.c.compiler.cygwin.exe.debug.option.optimization.level" useByScannerDiscovery="false" valueType="enumerated"/>
|
||||||
<option id="gnu.c.compiler.cygwin.exe.debug.option.debugging.level.196472971" name="Debug Level" superClass="gnu.c.compiler.cygwin.exe.debug.option.debugging.level" useByScannerDiscovery="false" value="gnu.c.debugging.level.max" valueType="enumerated"/>
|
<option id="gnu.c.compiler.cygwin.exe.debug.option.debugging.level.196472971" name="Debug Level" superClass="gnu.c.compiler.cygwin.exe.debug.option.debugging.level" useByScannerDiscovery="false" value="gnu.c.debugging.level.max" valueType="enumerated"/>
|
||||||
|
<option id="gnu.c.compiler.option.include.paths.1914441723" superClass="gnu.c.compiler.option.include.paths" valueType="includePath">
|
||||||
|
<listOptionValue builtIn="false" value=""${workspace_loc:/stubi_svn/src/ext}""/>
|
||||||
|
</option>
|
||||||
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.cygwin.1850965" superClass="cdt.managedbuild.tool.gnu.c.compiler.input.cygwin"/>
|
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.cygwin.1850965" superClass="cdt.managedbuild.tool.gnu.c.compiler.input.cygwin"/>
|
||||||
</tool>
|
</tool>
|
||||||
<tool id="cdt.managedbuild.tool.gnu.c.linker.cygwin.exe.debug.1913673353" name="Cygwin C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.cygwin.exe.debug">
|
<tool id="cdt.managedbuild.tool.gnu.c.linker.cygwin.exe.debug.1913673353" name="Cygwin C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.cygwin.exe.debug">
|
||||||
@@ -109,4 +112,6 @@
|
|||||||
</scannerConfigBuildInfo>
|
</scannerConfigBuildInfo>
|
||||||
</storageModule>
|
</storageModule>
|
||||||
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
|
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
|
||||||
|
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
|
||||||
|
<storageModule moduleId="refreshScope"/>
|
||||||
</cproject>
|
</cproject>
|
||||||
|
75
src/ext/xstring.c
Normal file
75
src/ext/xstring.c
Normal file
@@ -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;
|
||||||
|
}
|
21
src/ext/xstring.h
Normal file
21
src/ext/xstring.h
Normal file
@@ -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 <string.h>
|
||||||
|
|
||||||
|
char* gnu_basename(char *path);
|
||||||
|
char* strntrimStatic(char *aStr, size_t aMaxLength);
|
||||||
|
|
||||||
|
#endif /* XSTRING_H_ */
|
32
src/ext/xtime.h
Normal file
32
src/ext/xtime.h
Normal file
@@ -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 <time.h>
|
||||||
|
|
||||||
|
/*! @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_ */
|
41
src/ext/xtypes.h
Normal file
41
src/ext/xtypes.h
Normal file
@@ -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 <stddef.h> // definition of NULL
|
||||||
|
#include <stdint.h> // fixed width types
|
||||||
|
#include <stdbool.h> // 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_ */
|
78
src/main.c
Normal file
78
src/main.c
Normal file
@@ -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 <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <regex.h>
|
||||||
|
#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 <Source Dir> <Target Dir>\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;
|
||||||
|
}
|
271
src/stubi.c
271
src/stubi.c
@@ -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 <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <dirent.h>
|
|
||||||
#include <regex.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#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 <Source Dir> <Target Dir>\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;
|
|
||||||
}
|
|
||||||
|
|
207
src/stubser/stubser.c
Normal file
207
src/stubser/stubser.c
Normal file
@@ -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 <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <regex.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
19
src/stubser/stubser_if.h
Normal file
19
src/stubser/stubser_if.h
Normal file
@@ -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_ */
|
Reference in New Issue
Block a user