Skip to content

Commit

Permalink
Clang based header generator: Refactor emitter
Browse files Browse the repository at this point in the history
This CL moves additional functions and template strings to EmitterBase as we are going to use them in the new emitter.

PiperOrigin-RevId: 643321889
Change-Id: Iba50388141ff9fd978980becd4af22176a5d5842
  • Loading branch information
okunz authored and copybara-github committed Jun 14, 2024
1 parent cfa374b commit 131826f
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 124 deletions.
79 changes: 16 additions & 63 deletions sandboxed_api/tools/clang_generator/emitter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,14 @@

#include "sandboxed_api/tools/clang_generator/emitter.h"

#include <cstdint>
#include <string>
#include <utility>
#include <vector>

#include "absl/container/flat_hash_set.h"
#include "absl/log/log.h"
#include "absl/random/random.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/ascii.h"
#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
Expand All @@ -46,18 +42,18 @@

namespace sapi {

// Common header description with auto-generation notice.
constexpr absl::string_view kHeaderDescription =
R"(// AUTO-GENERATED by the Sandboxed API generator.
// Edits will be discarded when regenerating this file.)";

// Common header file prolog with auto-generation notice.
// Note: The includes will be adjusted by Copybara when converting to/from
// internal code. This is intentional.
// Text template arguments:
// 1. Header guard
constexpr absl::string_view kHeaderProlog =
R"(// AUTO-GENERATED by the Sandboxed API generator.
// Edits will be discarded when regenerating this file.
#ifndef %1$s
#define %1$s
constexpr absl::string_view kHeaderIncludes =
R"(
#include <cstdint>
#include <type_traits>
Expand All @@ -70,33 +66,12 @@ constexpr absl::string_view kHeaderProlog =
)";

// Text template arguments:
// 1. Header guard
constexpr absl::string_view kHeaderEpilog =
R"(
#endif // %1$s)";

// Text template arguments:
// 1. Include for embedded sandboxee objects
constexpr absl::string_view kEmbedInclude = R"(#include "%1$s_embed.h"
)";

// Text template arguments:
// 1. Namespace name
constexpr absl::string_view kNamespaceBeginTemplate =
R"(
namespace %1$s {
)";

// Text template arguments:
// 1. Namespace name
constexpr absl::string_view kNamespaceEndTemplate =
R"(
} // namespace %1$s
)";

// Text template arguments:
// 1. Class name
// 2. Embedded object identifier
Expand Down Expand Up @@ -136,38 +111,13 @@ constexpr absl::string_view kClassFooterTemplate = R"(
};
)";

std::string GetIncludeGuard(absl::string_view filename) {
if (filename.empty()) {
static auto* bit_gen = new absl::BitGen();
return absl::StrCat(
// Copybara will transform the string. This is intentional.
"SANDBOXED_API_GENERATED_HEADER_",
absl::AsciiStrToUpper(absl::StrCat(
absl::Hex(absl::Uniform<uint64_t>(*bit_gen), absl::kZeroPad16))),
"_");
// Returns a unique name for a parameter. If `decl` has no name, a unique name
// will be generated in the form of `unnamed<index>_`.
std::string GetParamName(const clang::ParmVarDecl* decl, int index) {
if (std::string name = decl->getName().str(); !name.empty()) {
return absl::StrCat(name, "_"); // Suffix to avoid collisions
}

constexpr absl::string_view kUnderscorePrefix = "SAPI_";
std::string guard;
guard.reserve(filename.size() + kUnderscorePrefix.size() + 1);
for (auto c : filename) {
if (absl::ascii_isalpha(c)) {
guard += absl::ascii_toupper(c);
continue;
}
if (guard.empty()) {
guard = kUnderscorePrefix;
}
if (absl::ascii_isdigit(c)) {
guard += c;
} else if (guard.back() != '_') {
guard += '_';
}
}
if (!absl::EndsWith(guard, "_")) {
guard += '_';
}
return guard;
return absl::StrCat("unnamed", index, "_");
}

// Returns a comment for the given function `decl` which represents the
Expand Down Expand Up @@ -305,7 +255,10 @@ absl::StatusOr<std::string> EmitHeader(
}
std::string out;
const std::string include_guard = GetIncludeGuard(options.out_file);
absl::StrAppend(&out, kHeaderDescription);
absl::StrAppendFormat(&out, kHeaderProlog, include_guard);
absl::StrAppend(&out, kHeaderIncludes);

// When embedding the sandboxee, add embed header include
if (!options.embed_name.empty()) {
// Not using JoinPath() because even on Windows include paths use plain
Expand Down
9 changes: 0 additions & 9 deletions sandboxed_api/tools/clang_generator/emitter.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@

#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "clang/AST/Decl.h"
#include "clang/AST/Type.h"
#include "sandboxed_api/tools/clang_generator/emitter_base.h"
Expand Down Expand Up @@ -48,14 +47,6 @@ class Emitter : public EmitterBase {
std::vector<std::string> rendered_functions_ordered_;
};

// Constructs an include guard name for the given filename. The name is of the
// same form as the include guards in this project and conforms to the Google
// C++ style. For example,
// sandboxed_api/examples/zlib/zlib-sapi.sapi.h
// will be mapped to
// SANDBOXED_API_EXAMPLES_ZLIB_ZLIB_SAPI_SAPI_H_
std::string GetIncludeGuard(absl::string_view filename);

} // namespace sapi

#endif // SANDBOXED_API_TOOLS_CLANG_GENERATOR_EMITTER_H_
84 changes: 35 additions & 49 deletions sandboxed_api/tools/clang_generator/emitter_base.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,18 @@
#include "sandboxed_api/tools/clang_generator/emitter_base.h"

#include <algorithm>
#include <cstdint>
#include <string>
#include <vector>

#include "absl/random/random.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/ascii.h"
#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_join.h"
#include "absl/strings/string_view.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
Expand All @@ -38,57 +42,12 @@

namespace sapi {

// Common header file prolog with auto-generation notice.
// Note: The includes will be adjusted by Copybara when converting to/from
// internal code. This is intentional.
// Text template arguments:
// 1. Header guard
constexpr absl::string_view kHeaderProlog =
R"(// AUTO-GENERATED by the Sandboxed API generator.
// Edits will be discarded when regenerating this file.
#ifndef %1$s
#define %1$s
#include <cstdint>
#include <type_traits>
#include "absl/base/macros.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "sandboxed_api/sandbox.h"
#include "sandboxed_api/util/status_macros.h"
#include "sandboxed_api/vars.h"
)";

// Text template arguments:
// 1. Header guard
constexpr absl::string_view kHeaderEpilog =
R"(
#endif // %1$s)";

// Text template arguments:
// 1. Include for embedded sandboxee objects
constexpr absl::string_view kEmbedInclude = R"(#include "%1$s_embed.h"
)";

// Text template arguments:
// 1. Namespace name
constexpr absl::string_view kNamespaceBeginTemplate =
R"(
namespace %1$s {
)";

// Text template arguments:
// 1. Namespace name
constexpr absl::string_view kNamespaceEndTemplate =
R"(
} // namespace %1$s
)";

