diff --git a/CMakeLists.txt b/CMakeLists.txt
index fdfc5cc..61d056e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -13,13 +13,13 @@ add_executable(
file(GLOB Source_Files2 src2/*.cpp)
add_executable(
- COptionParser
+ ExampleProgram
${Source_Files2}
)
-find_package (Boost REQUIRED)
+find_package (Boost COMPONENTS log log_setup REQUIRED)
if(Boost_FOUND)
include_directories(${Boost_INCLUDE_DIRS})
target_link_libraries(CodeGenerator ${Boost_LIBRARIES})
diff --git a/config-file b/config-file
index 7723b87..d921596 100644
--- a/config-file
+++ b/config-file
@@ -815,7 +815,7 @@ WARN_LOGFILE =
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
# Note: If this tag is empty the current directory is searched.
-INPUT = ./src
+INPUT = ./src, ./include
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
diff --git a/example/Example.xml b/example/Example.xml
deleted file mode 100644
index 9a20bdd..0000000
--- a/example/Example.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-
-
-
- options.h
- options.cpp
- DHBW
- COptionParser
-
- Erstellt einen Rumpf zum einlesen von Argumente aus der Kommandozeile.
- Es kann sowohl mit innenliegenden Container wie externer Klassenanbindung eine Datenhaltung erfolgen.
- Sobald ein Methodenaufruf abstrakt ist, wird die Basisklasse abstrakt.
- Fuer die Formatierung der generierten Dateien wird astyle verwendet.
-
-
- getoptgen [options] ... QUELLE
- getoptgen [--out-path] ... QUELLE
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/include/CodeGenerator.h b/include/CodeGenerator.h
new file mode 100644
index 0000000..37f3a41
--- /dev/null
+++ b/include/CodeGenerator.h
@@ -0,0 +1,62 @@
+/*
+ * Editors: Tobias Goetz
+ */
+
+#ifndef PROGRAMMING_C_CODEGENERATOR_H
+#define PROGRAMMING_C_CODEGENERATOR_H
+
+#include
+
+/**
+ * @brief Class for the CodeGenerator
+ */
+class CodeGenerator {
+private:
+ /**
+ * @brief String containing path to the file
+ */
+ std::string filePath;
+
+ /**
+ * @brief Output directory
+ */
+ std::string outputDir;
+
+public:
+ /**
+ * @brief Constructor
+ */
+ CodeGenerator() = default;
+
+ /**
+ * @brief Get the path to the file
+ * @return
+ */
+ std::string getFilePath();
+
+ /**
+ * Get the output directory
+ * @return the out directory as string
+ */
+ std::string getOutputDir();
+
+ /**
+ * @brief Set the path to the file
+ * @param filename
+ */
+ void setFilePath(const std::string &filename);
+
+ /**
+ * @brief Set the output directory
+ * @param dir
+ */
+ void setOutputDir(const std::string &dir);
+
+ /**
+ * @brief Runs the CodeGenerator
+ */
+ void run();
+};
+
+
+#endif //PROGRAMMING_C_CODEGENERATOR_H
diff --git a/include/HelpText.h b/include/HelpText.h
new file mode 100644
index 0000000..6e1a50c
--- /dev/null
+++ b/include/HelpText.h
@@ -0,0 +1,110 @@
+/*
+ * Editors: Sebastian Wolf, Tobias Goetz
+ */
+
+#ifndef CODEGENERATOR_HELPTEXT_H
+#define CODEGENERATOR_HELPTEXT_H
+
+#include "Justify.h"
+#include "models/GetOptSetup.h"
+#include
+#include
+#include
+
+using namespace std;
+
+/**
+ * @brief Class for the HelpText parsing
+ */
+class HelpText
+{
+public:
+ /**
+ * @brief Constructor for the HelpText
+ */
+ explicit HelpText(GetOptSetup *getOptSetup);
+ /**
+ * @brief Destructor for the HelpText
+ */
+ ~HelpText();
+
+ /**
+ * @brief add function wrapper and call parse methods
+ * @return getHelp() Function with message as string
+ */
+ string parseHelpMessage();
+
+private:
+ /**
+ * @brief concatenate the description strings to one string
+ * @brief and add to printHelpText
+ */
+ void parseDescription();
+
+ /**
+ * @brief concatenate usage strings to one string
+ * @brief and add to printHelpText
+ * @return all usage strings as a string with line break.
+ */
+ void parseUsage();
+
+ /**
+ * @brief concatenate the author information to one string
+ * @brief and add to printHelpText
+ */
+ void parseAuthor();
+
+ /**
+ * @brief concatenate the options to one string
+ * @brief and add to printHelpText
+ * call the getMaxParamLength() Method. Get concatenated params
+ * by calling concatParams function with i as iterator.
+ * write strings to buffer with a spacing using set()
+ * calculate a new signPerLine to space out the
+ * option description accordingly to the length
+ * of param and the shift.
+ * calculate a new shift for every line of the description
+ * that is pushed to the next line because of signPerLine,
+ * in order to shift the line to the right, matching the above.
+ * Justify the description text. Write justified text to
+ * class variable.
+ */
+ void parseOption();
+
+ /**
+ * @brief concatenate short opt and long opt to one string
+ * different checks if shortOpt and LongOpt are empty
+ * to concatenate the right signs to the string
+ * @param i iteration counter to determine which option is parsed
+ * @return concatenated opts as string
+ */
+ vector concatParams(const vector& sortedOpts);
+ /**
+ * @brief printHelp Text
+ * stores the string for the printHelp method.
+ */
+ string printHelpText;
+ /**
+ * @brief Length of longest Parameter
+ * Stores the length of the longest
+ * parameter in options.
+ */
+ int maxOptionParamLength = 0;
+ /**
+ * @brief shift
+ * extra shift / space can be defined
+ * for the space between parameters
+ * and description in options.
+ */
+ const int shift = 5;
+ /**
+ * @brief Justify object
+ */
+ Justify justify;
+ /**
+ * @brief GetOptSetup object
+ */
+ GetOptSetup *getOptSetup;
+};
+
+#endif //CODEGENERATOR_HELPTEXT_H
diff --git a/include/Justify.h b/include/Justify.h
new file mode 100644
index 0000000..a0f3608
--- /dev/null
+++ b/include/Justify.h
@@ -0,0 +1,80 @@
+/*
+ * Editors: Sebastian Wolf
+ */
+
+#ifndef CODEGENERATOR_JUSTIFY_H
+#define CODEGENERATOR_JUSTIFY_H
+#include "bits/stdc++.h"
+#include
+#include
+#include
+
+using namespace std;
+using namespace boost;
+
+/**
+ * @brief Class to justify a string
+ * Custom Justify class according to https://www.geeksforgeeks.org/justify-the-given-text-based-on-the-given-width-of-each-line/
+ */
+class Justify
+{
+private:
+ /**
+ * @brief Function to join the words with spaces spread evenly
+ * @param words vector with separated words
+ * @param start current line start
+ * @param end iterator
+ * @param num_spaces
+ * @param isOption check if its an options string
+ * @param curr_line current line string is in
+ * @param optionShift shift that needs to be added to aline lines
+ * @return justified text
+ */
+ static string JoinALineWithSpace(
+ vector& words,
+ int start, int end,
+ int num_spaces,
+ bool isOption,
+ int curr_line,
+ int optionShift);
+ /**
+ * @brief Function that justify the words of sentence of length of line L
+ * @param words vector with separated words
+ * @param L length of sign per line
+ * @param isOption check if its an options string
+ * @param optionShift shift that needs to be added to aline lines
+ * @return whole justified string
+ */
+ static vector JustifyText(
+ vector& words,
+ int L,
+ bool isOption,
+ int optionShift);
+ /**
+ * @brief separates a string in single words
+ * @param str string to parse
+ * @return vector with splitted words
+ */
+ static vector splitWords(const string& str);
+
+ /**
+ * @brief Function to return justified text
+ * @param result vector with justified strings
+ * @return justified text in as a string
+ */
+ static string returnJustifiedText(vector& result);
+
+public:
+ /**
+ * @brief function to call the justification
+ * @param str string to justify
+ * @param L length of sign per line
+ * @param isOption check if its an options string
+ * @param optionShift shift that needs to be added to aline lines
+ * @return justified text as a string
+ */
+ string justifyTheText(const string& str, int L, bool isOption, int optionShift);
+};
+
+
+#endif //CODEGENERATOR_JUSTIFY_H
diff --git a/include/Logger.h b/include/Logger.h
new file mode 100644
index 0000000..63f7dc9
--- /dev/null
+++ b/include/Logger.h
@@ -0,0 +1,66 @@
+/*
+ * Editors: Tobias Goetz, Sebastian Wolf
+ */
+
+#ifndef LOG_LOGGER_H
+#define LOG_LOGGER_H
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+BOOST_LOG_GLOBAL_LOGGER(sysLogger,
+ boost::log::sources::severity_channel_logger_mt);
+BOOST_LOG_GLOBAL_LOGGER(dataLogger,
+ boost::log::sources::severity_channel_logger_mt);
+
+/**
+ * @brief Custom logger class.
+ * Custom logger according to https://objectcomputing.com/resources/publications/sett/may-2016-boostlog-library
+ */
+class Logger {
+public:
+ /// Init with default trivial logging
+ static void init();
+
+ /// @param configFileName config ini file that contains boost logging properties.
+ /// If configFileName.empty() then default initialization.
+ static void initFromConfig(const std::string& configFileName);
+
+ /// Disable logging
+ static void disable();
+
+ /// Add a file sink for LOG_DATA_* for >= INFO.
+ /// This file sink will be used along with any configured via Config in init().
+ static void addDataFileLog(const std::string& logFileName);
+};
+
+#define LOG_LOG_LOCATION(LOGGER, LEVEL, ARG) \
+ BOOST_LOG_SEV(LOGGER, boost::log::trivial::LEVEL) \
+ << boost::log::add_value("Line", __LINE__) \
+ << boost::log::add_value("File", __FILE__) \
+ << boost::log::add_value("Function", __FUNCTION__) << ARG;
+
+/// System Log macros.
+/// TRACE < DEBUG < INFO < WARN < ERROR < FATAL
+#define LOG_TRACE(ARG) LOG_LOG_LOCATION(sysLogger::get(), trace, ARG);
+#define LOG_DEBUG(ARG) LOG_LOG_LOCATION(sysLogger::get(), debug, ARG);
+#define LOG_INFO(ARG) LOG_LOG_LOCATION(sysLogger::get(), info, ARG);
+#define LOG_WARN(ARG) LOG_LOG_LOCATION(sysLogger::get(), warning, ARG);
+#define LOG_ERROR(ARG) LOG_LOG_LOCATION(sysLogger::get(), error, ARG);
+#define LOG_FATAL(ARG) LOG_LOG_LOCATION(sysLogger::get(), fatal, ARG);
+
+/// Data Log macros. Does not include LINE, FILE, FUNCTION.
+/// TRACE < DEBUG < INFO < WARN < ERROR < FATAL
+#define LOG_DATA_TRACE(ARG) BOOST_LOG_SEV(dataLogger::get(), boost::log::trivial::trace) << ARG
+#define LOG_DATA_DEBUG(ARG) BOOST_LOG_SEV(dataLogger::get(), boost::log::trivial::debug) << ARG
+#define LOG_DATA_INFO(ARG) BOOST_LOG_SEV(dataLogger::get(), boost::log::trivial::info) << ARG
+#define LOG_DATA_WARN(ARG) BOOST_LOG_SEV(dataLogger::get(), boost::log::trivial::warning) << ARG
+#define LOG_DATA_ERROR(ARG) BOOST_LOG_SEV(dataLogger::get(), boost::log::trivial::error) << ARG
+#define LOG_DATA_FATAL(ARG) BOOST_LOG_SEV(dataLogger::get(), boost::log::trivial::fatal) << ARG
+
+#endif /* LOG_LOGGER_H */
\ No newline at end of file
diff --git a/src/SourceCodeWriter.h b/include/SourceCodeWriter.h
similarity index 67%
rename from src/SourceCodeWriter.h
rename to include/SourceCodeWriter.h
index f315097..5bba049 100644
--- a/src/SourceCodeWriter.h
+++ b/include/SourceCodeWriter.h
@@ -8,30 +8,36 @@
#include
#include "models/GetOptSetup.h"
+/**
+ * @brief Class for the SourceCodeWriter
+ */
class SourceCodeWriter {
private:
+ /**
+ * @brief The GetOptSetup
+ */
GetOptSetup *getOptSetup = nullptr;
+ /**
+ * @brief The header file
+ */
FILE *headerFile = nullptr;
+ /**
+ * @brief The source file
+ */
FILE *sourceFile = nullptr;
+ /**
+ * @brief Output directory
+ */
+ std::string outputDir;
+
// Helpers
+ /**
+ * @brief Get the type of the option depending on ConvertTo
+ * @param option The option
+ * @return The type of the option as string
+ */
static string getValueTypeByOption(Option &option);
-public:
- // Constructor
- explicit SourceCodeWriter(GetOptSetup *getOptSetup);
- ~SourceCodeWriter();
-
- // Getter
- GetOptSetup *getGetOptSetup() const;
- FILE *getHeaderFile();
- FILE *getSourceFile();
-
- // Setter
- void setHeaderFile(FILE *headerFile);
- void setSourceFile(FILE *sourceFile);
-
- // Methods
- void writeFile();
// Write code functions
/**
@@ -130,14 +136,61 @@ class SourceCodeWriter {
* @brief
* Generates the declaration of the printVersion function in the Header-File
*/
- void createHeaderPrintVersion();
+ void createHeaderPrintVersion();
+
+ /**
+ * @brief
+ * Generates the implementation of the printVersion function in the Source-File
+ */
+ void createSourcePrintVersion();
+
+ /**
+ * @brief
+ * Generates the declaration of the printHelp function in the Header-File
+ */
+ void createHeaderPrintHelp();
+
+ /**
+ * @brief
+ * Generates the implementation of the printHelp function in the Source-File
+ */
+ void createSourcePrintHelp();
+public:
+ // Constructor
+ /**
+ * @brief Constructor for the SourceCodeWriter
+ * @param getOptSetup The GetOptSetup
+ */
+ explicit SourceCodeWriter(GetOptSetup *getOptSetup);
+ /**
+ * @brief Destructor for the SourceCodeWriter
+ */
+ ~SourceCodeWriter();
+
+ /** @name Getter
+ * @brief Getter for the class
+ */
+ ///@{
+ GetOptSetup *getGetOptSetup() const;
+ FILE *getHeaderFile();
+ FILE *getSourceFile();
+ std::string getOutputDir();
+ ///@}
- /**
- * @brief
- * Generates the implementation of the printVersion function in the Source-File
- */
- void createSourcePrintVersion();
+ /** @name Setter
+ * @brief Setter for the class
+ */
+ ///@{
+ void setHeaderFile(FILE *headerFile);
+ void setSourceFile(FILE *sourceFile);
+ void setOutputDir(const std::string &dir);
+ ///@}
+ // Methods
+ /**
+ * @brief Write the .h and .cpp files
+ */
+ void writeFile();
};
diff --git a/src/StateMachine.h b/include/StateMachine.h
similarity index 100%
rename from src/StateMachine.h
rename to include/StateMachine.h
diff --git a/src/XMLParser.h b/include/XMLParser.h
similarity index 79%
rename from src/XMLParser.h
rename to include/XMLParser.h
index d38ac9b..44bb704 100644
--- a/src/XMLParser.h
+++ b/include/XMLParser.h
@@ -17,6 +17,9 @@ XERCES_CPP_NAMESPACE_USE
using namespace std;
+/**
+ * @brief Class for the XMLParser
+ */
class XMLParser : public HandlerBase {
private:
/**
@@ -25,11 +28,17 @@ class XMLParser : public HandlerBase {
*/
std::string filename;
+ /**
+ * @brief stateMachine
+ * StateMachine to parse the file.
+ */
StateMachine *sm = new StateMachine();
+ /**
+ * @brief getOptSetup
+ * GetOptSetup to parse the file.
+ */
GetOptSetup *getOptSetup = new GetOptSetup();
-
- wstring_convert,char16_t> converter;
public:
/**
* @brief XMLParser
@@ -38,6 +47,9 @@ class XMLParser : public HandlerBase {
*/
explicit XMLParser(const string &filename);
+ /**
+ * @brief The main parser function.
+ */
void parse();
void startDocument() override;
@@ -48,7 +60,7 @@ class XMLParser : public HandlerBase {
/**
* @brief getGetOptSetup
- * @return
+ * @return getOptSetup
*/
GetOptSetup *getGetOptSetup() const;
};
diff --git a/src/models/Author.h b/include/models/Author.h
similarity index 68%
rename from src/models/Author.h
rename to include/models/Author.h
index 7a5794f..30d0153 100644
--- a/src/models/Author.h
+++ b/include/models/Author.h
@@ -12,22 +12,38 @@
XERCES_CPP_NAMESPACE_USE
using namespace std;
+/**
+ * @brief Class for the Author-Tag
+ */
class Author {
public:
- // Constructors
+ /**
+ * @brief Constructor for the Author-Tag
+ */
Author();
- // Getters
+ /** @name Getter
+ * @brief Getter for the class
+ */
+ ///@{
const string &getName() const;
const string &getPhone() const;
const string &getMail() const;
+ ///@}
- // Setters
+ /** @name Setter
+ * @brief Setter for the class
+ */
+ ///@{
void setName(const string &name);
void setPhone(const string &phone);
void setMail(const string &email);
+ ///@}
- // Helpers
+ /**
+ * @brief Function to parse the Author-Tag
+ * @param attributes AttributeList of the Author-Tag
+ */
void parseAttributes(AttributeList &attributes);
private:
diff --git a/src/models/GetOptSetup.h b/include/models/GetOptSetup.h
similarity index 83%
rename from src/models/GetOptSetup.h
rename to include/models/GetOptSetup.h
index 2f2569a..86393d9 100644
--- a/src/models/GetOptSetup.h
+++ b/include/models/GetOptSetup.h
@@ -14,12 +14,20 @@
XERCES_CPP_NAMESPACE_USE
+/**
+ * @brief Class for the GetOptSetup-Tag
+ */
class GetOptSetup {
public:
- // Constructors
+ /**
+ * @brief Constructor for the GetOptSetup-Class
+ */
GetOptSetup();
- // Getters
+ /** @name Getter
+ * @brief Getter for the class
+ */
+ ///@{
const int &getSignPerLine() const;
const Author &getAuthor() const;
const string &getHeaderFileName() const;
@@ -29,8 +37,12 @@ class GetOptSetup {
const vector &getOverAllDescriptions() const;
const vector &getSampleUsages() const;
const vector &getOptions() const;
+ ///@}
- // Setters
+ /** @name Setter
+ * @brief Setter for the class
+ */
+ ///@{
void setSignPerLine(const string &signPerLine);
void setAuthor(const Author &author);
void setHeaderFileName(const string &headerFileName);
@@ -40,13 +52,22 @@ class GetOptSetup {
void setOverAllDescriptions(const vector &overAllDescriptions);
void setSampleUsages(const vector &sampleUsages);
void setOptions(const vector &options);
+ ///@}
- // Adders
+ /** @name Adder
+ * @brief Adder for the class
+ */
+ ///@{
void addOverAllDescription(const string &overAllDescription);
void addSampleUsage(const string &sampleUsage);
void addOption(const Option &option);
+ ///@}
// Helpers
+ /**
+ * @brief Function to check if the class is valid
+ * @param attributes AttributeList of the GetOptSetup-Tag
+ */
void parseAttributes(AttributeList &attributes);
private:
/**
diff --git a/src/models/Option.h b/include/models/Option.h
similarity index 87%
rename from src/models/Option.h
rename to include/models/Option.h
index 0f788ba..cd612df 100644
--- a/src/models/Option.h
+++ b/include/models/Option.h
@@ -12,24 +12,36 @@
XERCES_CPP_NAMESPACE_USE
+/**
+ * @brief enum for the ConvertTo of the Option-Tag
+ */
enum class ConvertToOptions {
STRING,
INTEGER,
BOOLEAN
};
+/**
+ * @brief enum for the HasArguments of the Option-Tag
+ */
enum class HasArguments {
NONE,
OPTIONAL,
REQUIRED
};
+/**
+ * @brief Class for the Option-Tag
+ */
class Option {
public:
// Constructor
Option();
- // Getters
+ /** @name Getter
+ * @brief Getter for the class
+ */
+ ///@{
int getRef() const;
char getShortOpt() const;
const std::string &getLongOpt() const;
@@ -41,8 +53,12 @@ class Option {
ConvertToOptions getConvertTo() const;
std::string getDefaultValue() const;
std::string getInterface() const;
+ ///@}
- // Setters
+ /** @name Setter
+ * @brief Setter for the class
+ */
+ ///@{
void setRef(const std::string &ref);
void setShortOpt(const std::string &shortOpt);
void setLongOpt(const std::string &longOpt);
@@ -54,8 +70,12 @@ class Option {
void setConvertTo(const std::string &convertTo);
void setDefaultValue(const std::string &defaultValue);
void setInterface(const std::string &interface);
+ ///@}
- // Helpers
+ /**
+ * @brief Function to parse the Option-Tag
+ * @param attributes AttributeList of the Option-Tag
+ */
void parseAttributes(AttributeList &attributes);
private:
/**
diff --git a/include2/ExampleProgram.h b/include2/ExampleProgram.h
new file mode 100644
index 0000000..36b2afe
--- /dev/null
+++ b/include2/ExampleProgram.h
@@ -0,0 +1,29 @@
+/*
+ * Editors: Philipp Kuest, Tobias Goetz
+ */
+
+#ifndef CODEGENERATOR_EXAMPLEPROGRAM_H
+#define CODEGENERATOR_EXAMPLEPROGRAM_H
+
+
+#include "ExtendedGeneratedCode.h"
+
+class ExampleProgram {
+private:
+ GC::GeneratedClass *generatedClass = nullptr;
+protected:
+public:
+ /**
+ * @brief Constructor, that generates a object of ExtendedGeneratedCode
+ */
+ explicit ExampleProgram(GC::GeneratedClass *generatedClass);
+
+ /**
+ * @brief Getter for generatedClass
+ * @return object of class ExtendedGeneratedCode
+ */
+ GC::GeneratedClass *getGeneratedClass();
+};
+
+
+#endif //CODEGENERATOR_EXAMPLEPROGRAM_H
diff --git a/include2/ExtendedGeneratedCode.h b/include2/ExtendedGeneratedCode.h
new file mode 100644
index 0000000..2a81587
--- /dev/null
+++ b/include2/ExtendedGeneratedCode.h
@@ -0,0 +1,22 @@
+/*
+ * Editors: Philipp Kuest, Tobias Goetz
+ */
+
+#ifndef CODEGENERATOR_EXTENDEDGENERATEDCODE_H
+#define CODEGENERATOR_EXTENDEDGENERATEDCODE_H
+
+#include "generatedCode.h"
+
+/**
+ * class with inheritance to generated class to use getopt of generated files
+ */
+class ExtendedGeneratedCode: public GC::GeneratedClass {
+
+ /**
+ * @brief overrides printVersion function in generated Code
+ */
+ void printVersion() override;
+};
+
+
+#endif //CODEGENERATOR_EXTENDEDGENERATEDCODE_H
diff --git a/logconfig.ini b/logconfig.ini
new file mode 100644
index 0000000..2a1c3ca
--- /dev/null
+++ b/logconfig.ini
@@ -0,0 +1,81 @@
+#
+# See http://www.boost.org/doc/libs/1_60_0/libs/log/doc/html/log/detailed/utilities.html#log.detailed.utilities.setup.filter_formatter
+#
+# Many of the property values have to be in quotes, best to just use quotes for all of them.
+#
+# SYSLF is the System Log File for logging standard 'debug' type info.
+# DATALF is the Data log File for logging modification to business data.
+#
+[Core]
+# Set DisableLogging to true to disable all logging.
+DisableLogging="false"
+
+# SYSLF - system log
+[Sinks.SYSLF]
+Destination="TextFile"
+# If Asynchronous true then thread dedicated to writing to log, otherwise blocks main thread to write.
+Asynchronous="true"
+# If AutoFlush is true then non-buffered output
+AutoFlush="true"
+# Line Formats available: TimeStamp, Uptime, Severity, LineID (counter), ProcessID, ThreadID, Line, File, Function
+# TimeStamp and Uptime support boost date time format:
+# http://www.boost.org/doc/libs/1_60_0/doc/html/date_time/date_time_io.html#date_time.format_flags
+Format="[%TimeStamp(format=\"%Y-%m-%d %H:%M:%S.%f\")%][%Uptime(format=\"%O:%M:%S.%f\")%][%Severity%] %File%(%Line%) %Function%: %Message%"
+# Target directory in which rotated files will be stored.
+Target="./logs"
+# FileName pattern to use. %N is a counter for files.
+FileName="app_syslog_%N.log"
+# RotationSize in bytes, File size, in bytes, upon which file rotation will be performed.
+# Time based rotation also available via RotationInterval and RotationTimePoint see boost log docs.
+RotationSize="10485760"
+# Matching used so that only files matching FileName pattern are deleted.
+ScanForFiles="Matching"
+# MaxSize - Total size of files in the target directory in bytes upon which the oldest file will be deleted.
+#MaxSize=100485760
+# MinFreeSpace - Minimum free space in the Target directory in bytes. Above this value oldest file is deleted.
+#MinFreeSpace=1485760
+# Specify level of log, options are: trace, debug, info, warning, error, fatal
+# Since Channel not part of filter all log output will be included.
+# If only SYSLF logging desired, change to: Filter="%Severity% >= trace & %Channel% matches \"SYSLF\""
+Filter="%Severity% >= trace"
+
+# DATALF - data log
+[Sinks.DATALF]
+Destination="TextFile"
+# If Asynchronous true then thread dedicated to writing to log, otherwise blocks main thread to write.
+Asynchronous="false"
+# If AutoFlush is true then non-buffered output
+AutoFlush="true"
+# Line Formats available: TimeStamp, Uptime, Severity, LineID (counter), ProcessID, ThreadID
+# TimeStamp and Uptime support boost date time format:
+# http://www.boost.org/doc/libs/1_60_0/doc/html/date_time/date_time_io.html#date_time.format_flags
+Format="[%TimeStamp(format=\"%Y-%m-%d %H:%M:%S.%f\")%][%Uptime(format=\"%O:%M:%S.%f\")%][%Severity%] %Message%"
+# Target directory in which rotated files will be stored.
+Target="./logs"
+# FileName pattern to use. %N is a counter for files.
+FileName="app_datalog_%N.log"
+# RotationSize in bytes, File size, in bytes, upon which file rotation will be performed.
+# Time based rotation also available via RotationInterval and RotationTimePoint see boost log docs.
+RotationSize="10485760"
+# Matching used so that only files matching FileName pattern are deleted.
+ScanForFiles="Matching"
+# MaxSize - Total size of files in the target directory in bytes upon which the oldest file will be deleted.
+#MaxSize=100485760
+# MinFreeSpace - Minimum free space in the Target directory in bytes. Above this value oldest file is deleted.
+#MinFreeSpace=1485760
+# Specify level of log, options are: trace, debug, info, warning, error, fatal
+# Specify Channel otherwise all log output will be included.
+Filter="%Severity% >= trace & %Channel% matches \"DATALF\""
+
+# Console log, logs both DATALF and SYSLF
+[Sinks.Console]
+# Remove the following lines to disable console logging
+Destination="Console"
+# If AutoFlush is true then non-buffered output
+AutoFlush="true"
+# Line Formats available: TimeStamp, Uptime, Severity, LineID (counter), ProcessID, ThreadID
+# TimeStamp and Uptime support boost date time format:
+# http://www.boost.org/doc/libs/1_60_0/doc/html/date_time/date_time_io.html#date_time.format_flags
+Format="[%TimeStamp(format=\"%Y-%m-%d %H:%M:%S.%f\")%][%Uptime(format=\"%O:%M:%S.%f\")%][%Severity%] - %Message%"
+# Specify level of log, options are: trace, debug, info, warning, error, fatal
+Filter="%Severity% >= info"
\ No newline at end of file
diff --git a/src/CodeGenerator.cpp b/src/CodeGenerator.cpp
index d57370f..3c2119a 100644
--- a/src/CodeGenerator.cpp
+++ b/src/CodeGenerator.cpp
@@ -1,18 +1,95 @@
/*
- * Editors: Tobias Goetz
+ * Editors: Tobias Goetz, Noel Kempter
*/
-
#include "CodeGenerator.h"
#include "XMLParser.h"
#include "SourceCodeWriter.h"
-#include
+#include "Logger.h"
+#include
+
+std::string CodeGenerator::getFilePath() {
+ return CodeGenerator::filePath;
+}
+
+std::string CodeGenerator::getOutputDir() {
+ return outputDir;
+}
+
+void CodeGenerator::setFilePath(const std::string &filename) {
+ CodeGenerator::filePath = filename;
+}
-int main() {
- printf("Starting Codegenerator!\n");
- XMLParser parser("example/Example.xml");
+void CodeGenerator::setOutputDir(const std::string &dir) {
+ outputDir = dir;
+}
+
+void CodeGenerator::run() {
+ LOG_INFO("Starting CodeGenerator");
+ if(getFilePath().empty()){
+ perror("The path to the XML-File must be set.");
+ LOG_ERROR("The path to the XML-File must be set.");
+ exit(EXIT_FAILURE);
+ }
+
+ LOG_INFO("Starting XMLParser");
+ XMLParser parser(getFilePath());
parser.parse();
+ LOG_INFO("Finished XMLParser");
+
+ LOG_INFO("Starting SourceCodeWriter");
SourceCodeWriter writer = SourceCodeWriter(parser.getGetOptSetup());
+ writer.setOutputDir(getOutputDir());
writer.writeFile();
- printf("Codegenerator finished!\n");
+ LOG_INFO("Finished SourceCodeWriter");
+
+ LOG_INFO("Codegenerator finished!");
+}
+
+
+int main(int argc, char **argv) {
+ Logger::initFromConfig("logconfig.ini");
+
+ CodeGenerator generator;
+ int c;
+ int option_index;
+ static struct option long_options[] = {
+ {"path", required_argument, 0, 'p'},
+ {"output", required_argument, 0, 'o'},
+ {0, 0, 0, 0}
+ };
+
+ while((c = getopt_long(argc, argv, "p:o:", long_options, &option_index)) != -1 ){
+ switch(c){
+ case 'p':
+ if (optarg == nullptr){
+ perror("The path to the XML-File to be parsed was not set.");
+ LOG_ERROR("The path to the XML-File to be parsed was not set.");
+ exit(EXIT_FAILURE);
+ }
+ generator.setFilePath(optarg);
+ break;
+ case 'o':
+ if(optarg == nullptr){
+ perror("When using \"-o/--output\" the path to the target directory must be set.");
+ LOG_ERROR("When using \"-o/--output\" the path to the target directory must be set.");
+ exit(EXIT_FAILURE);
+ }
+ generator.setOutputDir(optarg);
+ break;
+ case '?':
+ default:
+ perror("GetOpt encountered an unknown option.");
+ LOG_ERROR("GetOpt encountered an unknown option.");
+ exit(EXIT_FAILURE);
+ }
+ }
+ if (optind < argc) {
+ printf("non-option ARGV-elements: ");
+ while (optind < argc)
+ printf("%s ", argv[optind++]);
+ printf("\n");
+ }
+
+ generator.run();
return 0;
-}
\ No newline at end of file
+}
diff --git a/src/CodeGenerator.h b/src/CodeGenerator.h
deleted file mode 100644
index 11f015b..0000000
--- a/src/CodeGenerator.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Editors: Tobias Goetz
- */
-
-#ifndef PROGRAMMING_C_CODEGENERATOR_H
-#define PROGRAMMING_C_CODEGENERATOR_H
-
-
-class CodeGenerator{
-};
-
-
-#endif //PROGRAMMING_C_CODEGENERATOR_H
diff --git a/src/HelpText.cpp b/src/HelpText.cpp
new file mode 100644
index 0000000..7b15811
--- /dev/null
+++ b/src/HelpText.cpp
@@ -0,0 +1,167 @@
+/*
+ * Editors: Sebastian Wolf, Tobias Goetz
+ */
+
+#include "HelpText.h"
+#include "Logger.h"
+
+HelpText::HelpText(GetOptSetup *getOptSetup)
+{
+ this->getOptSetup = getOptSetup;
+}
+HelpText::~HelpText() = default;
+
+void HelpText::parseDescription()
+{
+ string new_description;
+
+ for (int i = 0; i < getOptSetup->getOverAllDescriptions().size(); i++)
+ {
+ // Add empty space in front of every string except the first
+ if (i > 0) {
+ new_description.append(" ");
+ }
+ // concatenate strings
+ new_description.append(getOptSetup->getOverAllDescriptions()[i]);
+ }
+ // justify and add to printHelpText
+ printHelpText.append("Description:\\n" + justify.justifyTheText(new_description, getOptSetup->getSignPerLine(), false, 0) + "\\n");
+}
+
+bool compareOptions(const Option &a, const Option &b) {
+ if (a.getShortOpt() != '\0' && b.getShortOpt() != '\0') {
+ return a.getShortOpt() < b.getShortOpt();
+ }
+ else if (a.getShortOpt() != '\0') {
+ return true;
+ }
+ else if (b.getShortOpt() != '\0') {
+ return false;
+ }
+ else {
+ return a.getLongOpt() < b.getLongOpt();
+ }
+}
+
+vector HelpText::concatParams(const vector& options)
+{
+ vector opts;
+
+ for (const auto & option : options) {
+ string opt;
+ // check if shortOpt isn't empty
+ if (option.getShortOpt() != '\0')
+ {
+ // for e.g. -h
+ opt += '-';
+ opt += option.getShortOpt();
+ // check if longOpt isn't empty
+ if (!option.getLongOpt().empty())
+ {
+ // for e.g. , --help
+ opt.append(", --" + option.getLongOpt());
+ }
+ }
+
+ // check if only longOpt isn't empty
+ else if (!option.getLongOpt().empty())
+ {
+ // for e.g. --help
+ opt.append("--" + option.getLongOpt());
+ }
+
+ // Find out the longest parameter length
+ if (opt.size() > maxOptionParamLength) {
+ maxOptionParamLength = (int) opt.length();
+ }
+ opts.push_back(opt);
+ }
+ return opts;
+}
+
+void HelpText::parseOption()
+{
+ // sorting options
+ vector sortedOpts = getOptSetup->getOptions();
+ std::sort(sortedOpts.begin(), sortedOpts.end(), compareOptions);
+
+ // concatenate params
+ vector opts = concatParams(sortedOpts);
+
+ // concatenate the options
+ std::stringstream buffer;
+ buffer << std::left << std::setw(maxOptionParamLength + shift) << "Parameters";
+ buffer << "Description" << "\\n";
+
+ for (int i = 0; i < sortedOpts.size(); i++)
+ {
+ // get the concatenated params
+ buffer << std::left << std::setw(maxOptionParamLength + shift) << opts[i];
+
+ // check if description isn't empty
+ if (!getOptSetup->getOptions()[i].getDescription().empty())
+ {
+ // subtract the length of the params and the shift
+ // to get the new signPerLine for the options
+ // needs to be less because of the Params and the shift
+ int new_signPerLine = getOptSetup->getSignPerLine() - maxOptionParamLength - shift;
+ // new shift for every description line after the first, to match the first line
+ int optionShift = maxOptionParamLength + shift;
+
+ // justify the description text
+ string new_description = justify.justifyTheText(sortedOpts[i].getDescription(), new_signPerLine, true, optionShift);
+ buffer << new_description;
+ }
+ }
+ buffer << "\\n";
+ printHelpText.append(buffer.str());
+}
+
+void HelpText::parseUsage()
+{
+ string new_usage;
+ for (const auto & sampleUsage : getOptSetup->getSampleUsages()) {
+ new_usage.append(sampleUsage + "\\n");
+ }
+ printHelpText.append("Usage:\\n" + justify.justifyTheText(new_usage, getOptSetup->getSignPerLine(), false, 0));
+}
+
+void HelpText::parseAuthor()
+{
+ printHelpText.append("Author:\\n" + justify.justifyTheText(getOptSetup->getAuthor().getName() + ", " + getOptSetup->getAuthor().getMail(), getOptSetup->getSignPerLine(), false, 0));
+}
+
+string HelpText::parseHelpMessage()
+{
+ LOG_TRACE("Starting to parse help message");
+ // add function beginning to string
+ printHelpText.append("void ");
+ printHelpText.append(getOptSetup->getClassName());
+ printHelpText.append("::printHelp(){puts(\"");
+
+ // parse the description and add text to string
+ LOG_TRACE("Starting to parse description");
+ parseDescription();
+ LOG_TRACE("Finished parsing description");
+
+ // parse the option and add text to string
+ LOG_TRACE("Starting to parse option");
+ parseOption();
+ LOG_TRACE("Finished parsing option");
+
+ // parse the usage and add text to string
+ LOG_TRACE("Starting to parse usage");
+ parseUsage();
+ LOG_TRACE("Finished parsing usage");
+
+ // parse the author and add text to string
+ LOG_TRACE("Starting to parse author");
+ parseAuthor();
+ LOG_TRACE("Finished parsing author");
+
+ // add function ending to string
+ printHelpText.append(R"(");})");
+ LOG_TRACE("Finished parsing help message");
+
+ return printHelpText;
+}
diff --git a/src/Justify.cpp b/src/Justify.cpp
new file mode 100644
index 0000000..5f5dd89
--- /dev/null
+++ b/src/Justify.cpp
@@ -0,0 +1,236 @@
+/*
+ * Editors: Sebastian Wolf
+ */
+
+#include "Justify.h"
+#include "Logger.h"
+
+string Justify::JoinALineWithSpace(
+ vector& words,
+ int start, int end,
+ int num_spaces,
+ bool isOption,
+ int curr_line,
+ int optionShift)
+{
+
+ // Number of words in current line
+ int num_words_curr_line
+ = end - start + 1;
+
+ // String to store the justified text
+ string line;
+
+ for (int i = start; i < end; i++) {
+
+ line += words[i];
+ --num_words_curr_line;
+
+ // Count number of current space needed
+ int num_curr_space
+ = ceil((double)(num_spaces)
+ / num_words_curr_line);
+
+ // Insert spaces in string line
+ line.append(num_curr_space, ' ');
+
+ // Delete the spaces inserted in line
+ num_spaces -= num_curr_space;
+ }
+
+ // Insert word to string line
+ if (!isOption || curr_line == 1)
+ {
+ line += words[end];
+ line.append(num_spaces, ' ');
+ }
+ else if (curr_line > 1)
+ {
+ line += words[end];
+ line.insert(0, optionShift, ' ');
+ }
+
+
+ // Return justified text
+ return line;
+}
+
+vector Justify::JustifyText(
+ vector& words,
+ int L,
+ bool isOption,
+ int optionShift)
+{
+
+ int curr_line = 1;
+ int curr_line_start = 0;
+ int num_words_curr_line = 0;
+ int curr_line_length = 0;
+
+ // To store the justified text
+ vector result;
+
+ // Traversing the words array
+ for (int i = 0; i < words.size(); i++) {
+
+ // curr_line_start is the first word
+ // in the current line, and i is
+ // used to identify the last word
+ ++num_words_curr_line;
+
+ int lookahead_line_length
+ = curr_line_length
+ + (int)words[i].size()
+ + (num_words_curr_line - 1);
+
+ // If by including the words length becomes L,
+ // then that set of words is justified
+ // and add the justified text to result
+ if (lookahead_line_length == L) {
+
+ // Justify the set of words
+ string ans
+ = JoinALineWithSpace(
+ words,
+ curr_line_start,
+ i,
+ i - curr_line_start,
+ isOption,
+ curr_line,
+ optionShift);
+
+ // Store the justified text in result
+ result.emplace_back(ans);
+
+ // Start the current line
+ // with next index
+ curr_line_start = i + 1;
+
+ // num of words in the current line
+ // and current line length set to 0
+ num_words_curr_line = 0;
+ curr_line_length = 0;
+ curr_line += 1;
+ }
+
+ // If by including the words such that
+ // length of words becomes greater than L,
+ // then hat set is justified with
+ // one less word and add the
+ // justified text to result
+ else if (lookahead_line_length > L) {
+
+ // Justify the set of words
+ string ans
+ = JoinALineWithSpace(
+ words,
+ curr_line_start,
+ i - 1,
+ L - curr_line_length,
+ isOption,
+ curr_line,
+ optionShift);
+
+ // Store the justified text in result
+ result.emplace_back(ans);
+
+ // Current line set to current word
+ curr_line_start = i;
+
+ // Number of words set to 1
+ num_words_curr_line = 1;
+
+ // Current line length set
+ // to current word length
+ curr_line_length = (int)words[i].size();
+ curr_line += 1;
+ }
+
+ // If length is less than L then,
+ // add the word to current line length
+ else {
+ curr_line_length
+ += (int)words[i].size();
+ }
+ }
+
+ // Last line is to be left-aligned
+ if (num_words_curr_line > 0) {
+ string line
+ = JoinALineWithSpace(
+ words,
+ curr_line_start,
+ (int)words.size() - 1,
+ num_words_curr_line - 1,
+ isOption,
+ curr_line,
+ optionShift);
+
+ line.append(
+ L - curr_line_length
+ - (num_words_curr_line - 1),
+ ' ');
+
+ // Insert the last line
+ // left-aligned to result
+ result.emplace_back(line);
+ }
+
+ // Return result
+ return result;
+}
+
+vector Justify::splitWords(const string& str)
+{
+
+ vector words;
+
+ // Tokenizer separates string to words
+ char_separator sep(" ");
+ tokenizer > tok(str, sep);
+ for (auto it=tok.begin(); it!=tok.end(); ++it)
+ {
+ // push words to vector
+ words.push_back(*it);
+ }
+
+ // Return the vector of
+ // words extracted from
+ // string
+ return words;
+}
+
+string Justify::returnJustifiedText(vector& result)
+{
+ stringstream buffer;
+
+ for (auto& it : result) {
+ buffer << it << "\\n";
+ }
+ return buffer.str();
+}
+
+string Justify::justifyTheText(const string& str, int L, bool isOption, int optionShift)
+{
+ LOG_TRACE("Starting Justify::justifyTheText");
+
+ vector words;
+
+ // Inserting words from
+ // given string
+ LOG_TRACE("Inserting words from given string");
+ words = this->splitWords(str);
+ LOG_TRACE("Inserting words from given string done");
+
+ // Function call to
+ // justify the text
+ LOG_TRACE("Function call to justify the text");
+ vector result
+ = this->JustifyText(words, L, isOption, optionShift);
+ LOG_TRACE("Function call to justify the text done");
+ // Return the justified
+ // text
+
+ LOG_TRACE("Returning the justified text");
+ return returnJustifiedText(result);
+}
\ No newline at end of file
diff --git a/src/Logger.cpp b/src/Logger.cpp
new file mode 100644
index 0000000..4488f07
--- /dev/null
+++ b/src/Logger.cpp
@@ -0,0 +1,164 @@
+/*
+ * Editors: Tobias Goetz, Sebastian Wolf
+ */
+
+#include "Logger.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+BOOST_LOG_GLOBAL_LOGGER_CTOR_ARGS(sysLogger,
+ boost::log::sources::severity_channel_logger_mt,
+ (boost::log::keywords::channel = "SYSLF"));
+
+BOOST_LOG_GLOBAL_LOGGER_CTOR_ARGS(dataLogger,
+ boost::log::sources::severity_channel_logger_mt,
+ (boost::log::keywords::channel = "DATALF"));
+
+// Custom formatter factory to add TimeStamp format support in config ini file.
+// Allows %TimeStamp(format=\"%Y.%m.%d %H:%M:%S.%f\")% to be used in ini config file for property Format.
+class TimeStampFormatterFactory :
+ public boost::log::basic_formatter_factory
+{
+public:
+ formatter_type create_formatter(const boost::log::attribute_name& name, const args_map& args) {
+ args_map::const_iterator it = args.find("format");
+ if (it != args.end()) {
+ return boost::log::expressions::stream
+ << boost::log::expressions::format_date_time(
+ boost::log::expressions::attr(name), it->second);
+ } else {
+ return boost::log::expressions::stream
+ << boost::log::expressions::attr(name);
+ }
+ }
+};
+
+// Custom formatter factory to add Uptime format support in config ini file.
+// Allows %Uptime(format=\"%O:%M:%S.%f\")% to be used in ini config file for property Format.
+// boost::log::attributes::timer value type is boost::posix_time::time_duration
+class UptimeFormatterFactory :
+ public boost::log::basic_formatter_factory
+{
+public:
+ formatter_type create_formatter(const boost::log::attribute_name& name, const args_map& args)
+ {
+ args_map::const_iterator it = args.find("format");
+ if (it != args.end()) {
+ return boost::log::expressions::stream
+ << boost::log::expressions::format_date_time(
+ boost::log::expressions::attr(name), it->second);
+ } else {
+ return boost::log::expressions::stream
+ << boost::log::expressions::attr(name);
+ }
+ }
+};
+
+void
+Logger::init() {
+ initFromConfig("");
+}
+
+void
+Logger::initFromConfig(const std::string& configFileName) {
+ // Disable all exceptions
+ boost::log::core::get()->set_exception_handler(boost::log::make_exception_suppressor());
+
+ // Add common attributes: LineID, TimeStamp, ProcessID, ThreadID
+ boost::log::add_common_attributes();
+ // Add boost log timer as global attribute Uptime
+ boost::log::core::get()->add_global_attribute("Uptime", boost::log::attributes::timer());
+ // Allows %Severity% to be used in ini config file for property Filter.
+ boost::log::register_simple_filter_factory("Severity");
+ // Allows %Severity% to be used in ini config file for property Format.
+ boost::log::register_simple_formatter_factory("Severity");
+ // Allows %TimeStamp(format=\"%Y.%m.%d %H:%M:%S.%f\")% to be used in ini config file for property Format.
+ boost::log::register_formatter_factory("TimeStamp", boost::make_shared());
+ // Allows %Uptime(format=\"%O:%M:%S.%f\")% to be used in ini config file for property Format.
+ boost::log::register_formatter_factory("Uptime", boost::make_shared());
+
+ if (configFileName.empty()) {
+ // Make sure we log to console if nothing specified.
+ // Severity logger logs to console by default.
+ } else {
+ std::ifstream ifs(configFileName);
+ if (!ifs.is_open()) {
+ // We can log this because console is setup by default
+ LOG_WARN("Unable to open logging config file: " << configFileName);
+ } else {
+ try {
+ // Still can throw even with the exception suppressor above.
+ boost::log::init_from_stream(ifs);
+ } catch (std::exception &e) {
+ std::string err = "Caught exception initializing boost logging: ";
+ err += e.what();
+ // Since we cannot be sure of boost log state, output to cerr and cout.
+ std::cerr << "ERROR: " << err << std::endl;
+ std::cout << "ERROR: " << err << std::endl;
+ LOG_ERROR(err);
+ }
+ }
+ }
+
+ // Indicate start of logging
+ LOG_INFO("Log Start");
+}
+
+void
+Logger::disable() {
+ boost::log::core::get()->set_logging_enabled(false);
+}
+
+
+void
+Logger::addDataFileLog(const std::string& logFileName) {
+ // Create a text file sink
+ boost::shared_ptr backend(
+ new boost::log::sinks::text_ostream_backend());
+ backend->add_stream(boost::shared_ptr(new std::ofstream(logFileName)));
+
+ // Flush after each log record
+ backend->auto_flush(true);
+
+ // Create a sink for the backend
+ typedef boost::log::sinks::synchronous_sink sink_t;
+ boost::shared_ptr sink(new sink_t(backend));
+
+ // The log output formatter
+ sink->set_formatter(
+ boost::log::expressions::format("[%1%][%2%] %3%")
+ % boost::log::expressions::attr("TimeStamp")
+ % boost::log::trivial::severity
+ % boost::log::expressions::smessage
+ );
+
+ // Filter by severity and by DATALF channel
+ sink->set_filter(
+ boost::log::trivial::severity >= boost::log::trivial::info &&
+ boost::log::expressions::attr("Channel") == "DATALF");
+
+ // Add it to the core
+ boost::log::core::get()->add_sink(sink);
+}
\ No newline at end of file
diff --git a/src/SourceCodeWriter.cpp b/src/SourceCodeWriter.cpp
index f2ba625..02bc8aa 100644
--- a/src/SourceCodeWriter.cpp
+++ b/src/SourceCodeWriter.cpp
@@ -3,16 +3,20 @@
*/
#include "SourceCodeWriter.h"
+#include "Logger.h"
+#include "HelpText.h"
#include
// Constructor
SourceCodeWriter::SourceCodeWriter(GetOptSetup *getOptSetup) {
if (getOptSetup->getSourceFileName().empty() || getOptSetup->getHeaderFileName().empty()) {
+ LOG_ERROR("No source or header file name given.");
perror("Both the Header-Filename and the Sourcefilename must be set.");
exit(1);
}
if (getOptSetup->getClassName().empty()) {
+ LOG_ERROR("No class name given.");
perror("The Class-Name must be set. ");
exit(1);
}
@@ -30,30 +34,42 @@ SourceCodeWriter::~SourceCodeWriter() {
// Getter
FILE *SourceCodeWriter::getHeaderFile() {
+ LOG_DEBUG("Getting Header-File: " + (getOutputDir() + getGetOptSetup()->getHeaderFileName()));
if (headerFile == nullptr) {
- setHeaderFile(fopen(getGetOptSetup()->getHeaderFileName().c_str(), "w"));
+ setHeaderFile(fopen((getOutputDir() + getGetOptSetup()->getHeaderFileName()).c_str(), "w"));
}
+ LOG_TRACE("Finished getting Header-File");
return headerFile;
}
FILE *SourceCodeWriter::getSourceFile() {
+ LOG_DEBUG("Getting Source-File: " + (getOutputDir() + getGetOptSetup()->getSourceFileName()));
if (sourceFile == nullptr) {
- setSourceFile(fopen(getGetOptSetup()->getSourceFileName().c_str(), "w"));
+ setSourceFile(fopen((getOutputDir() + getGetOptSetup()->getSourceFileName()).c_str(), "w"));
}
+ LOG_TRACE("Finished getting Source-File");
return sourceFile;
}
+std::string SourceCodeWriter::getOutputDir() {
+ return outputDir;
+}
+
GetOptSetup *SourceCodeWriter::getGetOptSetup() const {
return getOptSetup;
}
// Setter
-void SourceCodeWriter::setHeaderFile(FILE *headerFile) {
- this->headerFile = headerFile;
+void SourceCodeWriter::setHeaderFile(FILE *_headerFile) {
+ this->headerFile = _headerFile;
+}
+
+void SourceCodeWriter::setSourceFile(FILE *_sourceFile) {
+ this->sourceFile = _sourceFile;
}
-void SourceCodeWriter::setSourceFile(FILE *sourceFile) {
- this->sourceFile = sourceFile;
+void SourceCodeWriter::setOutputDir(const std::string &dir) {
+ outputDir = dir;
}
/*
@@ -65,8 +81,7 @@ void SourceCodeWriter::setSourceFile(FILE *sourceFile) {
* @param option a single option object
* @return string with correct value type
*/
-string SourceCodeWriter::getValueTypeByOption(Option &option)
-{
+string SourceCodeWriter::getValueTypeByOption(Option &option) {
switch (option.getConvertTo()) {
case ConvertToOptions::STRING:
return "std::string";
@@ -81,6 +96,7 @@ string SourceCodeWriter::getValueTypeByOption(Option &option)
//from here on are all the headerFiles
void SourceCodeWriter::headerFileIncludes() {
+ LOG_TRACE("Writing includes to Header-File");
// Define static and always used includes here
string includes[] = {"getopt.h", "iostream", "boost/lexical_cast.hpp"};
@@ -100,9 +116,11 @@ void SourceCodeWriter::headerFileIncludes() {
// Close header file
fprintf(getHeaderFile(), "\n#endif //%s_H", defineString.c_str());
+ LOG_TRACE("Finished writing includes to Header-File");
}
void SourceCodeWriter::headerFileNamespace() {
+ LOG_TRACE("Writing namespace to Header-File");
//start of namespace
if (!getGetOptSetup()->getNamespaceName().empty()) {
fprintf(getHeaderFile(), "namespace %s {\n\n", getGetOptSetup()->getNamespaceName().c_str());
@@ -116,9 +134,11 @@ void SourceCodeWriter::headerFileNamespace() {
if (!getGetOptSetup()->getNamespaceName().empty()) {
fprintf(getHeaderFile(), "}\n");
}
+ LOG_TRACE("Finished writing namespace to Header-File");
}
void SourceCodeWriter::headerFileClass() {
+ LOG_TRACE("Writing class to Header-File");
//start of class
fprintf(getHeaderFile(), "class %s {\n", getGetOptSetup()->getClassName().c_str());
@@ -129,7 +149,8 @@ void SourceCodeWriter::headerFileClass() {
// Values for the options
for (Option option: getGetOptSetup()->getOptions()) {
if (option.isHasArguments() != HasArguments::NONE) {
- fprintf(getHeaderFile(), "%s %sValue", getValueTypeByOption(option).c_str(), determineArgsName(option).c_str());
+ fprintf(getHeaderFile(), "%s %sValue", getValueTypeByOption(option).c_str(),
+ determineArgsName(option).c_str());
if (option.isHasArguments() == HasArguments::OPTIONAL && !option.getDefaultValue().empty()) {
switch (option.getConvertTo()) {
case ConvertToOptions::STRING:
@@ -151,6 +172,7 @@ void SourceCodeWriter::headerFileClass() {
fprintf(getHeaderFile(), "\n");
fprintf(getHeaderFile(), "protected:\n");
//put all elements inside class -> protected here
+ createHeaderPrintHelp();
fprintf(getHeaderFile(), "\n");
fprintf(getHeaderFile(), "public:\n");
@@ -163,9 +185,11 @@ void SourceCodeWriter::headerFileClass() {
//end of class
fprintf(getHeaderFile(), "};\n");
+ LOG_TRACE("Finished writing class to Header-File");
}
void SourceCodeWriter::createHeaderStructArgs() {
+ LOG_TRACE("Writing struct Args to Header-File");
fprintf(getHeaderFile(), "struct Args {\n");
for (auto &option: getGetOptSetup()->getOptions()) {
fprintf(getHeaderFile(), "struct {\n");
@@ -176,19 +200,23 @@ void SourceCodeWriter::createHeaderStructArgs() {
fprintf(getHeaderFile(), "} %s;\n", determineArgsName(option).c_str());
}
fprintf(getHeaderFile(), "};\n\n");
+ LOG_TRACE("Finished writing struct Args to Header-File");
}
//from here on are all the sourceFiles
void SourceCodeWriter::sourceFileIncludes() {
+ LOG_TRACE("Writing includes to Source-File");
fprintf(getSourceFile(), "#include \"%s\"\n\n", getGetOptSetup()->getHeaderFileName().c_str());
//Here further generation-Methods
// Close source file includes
fprintf(getSourceFile(), "\n");
+ LOG_TRACE("Finished writing includes to Source-File");
}
void SourceCodeWriter::sourceFileNamespace() {
+ LOG_TRACE("Writing namespace to Source-File");
//start of namespace
if (!getGetOptSetup()->getNamespaceName().empty()) {
fprintf(getSourceFile(), "namespace %s {\n\n", getGetOptSetup()->getNamespaceName().c_str());
@@ -201,32 +229,38 @@ void SourceCodeWriter::sourceFileNamespace() {
createSourceUnknownOption();
//Hier kommt der Help-Text dazu
+ createSourcePrintHelp();
//end of namespace
if (!getGetOptSetup()->getNamespaceName().empty()) {
fprintf(getSourceFile(), "}\n");
}
+ LOG_TRACE("Finished writing namespace to Source-File");
}
void SourceCodeWriter::createHeaderParsingFunction() {
+ LOG_TRACE("Writing parsing function to Header-File");
fprintf(getHeaderFile(), "void parseOptions(int argc, char **argv);\n");
+ LOG_TRACE("Finished writing parsing function to Header-File");
}
void SourceCodeWriter::sourceFileParse() {
+ LOG_TRACE("Writing parsing function to Source-File");
fprintf(getSourceFile(), "void %s::parse() {\n", getGetOptSetup()->getClassName().c_str());
- for (auto &option : getGetOptSetup()->getOptions()) {
+ for (auto &option: getGetOptSetup()->getOptions()) {
std::string optionName = determineArgsName(option);
fprintf(getSourceFile(), "if (args.%s.isSet) {\n", optionName.c_str());
// exclusions
if (!option.getExclusions().empty()) {
- for (auto &exclusion : option.getExclusions()) {
+ for (auto &exclusion: option.getExclusions()) {
// Iterate over options again and compare exclusion with ref
- for (auto &option2 : getGetOptSetup()->getOptions()) {
+ for (auto &option2: getGetOptSetup()->getOptions()) {
std::string option2Name = determineArgsName(option2);
if (option2.getRef() == exclusion) {
fprintf(getSourceFile(), "if (args.%s.isSet) {\n", option2Name.c_str());
- fprintf(getSourceFile(), "perror(\"%s and %s cannot be used together.\");\n", optionName.c_str(), option2Name.c_str());
+ fprintf(getSourceFile(), "perror(\"%s and %s cannot be used together.\");\n",
+ optionName.c_str(), option2Name.c_str());
fprintf(getSourceFile(), "exit(1);\n");
fprintf(getSourceFile(), "}\n");
}
@@ -245,9 +279,11 @@ void SourceCodeWriter::sourceFileParse() {
fprintf(getSourceFile(), "if (!args.%s.value.empty()) {\n", optionName.c_str());
//TODO This might not work this way, check back later
fprintf(getSourceFile(), "try {\n");
- fprintf(getSourceFile(), "%sValue = boost::lexical_cast(args.%s.value);\n", optionName.c_str(), optionName.c_str(), optionName.c_str());
+ fprintf(getSourceFile(), "%sValue = boost::lexical_cast(args.%s.value);\n",
+ optionName.c_str(), optionName.c_str(), optionName.c_str());
fprintf(getSourceFile(), "} catch (boost::bad_lexical_cast &) {\n");
- fprintf(getSourceFile(), "perror(\"%s is not convertible to %s.\");\n}\n", optionName.c_str(), getValueTypeByOption(option).c_str());
+ fprintf(getSourceFile(), "perror(\"%s is not convertible to %s.\");\n}\n", optionName.c_str(),
+ getValueTypeByOption(option).c_str());
fprintf(getSourceFile(), "}\n");
}
@@ -269,9 +305,11 @@ void SourceCodeWriter::sourceFileParse() {
fprintf(getSourceFile(), "}\n");
}
fprintf(getSourceFile(), "}\n");
+ LOG_TRACE("Finished writing parsing function to Source-File");
}
void SourceCodeWriter::createSourceParsingFunction() {
+ LOG_TRACE("Writing parsing function to Source-File");
vector options = getGetOptSetup()->getOptions();
fprintf(getSourceFile(), "void %s::parseOptions(int argc, char **argv){\nargs = Args();\n"
"opterr = 0;\nint opt;\nstatic struct option long_options[] = {\n",
@@ -298,7 +336,7 @@ void SourceCodeWriter::createSourceParsingFunction() {
else
fprintf(getSourceFile(), "0, '%c'},\n", option.getShortOpt());
}
- };
+ }
longOptsWithoutShortOpt = 0;
fprintf(getSourceFile(), "{0, 0, 0, 0}\n};\nint option_index = 0;\n\n");
@@ -345,12 +383,12 @@ void SourceCodeWriter::createSourceParsingFunction() {
fprintf(getSourceFile(), "if(optarg == nullptr){\n"
"perror(\"There was no argument passed for the option \\\"%s\\\" "
"which requires one.\");\n"
- "exit(1);\n}\nargs.%s.value = optarg;\n",
+ "exit(1);\n}\n",
bothOpts.c_str(), determineArgsName(option).c_str());
if (option.getConvertTo() == ConvertToOptions::BOOLEAN) {
- fprintf(getSourceFile(), "if(strcmp(optarg, \"true\"))\nargs.%s.value = \"1\";\n"
- "else if(strcmp(optarg, \"false\"))\nargs.%s.value = \"0\";\n"
- "else\nargs.%s.value = optarg;\n",
+ fprintf(getSourceFile(), "args.%s.value = optarg;\nif(strcmp(optarg, \"true\")"
+ ")\nargs.%s.value = \"1\";\n"
+ "else if(strcmp(optarg, \"false\"))\nargs.%s.value = \"0\";\n",
determineArgsName(option).c_str(), determineArgsName(option).c_str(),
determineArgsName(option).c_str());
} else
@@ -358,16 +396,15 @@ void SourceCodeWriter::createSourceParsingFunction() {
determineArgsName(option).c_str());
break;
case HasArguments::OPTIONAL:
- fprintf(getSourceFile(), "if(optarg != nullptr)\nargs.%s.value = optarg;",
- determineArgsName(option).c_str());
+ fprintf(getSourceFile(), "if(optarg != nullptr){\n");
if (option.getConvertTo() == ConvertToOptions::BOOLEAN) {
- fprintf(getSourceFile(), "if(strcmp(optarg, \"true\"))\nargs.%s.value = \"1\";\n"
- "else if(strcmp(optarg, \"false\"))\nargs.%s.value = \"0\";\n"
- "else\nargs.%s.value = optarg;\n",
+ fprintf(getSourceFile(), "args.%s.value = optarg;\nif(strcmp(optarg, \"true\"))"
+ "\nargs.%s.value = \"1\";\n"
+ "else if(strcmp(optarg, \"false\"))\nargs.%s.value = \"0\";\n}\n",
determineArgsName(option).c_str(), determineArgsName(option).c_str(),
determineArgsName(option).c_str());
} else
- fprintf(getSourceFile(), "args.%s.value = optarg;\n",
+ fprintf(getSourceFile(), "args.%s.value = optarg;\n}\n",
determineArgsName(option).c_str());
break;
default:
@@ -381,7 +418,7 @@ void SourceCodeWriter::createSourceParsingFunction() {
//Close case
fprintf(getSourceFile(), "break;\n");
- };
+ }
//Close switch-case
fprintf(getSourceFile(), "case '?':\ndefault:\nunknownOption(std::to_string(optopt));\nbreak;}\n");
@@ -397,20 +434,26 @@ void SourceCodeWriter::createSourceParsingFunction() {
//Close function parseOptions
fprintf(getSourceFile(), "}\n");
+ LOG_TRACE("Finished generating parseOptions()");
}
void SourceCodeWriter::createHeaderUnknownOption() {
+ LOG_TRACE("Generating unknownOption() header");
fprintf(getHeaderFile(), "virtual void unknownOption(const std::string &unknownOption);\n\n");
+ LOG_TRACE("Finished generating unknownOption() header");
}
void SourceCodeWriter::createSourceUnknownOption() {
+ LOG_TRACE("Generating unknownOption() source");
fprintf(getSourceFile(), "void %s::unknownOption(const std::string &unknownOption){\n"
"perror(\"GetOpt encountered an unknown option.\");\n"
"exit(1);\n}\n", getGetOptSetup()->getClassName().c_str());
+ LOG_TRACE("Finished generating unknownOption() source");
}
// Helper functions
std::string SourceCodeWriter::determineArgsName(const Option &option) {
+ LOG_TRACE("Determining args name for " + option.getLongOpt() + " (" + option.getShortOpt() + ")");
std::string argsName;
if (!option.getInterface().empty()) {
argsName = option.getInterface();
@@ -432,14 +475,17 @@ std::string SourceCodeWriter::determineArgsName(const Option &option) {
}
if (argsName.empty()) {
+ LOG_ERROR("Could not determine args name for " + option.getLongOpt() + " (" + option.getShortOpt() + ")");
perror("Every option must at least have either an Interface, a LongOpt or a ShortOpt.");
exit(1);
}
+ LOG_TRACE("Determined args name for " + option.getLongOpt() + " (" + option.getShortOpt() + ") as " + argsName);
return argsName;
}
void SourceCodeWriter::createHeaderGetter() {
+ LOG_TRACE("Generating getter() header");
for (Option option: getGetOptSetup()->getOptions()) {
string capitalizedArgsName = determineArgsName(option);
capitalizedArgsName[0] = toupper(capitalizedArgsName[0], locale());
@@ -454,9 +500,11 @@ void SourceCodeWriter::createHeaderGetter() {
fprintf(getHeaderFile(), "bool isSet%s() const;\n", capitalizedArgsName.c_str());
}
}
+ LOG_TRACE("Finished generating getter() header");
}
void SourceCodeWriter::createSourceGetter() {
+ LOG_TRACE("Generating getter() source");
for (Option option: getGetOptSetup()->getOptions()) {
string capitalizedArgsName = determineArgsName(option);
capitalizedArgsName[0] = toupper(capitalizedArgsName[0], locale());
@@ -466,7 +514,8 @@ void SourceCodeWriter::createSourceGetter() {
determineArgsName(option).c_str());
if (option.isHasArguments() != HasArguments::NONE) {
fprintf(getSourceFile(), "%s %s::getValueOf%s() const{\nreturn %sValue;\n}\n",
- getValueTypeByOption(option).c_str(), getGetOptSetup()->getClassName().c_str(), capitalizedArgsName.c_str(),
+ getValueTypeByOption(option).c_str(), getGetOptSetup()->getClassName().c_str(),
+ capitalizedArgsName.c_str(),
determineArgsName(option).c_str());
}
} else if (option.getInterface().empty() && option.getConnectToInternalMethod().empty()
@@ -476,35 +525,56 @@ void SourceCodeWriter::createSourceGetter() {
determineArgsName(option).c_str());
}
}
+ LOG_TRACE("Finished generating getter() source");
}
void SourceCodeWriter::createExternalFunctions() {
+ LOG_TRACE("Generating external functions");
vector options = getGetOptSetup()->getOptions();
- for(auto &option : options){
- if(!option.getConnectToExternalMethod().empty()){
+ for (auto &option: options) {
+ if (!option.getConnectToExternalMethod().empty()) {
fprintf(getHeaderFile(), "virtual void %s(", option.getConnectToExternalMethod().c_str());
- if(option.isHasArguments() == HasArguments::OPTIONAL || option.isHasArguments() == HasArguments::REQUIRED){
+ if (option.isHasArguments() == HasArguments::OPTIONAL ||
+ option.isHasArguments() == HasArguments::REQUIRED) {
std::string type = getValueTypeByOption(option);
fprintf(getHeaderFile(), "%s arg", type.c_str());
}
fprintf(getHeaderFile(), ") = 0;\n");
}
}
+ LOG_TRACE("Finished generating external functions");
}
void SourceCodeWriter::createHeaderPrintVersion() {
+ LOG_TRACE("Generating printVersion() header");
fprintf(getHeaderFile(), "virtual void printVersion();\n");
+ LOG_TRACE("Finished generating printVersion() header");
}
void SourceCodeWriter::createSourcePrintVersion() {
- fprintf(getSourceFile(), "void %s::printVersion(){\nprintf(\"version: 1.0.0\");\n}\n",
+ LOG_TRACE("Generating printVersion() source");
+ fprintf(getSourceFile(), "void %s::printVersion(){\nprintf(\"version: 1.0.0\\n\");\n}\n",
getGetOptSetup()->getClassName().c_str());
+ LOG_TRACE("Finished generating printVersion() source");
+
+}
+
+void SourceCodeWriter::createHeaderPrintHelp() {
+ LOG_TRACE("Generating printHelp() header");
+ fprintf(getHeaderFile(), "virtual void printHelp();\n");
+ LOG_TRACE("Finished generating printHelp() header");
+}
+void SourceCodeWriter::createSourcePrintHelp() {
+ LOG_TRACE("Generating printHelp() source");
+ fprintf(getSourceFile(), "%s", HelpText(getGetOptSetup()).parseHelpMessage().c_str());
+ LOG_TRACE("Finished generating printHelp() source");
}
void SourceCodeWriter::writeFile() {
+ LOG_INFO("Starting to write source code...");
// printf("Writing file...\n");
//Write header files --> put methods here
@@ -513,5 +583,6 @@ void SourceCodeWriter::writeFile() {
//Write source files --> put methods here
sourceFileIncludes();
sourceFileNamespace();
+ LOG_INFO("Finished writing source code.");
}
diff --git a/src/StateMachine.cpp b/src/StateMachine.cpp
index 035f3af..c3ac7de 100644
--- a/src/StateMachine.cpp
+++ b/src/StateMachine.cpp
@@ -3,6 +3,93 @@
*/
#include "StateMachine.h"
+#include "Logger.h"
+
+inline std::string eventToString(Event event) {
+ switch (event) {
+ case Event::GETOPTSETUPSTART:
+ return "GETOPTSETUPSTART";
+ case Event::GETOPTSETUPEND:
+ return "GETOPTSETUPEND";
+ case Event::AUTHORSTART:
+ return "AUTHORSTART";
+ case Event::AUTHOREND:
+ return "AUTHOREND";
+ case Event::HEADERFILENAMESTART:
+ return "HEADERFILENAMESTART";
+ case Event::HEADERFILENAMEEND:
+ return "HEADERFILENAMEEND";
+ case Event::SOURCEFILENAMESTART:
+ return "SOURCEFILENAMESTART";
+ case Event::SOURCEFILENAMEEND:
+ return "SOURCEFILENAMEEND";
+ case Event::NAMESPACESTART:
+ return "NAMESPACESTART";
+ case Event::NAMESPACEEND:
+ return "NAMESPACEEND";
+ case Event::CLASSNAMESTART:
+ return "CLASSNAMESTART";
+ case Event::CLASSNAMEEND:
+ return "CLASSNAMEEND";
+ case Event::OVERALLDESCRIPTIONSTART:
+ return "OVERALLDESCRIPTIONSTART";
+ case Event::OVERALLDESCRIPTIONEND:
+ return "OVERALLDESCRIPTIONEND";
+ case Event::BLOCKSTART:
+ return "BLOCKSTART";
+ case Event::BLOCKEND:
+ return "BLOCKEND";
+ case Event::SAMPLEUSAGESTART:
+ return "SAMPLEUSAGESTART";
+ case Event::SAMPLEUSAGEEND:
+ return "SAMPLEUSAGEEND";
+ case Event::SAMPLESTART:
+ return "SAMPLESTART";
+ case Event::SAMPLEEND:
+ return "SAMPLEEND";
+ case Event::OPTIONSSTART:
+ return "OPTIONSSTART";
+ case Event::OPTIONSEND:
+ return "OPTIONSEND";
+ case Event::OPTIONSTART:
+ return "OPTIONSTART";
+ case Event::OPTIONEND:
+ return "OPTIONEND";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+inline std::string stateToString(State state) {
+ switch (state) {
+ case State::GETOPTSETUP:
+ return "GETOPTSETUP";
+ case State::AUTHOR:
+ return "AUTHOR";
+ case State::HEADERFILENAME:
+ return "HEADERFILENAME";
+ case State::SOURCEFILENAME:
+ return "SOURCEFILENAME";
+ case State::NAMESPACE:
+ return "NAMESPACE";
+ case State::CLASSNAME:
+ return "CLASSNAME";
+ case State::OVERALLDESCRIPTION:
+ return "OVERALLDESCRIPTION";
+ case State::BLOCK:
+ return "BLOCK";
+ case State::SAMPLEUSAGE:
+ return "SAMPLEUSAGE";
+ case State::SAMPLE:
+ return "SAMPLE";
+ case State::OPTIONS:
+ return "OPTIONS";
+ case State::OPTION:
+ return "OPTION";
+ default:
+ return "UNKNOWN";
+ }
+}
// Constructor
StateMachine::StateMachine() {
@@ -24,6 +111,7 @@ void StateMachine::setState(State state) {
// Methods
void StateMachine::handleEvent(Event event) {
+ LOG_TRACE("State: " + stateToString(currentState) + " Event: " + eventToString(event));
switch (currentState) {
case State::START:
switch (event) {
diff --git a/src/XMLParser.cpp b/src/XMLParser.cpp
index a3f2bf7..c82bca7 100644
--- a/src/XMLParser.cpp
+++ b/src/XMLParser.cpp
@@ -6,6 +6,7 @@
#include
#include "XMLParser.h"
+#include "Logger.h"
#include
@@ -17,6 +18,7 @@ XMLParser::XMLParser(const std::string &filename) {
}
void XMLParser::parse() {
+ LOG_INFO("Starting parsing of file " + filename);
try {
XMLPlatformUtils::Initialize();
}
@@ -27,8 +29,7 @@ void XMLParser::parse() {
XMLString::release(&message);
}
- SAXParser* parser = {nullptr};
- parser = new SAXParser;
+ auto* parser = new SAXParser;
int errorCount = {0};
@@ -47,12 +48,6 @@ void XMLParser::parse() {
{
char* message = XMLString::transcode(toCatch.getMessage());
- //XMLString::release(message);
- /*
- XERCES_STD_QUALIFIER cerr << "\nAn error occurred\n Error: "
- << StrX(toCatch.getMessage())
- << "\n" << XERCES_STD_QUALIFIER endl;
- */
cerr << "XMLException: " << message << endl;
}
catch(...) {
@@ -60,6 +55,7 @@ void XMLParser::parse() {
}
if (errorCount > 0) {
+ LOG_ERROR("There were " + to_string(errorCount) + " errors during parsing of file " + filename);
perror("There were errors during parsing.");
exit(1);
}
@@ -68,6 +64,7 @@ void XMLParser::parse() {
delete parser;
//Terminate muss immer am Schluss stehen
XMLPlatformUtils::Terminate();
+ LOG_INFO("Finished parsing of file " + filename);
}
void XMLParser::startDocument() {
@@ -79,8 +76,7 @@ void XMLParser::endDocument() {
}
void XMLParser::startElement(const XMLCh *const name, AttributeList &attributes) {
-// cout << "Start-Element: " << converter.to_bytes(name) << endl;
-
+ LOG_TRACE("Start Element: " + string(XMLString::transcode(name)));
if (!XMLString::compareString(name, u"GetOptSetup")) {
sm->handleEvent(Event::GETOPTSETUPSTART);
getOptSetup->parseAttributes(attributes);
@@ -116,8 +112,7 @@ void XMLParser::startElement(const XMLCh *const name, AttributeList &attributes)
}
void XMLParser::endElement(const XMLCh *const name) {
-// cout << "End-Element: " << converter.to_bytes(name) << endl;
-
+ LOG_TRACE("End Element: " + string(XMLString::transcode(name)));
if (!XMLString::compareString(name, u"GetOptSetup")) {
sm->handleEvent(Event::GETOPTSETUPEND);
} else if (!XMLString::compareString(name, u"Author")) {
@@ -146,7 +141,7 @@ void XMLParser::endElement(const XMLCh *const name) {
}
void XMLParser::characters(const XMLCh *const chars, const XMLSize_t length) {
-// cout << "Characters (" << length << "):" << converter.to_bytes(chars, chars + length) << endl;
+ LOG_TRACE("Characters: " + string(XMLString::transcode(chars)));
switch (sm->getState()) {
case State::START:
break;
diff --git a/src/models/Author.cpp b/src/models/Author.cpp
index 81fd7f1..8304298 100644
--- a/src/models/Author.cpp
+++ b/src/models/Author.cpp
@@ -3,13 +3,13 @@
*/
#include
-#include "Author.h"
+#include "models/Author.h"
+#include "Logger.h"
-// Constructors
+//Constructor
Author::Author() = default;
-
-// Getters
+//Getters
const string &Author::getName() const {
return name;
}
@@ -23,7 +23,7 @@ const string &Author::getMail() const {
}
-// Setters
+//Setters
void Author::setName(const string &_name) {
Author::name = _name;
}
@@ -36,9 +36,9 @@ void Author::setMail(const string &_mail) {
Author::mail = _mail;
}
-
-// Helpers
+//helper function to parse the Author-Tag
void Author::parseAttributes(AttributeList &attributes) {
+ LOG_TRACE("Starting Author-Attributes parse");
for (unsigned int i = 0; i < attributes.getLength(); i++) {
if (!XMLString::compareString(attributes.getName(i), u"Name")) {
setName(std::string(XMLString::transcode(attributes.getValue(i))));
@@ -48,4 +48,5 @@ void Author::parseAttributes(AttributeList &attributes) {
setMail(std::string(XMLString::transcode(attributes.getValue(i))));
}
}
+ LOG_TRACE("Finished Author-Attributes parse");
}
diff --git a/src/models/GetOptSetup.cpp b/src/models/GetOptSetup.cpp
index 403b453..1ba018a 100644
--- a/src/models/GetOptSetup.cpp
+++ b/src/models/GetOptSetup.cpp
@@ -4,7 +4,8 @@
#include
#include
-#include "GetOptSetup.h"
+#include "models/GetOptSetup.h"
+#include "Logger.h"
// Constructors
GetOptSetup::GetOptSetup() = default;
@@ -100,9 +101,11 @@ void GetOptSetup::addOption(const Option &option) {
// Helpers
void GetOptSetup::parseAttributes(AttributeList &attributes) {
+ LOG_TRACE("Starting GetOptSetup-Attributes parse");
for (unsigned int i = 0; i < attributes.getLength(); i++) {
if (!XMLString::compareString(attributes.getName(i), u"SignPerLine")) {
setSignPerLine(std::string(XMLString::transcode(attributes.getValue(i))));
}
}
+ LOG_TRACE("Finished GetOptSetup-Attributes parse");
}
diff --git a/src/models/Option.cpp b/src/models/Option.cpp
index de3f27b..cfd2e65 100644
--- a/src/models/Option.cpp
+++ b/src/models/Option.cpp
@@ -2,7 +2,8 @@
* Editors: Tobias Goetz
*/
-#include "Option.h"
+#include "models/Option.h"
+#include "Logger.h"
#include
#include
#include
@@ -65,6 +66,7 @@ void Option::setRef(const std::string &ref) {
int _ref = boost::lexical_cast(ref);
if (_ref < 1 || _ref > 63) {
std::cerr << "Error: Invalid ref value: [" << _ref << "]. Must be between 1 and 63." << std::endl;
+ LOG_ERROR("Error: Invalid ref value: [" << _ref << "]. Must be between 1 and 63.");
exit(EXIT_FAILURE);
}
Option::ref = _ref;
@@ -105,6 +107,7 @@ void Option::setHasArguments(const std::string &_hasArguments) {
Option::hasArguments = HasArguments::REQUIRED;
} else {
throw std::runtime_error("Invalid value for hasArguments");
+ LOG_ERROR("Invalid value for hasArguments");
}
}
@@ -117,6 +120,7 @@ void Option::setConvertTo(const std::string &_convertTo) {
Option::convertTo = ConvertToOptions::BOOLEAN;
} else {
throw std::runtime_error("Invalid value for convertTo");
+ LOG_ERROR("Invalid value for convertTo");
}
}
@@ -131,6 +135,7 @@ void Option::setInterface(const std::string &_interface) {
// Helpers
void Option::parseAttributes(AttributeList &attributes) {
+ LOG_TRACE("Starting Option-Attributes parse");
for (unsigned int i = 0; i < attributes.getLength(); i++) {
if (!XMLString::compareString(attributes.getName(i), u"Ref")) {
setRef(std::string(XMLString::transcode(attributes.getValue(i))));
@@ -156,4 +161,5 @@ void Option::parseAttributes(AttributeList &attributes) {
setInterface(std::string(XMLString::transcode(attributes.getValue(i))));
}
}
+ LOG_TRACE("Finished Option-Attributes parse");
}
diff --git a/src2/COptionParser.cpp b/src2/COptionParser.cpp
deleted file mode 100644
index a401ecf..0000000
--- a/src2/COptionParser.cpp
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Editors: Tobias Goetz, Noel Kempter, Philipp Kuest, Sebastian Wolf
- */
-
-#include "COptionParser.h"
-#include
-#include
-
-namespace DHBW {
- // Getter
- std::string COptionParser::getValueOfOutputPath() const {
- return outputPathValue;
- }
-
- bool COptionParser::isSetOutputPath() const {
- return args.outputPath.isSet;
- }
-
- void COptionParser::parse() {
- // Check if getopt was set and execute functions if no exclusion
- if (args.help.isSet) {
- if (args.version.isSet) {
- perror ("--help and --version cannot be used together.");
- exit(1);
- }
-
- // More exclusions here in other if statements
- }
-
- if (args.version.isSet) {
- if (args.help.isSet) {
- perror ("--version and --help cannot be used together.");
- exit(1);
- }
-
- // More exclusions here in other if statements
- }
-
- if (args.outputPath.isSet) {
- // More exclusions here in other if statements
- }
-
- // Run code here
- if (args.help.isSet) {
- printHelp();
- }
-
- if (args.version.isSet) {
- printVersion();
- }
-
- if (args.outputPath.isSet) {
- // Set values of argument optional or required and param not empty
- outputPathValue = boost::lexical_cast(args.outputPath.value);
- // Interface doesn't need function call
- }
- }
-
- void COptionParser::printHelp() {
- printf("Executed printHelp()\n");
- }
-
- void COptionParser::printVersion() {
- printf("Executed printVersion()\n");
- }
-
- void COptionParser::parseOptions(int argc, char **argv) {
- args = Args();
-
- int digit_optind = 0;
-
- while (true) {
- int c;
-
- int this_option_optind = optind ? optind : 1;
- int option_index = 0;
- static struct option long_options[] = {
- {"help", no_argument, 0, 0 },
- {"version", no_argument, 0, 0 },
- {"out-path", required_argument, 0, 0 },
- {0, 0, 0, 0}
- };
-
- c = getopt_long(argc, argv, "hv", long_options, &option_index);
- if (c == -1) {
- break;
- }
-
- switch (c) {
- case 0:
- // LongOpts
- if (strcmp("help", long_options[option_index].name) == 0) {
- args.help.isSet = true;
- }
- if (strcmp("version", long_options[option_index].name) == 0) {
- args.version.isSet = true;
- }
- if (strcmp("out-path", long_options[option_index].name) == 0) {
- args.outputPath.isSet = true;
- // Only add value if Arguments is Required or Optional
- args.outputPath.value = optarg;
- }
- break;
-
- // ShortOpts
- case 'h':
- args.help.isSet = true;
- break;
-
- case 'v':
- args.version.isSet = true;
- break;
-
- default:
- printf("?? getopt returned character code 0%o ??\n", c);
- }
- }
-
- if (optind < argc) {
- printf("non-option ARGV-elements: ");
- while (optind < argc)
- printf("%s ", argv[optind++]);
- printf("\n");
- }
-
- // Parse the arguments
- parse();
-
- exit(EXIT_SUCCESS);
- }
-}
-
-int main(int argc, char* argv[]) {
- DHBW::COptionParser parser;
- parser.parseOptions(argc, argv);
-}
\ No newline at end of file
diff --git a/src2/COptionParser.h b/src2/COptionParser.h
deleted file mode 100644
index eb46d8a..0000000
--- a/src2/COptionParser.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Editors: Tobias Goetz, Noel Kempter, Philipp Kuest, Sebastian Wolf
- */
-
-#ifndef CODEGENERATOR_COPTIONPARSER_H
-#define CODEGENERATOR_COPTIONPARSER_H
-
-#include
-#include
-#include /* for printf */
-#include /* for exit */
-
-struct Args {
- struct {
- bool isSet = false;
- } help;
-
- struct {
- bool isSet = false;
- } version;
-
- // Important: Name priority Interface > LongOpt > ShortOpt and remove the "-" from the name
- struct {
- bool isSet = false;
- // Only add value if Arguments is Required or Optional
- std::string value;
- } outputPath;
-};
-
-namespace DHBW {
-
- class COptionParser {
- private:
- Args args;
-
- std::string outputPathValue;
- protected:
- virtual void printHelp();
- virtual void printVersion();
- public:
- void parse();
-
- // Getter
- std::string getValueOfOutputPath() const;
- bool isSetOutputPath() const;
-
- // Helper
- void parseOptions(int argc, char* argv[]);
- };
-}
-
-#endif //CODEGENERATOR_COPTIONPARSER_H
diff --git a/src2/ExampleProgram.cpp b/src2/ExampleProgram.cpp
new file mode 100644
index 0000000..d989e51
--- /dev/null
+++ b/src2/ExampleProgram.cpp
@@ -0,0 +1,82 @@
+/*
+ * Editors: Philipp Kuest, Tobias Goetz
+ */
+
+#include "../include2/ExampleProgram.h"
+#include "../include2/generatedCode.h"
+
+ExampleProgram::ExampleProgram(GC::GeneratedClass *generatedClass) {
+ this->generatedClass = generatedClass;
+}
+
+GC::GeneratedClass *ExampleProgram::getGeneratedClass() {
+ return generatedClass;
+}
+
+/**
+ * @brief prints in command line if option 'version' was set
+ * @param ep object of class ExampleProgram
+ */
+void checkVersion(ExampleProgram ep){
+ if(ep.getGeneratedClass()->isSetVersion()){
+ //ep.getGeneratedClass()->printVersion();
+ printf("The option 'version' was called --> isSetVersion=true\n");
+ } else {
+ printf("The option 'version' was not called --> isSetVersion=false\n");
+ }
+}
+
+/**
+ * @brief prints in command line if option 'exclusion' was set
+ * @param ep object of class ExampleProgram
+ */
+void checkExclusion(ExampleProgram ep){
+ if(ep.getGeneratedClass()->isSetExclusion()){
+ printf("The option 'exclusion' was called --> isSetExclusion=true\n");
+ } else {
+ printf("The option 'exclusion' was not called --> isSetExclusion=false\n");
+ }
+}
+
+/**
+ * @brief prints in command line if option 'arguments' was set and depending on it the argument
+ * @param ep object of class ExampleProgram
+ */
+void checkArguments(ExampleProgram ep){
+ if(ep.getGeneratedClass()->isSetArguments()){
+ printf("The option 'arguments' was called --> isSetExclusion=true\n");
+ printf("The argument is: %d\n", ep.getGeneratedClass()->getValueOfArguments());
+ } else {
+ printf("The option 'arguments' was not called --> isSetExclusion=false\n");
+ }
+}
+
+/**
+ * @brief prints in command line if option 'arguments' was set and depending on it the argument
+ * @param ep object of class ExampleProgram
+ */
+void checkOptional(ExampleProgram ep){
+ if(ep.getGeneratedClass()->isSetOptional()){
+ printf("The option 'optional' was called --> isSetOptional=true\n");
+ printf("The argument is: %d\n", ep.getGeneratedClass()->getValueOfOptional());
+ } else {
+ printf("The option 'optional' was not called --> isSetOptional=false\n");
+ }
+}
+
+/**
+ * @brief Generates object of class ExampleProgram, calls parseOptions and checks which options were set
+ * @param argc amount of arguments
+ * @param argv array of arguments
+ */
+int main(int argc, char* argv[] ) {
+ ExampleProgram exampleProgram = ExampleProgram(new ExtendedGeneratedCode());
+ exampleProgram.getGeneratedClass()->parseOptions(argc, argv);
+
+ checkVersion(exampleProgram);
+ checkExclusion(exampleProgram);
+ checkArguments(exampleProgram);
+ checkOptional(exampleProgram);
+
+ return 0;
+}
\ No newline at end of file
diff --git a/src2/ExtendedGeneratedCode.cpp b/src2/ExtendedGeneratedCode.cpp
new file mode 100644
index 0000000..975ef17
--- /dev/null
+++ b/src2/ExtendedGeneratedCode.cpp
@@ -0,0 +1,9 @@
+/*
+ * Editors: Philipp Kuest, Tobias Goetz
+ */
+
+#include "../include2/ExtendedGeneratedCode.h"
+
+void ExtendedGeneratedCode::printVersion() {
+ printf("Version: 2.0.0\n");
+}
diff --git a/exampleProgram/exampleProgram.xml b/src2/exampleProgram.xml
similarity index 59%
rename from exampleProgram/exampleProgram.xml
rename to src2/exampleProgram.xml
index a209984..338df73 100644
--- a/exampleProgram/exampleProgram.xml
+++ b/src2/exampleProgram.xml
@@ -1,24 +1,24 @@
-
+
generatedCode.h
generatedCode.cpp
GC
- generatedClass
+ GeneratedClass
- Erstellt einen Rumpf zum einlesen von Argumente aus der Kommandozeile.
- Es kann sowohl mit innenliegenden Container wie externer Klassenanbindung eine Datenhaltung erfolgen.
- Sobald ein Methodenaufruf abstrakt ist, wird die Basisklasse abstrakt.
- Fuer die Formatierung der generierten Dateien wird astyle verwendet.
+ Gibt die verschiedenen Werte aus, welche von getOpt angenommen wurden.
+ Dies geschieht in der Kommandozeile.
- getoptgen -h
+ ExampleProgram -h
+ ExampleProgram --optional=23
+ ExampleProgram --arguments=45
-
+