initial commit for github
This commit is contained in:
commit
60968612de
370 changed files with 68427 additions and 0 deletions
|
@ -0,0 +1,381 @@
|
|||
/**
|
||||
* @file
|
||||
*
|
||||
* @copyright
|
||||
* @verbatim
|
||||
Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved.
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla
|
||||
Public License, v. 2.0. If a copy of the MPL was not distributed
|
||||
with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
If it is not possible or desirable to put the notice in a particular file, then
|
||||
You may include the notice in a location (such as a LICENSE file in a
|
||||
relevant directory) where a recipient would be likely to look for such a notice.
|
||||
|
||||
You may add additional accurate notices of copyright ownership.
|
||||
@endverbatim
|
||||
*/
|
||||
|
||||
#include <ddl.h>
|
||||
#include "header_printer.h"
|
||||
#include "header_header.h"
|
||||
#include "header_basic_type.h"
|
||||
|
||||
namespace ddl_generator
|
||||
{
|
||||
namespace oo
|
||||
{
|
||||
//define all needed error types and values locally
|
||||
_MAKE_RESULT(0, ERR_NOERROR)
|
||||
_MAKE_RESULT(-4, ERR_POINTER)
|
||||
_MAKE_RESULT(-5, ERR_INVALID_ARG)
|
||||
_MAKE_RESULT(-11, ERR_INVALID_FILE)
|
||||
_MAKE_RESULT(-20, ERR_NOT_FOUND)
|
||||
_MAKE_RESULT(-24, ERR_PATH_NOT_FOUND)
|
||||
_MAKE_RESULT(-27, ERR_OPEN_FAILED)
|
||||
_MAKE_RESULT(-38, ERR_FAILED)
|
||||
}
|
||||
}
|
||||
|
||||
using namespace ddl_generator::oo;
|
||||
|
||||
using namespace ddl;
|
||||
|
||||
namespace ddl
|
||||
{
|
||||
|
||||
HeaderPrinter::HeaderPrinter() : _header(NULL)
|
||||
{ }
|
||||
|
||||
HeaderPrinter::~HeaderPrinter()
|
||||
{ }
|
||||
|
||||
a_util::result::Result HeaderPrinter::writeToFile(const a_util::filesystem::Path &filename)
|
||||
{
|
||||
std::string guarded_header_output = addHeaderGuards(filename, _header_output);
|
||||
if (a_util::filesystem::writeTextFile(filename, guarded_header_output) != a_util::filesystem::OK)
|
||||
{
|
||||
return (ERR_OPEN_FAILED);
|
||||
}
|
||||
return ERR_NOERROR;
|
||||
}
|
||||
|
||||
const std::string& HeaderPrinter::getHeader()
|
||||
{
|
||||
return _header_output;
|
||||
}
|
||||
|
||||
a_util::result::Result HeaderPrinter::visit(const Header* header)
|
||||
{
|
||||
_header = header;
|
||||
_header_output = "";
|
||||
_header_output.append("// This is a generated file, changes to it may be overwritten in the future.\n\n");
|
||||
|
||||
if (_name_space.length() > 0)
|
||||
{
|
||||
_header_output.append(a_util::strings::format("namespace %s\n{\n", _name_space.c_str()));
|
||||
}
|
||||
|
||||
HeaderTypedefs typedefs = header->getTypedefs();
|
||||
for (HeaderTypedefs::iterator iter = typedefs.begin(); iter != typedefs.end(); iter++)
|
||||
{
|
||||
if (isFailed((appendType(*iter))))
|
||||
{
|
||||
return ERR_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
HeaderEnums enums = header->getEnums();
|
||||
for (auto iter = enums.begin(); iter != enums.end(); iter++)
|
||||
{
|
||||
if (isFailed(((*iter)->accept(this))))
|
||||
{
|
||||
return ERR_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
HeaderStructs structs = header->getStructs();
|
||||
for (HeaderStructs::iterator iter = structs.begin(); iter != structs.end(); iter++)
|
||||
{
|
||||
if (isFailed((appendType(*iter))))
|
||||
{
|
||||
return ERR_FAILED;
|
||||
}
|
||||
}
|
||||
HeaderConstants constants = header->getConstants();
|
||||
for (HeaderConstants::iterator iter = constants.begin(); iter != constants.end(); iter++)
|
||||
{
|
||||
if (isFailed(((*iter)->accept(this))))
|
||||
{
|
||||
return ERR_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
if (isFailed((printUnknownTypes())))
|
||||
{
|
||||
return ERR_FAILED;
|
||||
}
|
||||
|
||||
if (_name_space.length() > 0)
|
||||
{
|
||||
_header_output.append(a_util::strings::format("} // namespace %s\n", _name_space.c_str()));
|
||||
}
|
||||
|
||||
return ERR_NOERROR;
|
||||
}
|
||||
|
||||
a_util::result::Result HeaderPrinter::visit(const HeaderBasicType* basic_type)
|
||||
{
|
||||
CollectType(basic_type, true);
|
||||
_header_output.append("// The following type is assumed to be known:\n");
|
||||
_header_output.append("// ");
|
||||
_header_output.append(basic_type->getName());
|
||||
_header_output.append("\n\n");
|
||||
return ERR_NOERROR;
|
||||
}
|
||||
|
||||
a_util::result::Result HeaderPrinter::visit(const HeaderTypedef* type_def)
|
||||
{
|
||||
printDescription(type_def);
|
||||
// Set known first, so no infinite loop will occur when looking for base type
|
||||
CollectType(type_def, true);
|
||||
appendType(type_def->getOriginalType());
|
||||
_header_output.append(a_util::strings::format("typedef %s %s;\n\n",
|
||||
type_def->getOriginalType()->getName().c_str(), type_def->getName().c_str()));
|
||||
return ERR_NOERROR;
|
||||
}
|
||||
|
||||
a_util::result::Result HeaderPrinter::visit(const HeaderConstant* constant)
|
||||
{
|
||||
appendType(constant->getType());
|
||||
_header_output.append("const ");
|
||||
_header_output.append(constant->getType()->getName());
|
||||
_header_output.append(" ");
|
||||
_header_output.append(constant->getName());
|
||||
_header_output.append(" = ");
|
||||
_header_output.append(constant->asString());
|
||||
_header_output.append(";\n\n");
|
||||
return ERR_NOERROR;
|
||||
}
|
||||
|
||||
a_util::result::Result HeaderPrinter::visit(const HeaderStruct* header_struct)
|
||||
{
|
||||
printDescription(header_struct);
|
||||
// Set known first, so no infinite loop will occur when looking for base type
|
||||
CollectType(header_struct, true);
|
||||
// Make sure all types are already defined
|
||||
HeaderStructElementVec elements = header_struct->getElements();
|
||||
for (HeaderStructElementVec::iterator iter = elements.begin(); iter != elements.end(); iter++)
|
||||
{
|
||||
appendType((*iter)->getType());
|
||||
}
|
||||
_header_output.append(a_util::strings::format("#pragma pack(push,%d)\n", header_struct->getPacking()));
|
||||
_header_output.append("typedef struct\n{\n");
|
||||
for (HeaderStructElementVec::iterator iter = elements.begin(); iter != elements.end(); iter++)
|
||||
{
|
||||
if (isFailed(((*iter)->accept(this))))
|
||||
{
|
||||
return ERR_FAILED;
|
||||
}
|
||||
}
|
||||
_header_output.append(a_util::strings::format("} %s;\n", header_struct->getName().c_str()));
|
||||
_header_output.append("#pragma pack(pop)\n\n");
|
||||
CollectType(header_struct, true);
|
||||
return ERR_NOERROR;
|
||||
}
|
||||
|
||||
a_util::result::Result HeaderPrinter::visit(const HeaderStructElement* header_struct)
|
||||
{
|
||||
if (!header_struct || !header_struct->getType())
|
||||
{
|
||||
return ERR_INVALID_ARG;
|
||||
}
|
||||
printDescription(header_struct->getDescription(), header_struct->getComment(), true);
|
||||
appendType(header_struct->getType());
|
||||
_header_output.append(" ");
|
||||
if (header_struct->isStatic())
|
||||
{
|
||||
_header_output.append("static ");
|
||||
}
|
||||
if (header_struct->isConst())
|
||||
{
|
||||
_header_output.append("const ");
|
||||
}
|
||||
_header_output.append(header_struct->getType()->getName());
|
||||
if (header_struct->isPointer())
|
||||
{
|
||||
_header_output.append("* ");
|
||||
}
|
||||
_header_output.append(" ");
|
||||
_header_output.append(header_struct->getName());
|
||||
if (header_struct->getArraySize() > 1)
|
||||
{
|
||||
_header_output.append(a_util::strings::format("[%d]", header_struct->getArraySize()));
|
||||
}
|
||||
_header_output.append(";\n");
|
||||
return ERR_NOERROR;
|
||||
}
|
||||
|
||||
a_util::result::Result HeaderPrinter::visit(const HeaderEnum* header_enum)
|
||||
{
|
||||
CollectType(header_enum, true);
|
||||
printDescription(header_enum);
|
||||
_header_output.append("typedef enum {\n");
|
||||
for (auto iter = header_enum->getValues().begin(); iter != header_enum->getValues().end(); iter++)
|
||||
{
|
||||
_header_output.append(a_util::strings::format(" %s=%i,\n", iter->second.c_str(), iter->first));
|
||||
}
|
||||
if (header_enum->getValues().size() > 0)
|
||||
{
|
||||
// remove last ',' since some versions of C/C++ don't allow trailing commas in enums
|
||||
_header_output.resize(_header_output.length() - 2);
|
||||
}
|
||||
_header_output.append(a_util::strings::format("\n} %s;\n\n", header_enum->getName().c_str()));
|
||||
return ERR_NOERROR;
|
||||
}
|
||||
|
||||
a_util::result::Result HeaderPrinter::appendType(const HeaderType* type)
|
||||
{
|
||||
// See if we already know this type and therefore have printed it already
|
||||
for (HeaderConstTypes::iterator iter = _known_types.begin(); iter != _known_types.end(); iter++)
|
||||
{
|
||||
if (*iter == type)
|
||||
{
|
||||
return ERR_NOERROR;
|
||||
}
|
||||
}
|
||||
// Search the header for the type.
|
||||
if (_header != NULL)
|
||||
{
|
||||
for (HeaderTypedefs::const_iterator iter = _header->getTypedefs().begin(); iter != _header->getTypedefs().end(); iter++)
|
||||
{
|
||||
if (*iter == type)
|
||||
{
|
||||
// Found it, append it
|
||||
return ((*iter)->accept(this));
|
||||
}
|
||||
}
|
||||
for (HeaderStructs::const_iterator iter = _header->getStructs().begin(); iter != _header->getStructs().end(); iter++)
|
||||
{
|
||||
if (*iter == type)
|
||||
{
|
||||
// Found it, append it
|
||||
return ((*iter)->accept(this));
|
||||
}
|
||||
}
|
||||
}
|
||||
// Nothing found so far, so type is unknown
|
||||
CollectType(type, false);
|
||||
return (ERR_NOT_FOUND);
|
||||
}
|
||||
|
||||
a_util::result::Result HeaderPrinter::CollectType(const ddl::HeaderType* type, bool is_known)
|
||||
{
|
||||
if (is_known)
|
||||
{
|
||||
if (std::find(_known_types.begin(), _known_types.end(), type) ==
|
||||
_known_types.end())
|
||||
{
|
||||
_known_types.push_back(type);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (std::find(_unknown_types.begin(), _unknown_types.end(), type) ==
|
||||
_unknown_types.end())
|
||||
{
|
||||
_unknown_types.push_back(type);
|
||||
}
|
||||
}
|
||||
return ERR_NOERROR;
|
||||
}
|
||||
|
||||
a_util::result::Result HeaderPrinter::printUnknownTypes()
|
||||
{
|
||||
// visit all types that are in the unknown types set but not in the knowN types set
|
||||
HeaderConstTypes vec = _unknown_types;
|
||||
for (HeaderConstTypes::iterator iter = vec.begin(); iter != vec.end(); iter++)
|
||||
{
|
||||
if (std::find(_known_types.begin(), _known_types.end(), *iter) == _known_types.end())
|
||||
{
|
||||
(*iter)->accept(this);
|
||||
}
|
||||
}
|
||||
if (vec.size() != _unknown_types.size())
|
||||
{
|
||||
printUnknownTypes();
|
||||
}
|
||||
return ERR_NOERROR;
|
||||
}
|
||||
|
||||
a_util::result::Result HeaderPrinter::printDescription(const std::string& description, const std::string& comment, bool indent)
|
||||
{
|
||||
if (description.length() == 0 && comment.length() == 0)
|
||||
{
|
||||
return ERR_NOERROR;
|
||||
}
|
||||
|
||||
std::string indent_string;
|
||||
if (indent)
|
||||
{
|
||||
indent_string = " ";
|
||||
}
|
||||
|
||||
_header_output.append(indent_string);
|
||||
_header_output.append("/**\n");
|
||||
if (description.length() > 0)
|
||||
{
|
||||
_header_output.append(a_util::strings::format("%s * %s\n", indent_string.c_str(), description.c_str()));
|
||||
}
|
||||
if (comment.length() > 0)
|
||||
{
|
||||
_header_output.append(a_util::strings::format("%s * %s\n", indent_string.c_str(), comment.c_str()));
|
||||
}
|
||||
_header_output.append(indent_string);
|
||||
_header_output.append("*/\n");
|
||||
return ERR_NOERROR;
|
||||
}
|
||||
|
||||
a_util::result::Result HeaderPrinter::printDescription(const HeaderType* type)
|
||||
{
|
||||
return printDescription(type->getDescription(), type->getComment());
|
||||
}
|
||||
|
||||
bool invalidHeaderChar(char c)
|
||||
{
|
||||
bool is_num = (c >= '0' && c <= '9');
|
||||
bool is_uppercase_alpha = (c >= 'A' && c <= 'Z');
|
||||
bool is_lowercase_alpha = (c >= 'a' && c <= 'z');
|
||||
bool is_allowed_punctuation = (c == '.' || c == '_' || c == '-');
|
||||
return !(is_num || is_uppercase_alpha || is_lowercase_alpha || is_allowed_punctuation);
|
||||
}
|
||||
|
||||
std::string HeaderPrinter::addHeaderGuards(const a_util::filesystem::Path &filename, const std::string &unguarded_header_content)
|
||||
{
|
||||
std::string guard_name = filename.getLastElement().toString();
|
||||
guard_name.erase(std::remove_if(guard_name.begin(), guard_name.end(), invalidHeaderChar), guard_name.end());
|
||||
std::replace(guard_name.begin(), guard_name.end(), '.', '_');
|
||||
std::transform(guard_name.begin(), guard_name.end(), guard_name.begin(), ::toupper);
|
||||
|
||||
std::string output;
|
||||
|
||||
output.append("#ifndef ");
|
||||
output.append(guard_name + "\n");
|
||||
output.append("#define ");
|
||||
output.append(guard_name + "\n\n");
|
||||
|
||||
output.append(unguarded_header_content);
|
||||
|
||||
output.append("\n#endif //");
|
||||
output.append(guard_name + "\n");
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
void HeaderPrinter::SetNamespace(std::string name_space)
|
||||
{
|
||||
_name_space = name_space;
|
||||
}
|
||||
|
||||
} // namespace ddl
|
Loading…
Add table
Add a link
Reference in a new issue