// Text template arguments:
// 1. Class name
// 2. Embedded object identifier
Expand Down Expand Up @@ -248,11 +207,38 @@ std::string GetSpelling(const clang::Decl* decl) {

} // namespace

std::string GetParamName(const clang::ParmVarDecl* decl, int index) {
if (std::string name = decl->getName().str(); !name.empty()) {
return absl::StrCat(name, "_"); // Suffix to avoid collisions
std::string GetIncludeGuard(absl::string_view filename) {
if (filename.empty()) {
static auto* bit_gen = new absl::BitGen();
return absl::StrCat(
// Copybara will transform the string. This is intentional.
"SANDBOXED_API_GENERATED_HEADER_",
absl::AsciiStrToUpper(absl::StrCat(
absl::Hex(absl::Uniform<uint64_t>(*bit_gen), absl::kZeroPad16))),
"_");
}

constexpr absl::string_view kUnderscorePrefix = "SAPI_";
std::string guard;
guard.reserve(filename.size() + kUnderscorePrefix.size() + 1);
for (auto c : filename) {
if (absl::ascii_isalpha(c)) {
guard += absl::ascii_toupper(c);
continue;
}
if (guard.empty()) {
guard = kUnderscorePrefix;
}
if (absl::ascii_isdigit(c)) {
guard += c;
} else if (guard.back() != '_') {
guard += '_';
}
}
if (!absl::EndsWith(guard, "_")) {
guard += '_';
}
return absl::StrCat("unnamed", index, "_");
return guard;
}

void EmitterBase::EmitType(clang::TypeDecl* type_decl) {
Expand Down
40 changes: 37 additions & 3 deletions sandboxed_api/tools/clang_generator/emitter_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "absl/container/node_hash_set.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "clang/AST/Decl.h"
#include "clang/AST/Type.h"

Expand All @@ -40,6 +41,36 @@ absl::StatusOr<std::string> ReformatGoogleStyle(const std::string& filename,

} // namespace internal

// Text template arguments:
// 1. Namespace name
inline constexpr absl::string_view kNamespaceBeginTemplate =
R"(
namespace %1$s {
)";

// Text template arguments:
// 1. Namespace name
inline constexpr absl::string_view kNamespaceEndTemplate =
R"(
} // namespace %1$s
)";

// Text template arguments:
// 1. Header guard
inline constexpr absl::string_view kHeaderProlog =
R"(
#ifndef %1$s
#define %1$s
)";

// Text template arguments:
// 1. Header guard
inline constexpr absl::string_view kHeaderEpilog =
R"(
#endif // %1$s)";

class RenderedType {
public:
RenderedType(std::string ns_name, std::string spelling)
Expand Down Expand Up @@ -89,9 +120,12 @@ class EmitterBase {
void EmitType(clang::TypeDecl* type_decl);
};

// Returns a unique name for a parameter. If `decl` has no name, a unique name
// will be generated in the form of `unnamed<index>_`.
std::string GetParamName(const clang::ParmVarDecl* decl, int index);
// Constructs an include guard for the given filename. The generated string
// conforms to the Google C++ style. For example,
// sandboxed_api/examples/zlib/zlib-sapi.sapi.h
// will be mapped to
// SANDBOXED_API_EXAMPLES_ZLIB_ZLIB_SAPI_SAPI_H_
std::string GetIncludeGuard(absl::string_view filename);

} // namespace sapi

Expand Down

0 comments on commit 131826f

Please sign in to comment.