generate C++ interface header, proxy and stub headers and sources.
diff --git a/AST.h b/AST.h
index 497deb7..942b718 100644
--- a/AST.h
+++ b/AST.h
@@ -7,12 +7,14 @@
#include <utils/Vector.h>
#include "FQName.h"
+#include "Type.h"
namespace android {
struct Coordinator;
struct Formatter;
-struct Type;
+struct Method;
+struct TypedVar;
struct Scope;
struct AST {
@@ -45,6 +47,8 @@
void dump(Formatter &out) const;
+ status_t generateCpp() const;
+
private:
Coordinator *mCoordinator;
Vector<Scope *> mScopePath;
@@ -54,6 +58,41 @@
FQName mPackage;
+ void getPackageComponents(std::vector<std::string> *components) const;
+
+ void getPackageAndVersionComponents(
+ std::vector<std::string> *components, bool cpp_compatible) const;
+
+ std::string makeHeaderGuard(const std::string &baseName) const;
+ void enterLeaveNamespace(Formatter &out, bool enter) const;
+
+ status_t generateInterfaceHeader() const;
+ status_t generateStubHeader() const;
+ status_t generateProxyHeader() const;
+ status_t generateAllSource() const;
+
+ status_t generateTypeSource(
+ Formatter &out, const std::string &ifaceName) const;
+
+ status_t generateProxySource(
+ Formatter &out, const std::string &baseName) const;
+
+ status_t generateStubSource(
+ Formatter &out, const std::string &baseName) const;
+
+ status_t generateStubSourceForMethod(
+ Formatter &out, const Method *method) const;
+
+ void emitCppReaderWriter(
+ Formatter &out,
+ const std::string &parcelObj,
+ bool parcelObjIsPointer,
+ const TypedVar *arg,
+ bool isReader,
+ Type::ErrorMode mode) const;
+
+ status_t emitTypeDeclarations(Formatter &out) const;
+
DISALLOW_COPY_AND_ASSIGN(AST);
};
diff --git a/Android.mk b/Android.mk
index ac3e3f4..4ae915f 100644
--- a/Android.mk
+++ b/Android.mk
@@ -13,6 +13,7 @@
EnumType.cpp \
Formatter.cpp \
FQName.cpp \
+ generateCpp.cpp \
HandleType.cpp \
hidl-gen_y.yy \
hidl-gen_l.ll \
@@ -36,4 +37,6 @@
LOCAL_STATIC_LIBRARIES := \
libutils \
+LOCAL_CFLAGS := -O0 -g
+
include $(BUILD_HOST_EXECUTABLE)
diff --git a/ArrayType.cpp b/ArrayType.cpp
index 9137de1..7feb9fb 100644
--- a/ArrayType.cpp
+++ b/ArrayType.cpp
@@ -2,6 +2,8 @@
#include "Formatter.h"
+#include <android-base/logging.h>
+
namespace android {
ArrayType::ArrayType(Type *elementType, const char *dimension)
@@ -14,5 +16,136 @@
out << "[" << mDimension << "]";
}
+std::string ArrayType::getCppType(StorageMode mode, std::string *extra) const {
+ const std::string base = mElementType->getCppType(extra);
+
+ CHECK(extra->empty());
+
+ *extra = "[" + mDimension + "]";
+
+ switch (mode) {
+ case StorageMode_Stack:
+ return base;
+
+ case StorageMode_Argument:
+ return "const " + base;
+
+ case StorageMode_Result:
+ {
+ extra->clear();
+ return "const " + base + "*";
+ }
+ }
+}
+
+void ArrayType::emitReaderWriter(
+ Formatter &out,
+ const std::string &name,
+ const std::string &parcelObj,
+ bool parcelObjIsPointer,
+ bool isReader,
+ ErrorMode mode) const {
+ std::string baseExtra;
+ std::string baseType = mElementType->getCppType(&baseExtra);
+
+ const std::string parentName = "_aidl_" + name + "_parent";
+
+ out << "size_t " << parentName << ";\n\n";
+
+ const std::string parcelObjDeref =
+ parcelObj + (parcelObjIsPointer ? "->" : ".");
+
+ if (isReader) {
+ out << name
+ << " = (const "
+ << baseType
+ << " *)"
+ << parcelObjDeref
+ << "readBuffer(&"
+ << parentName
+ << ");\n\n";
+
+ out << "if (" << name << " == nullptr) {\n";
+
+ out.indent();
+
+ out << "_aidl_err = ::android::UNKNOWN_ERROR;\n";
+ handleError2(out, mode);
+
+ out.unindent();
+ out << "}\n\n";
+ } else {
+ out << "_aidl_err = "
+ << parcelObjDeref
+ << "writeBuffer("
+ << name
+ << ", "
+ << mDimension
+ << " * sizeof("
+ << baseType
+ << "), &"
+ << parentName
+ << ");\n";
+
+ handleError(out, mode);
+ }
+
+ emitReaderWriterEmbedded(
+ out,
+ name,
+ isReader /* nameIsPointer */,
+ parcelObj,
+ parcelObjIsPointer,
+ isReader,
+ mode,
+ parentName,
+ "0 /* parentOffset */");
+}
+
+void ArrayType::emitReaderWriterEmbedded(
+ Formatter &out,
+ const std::string &name,
+ bool nameIsPointer,
+ const std::string &parcelObj,
+ bool parcelObjIsPointer,
+ bool isReader,
+ ErrorMode mode,
+ const std::string &parentName,
+ const std::string &offsetText) const {
+ if (!mElementType->needsEmbeddedReadWrite()) {
+ return;
+ }
+
+ const std::string nameDeref = name + (nameIsPointer ? "->" : ".");
+
+ std::string baseExtra;
+ std::string baseType = mElementType->getCppType(&baseExtra);
+
+ out << "for (size_t _aidl_index = 0; _aidl_index < "
+ << mDimension
+ << "; ++_aidl_index) {\n";
+
+ out.indent();
+
+ mElementType->emitReaderWriterEmbedded(
+ out,
+ name + "[_aidl_index]",
+ false /* nameIsPointer */,
+ parcelObj,
+ parcelObjIsPointer,
+ isReader,
+ mode,
+ parentName,
+ offsetText + " + _aidl_index * sizeof(" + baseType + ")");
+
+ out.unindent();
+
+ out << "}\n\n";
+}
+
+bool ArrayType::needsEmbeddedReadWrite() const {
+ return mElementType->needsEmbeddedReadWrite();
+}
+
} // namespace android
diff --git a/ArrayType.h b/ArrayType.h
index 25320f4..3e44fe4 100644
--- a/ArrayType.h
+++ b/ArrayType.h
@@ -13,6 +13,29 @@
void dump(Formatter &out) const override;
+ std::string getCppType(StorageMode mode, std::string *extra) const override;
+
+ void emitReaderWriter(
+ Formatter &out,
+ const std::string &name,
+ const std::string &parcelObj,
+ bool parcelObjIsPointer,
+ bool isReader,
+ ErrorMode mode) const override;
+
+ void emitReaderWriterEmbedded(
+ Formatter &out,
+ const std::string &name,
+ bool nameIsPointer,
+ const std::string &parcelObj,
+ bool parcelObjIsPointer,
+ bool isReader,
+ ErrorMode mode,
+ const std::string &parentName,
+ const std::string &offsetText) const override;
+
+ bool needsEmbeddedReadWrite() const override;
+
private:
Type *mElementType;
std::string mDimension;
diff --git a/CompoundType.cpp b/CompoundType.cpp
index ce8dc86..a96c7e2 100644
--- a/CompoundType.cpp
+++ b/CompoundType.cpp
@@ -15,13 +15,21 @@
out << " " << mName << ";";
}
+std::string CompoundField::name() const {
+ return mName;
+}
+
+const Type &CompoundField::type() const {
+ return *mType;
+}
+
CompoundType::CompoundType(Style style, const char *name)
: Scope(name),
mStyle(style),
mFields(NULL) {
}
-void CompoundType::setFields(Vector<CompoundField *> *fields) {
+void CompoundType::setFields(std::vector<CompoundField *> *fields) {
mFields = fields;
}
@@ -36,7 +44,7 @@
Scope::dump(out);
for (size_t i = 0; i < mFields->size(); ++i) {
- mFields->itemAt(i)->dump(out);
+ (*mFields)[i]->dump(out);
out << "\n";
}
@@ -45,5 +53,258 @@
out << "};\n\n";
}
+std::string CompoundType::getCppType(
+ StorageMode mode, std::string *extra) const {
+ extra->clear();
+ const std::string base = name();
+
+ switch (mode) {
+ case StorageMode_Stack:
+ return base;
+
+ case StorageMode_Argument:
+ return "const " + base + "&";
+
+ case StorageMode_Result:
+ return "const " + base + "*";
+ }
+}
+
+void CompoundType::emitReaderWriter(
+ Formatter &out,
+ const std::string &name,
+ const std::string &parcelObj,
+ bool parcelObjIsPointer,
+ bool isReader,
+ ErrorMode mode) const {
+ const std::string parentName = "_aidl_" + name + "_parent";
+
+ out << "size_t " << parentName << ";\n\n";
+
+ const std::string parcelObjDeref =
+ parcelObj + (parcelObjIsPointer ? "->" : ".");
+
+ if (isReader) {
+ out << name
+ << " = (const "
+ << this->name()
+ << " *)"
+ << parcelObjDeref
+ << "readBuffer("
+ << "&"
+ << parentName
+ << ");\n";
+
+ out << "if ("
+ << name
+ << " == nullptr) {\n";
+
+ out.indent();
+
+ out << "_aidl_err = ::android::UNKNOWN_ERROR;\n";
+ handleError2(out, mode);
+
+ out.unindent();
+ out << "}\n\n";
+ } else {
+ out << "_aidl_err = "
+ << parcelObjDeref
+ << "writeBuffer(&"
+ << name
+ << ", sizeof("
+ << name
+ << "), &"
+ << parentName
+ << ");\n";
+
+ handleError(out, mode);
+ }
+
+ if (mStyle != STYLE_STRUCT || !needsEmbeddedReadWrite()) {
+ return;
+ }
+
+ emitReaderWriterEmbedded(
+ out,
+ name,
+ isReader /* nameIsPointer */,
+ parcelObj,
+ parcelObjIsPointer,
+ isReader,
+ mode,
+ parentName,
+ "0 /* parentOffset */");
+}
+
+void CompoundType::emitReaderWriterEmbedded(
+ Formatter &out,
+ const std::string &name,
+ bool nameIsPointer,
+ const std::string &parcelObj,
+ bool parcelObjIsPointer,
+ bool isReader,
+ ErrorMode mode,
+ const std::string &parentName,
+ const std::string &offsetText) const {
+ emitReaderWriterEmbeddedForTypeName(
+ out,
+ name,
+ nameIsPointer,
+ parcelObj,
+ parcelObjIsPointer,
+ isReader,
+ mode,
+ parentName,
+ offsetText,
+ this->name(),
+ "" /* childName */);
+}
+
+status_t CompoundType::emitTypeDeclarations(Formatter &out) const {
+ out << ((mStyle == STYLE_STRUCT) ? "struct" : "union")
+ << " "
+ << name()
+ << " {\n";
+
+ out.indent();
+
+ Scope::emitTypeDeclarations(out);
+
+ for (const auto &field : *mFields) {
+ std::string extra;
+ out << field->type().getCppType(&extra)
+ << " "
+ << field->name()
+ << extra
+ << ";\n";
+ }
+
+ if (needsEmbeddedReadWrite()) {
+ out << "\n::android::status_t readEmbeddedFromParcel(\n";
+
+ out.indent();
+ out.indent();
+
+ out << "const ::android::hidl::Parcel &parcel,\n"
+ << "size_t parentHandle,\n"
+ << "size_t parentOffset);\n\n";
+
+ out.unindent();
+ out.unindent();
+
+ out << "::android::status_t writeEmbeddedToParcel(\n";
+
+ out.indent();
+ out.indent();
+
+ out << "::android::hidl::Parcel *parcel,\n"
+ << "size_t parentHandle,\n"
+ << "size_t parentOffset) const;\n";
+
+ out.unindent();
+ out.unindent();
+ }
+
+ out.unindent();
+ out << "};\n\n";
+
+ return OK;
+}
+
+status_t CompoundType::emitTypeDefinitions(
+ Formatter &out, const std::string prefix) const {
+ status_t err = Scope::emitTypeDefinitions(out, prefix + "::" + name());
+
+ if (err != OK) {
+ return err;
+ }
+
+ if (!needsEmbeddedReadWrite()) {
+ return OK;
+ }
+
+ emitStructReaderWriter(out, prefix, true /* isReader */);
+ emitStructReaderWriter(out, prefix, false /* isReader */);
+
+ return OK;
+}
+
+void CompoundType::emitStructReaderWriter(
+ Formatter &out, const std::string &prefix, bool isReader) const {
+ out << "::android::status_t "
+ << (prefix.empty() ? "" : (prefix + "::"))
+ << name()
+ << (isReader ? "::readEmbeddedFromParcel"
+ : "::writeEmbeddedToParcel")
+ << "(\n";
+
+ out.indent();
+ out.indent();
+
+ if (isReader) {
+ out << "const ::android::hidl::Parcel &parcel,\n";
+ } else {
+ out << "::android::hidl::Parcel *parcel,\n";
+ }
+
+ out << "size_t parentHandle,\n"
+ << "size_t parentOffset)";
+
+ if (!isReader) {
+ out << " const";
+ }
+
+ out << " {\n";
+
+ out.unindent();
+ out.unindent();
+ out.indent();
+
+ out << "::android::status_t _aidl_err = ::android::OK;\n\n";
+
+ for (const auto &field : *mFields) {
+ if (!field->type().needsEmbeddedReadWrite()) {
+ continue;
+ }
+
+ field->type().emitReaderWriterEmbedded(
+ out,
+ field->name(),
+ false /* nameIsPointer */,
+ "parcel",
+ !isReader /* parcelObjIsPointer */,
+ isReader,
+ ErrorMode_Goto,
+ "parentHandle",
+ "parentOffset + offsetof(" + name() + ", " + field->name() + ")");
+ }
+
+ out.unindent();
+ out << "_aidl_error:\n";
+ out.indent();
+ out << "return _aidl_err;\n";
+
+ out.unindent();
+ out << "}\n\n";
+}
+
+bool CompoundType::needsEmbeddedReadWrite() const {
+ if (mStyle != STYLE_STRUCT) {
+ return false;
+ }
+
+ for (const auto &field : *mFields) {
+ if (field->type().needsEmbeddedReadWrite()) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool CompoundType::resultNeedsDeref() const {
+ return true;
+}
+
} // namespace android
diff --git a/CompoundType.h b/CompoundType.h
index 8d4b837..7653a1a 100644
--- a/CompoundType.h
+++ b/CompoundType.h
@@ -4,7 +4,7 @@
#include "Scope.h"
-#include <utils/Vector.h>
+#include <vector>
namespace android {
@@ -13,6 +13,9 @@
void dump(Formatter &out) const;
+ std::string name() const;
+ const Type &type() const;
+
private:
std::string mName;
Type *mType;
@@ -28,13 +31,45 @@
CompoundType(Style style, const char *name);
- void setFields(Vector<CompoundField *> *fields);
+ void setFields(std::vector<CompoundField *> *fields);
void dump(Formatter &out) const override;
+ std::string getCppType(StorageMode mode, std::string *extra) const override;
+
+ void emitReaderWriter(
+ Formatter &out,
+ const std::string &name,
+ const std::string &parcelObj,
+ bool parcelObjIsPointer,
+ bool isReader,
+ ErrorMode mode) const override;
+
+ void emitReaderWriterEmbedded(
+ Formatter &out,
+ const std::string &name,
+ bool nameIsPointer,
+ const std::string &parcelObj,
+ bool parcelObjIsPointer,
+ bool isReader,
+ ErrorMode mode,
+ const std::string &parentName,
+ const std::string &offsetText) const override;
+
+ status_t emitTypeDeclarations(Formatter &out) const override;
+
+ status_t emitTypeDefinitions(
+ Formatter &out, const std::string prefix) const override;
+
+ bool needsEmbeddedReadWrite() const override;
+ bool resultNeedsDeref() const override;
+
private:
Style mStyle;
- Vector<CompoundField *> *mFields;
+ std::vector<CompoundField *> *mFields;
+
+ void emitStructReaderWriter(
+ Formatter &out, const std::string &prefix, bool isReader) const;
DISALLOW_COPY_AND_ASSIGN(CompoundType);
};
diff --git a/Coordinator.cpp b/Coordinator.cpp
index 196c739..97b176f 100644
--- a/Coordinator.cpp
+++ b/Coordinator.cpp
@@ -102,7 +102,8 @@
return ast;
}
-std::string Coordinator::getPackagePath(const FQName &fqName) const {
+std::string Coordinator::getPackagePath(
+ const FQName &fqName, bool relative) const {
CHECK(!fqName.package().empty());
CHECK(!fqName.version().empty());
const char *const kPrefix = "android.hardware.";
@@ -110,7 +111,10 @@
const std::string packageSuffix = fqName.package().substr(strlen(kPrefix));
- std::string packagePath = mInterfacesPath;
+ std::string packagePath;
+ if (!relative) {
+ packagePath = mInterfacesPath;
+ }
size_t startPos = 0;
size_t dotPos;
diff --git a/Coordinator.h b/Coordinator.h
index 0594d5b..8f72e7e 100644
--- a/Coordinator.h
+++ b/Coordinator.h
@@ -20,7 +20,8 @@
Type *lookupType(const FQName &fqName) const;
- std::string getPackagePath(const FQName &fqName) const;
+ std::string getPackagePath(
+ const FQName &fqName, bool relative = false) const;
private:
std::string mInterfacesPath;
diff --git a/EnumType.cpp b/EnumType.cpp
index c4d27c1..506c796 100644
--- a/EnumType.cpp
+++ b/EnumType.cpp
@@ -1,6 +1,7 @@
#include "EnumType.h"
#include "Formatter.h"
+#include "ScalarType.h"
namespace android {
@@ -19,11 +20,22 @@
out << ",";
}
+std::string EnumValue::name() const {
+ return mName;
+}
+
+const char *EnumValue::value() const {
+ return mValue;
+}
+
EnumType::EnumType(
- const char *name, Vector<EnumValue *> *values, Type *storageType)
+ const char *name, std::vector<EnumValue *> *values, Type *storageType)
: NamedType(name),
mValues(values),
- mStorageType(storageType) {
+ mStorageType(
+ storageType != NULL
+ ? storageType
+ : new ScalarType(ScalarType::KIND_INT32)) {
}
void EnumType::dump(Formatter &out) const {
@@ -39,7 +51,7 @@
out.indent();
for (size_t i = 0; i < mValues->size(); ++i) {
- mValues->itemAt(i)->dump(out);
+ (*mValues)[i]->dump(out);
out << "\n";
}
@@ -48,5 +60,50 @@
out << "};\n\n";
}
+std::string EnumType::getCppType(StorageMode, std::string *extra) const {
+ extra->clear();
+
+ return name();
+}
+
+void EnumType::emitReaderWriter(
+ Formatter &out,
+ const std::string &name,
+ const std::string &parcelObj,
+ bool parcelObjIsPointer,
+ bool isReader,
+ ErrorMode mode) const {
+ mStorageType->emitReaderWriter(
+ out, name, parcelObj, parcelObjIsPointer, isReader, mode);
+}
+
+status_t EnumType::emitTypeDeclarations(Formatter &out) const {
+ std::string extra;
+
+ out << "enum class "
+ << name()
+ << " : "
+ << mStorageType->getCppType(&extra)
+ << " {\n";
+
+ out.indent();
+
+ for (const auto &entry : *mValues) {
+ out << entry->name();
+
+ const char *value = entry->value();
+ if (value != NULL) {
+ out << " = " << value;
+ }
+
+ out << ",\n";
+ }
+
+ out.unindent();
+ out << "};\n\n";
+
+ return OK;
+}
+
} // namespace android
diff --git a/EnumType.h b/EnumType.h
index 7f44d59..a0d866a 100644
--- a/EnumType.h
+++ b/EnumType.h
@@ -4,7 +4,7 @@
#include "NamedType.h"
-#include <utils/Vector.h>
+#include <vector>
namespace android {
@@ -13,6 +13,9 @@
void dump(Formatter &out) const;
+ std::string name() const;
+ const char *value() const;
+
private:
std::string mName;
const char *mValue;
@@ -22,13 +25,25 @@
struct EnumType : public NamedType {
EnumType(const char *name,
- Vector<EnumValue *> *values,
+ std::vector<EnumValue *> *values,
Type *storageType = NULL);
void dump(Formatter &out) const override;
+ std::string getCppType(StorageMode mode, std::string *extra) const override;
+
+ void emitReaderWriter(
+ Formatter &out,
+ const std::string &name,
+ const std::string &parcelObj,
+ bool parcelObjIsPointer,
+ bool isReader,
+ ErrorMode mode) const override;
+
+ status_t emitTypeDeclarations(Formatter &out) const override;
+
private:
- Vector<EnumValue *> *mValues;
+ std::vector<EnumValue *> *mValues;
Type *mStorageType;
DISALLOW_COPY_AND_ASSIGN(EnumType);
diff --git a/Formatter.cpp b/Formatter.cpp
index 50b5368..bd04271 100644
--- a/Formatter.cpp
+++ b/Formatter.cpp
@@ -6,11 +6,19 @@
namespace android {
-Formatter::Formatter()
- : mIndentDepth(0),
+Formatter::Formatter(FILE *file)
+ : mFile(file == NULL ? stdout : file),
+ mIndentDepth(0),
mAtStartOfLine(true) {
}
+Formatter::~Formatter() {
+ if (mFile != stdout) {
+ fclose(mFile);
+ }
+ mFile = NULL;
+}
+
void Formatter::indent() {
++mIndentDepth;
}
@@ -28,23 +36,23 @@
if (pos == string::npos) {
if (mAtStartOfLine) {
- printf("%*s", (int)(2 * mIndentDepth), "");
+ fprintf(mFile, "%*s", (int)(2 * mIndentDepth), "");
mAtStartOfLine = false;
}
- printf("%s", out.substr(start).c_str());
+ fprintf(mFile, "%s", out.substr(start).c_str());
break;
}
if (pos == start) {
- printf("\n");
+ fprintf(mFile, "\n");
mAtStartOfLine = true;
} else if (pos > start) {
if (mAtStartOfLine) {
- printf("%*s", (int)(2 * mIndentDepth), "");
+ fprintf(mFile, "%*s", (int)(2 * mIndentDepth), "");
}
- printf("%s", out.substr(start, pos - start + 1).c_str());
+ fprintf(mFile, "%s", out.substr(start, pos - start + 1).c_str());
mAtStartOfLine = true;
}
diff --git a/Formatter.h b/Formatter.h
index 38e5419..a768608 100644
--- a/Formatter.h
+++ b/Formatter.h
@@ -24,7 +24,9 @@
namespace android {
struct Formatter {
- Formatter();
+ // Assumes ownership of file. Directed to stdout if file == NULL.
+ Formatter(FILE *file = NULL);
+ ~Formatter();
void indent();
void unindent();
@@ -33,6 +35,7 @@
Formatter &operator<<(size_t n);
private:
+ FILE *mFile;
size_t mIndentDepth;
bool mAtStartOfLine;
diff --git a/HandleType.cpp b/HandleType.cpp
index 70ffa5f..ea5d665 100644
--- a/HandleType.cpp
+++ b/HandleType.cpp
@@ -10,5 +10,136 @@
out << "handle";
}
+std::string HandleType::getCppType(StorageMode mode, std::string *extra) const {
+ extra->clear();
+
+ const std::string base = "::android::sp<::android::NativeHandle>";
+
+ switch (mode) {
+ case StorageMode_Stack:
+ case StorageMode_Result:
+ return base;
+
+ case StorageMode_Argument:
+ return "const " + base + "&";
+ }
+}
+
+void HandleType::emitReaderWriter(
+ Formatter &out,
+ const std::string &name,
+ const std::string &parcelObj,
+ bool parcelObjIsPointer,
+ bool isReader,
+ ErrorMode mode) const {
+ const std::string parcelObjDeref =
+ parcelObj + (parcelObjIsPointer ? "->" : ".");
+
+ if (isReader) {
+ out << name
+ << " = "
+ << "::android::NativeHandle::create(\n";
+
+ out.indent();
+ out.indent();
+
+ out << parcelObjDeref
+ << "readNativeHandle(), true /* ownsHandle */);\n\n";
+
+ out.unindent();
+ out.unindent();
+
+ out << "if ("
+ << name
+ << " == nullptr) {\n";
+
+ out.indent();
+
+ out << "_aidl_err = ::android::UNKNOWN_ERROR;\n";
+ handleError2(out, mode);
+
+ out.unindent();
+ out << "}\n\n";
+ } else {
+ out << "_aidl_err = ";
+ out << parcelObjDeref
+ << "writeNativeHandle("
+ << name
+ << "->handle());\n";
+
+ handleError(out, mode);
+ }
+}
+
+void HandleType::emitReaderWriterEmbedded(
+ Formatter &out,
+ const std::string &name,
+ bool nameIsPointer,
+ const std::string &parcelObj,
+ bool parcelObjIsPointer,
+ bool isReader,
+ ErrorMode mode,
+ const std::string &parentName,
+ const std::string &offsetText) const {
+ if (isReader) {
+ const std::string ptrName = "_aidl_" + name + "_ptr";
+
+ out << "const native_handle_t *"
+ << ptrName
+ << " = "
+ << parcelObj
+ << (parcelObjIsPointer ? "->" : ".")
+ << "readEmbeddedNativeHandle(\n";
+
+ out.indent();
+ out.indent();
+
+ out << parentName
+ << ",\n"
+ << offsetText
+ << "/* + offsetof(::android::NativeHandle, mHandle) */"
+ << ");\n\n";
+
+ out.unindent();
+ out.unindent();
+
+ out << "if ("
+ << ptrName
+ << " == nullptr) {\n";
+
+ out.indent();
+ out << "_aidl_err = ::android::UNKNOWN_ERROR;\n";
+ handleError2(out, mode);
+ out.unindent();
+ out << "}\n\n";
+ } else {
+ out << "_aidl_err = "
+ << parcelObj
+ << (parcelObjIsPointer ? "->" : ".")
+ << "writeEmbeddedNativeHandle(\n";
+
+ out.indent();
+ out.indent();
+
+ out << name
+ << (nameIsPointer ? "->" : ".")
+ << "handle(),\n"
+ << parentName
+ << ",\n"
+ << offsetText
+ << "/* + offsetof(::android::NativeHandle, mHandle) */"
+ << ");\n\n";
+
+ out.unindent();
+ out.unindent();
+
+ handleError(out, mode);
+ }
+}
+
+bool HandleType::needsEmbeddedReadWrite() const {
+ return true;
+}
+
} // namespace android
diff --git a/HandleType.h b/HandleType.h
index fa9eb8e..5eb283d 100644
--- a/HandleType.h
+++ b/HandleType.h
@@ -10,6 +10,29 @@
HandleType();
void dump(Formatter &out) const override;
+
+ std::string getCppType(StorageMode mode, std::string *extra) const override;
+
+ void emitReaderWriter(
+ Formatter &out,
+ const std::string &name,
+ const std::string &parcelObj,
+ bool parcelObjIsPointer,
+ bool isReader,
+ ErrorMode mode) const override;
+
+ void emitReaderWriterEmbedded(
+ Formatter &out,
+ const std::string &name,
+ bool nameIsPointer,
+ const std::string &parcelObj,
+ bool parcelObjIsPointer,
+ bool isReader,
+ ErrorMode mode,
+ const std::string &parentName,
+ const std::string &offsetText) const override;
+
+ bool needsEmbeddedReadWrite() const override;
};
} // namespace android
diff --git a/Interface.cpp b/Interface.cpp
index ef4b573..f845bc5 100644
--- a/Interface.cpp
+++ b/Interface.cpp
@@ -46,5 +46,66 @@
return true;
}
+const std::vector<Method *> &Interface::methods() const {
+ return mMethods;
+}
+
+std::string Interface::getCppType(StorageMode mode, std::string *extra) const {
+ extra->clear();
+ const std::string base = "::android::sp<" + name() + ">";
+
+ switch (mode) {
+ case StorageMode_Stack:
+ case StorageMode_Result:
+ return base;
+
+ case StorageMode_Argument:
+ return "const " + base + "&";
+ }
+}
+
+void Interface::emitReaderWriter(
+ Formatter &out,
+ const std::string &name,
+ const std::string &parcelObj,
+ bool parcelObjIsPointer,
+ bool isReader,
+ ErrorMode mode) const {
+ const std::string parcelObjDeref =
+ parcelObj + (parcelObjIsPointer ? "->" : ".");
+
+ if (isReader) {
+ const std::string binderName = "_aidl_" + name + "_binder";
+
+ out << "::android::sp<::android::hidl::IBinder> "
+ << binderName << ";\n";
+
+ out << "_aidl_err = ";
+ out << parcelObjDeref
+ << "readNullableStrongBinder(&"
+ << binderName
+ << ");\n";
+
+ handleError(out, mode);
+
+ out << name
+ << " = "
+ << this->name()
+ << "::asInterface("
+ << binderName
+ << ");\n";
+ } else {
+ out << "_aidl_err = ";
+ out << parcelObjDeref
+ << "writeStrongBinder("
+ << this->name()
+ << "::asBinder("
+ << name
+ << "));\n";
+
+ handleError(out, mode);
+ }
+}
+
} // namespace android
diff --git a/Interface.h b/Interface.h
index 1a035b6..04a272c 100644
--- a/Interface.h
+++ b/Interface.h
@@ -4,7 +4,7 @@
#include "Scope.h"
-#include <utils/Vector.h>
+#include <vector>
namespace android {
@@ -20,9 +20,21 @@
const Type *superType() const;
+ const std::vector<Method *> &methods() const;
+
+ std::string getCppType(StorageMode mode, std::string *extra) const override;
+
+ void emitReaderWriter(
+ Formatter &out,
+ const std::string &name,
+ const std::string &parcelObj,
+ bool parcelObjIsPointer,
+ bool isReader,
+ ErrorMode mode) const override;
+
private:
Type *mSuperType;
- Vector<Method *> mMethods;
+ std::vector<Method *> mMethods;
DISALLOW_COPY_AND_ASSIGN(Interface);
};
diff --git a/Method.cpp b/Method.cpp
index b9eb885..b6281d1 100644
--- a/Method.cpp
+++ b/Method.cpp
@@ -16,10 +16,19 @@
out << mName;
}
+std::string TypedVar::name() const {
+ return mName;
+}
+
+const Type &TypedVar::type() const {
+ return *mType;
+}
+
+
Method::Method(
const char *name,
- Vector<TypedVar *> *args,
- Vector<TypedVar *> *results)
+ std::vector<TypedVar *> *args,
+ std::vector<TypedVar *> *results)
: mName(name),
mArgs(args),
mResults(results) {
@@ -33,7 +42,7 @@
out << ", ";
}
- mArgs->itemAt(i)->dump(out);
+ (*mArgs)[i]->dump(out);
}
out << ")";
@@ -46,7 +55,7 @@
out << ", ";
}
- mResults->itemAt(i)->dump(out);
+ (*mResults)[i]->dump(out);
}
out << ")";
@@ -55,5 +64,38 @@
out << ";";
}
+std::string Method::name() const {
+ return mName;
+}
+
+const std::vector<TypedVar *> &Method::args() const {
+ return *mArgs;
+}
+
+const std::vector<TypedVar *> &Method::results() const {
+ return *mResults;
+}
+
+// static
+std::string Method::GetSignature(const std::vector<TypedVar *> &args) {
+ bool first = true;
+ std::string out;
+ for (const auto &arg : args) {
+ if (!first) {
+ out += ", ";
+ }
+
+ std::string extra;
+ out += arg->type().getCppArgumentType(&extra);
+ out += " ";
+ out += arg->name();
+ out += extra;
+
+ first = false;
+ }
+
+ return out;
+}
+
} // namespace android
diff --git a/Method.h b/Method.h
index 3f80402..ab5cefc 100644
--- a/Method.h
+++ b/Method.h
@@ -4,7 +4,7 @@
#include <android-base/macros.h>
#include <string>
-#include <utils/Vector.h>
+#include <vector>
namespace android {
@@ -16,6 +16,9 @@
void dump(Formatter &out) const;
+ std::string name() const;
+ const Type &type() const;
+
private:
std::string mName;
Type *mType;
@@ -25,15 +28,21 @@
struct Method {
Method(const char *name,
- Vector<TypedVar *> *args,
- Vector<TypedVar *> *results = NULL);
+ std::vector<TypedVar *> *args,
+ std::vector<TypedVar *> *results = NULL);
void dump(Formatter &out) const;
+ std::string name() const;
+ const std::vector<TypedVar *> &args() const;
+ const std::vector<TypedVar *> &results() const;
+
+ static std::string GetSignature(const std::vector<TypedVar *> &args);
+
private:
std::string mName;
- Vector<TypedVar *> *mArgs;
- Vector<TypedVar *> *mResults;
+ std::vector<TypedVar *> *mArgs;
+ std::vector<TypedVar *> *mResults;
DISALLOW_COPY_AND_ASSIGN(Method);
};
diff --git a/RefType.cpp b/RefType.cpp
index fe1fb51..c71d1d7 100644
--- a/RefType.cpp
+++ b/RefType.cpp
@@ -17,5 +17,42 @@
out << name();
}
+std::string RefType::getCppType(StorageMode mode, std::string *extra) const {
+ return mReferencedType->getCppType(mode, extra);
+}
+
+void RefType::emitReaderWriter(
+ Formatter &out,
+ const std::string &name,
+ const std::string &parcelObj,
+ bool parcelObjIsPointer,
+ bool isReader,
+ ErrorMode mode) const {
+ mReferencedType->emitReaderWriter(
+ out, name, parcelObj, parcelObjIsPointer, isReader, mode);
+}
+
+void RefType::emitReaderWriterEmbedded(
+ Formatter &out,
+ const std::string &name,
+ bool nameIsPointer,
+ const std::string &parcelObj,
+ bool parcelObjIsPointer,
+ bool isReader,
+ ErrorMode mode,
+ const std::string &parentName,
+ const std::string &offsetText) const {
+ mReferencedType->emitReaderWriterEmbedded(
+ out,
+ name,
+ nameIsPointer,
+ parcelObj,
+ parcelObjIsPointer,
+ isReader,
+ mode,
+ parentName,
+ offsetText);
+}
+
} // namespace android
diff --git a/RefType.h b/RefType.h
index 74093fc..87e2194 100644
--- a/RefType.h
+++ b/RefType.h
@@ -13,6 +13,27 @@
const Type *referencedType() const;
+ std::string getCppType(StorageMode mode, std::string *extra) const override;
+
+ void emitReaderWriter(
+ Formatter &out,
+ const std::string &name,
+ const std::string &parcelObj,
+ bool parcelObjIsPointer,
+ bool isReader,
+ ErrorMode mode) const override;
+
+ void emitReaderWriterEmbedded(
+ Formatter &out,
+ const std::string &name,
+ bool nameIsPointer,
+ const std::string &parcelObj,
+ bool parcelObjIsPointer,
+ bool isReader,
+ ErrorMode mode,
+ const std::string &parentName,
+ const std::string &offsetText) const override;
+
private:
Type *mReferencedType;
diff --git a/ScalarType.cpp b/ScalarType.cpp
index ef816a9..c498f8c 100644
--- a/ScalarType.cpp
+++ b/ScalarType.cpp
@@ -16,5 +16,69 @@
out << kName[mKind];
}
+std::string ScalarType::getCppType(StorageMode, std::string *extra) const {
+ static const char *const kName[] = {
+ "char",
+ "bool",
+ "void *",
+ "int8_t",
+ "uint8_t",
+ "int16_t",
+ "uint16_t",
+ "int32_t",
+ "uint32_t",
+ "int64_t",
+ "uint64_t",
+ "float",
+ "double"
+ };
+
+ extra->clear();
+
+ return kName[mKind];
+}
+
+void ScalarType::emitReaderWriter(
+ Formatter &out,
+ const std::string &name,
+ const std::string &parcelObj,
+ bool parcelObjIsPointer,
+ bool isReader,
+ ErrorMode mode) const {
+ static const char *const kSuffix[] = {
+ "Uint8",
+ "Uint8",
+ "Pointer",
+ "Int8",
+ "Uint8",
+ "Int16",
+ "Uint16",
+ "Int32",
+ "Uint32",
+ "Int64",
+ "Uint64",
+ "Float",
+ "Double"
+ };
+
+ const std::string parcelObjDeref =
+ parcelObj + (parcelObjIsPointer ? "->" : ".");
+
+ out << "_aidl_err = "
+ << parcelObjDeref
+ << (isReader ? "read" : "write")
+ << kSuffix[mKind]
+ << "(";
+
+ if (isReader) {
+ out << "&";
+ }
+
+ out << name
+ << ");\n";
+
+ handleError(out, mode);
+}
+
} // namespace android
diff --git a/ScalarType.h b/ScalarType.h
index e574b80..2bd7cae 100644
--- a/ScalarType.h
+++ b/ScalarType.h
@@ -27,6 +27,16 @@
void dump(Formatter &out) const override;
+ std::string getCppType(StorageMode mode, std::string *extra) const override;
+
+ void emitReaderWriter(
+ Formatter &out,
+ const std::string &name,
+ const std::string &parcelObj,
+ bool parcelObjIsPointer,
+ bool isReader,
+ ErrorMode mode) const override;
+
private:
Kind mKind;
diff --git a/Scope.cpp b/Scope.cpp
index 45d766e..a009204 100644
--- a/Scope.cpp
+++ b/Scope.cpp
@@ -64,14 +64,49 @@
return true;
}
-bool Scope::containsSingleInterface(std::string *ifaceName) const {
+Interface *Scope::getInterface() const {
if (mTypes.size() == 1 && mTypes[0]->isInterface()) {
- *ifaceName = static_cast<Interface *>(mTypes[0])->name();
+ return static_cast<Interface *>(mTypes[0]);
+ }
+
+ return NULL;
+}
+
+bool Scope::containsSingleInterface(std::string *ifaceName) const {
+ Interface *iface = getInterface();
+
+ if (iface != NULL) {
+ *ifaceName = iface->name();
return true;
}
return false;
}
+status_t Scope::emitTypeDeclarations(Formatter &out) const {
+ for (size_t i = 0; i < mTypes.size(); ++i) {
+ status_t err = mTypes[i]->emitTypeDeclarations(out);
+
+ if (err != OK) {
+ return err;
+ }
+ }
+
+ return OK;
+}
+
+status_t Scope::emitTypeDefinitions(
+ Formatter &out, const std::string prefix) const {
+ for (size_t i = 0; i < mTypes.size(); ++i) {
+ status_t err = mTypes[i]->emitTypeDefinitions(out, prefix);
+
+ if (err != OK) {
+ return err;
+ }
+ }
+
+ return OK;
+}
+
} // namespace android
diff --git a/Scope.h b/Scope.h
index b5c65d6..132e20c 100644
--- a/Scope.h
+++ b/Scope.h
@@ -10,6 +10,8 @@
namespace android {
struct Constant;
+struct Formatter;
+struct Interface;
struct Scope : public NamedType {
Scope(const char *name);
@@ -21,8 +23,17 @@
void dump(Formatter &out) const override;
bool isScope() const override;
+
+ // Returns the single interface or NULL.
+ Interface *getInterface() const;
+
bool containsSingleInterface(std::string *ifaceName) const;
+ status_t emitTypeDeclarations(Formatter &out) const override;
+
+ status_t emitTypeDefinitions(
+ Formatter &out, const std::string prefix) const override;
+
private:
Vector<Type *> mTypes;
KeyedVector<std::string, size_t> mTypeIndexByName;
diff --git a/StringType.cpp b/StringType.cpp
index 2356e3a..52b27fe 100644
--- a/StringType.cpp
+++ b/StringType.cpp
@@ -10,5 +10,113 @@
out << "string";
}
+std::string StringType::getCppType(StorageMode mode, std::string *extra) const {
+ extra->clear();
+
+ const std::string base = "::android::hidl::hidl_string";
+
+ switch (mode) {
+ case StorageMode_Stack:
+ return base;
+
+ case StorageMode_Argument:
+ return "const " + base + "&";
+
+ case StorageMode_Result:
+ return "const " + base + "*";
+ }
+}
+
+void StringType::emitReaderWriter(
+ Formatter &out,
+ const std::string &name,
+ const std::string &parcelObj,
+ bool parcelObjIsPointer,
+ bool isReader,
+ ErrorMode mode) const {
+ const std::string parentName = "_aidl_" + name + "_parent";
+ out << "size_t " << parentName << ";\n\n";
+
+ const std::string parcelObjDeref =
+ parcelObj + (parcelObjIsPointer ? "->" : ".");
+
+ if (isReader) {
+ out << name
+ << " = (const ::android::hidl::hidl_string *)"
+ << parcelObjDeref
+ << "readBuffer("
+ << "&"
+ << parentName
+ << ");\n";
+
+ out << "if ("
+ << name
+ << " == nullptr) {\n";
+
+ out.indent();
+
+ out << "_aidl_err = ::android::UNKNOWN_ERROR;\n";
+ handleError2(out, mode);
+
+ out.unindent();
+ out << "}\n\n";
+ } else {
+ out << "_aidl_err = "
+ << parcelObjDeref
+ << "writeBuffer(&"
+ << name
+ << ", sizeof("
+ << name
+ << "), &"
+ << parentName
+ << ");\n";
+
+ handleError(out, mode);
+ }
+
+ emitReaderWriterEmbedded(
+ out,
+ name,
+ isReader /* nameIsPointer */,
+ parcelObj,
+ parcelObjIsPointer,
+ isReader,
+ mode,
+ parentName,
+ "0 /* parentOffset */");
+}
+
+void StringType::emitReaderWriterEmbedded(
+ Formatter &out,
+ const std::string &name,
+ bool nameIsPointer,
+ const std::string &parcelObj,
+ bool parcelObjIsPointer,
+ bool isReader,
+ ErrorMode mode,
+ const std::string &parentName,
+ const std::string &offsetText) const {
+ emitReaderWriterEmbeddedForTypeName(
+ out,
+ name,
+ nameIsPointer,
+ parcelObj,
+ parcelObjIsPointer,
+ isReader,
+ mode,
+ parentName,
+ offsetText,
+ "::android::hidl::hidl_string",
+ "" /* childName */);
+}
+
+bool StringType::needsEmbeddedReadWrite() const {
+ return true;
+}
+
+bool StringType::resultNeedsDeref() const {
+ return true;
+}
+
} // namespace android
diff --git a/StringType.h b/StringType.h
index 8016f4e..b50a9d8 100644
--- a/StringType.h
+++ b/StringType.h
@@ -10,6 +10,30 @@
StringType();
void dump(Formatter &out) const override;
+
+ std::string getCppType(StorageMode mode, std::string *extra) const override;
+
+ void emitReaderWriter(
+ Formatter &out,
+ const std::string &name,
+ const std::string &parcelObj,
+ bool parcelObjIsPointer,
+ bool isReader,
+ ErrorMode mode) const override;
+
+ void emitReaderWriterEmbedded(
+ Formatter &out,
+ const std::string &name,
+ bool nameIsPointer,
+ const std::string &parcelObj,
+ bool parcelObjIsPointer,
+ bool isReader,
+ ErrorMode mode,
+ const std::string &parentName,
+ const std::string &offsetText) const override;
+
+ bool needsEmbeddedReadWrite() const override;
+ bool resultNeedsDeref() const override;
};
} // namespace android
diff --git a/Type.cpp b/Type.cpp
index 136cb88..5f3c462 100644
--- a/Type.cpp
+++ b/Type.cpp
@@ -1,5 +1,9 @@
#include "Type.h"
+#include "Formatter.h"
+
+#include <android-base/logging.h>
+
namespace android {
Type::Type() {}
@@ -13,5 +17,160 @@
return false;
}
+std::string Type::getCppType(StorageMode, std::string *) const {
+ CHECK(!"Should not be here");
+ return std::string();
+}
+
+void Type::emitReaderWriter(
+ Formatter &,
+ const std::string &,
+ const std::string &,
+ bool,
+ bool,
+ ErrorMode) const {
+ CHECK(!"Should not be here");
+}
+
+void Type::emitReaderWriterEmbedded(
+ Formatter &,
+ const std::string &,
+ bool,
+ const std::string &,
+ bool,
+ bool,
+ ErrorMode,
+ const std::string &,
+ const std::string &) const {
+ CHECK(!"Should not be here");
+}
+
+void Type::handleError(Formatter &out, ErrorMode mode) const {
+ switch (mode) {
+ case ErrorMode_Ignore:
+ {
+ out << "/* _aidl_err ignored! */\n\n";
+ break;
+ }
+
+ case ErrorMode_Goto:
+ {
+ out << "if (_aidl_err != ::android::OK) { goto _aidl_error; }\n\n";
+ break;
+ }
+
+ case ErrorMode_Break:
+ {
+ out << "if (_aidl_err != ::android::OK) { break; }\n\n";
+ break;
+ }
+ }
+}
+
+void Type::handleError2(Formatter &out, ErrorMode mode) const {
+ switch (mode) {
+ case ErrorMode_Goto:
+ {
+ out << "goto _aidl_error;\n";
+ break;
+ }
+ case ErrorMode_Break:
+ {
+ out << "break;\n";
+ break;
+ }
+ case ErrorMode_Ignore:
+ {
+ out << "/* ignoring _aidl_error! */";
+ break;
+ }
+ }
+}
+
+void Type::emitReaderWriterEmbeddedForTypeName(
+ Formatter &out,
+ const std::string &name,
+ bool nameIsPointer,
+ const std::string &parcelObj,
+ bool parcelObjIsPointer,
+ bool isReader,
+ ErrorMode mode,
+ const std::string &parentName,
+ const std::string &offsetText,
+ const std::string &typeName,
+ const std::string &childName) const {
+ const std::string parcelObjDeref =
+ parcelObjIsPointer ? ("*" + parcelObj) : parcelObj;
+
+ const std::string parcelObjPointer =
+ parcelObjIsPointer ? parcelObj : ("&" + parcelObj);
+
+ const std::string nameDeref = name + (nameIsPointer ? "->" : ".");
+ const std::string namePointer = nameIsPointer ? name : ("&" + name);
+
+ out << "_aidl_err = ";
+
+ if (isReader) {
+ out << "const_cast<"
+ << typeName
+ << " *>("
+ << namePointer
+ << ")->readEmbeddedFromParcel(\n";
+ } else {
+ out << nameDeref
+ << "writeEmbeddedToParcel(\n";
+ }
+
+ out.indent();
+ out.indent();
+
+ out << (isReader ? parcelObjDeref : parcelObjPointer)
+ << ",\n"
+ << parentName
+ << ",\n"
+ << offsetText;
+
+ if (!childName.empty()) {
+ out << ", &"
+ << childName;
+ }
+
+ out << ");\n\n";
+
+ out.unindent();
+ out.unindent();
+
+ handleError(out, mode);
+}
+
+status_t Type::emitTypeDeclarations(Formatter &) const {
+ return OK;
+}
+
+status_t Type::emitTypeDefinitions(
+ Formatter &, const std::string) const {
+ return OK;
+}
+
+bool Type::needsEmbeddedReadWrite() const {
+ return false;
+}
+
+bool Type::resultNeedsDeref() const {
+ return false;
+}
+
+std::string Type::getCppType(std::string *extra) const {
+ return getCppType(StorageMode_Stack, extra);
+}
+
+std::string Type::getCppResultType(std::string *extra) const {
+ return getCppType(StorageMode_Result, extra);
+}
+
+std::string Type::getCppArgumentType(std::string *extra) const {
+ return getCppType(StorageMode_Argument, extra);
+}
+
} // namespace android
diff --git a/Type.h b/Type.h
index e4d6d03..f7f8509 100644
--- a/Type.h
+++ b/Type.h
@@ -3,6 +3,8 @@
#define TYPE_H_
#include <android-base/macros.h>
+#include <string>
+#include <utils/Errors.h>
namespace android {
@@ -16,6 +18,69 @@
virtual bool isScope() const;
virtual bool isInterface() const;
+ enum StorageMode {
+ StorageMode_Stack,
+ StorageMode_Argument,
+ StorageMode_Result
+ };
+ virtual std::string getCppType(
+ StorageMode mode, std::string *extra) const;
+
+ // Convenience, gets StorageMode_Stack type.
+ std::string getCppType(std::string *extra) const;
+
+ std::string getCppResultType(std::string *extra) const;
+ std::string getCppArgumentType(std::string *extra) const;
+
+ enum ErrorMode {
+ ErrorMode_Ignore,
+ ErrorMode_Goto,
+ ErrorMode_Break,
+ };
+ virtual void emitReaderWriter(
+ Formatter &out,
+ const std::string &name,
+ const std::string &parcelObj,
+ bool parcelObjIsPointer,
+ bool isReader,
+ ErrorMode mode) const;
+
+ virtual void emitReaderWriterEmbedded(
+ Formatter &out,
+ const std::string &name,
+ bool nameIsPointer,
+ const std::string &parcelObj,
+ bool parcelObjIsPointer,
+ bool isReader,
+ ErrorMode mode,
+ const std::string &parentName,
+ const std::string &offsetText) const;
+
+ virtual status_t emitTypeDeclarations(Formatter &out) const;
+
+ virtual status_t emitTypeDefinitions(
+ Formatter &out, const std::string prefix) const;
+
+ virtual bool needsEmbeddedReadWrite() const;
+ virtual bool resultNeedsDeref() const;
+
+protected:
+ void handleError(Formatter &out, ErrorMode mode) const;
+ void handleError2(Formatter &out, ErrorMode mode) const;
+
+ void emitReaderWriterEmbeddedForTypeName(
+ Formatter &out,
+ const std::string &name,
+ bool nameIsPointer,
+ const std::string &parcelObj,
+ bool parcelObjIsPointer,
+ bool isReader,
+ ErrorMode mode,
+ const std::string &parentName,
+ const std::string &offsetText,
+ const std::string &typeName,
+ const std::string &childName) const;
+
private:
DISALLOW_COPY_AND_ASSIGN(Type);
};
diff --git a/TypeDef.cpp b/TypeDef.cpp
index c365e5d..163a7e7 100644
--- a/TypeDef.cpp
+++ b/TypeDef.cpp
@@ -19,5 +19,42 @@
out << " " << name() << ";\n\n";
}
+std::string TypeDef::getCppType(StorageMode mode, std::string *extra) const {
+ return mReferencedType->getCppType(mode, extra);
+}
+
+void TypeDef::emitReaderWriter(
+ Formatter &out,
+ const std::string &name,
+ const std::string &parcelObj,
+ bool parcelObjIsPointer,
+ bool isReader,
+ ErrorMode mode) const {
+ mReferencedType->emitReaderWriter(
+ out, name, parcelObj, parcelObjIsPointer, isReader, mode);
+}
+
+void TypeDef::emitReaderWriterEmbedded(
+ Formatter &out,
+ const std::string &name,
+ bool nameIsPointer,
+ const std::string &parcelObj,
+ bool parcelObjIsPointer,
+ bool isReader,
+ ErrorMode mode,
+ const std::string &parentName,
+ const std::string &offsetText) const {
+ mReferencedType->emitReaderWriterEmbedded(
+ out,
+ name,
+ nameIsPointer,
+ parcelObj,
+ parcelObjIsPointer,
+ isReader,
+ mode,
+ parentName,
+ offsetText);
+}
+
} // namespace android
diff --git a/TypeDef.h b/TypeDef.h
index 716c853..6e2c54c 100644
--- a/TypeDef.h
+++ b/TypeDef.h
@@ -13,6 +13,27 @@
const Type *referencedType() const;
+ std::string getCppType(StorageMode mode, std::string *extra) const override;
+
+ void emitReaderWriter(
+ Formatter &out,
+ const std::string &name,
+ const std::string &parcelObj,
+ bool parcelObjIsPointer,
+ bool isReader,
+ ErrorMode mode) const override;
+
+ void emitReaderWriterEmbedded(
+ Formatter &out,
+ const std::string &name,
+ bool nameIsPointer,
+ const std::string &parcelObj,
+ bool parcelObjIsPointer,
+ bool isReader,
+ ErrorMode mode,
+ const std::string &parentName,
+ const std::string &offsetText) const override;
+
private:
Type *mReferencedType;
diff --git a/VectorType.cpp b/VectorType.cpp
index 2343868..903478a 100644
--- a/VectorType.cpp
+++ b/VectorType.cpp
@@ -2,6 +2,8 @@
#include "Formatter.h"
+#include <android-base/logging.h>
+
namespace android {
VectorType::VectorType(Type *elementType)
@@ -14,5 +16,154 @@
out << ">";
}
+std::string VectorType::getCppType(StorageMode mode, std::string *extra) const {
+ const std::string base =
+ "::android::hidl::hidl_vec<"
+ + mElementType->getCppType(extra)
+ + ">";
+
+ CHECK(extra->empty());
+
+ switch (mode) {
+ case StorageMode_Stack:
+ return base;
+
+ case StorageMode_Argument:
+ return "const " + base + "&";
+
+ case StorageMode_Result:
+ return "const " + base + "*";
+ }
+}
+
+void VectorType::emitReaderWriter(
+ Formatter &out,
+ const std::string &name,
+ const std::string &parcelObj,
+ bool parcelObjIsPointer,
+ bool isReader,
+ ErrorMode mode) const {
+ std::string baseExtra;
+ std::string baseType = mElementType->getCppType(&baseExtra);
+
+ const std::string parentName = "_aidl_" + name + "_parent";
+
+ out << "size_t " << parentName << ";\n\n";
+
+ const std::string parcelObjDeref =
+ parcelObj + (parcelObjIsPointer ? "->" : ".");
+
+ if (isReader) {
+ out << name
+ << " = (const ::android::hidl::hidl_vec<"
+ << baseType
+ << "> *)"
+ << parcelObjDeref
+ << "readBuffer(&"
+ << parentName
+ << ");\n\n";
+
+ out << "if (" << name << " == nullptr) {\n";
+
+ out.indent();
+
+ out << "_aidl_err = ::android::UNKNOWN_ERROR;\n";
+ handleError2(out, mode);
+
+ out.unindent();
+ out << "}\n\n";
+ } else {
+ out << "_aidl_err = "
+ << parcelObjDeref
+ << "writeBuffer(&"
+ << name
+ << ", sizeof("
+ << name
+ << "), &"
+ << parentName
+ << ");\n";
+
+ handleError(out, mode);
+ }
+
+ emitReaderWriterEmbedded(
+ out,
+ name,
+ isReader /* nameIsPointer */,
+ parcelObj,
+ parcelObjIsPointer,
+ isReader,
+ mode,
+ parentName,
+ "0 /* parentOffset */");
+}
+
+void VectorType::emitReaderWriterEmbedded(
+ Formatter &out,
+ const std::string &name,
+ bool nameIsPointer,
+ const std::string &parcelObj,
+ bool parcelObjIsPointer,
+ bool isReader,
+ ErrorMode mode,
+ const std::string &parentName,
+ const std::string &offsetText) const {
+ std::string baseExtra;
+ std::string baseType = Type::getCppType(&baseExtra);
+
+ const std::string childName = "_aidl_" + name + "_child";
+ out << "size_t " << childName << ";\n\n";
+
+ emitReaderWriterEmbeddedForTypeName(
+ out,
+ name,
+ nameIsPointer,
+ parcelObj,
+ parcelObjIsPointer,
+ isReader,
+ mode,
+ parentName,
+ offsetText,
+ baseType,
+ childName);
+
+ if (!mElementType->needsEmbeddedReadWrite()) {
+ return;
+ }
+
+ const std::string nameDeref = name + (nameIsPointer ? "->" : ".");
+
+ baseType = mElementType->getCppType(&baseExtra);
+
+ out << "for (size_t _aidl_index = 0; _aidl_index < "
+ << nameDeref
+ << "count; ++_aidl_index) {\n";
+
+ out.indent();
+
+ mElementType->emitReaderWriterEmbedded(
+ out,
+ nameDeref + "buffer[_aidl_index]",
+ false /* nameIsPointer */,
+ parcelObj,
+ parcelObjIsPointer,
+ isReader,
+ mode,
+ childName,
+ "_aidl_index * sizeof(" + baseType + ")");
+
+ out.unindent();
+
+ out << "}\n\n";
+}
+
+bool VectorType::needsEmbeddedReadWrite() const {
+ return true;
+}
+
+bool VectorType::resultNeedsDeref() const {
+ return true;
+}
+
} // namespace android
diff --git a/VectorType.h b/VectorType.h
index 0cde849..53092af 100644
--- a/VectorType.h
+++ b/VectorType.h
@@ -11,6 +11,30 @@
void dump(Formatter &out) const override;
+ std::string getCppType(StorageMode mode, std::string *extra) const override;
+
+ void emitReaderWriter(
+ Formatter &out,
+ const std::string &name,
+ const std::string &parcelObj,
+ bool parcelObjIsPointer,
+ bool isReader,
+ ErrorMode mode) const override;
+
+ void emitReaderWriterEmbedded(
+ Formatter &out,
+ const std::string &name,
+ bool nameIsPointer,
+ const std::string &parcelObj,
+ bool parcelObjIsPointer,
+ bool isReader,
+ ErrorMode mode,
+ const std::string &parentName,
+ const std::string &offsetText) const override;
+
+ bool needsEmbeddedReadWrite() const override;
+ bool resultNeedsDeref() const override;
+
private:
Type *mElementType;
diff --git a/generateCpp.cpp b/generateCpp.cpp
new file mode 100644
index 0000000..f9b1189
--- /dev/null
+++ b/generateCpp.cpp
@@ -0,0 +1,889 @@
+#include "AST.h"
+
+#include "Coordinator.h"
+#include "Formatter.h"
+#include "Interface.h"
+#include "Method.h"
+#include "Scope.h"
+
+#include <android-base/logging.h>
+#include <sys/stat.h>
+#include <vector>
+
+namespace android {
+
+static bool MakeParentHierarchy(const std::string &path) {
+ static const mode_t kMode = 0755;
+
+ size_t start = 1; // Ignore leading '/'
+ size_t slashPos;
+ while ((slashPos = path.find("/", start)) != std::string::npos) {
+ std::string partial = path.substr(0, slashPos);
+
+ struct stat st;
+ if (stat(partial.c_str(), &st) < 0) {
+ if (errno != ENOENT) {
+ return false;
+ }
+
+ int res = mkdir(partial.c_str(), kMode);
+ if (res < 0) {
+ return false;
+ }
+ } else if (!S_ISDIR(st.st_mode)) {
+ return false;
+ }
+
+ start = slashPos + 1;
+ }
+
+ return true;
+}
+
+static void SplitString(
+ const std::string &s, char c, std::vector<std::string> *components) {
+ components->clear();
+
+ size_t startPos = 0;
+ size_t matchPos;
+ while ((matchPos = s.find(c, startPos)) != std::string::npos) {
+ components->push_back(s.substr(startPos, matchPos - startPos));
+ startPos = matchPos + 1;
+ }
+
+ if (startPos + 1 < s.length()) {
+ components->push_back(s.substr(startPos));
+ }
+}
+
+static std::string upcase(const std::string in) {
+ std::string out{in};
+
+ for (auto &ch : out) {
+ ch = toupper(ch);
+ }
+
+ return out;
+}
+
+status_t AST::generateCpp() const {
+ status_t err = generateInterfaceHeader();
+
+ if (err == OK) {
+ err = generateStubHeader();
+ }
+
+ if (err == OK) {
+ err = generateProxyHeader();
+ }
+
+ if (err == OK) {
+ err = generateAllSource();
+ }
+
+ return err;
+}
+
+void AST::getPackageComponents(
+ std::vector<std::string> *components) const {
+ SplitString(mPackage.package(), '.', components);
+}
+
+void AST::getPackageAndVersionComponents(
+ std::vector<std::string> *components, bool cpp_compatible) const {
+ getPackageComponents(components);
+
+ const std::string packageVersion = mPackage.version();
+ CHECK(packageVersion[0] == '@');
+
+ if (!cpp_compatible) {
+ components->push_back(packageVersion.substr(1));
+ return;
+ }
+
+ const size_t dotPos = packageVersion.find('.');
+
+ // Form "Vmajor_minor".
+ std::string versionString = "V";
+ versionString.append(packageVersion.substr(1, dotPos - 1));
+ versionString.append("_");
+ versionString.append(packageVersion.substr(dotPos + 1));
+
+ components->push_back(versionString);
+}
+
+std::string AST::makeHeaderGuard(const std::string &baseName) const {
+ std::vector<std::string> packageComponents;
+ getPackageAndVersionComponents(
+ &packageComponents, true /* cpp_compatible */);
+
+ std::string guard = "HIDL_GENERATED";
+ for (const auto &component : packageComponents) {
+ guard += "_";
+ guard += component;
+ }
+
+ guard += "_";
+ guard += baseName;
+ guard += "_H_";
+
+ return guard;
+}
+
+void AST::enterLeaveNamespace(Formatter &out, bool enter) const {
+ std::vector<std::string> packageComponents;
+ getPackageAndVersionComponents(
+ &packageComponents, true /* cpp_compatible */);
+
+ if (enter) {
+ for (const auto &component : packageComponents) {
+ out << "namespace " << component << " {\n";
+ }
+ } else {
+ for (auto it = packageComponents.rbegin();
+ it != packageComponents.rend();
+ ++it) {
+ out << "} // namespace " << *it << "\n";
+ }
+ }
+}
+
+status_t AST::generateInterfaceHeader() const {
+ const std::string packagePath =
+ mCoordinator->getPackagePath(mPackage, true /* relative */);
+
+ std::string path = "/tmp/android/hardware/";
+ path.append(packagePath);
+
+ std::string ifaceName;
+ bool isInterface = true;
+ if (!AST::isInterface(&ifaceName)) {
+ ifaceName = "types";
+ isInterface = false;
+ }
+ path.append(ifaceName);
+ path.append(".h");
+
+ CHECK(MakeParentHierarchy(path));
+ FILE *file = fopen(path.c_str(), "w");
+
+ if (file == NULL) {
+ return -errno;
+ }
+
+ Formatter out(file);
+
+ const std::string guard = makeHeaderGuard(ifaceName);
+
+ out << "#ifndef " << guard << "\n";
+ out << "#define " << guard << "\n\n";
+
+ out << "#include <hwbinder/HidlSupport.h>\n";
+
+ if (isInterface) {
+ out << "#include <hwbinder/IBinder.h>\n";
+ out << "#include <hwbinder/IInterface.h>\n";
+ out << "#include <hwbinder/Status.h>\n";
+ }
+
+ out << "#include <utils/NativeHandle.h>\n\n";
+
+ enterLeaveNamespace(out, true /* enter */);
+ out << "\n";
+
+ if (isInterface) {
+ out << "struct "
+ << ifaceName
+ << " : public ::android::hidl::IInterface {\n";
+
+ out.indent();
+
+ out << "DECLARE_HWBINDER_META_INTERFACE(" << ifaceName << ");\n\n";
+ }
+
+ status_t err = emitTypeDeclarations(out);
+
+ if (err != OK) {
+ return err;
+ }
+
+ if (isInterface) {
+ const Interface *iface = mRootScope->getInterface();
+
+ out << "enum Call {\n";
+ out.indent();
+
+ bool first = true;
+ for (const auto &method : iface->methods()) {
+ out << upcase(method->name());
+
+ if (first) {
+ out << " = ::android::hidl::IBinder::FIRST_CALL_TRANSACTION";
+ first = false;
+ }
+
+ out << ",\n";
+ }
+
+ out.unindent();
+ out << "};\n\n";
+
+ bool haveCallbacks = false;
+ for (const auto &method : iface->methods()) {
+ const bool returnsValue = !method->results().empty();
+
+ if (!returnsValue) {
+ continue;
+ }
+
+ haveCallbacks = true;
+
+ out << "using "
+ << method->name()
+ << "_cb = std::function<void("
+ << Method::GetSignature(method->results())
+ << ")>;\n";
+ }
+
+ if (haveCallbacks) {
+ out << "\n";
+ }
+
+ for (const auto &method : iface->methods()) {
+ const bool returnsValue = !method->results().empty();
+
+ out << "virtual ::android::hidl::binder::Status "
+ << method->name()
+ << "("
+ << Method::GetSignature(method->args());
+
+ if (returnsValue) {
+ if (!method->args().empty()) {
+ out << ", ";
+ }
+
+ out << method->name() << "_cb _aidl_cb = nullptr";
+ }
+
+ out << ") = 0;\n";
+ }
+ }
+
+ if (isInterface) {
+ out.unindent();
+
+ out << "};\n";
+ }
+
+ out << "\n";
+ enterLeaveNamespace(out, false /* enter */);
+
+ out << "\n#endif // " << guard << "\n";
+
+ return OK;
+}
+
+status_t AST::emitTypeDeclarations(Formatter &out) const {
+ return mRootScope->emitTypeDeclarations(out);
+}
+
+status_t AST::generateStubHeader() const {
+ std::string ifaceName;
+ if (!AST::isInterface(&ifaceName)) {
+ // types.hal does not get a stub header.
+ return OK;
+ }
+
+ const std::string packagePath =
+ mCoordinator->getPackagePath(mPackage, true /* relative */);
+
+ // cut off the leading 'I'.
+ const std::string baseName = ifaceName.substr(1);
+
+ std::string path = "/tmp/android/hardware/";
+ path.append(packagePath);
+ path.append("Bn");
+ path.append(baseName);
+ path.append(".h");
+
+ CHECK(MakeParentHierarchy(path));
+ FILE *file = fopen(path.c_str(), "w");
+
+ if (file == NULL) {
+ return -errno;
+ }
+
+ Formatter out(file);
+
+ const std::string guard = makeHeaderGuard("Bn" + baseName);
+
+ out << "#ifndef " << guard << "\n";
+ out << "#define " << guard << "\n\n";
+
+ std::vector<std::string> packageComponents;
+ getPackageAndVersionComponents(
+ &packageComponents, false /* cpp_compatible */);
+
+ out << "#include <";
+ for (const auto &component : packageComponents) {
+ out << component << "/";
+ }
+ out << ifaceName << ".h>\n\n";
+
+ enterLeaveNamespace(out, true /* enter */);
+ out << "\n";
+
+ out << "struct "
+ << "Bn"
+ << baseName
+ << " : public ::android::hidl::BnInterface<"
+ << ifaceName
+ << "> {\n";
+
+ out.indent();
+
+ out << "::android::status_t onTransact(\n";
+ out.indent();
+ out.indent();
+ out << "uint32_t _aidl_code,\n";
+ out << "const ::android::hidl::Parcel &_aidl_data,\n";
+ out << "::android::hidl::Parcel *_aidl_reply,\n";
+ out << "uint32_t _aidl_flags = 0,\n";
+ out << "TransactCallback _aidl_cb = nullptr) override;\n";
+ out.unindent();
+ out.unindent();
+
+ out.unindent();
+
+ out << "};\n\n";
+
+ enterLeaveNamespace(out, false /* enter */);
+
+ out << "\n#endif // " << guard << "\n";
+
+ return OK;
+}
+
+status_t AST::generateProxyHeader() const {
+ std::string ifaceName;
+ if (!AST::isInterface(&ifaceName)) {
+ // types.hal does not get a proxy header.
+ return OK;
+ }
+
+ const std::string packagePath =
+ mCoordinator->getPackagePath(mPackage, true /* relative */);
+
+ // cut off the leading 'I'.
+ const std::string baseName = ifaceName.substr(1);
+
+ std::string path = "/tmp/android/hardware/";
+ path.append(packagePath);
+ path.append("Bp");
+ path.append(baseName);
+ path.append(".h");
+
+ CHECK(MakeParentHierarchy(path));
+ FILE *file = fopen(path.c_str(), "w");
+
+ if (file == NULL) {
+ return -errno;
+ }
+
+ Formatter out(file);
+
+ const std::string guard = makeHeaderGuard("Bp" + baseName);
+
+ out << "#ifndef " << guard << "\n";
+ out << "#define " << guard << "\n\n";
+
+ std::vector<std::string> packageComponents;
+ getPackageAndVersionComponents(
+ &packageComponents, false /* cpp_compatible */);
+
+ out << "#include <";
+ for (const auto &component : packageComponents) {
+ out << component << "/";
+ }
+ out << ifaceName << ".h>\n\n";
+
+ enterLeaveNamespace(out, true /* enter */);
+ out << "\n";
+
+ out << "struct "
+ << "Bp"
+ << baseName
+ << " : public ::android::hidl::BpInterface<"
+ << ifaceName
+ << "> {\n";
+
+ out.indent();
+
+ out << "explicit Bp"
+ << baseName
+ << "(const ::android::sp<::android::hidl::IBinder> &_aidl_impl);"
+ << "\n\n";
+
+ const Interface *iface = mRootScope->getInterface();
+
+ for (const auto &method : iface->methods()) {
+ const bool returnsValue = !method->results().empty();
+
+ out << "::android::hidl::binder::Status "
+ << method->name()
+ << "("
+ << Method::GetSignature(method->args());
+
+ if (returnsValue) {
+ if (!method->args().empty()) {
+ out << ", ";
+ }
+
+ out << method->name() << "_cb _aidl_cb";
+ }
+
+ out << ") override;\n";
+ }
+
+ out.unindent();
+
+ out << "};\n\n";
+
+ enterLeaveNamespace(out, false /* enter */);
+
+ out << "\n#endif // " << guard << "\n";
+
+ return OK;
+}
+
+status_t AST::generateAllSource() const {
+ const std::string packagePath =
+ mCoordinator->getPackagePath(mPackage, true /* relative */);
+
+ std::string path = "/tmp/android/hardware/";
+ path.append(packagePath);
+
+ std::string ifaceName;
+ std::string baseName;
+
+ bool isInterface = true;
+ if (!AST::isInterface(&ifaceName)) {
+ baseName = "types";
+ isInterface = false;
+ } else {
+ baseName = ifaceName.substr(1); // cut off the leading 'I'.
+ }
+
+ path.append(baseName);
+
+ if (baseName != "types") {
+ path.append("All");
+ }
+
+ path.append(".cpp");
+
+ CHECK(MakeParentHierarchy(path));
+ FILE *file = fopen(path.c_str(), "w");
+
+ if (file == NULL) {
+ return -errno;
+ }
+
+ Formatter out(file);
+
+ std::vector<std::string> packageComponents;
+ getPackageAndVersionComponents(
+ &packageComponents, false /* cpp_compatible */);
+
+ std::string prefix;
+ for (const auto &component : packageComponents) {
+ prefix += component;
+ prefix += "/";
+ }
+
+ if (isInterface) {
+ out << "#include <" << prefix << "/Bp" << baseName << ".h>\n";
+ out << "#include <" << prefix << "/Bn" << baseName << ".h>\n";
+ } else {
+ out << "#include <" << prefix << "types.h>\n";
+ }
+
+ out << "\n";
+
+ enterLeaveNamespace(out, true /* enter */);
+ out << "\n";
+
+ status_t err = generateTypeSource(out, ifaceName);
+
+ if (err == OK && isInterface) {
+ err = generateProxySource(out, baseName);
+ }
+
+ if (err == OK && isInterface) {
+ err = generateStubSource(out, baseName);
+ }
+
+ enterLeaveNamespace(out, false /* enter */);
+
+ return err;
+}
+
+status_t AST::generateTypeSource(
+ Formatter &out, const std::string &ifaceName) const {
+ return mRootScope->emitTypeDefinitions(out, ifaceName);
+}
+
+void AST::emitCppReaderWriter(
+ Formatter &out,
+ const std::string &parcelObj,
+ bool parcelObjIsPointer,
+ const TypedVar *arg,
+ bool isReader,
+ Type::ErrorMode mode) const {
+ const Type &type = arg->type();
+
+ if (isReader) {
+ std::string extra;
+ out << type.getCppResultType(&extra)
+ << " "
+ << arg->name()
+ << extra
+ << ";\n";
+ }
+
+ type.emitReaderWriter(
+ out,
+ arg->name(),
+ parcelObj,
+ parcelObjIsPointer,
+ isReader,
+ mode);
+}
+
+status_t AST::generateProxySource(
+ Formatter &out, const std::string &baseName) const {
+ const std::string klassName = "Bp" + baseName;
+
+ out << klassName
+ << "::"
+ << klassName
+ << "(const ::android::sp<::android::hidl::IBinder> &_aidl_impl)\n";
+
+ out.indent();
+ out.indent();
+
+ out << ": BpInterface"
+ << "<I"
+ << baseName
+ << ">(_aidl_impl) {\n";
+
+ out.unindent();
+ out.unindent();
+ out << "}\n\n";
+
+ const Interface *iface = mRootScope->getInterface();
+
+ for (const auto &method : iface->methods()) {
+ const bool returnsValue = !method->results().empty();
+
+ out << "::android::hidl::binder::Status "
+ << klassName
+ << "::"
+ << method->name()
+ << "("
+ << Method::GetSignature(method->args());
+
+ if (returnsValue) {
+ if (!method->args().empty()) {
+ out << ", ";
+ }
+
+ out << method->name() << "_cb _aidl_cb";
+ }
+
+ out << ") {\n";
+
+ out.indent();
+
+ out << "::android::hidl::Parcel _aidl_data;\n";
+ out << "::android::hidl::Parcel _aidl_reply;\n";
+ out << "::android::status_t _aidl_err;\n\n";
+ out << "::android::hidl::binder::Status _aidl_status;\n";
+
+ out << "_aidl_err = _aidl_data.writeInterfaceToken("
+ "getInterfaceDescriptor());\n";
+
+ out << "if (_aidl_err != ::android::OK) { goto _aidl_error; }\n\n";
+
+ for (const auto &arg : method->args()) {
+ emitCppReaderWriter(
+ out,
+ "_aidl_data",
+ false /* parcelObjIsPointer */,
+ arg,
+ false /* reader */,
+ Type::ErrorMode_Goto);
+ }
+
+ out << "_aidl_err = remote()->transact(I"
+ << baseName
+ << "::"
+ << upcase(method->name())
+ << ", _aidl_data, &_aidl_reply);\n";
+
+ out << "if (_aidl_err != ::android::OK) { goto _aidl_error; }\n\n";
+
+ out << "_aidl_err = _aidl_status.readFromParcel(_aidl_reply);\n";
+ out << "if (_aidl_err != ::android::OK) { goto _aidl_error; }\n\n";
+
+ out << "if (!_aidl_status.isOk()) { return _aidl_status; }\n\n";
+
+ for (const auto &arg : method->results()) {
+ emitCppReaderWriter(
+ out,
+ "_aidl_reply",
+ false /* parcelObjIsPointer */,
+ arg,
+ true /* reader */,
+ Type::ErrorMode_Goto);
+ }
+
+ if (returnsValue) {
+ out << "if (_aidl_cb != nullptr) {\n";
+ out.indent();
+ out << "_aidl_cb(";
+
+ bool first = true;
+ for (const auto &arg : method->results()) {
+ if (!first) {
+ out << ", ";
+ }
+
+ if (arg->type().resultNeedsDeref()) {
+ out << "*";
+ }
+ out << arg->name();
+
+ first = false;
+ }
+
+ out << ");\n";
+ out.unindent();
+ out << "}\n\n";
+ }
+
+ out.unindent();
+ out << "_aidl_error:\n";
+ out.indent();
+ out << "_aidl_status.setFromStatusT(_aidl_err);\n"
+ << "return _aidl_status;\n";
+
+ out.unindent();
+ out << "}\n\n";
+ }
+
+ return OK;
+}
+
+status_t AST::generateStubSource(
+ Formatter &out, const std::string &baseName) const {
+ out << "IMPLEMENT_HWBINDER_META_INTERFACE("
+ << baseName
+ << ", \""
+ << mPackage.string()
+ << "::I"
+ << baseName
+ << "\");\n\n";
+
+ const std::string klassName = "Bn" + baseName;
+
+ out << "::android::status_t " << klassName << "::onTransact(\n";
+
+ out.indent();
+ out.indent();
+
+ out << "uint32_t _aidl_code,\n"
+ << "const ::android::hidl::Parcel &_aidl_data,\n"
+ << "::android::hidl::Parcel *_aidl_reply,\n"
+ << "uint32_t _aidl_flags,\n"
+ << "TransactCallback _aidl_cb) {\n";
+
+ out.unindent();
+
+ out << "::android::status_t _aidl_err = ::android::OK;\n\n";
+
+ out << "switch (_aidl_code) {\n";
+ out.indent();
+
+ const Interface *iface = mRootScope->getInterface();
+
+ for (const auto &method : iface->methods()) {
+ out << "case Call::" << upcase(method->name()) << ":\n{\n";
+ out.indent();
+
+ status_t err = generateStubSourceForMethod(out, method);
+
+ if (err != OK) {
+ return err;
+ }
+
+ out.unindent();
+ out << "}\n\n";
+ }
+
+ out << "default:\n{\n";
+ out.indent();
+
+ out << "return ::android::hidl::BnInterface<I"
+ << baseName
+ << ">::onTransact(\n";
+
+ out.indent();
+ out.indent();
+
+ out << "_aidl_code, _aidl_data, _aidl_reply, "
+ << "_aidl_flags, _aidl_cb);\n";
+
+ out.unindent();
+ out.unindent();
+
+ out.unindent();
+ out << "}\n";
+
+ out.unindent();
+ out << "}\n\n";
+
+ out << "if (_aidl_err == ::android::UNEXPECTED_NULL) {\n";
+ out.indent();
+ out << "_aidl_err = ::android::hidl::binder::Status::fromExceptionCode(\n";
+ out.indent();
+ out.indent();
+ out << "::android::hidl::binder::Status::EX_NULL_POINTER)\n";
+ out.indent();
+ out.indent();
+ out << ".writeToParcel(_aidl_reply);\n";
+ out.unindent();
+ out.unindent();
+ out.unindent();
+ out.unindent();
+
+ out.unindent();
+ out << "}\n\n";
+
+ out << "return _aidl_err;\n";
+
+ out.unindent();
+ out << "}\n\n";
+
+ return OK;
+}
+
+status_t AST::generateStubSourceForMethod(
+ Formatter &out, const Method *method) const {
+ out << "if (!_aidl_data.checkInterface(this)) {\n";
+ out.indent();
+ out << "_aidl_err = ::android::BAD_TYPE;\n";
+ out << "break;\n";
+ out.unindent();
+ out << "}\n\n";
+
+ for (const auto &arg : method->args()) {
+ emitCppReaderWriter(
+ out,
+ "_aidl_data",
+ false /* parcelObjIsPointer */,
+ arg,
+ true /* reader */,
+ Type::ErrorMode_Break);
+ }
+
+ const bool returnsValue = !method->results().empty();
+
+ if (returnsValue) {
+ out << "bool _aidl_callbackCalled = false;\n\n";
+ }
+
+ out << "::android::hidl::binder::Status _aidl_status(\n";
+ out.indent();
+ out.indent();
+ out << method->name() << "(";
+
+ bool first = true;
+ for (const auto &arg : method->args()) {
+ if (!first) {
+ out << ", ";
+ }
+
+ if (arg->type().resultNeedsDeref()) {
+ out << "*";
+ }
+
+ out << arg->name();
+
+ first = false;
+ }
+
+ if (returnsValue) {
+ if (!first) {
+ out << ", ";
+ }
+
+ out << "[&](";
+
+ first = true;
+ for (const auto &arg : method->results()) {
+ if (!first) {
+ out << ", ";
+ }
+
+ out << "const auto &" << arg->name();
+
+ first = false;
+ }
+
+ out << ") {\n";
+ out.indent();
+ out << "_aidl_callbackCalled = true;\n\n";
+
+ out << "::android::hidl::binder::Status::ok()"
+ << ".writeToParcel(_aidl_reply);\n\n";
+
+ for (const auto &arg : method->results()) {
+ emitCppReaderWriter(
+ out,
+ "_aidl_reply",
+ true /* parcelObjIsPointer */,
+ arg,
+ false /* reader */,
+ Type::ErrorMode_Ignore);
+ }
+
+ out << "_aidl_cb(*_aidl_reply);\n";
+
+ out.unindent();
+ out << "}\n";
+ }
+
+ out.unindent();
+ out.unindent();
+ out << "));\n\n";
+
+ if (returnsValue) {
+ out << "if (!_aidl_callbackCalled) {\n";
+ out.indent();
+ }
+
+ out << "_aidl_err = _aidl_status.writeToParcel(_aidl_reply);\n";
+
+ if (returnsValue) {
+ out.unindent();
+ out << "}\n\n";
+ }
+
+ out << "break;\n";
+
+ return OK;
+}
+
+} // namespace android
+
diff --git a/hidl-gen_l.ll b/hidl-gen_l.ll
index f1424ed..ad5446e 100644
--- a/hidl-gen_l.ll
+++ b/hidl-gen_l.ll
@@ -110,7 +110,7 @@
%%
-int yywrap(yyscan_t scanner) {
+int yywrap(yyscan_t) {
return 1;
}
diff --git a/hidl-gen_y.yy b/hidl-gen_y.yy
index 07c9af5..af0e1a0 100644
--- a/hidl-gen_y.yy
+++ b/hidl-gen_y.yy
@@ -78,11 +78,11 @@
android::Type *type;
android::CompoundType *compoundType;
android::CompoundField *field;
- android::Vector<android::CompoundField *> *fields;
+ std::vector<android::CompoundField *> *fields;
android::EnumValue *enumValue;
- android::Vector<android::EnumValue *> *enumValues;
+ std::vector<android::EnumValue *> *enumValues;
android::TypedVar *typedVar;
- android::Vector<android::TypedVar *> *typedVars;
+ std::vector<android::TypedVar *> *typedVars;
android::Method *method;
android::CompoundType::Style compoundStyle;
android::Vector<std::string> *stringVec;
@@ -220,7 +220,7 @@
method_declaration
: IDENTIFIER '(' typed_vars ')' ';'
{
- $$ = new Method($1, $3);
+ $$ = new Method($1, $3, new std::vector<TypedVar *>);
}
| IDENTIFIER '(' typed_vars ')' GENERATES '(' typed_vars ')' ';'
{
@@ -231,11 +231,11 @@
typed_vars
: /* empty */
{
- $$ = new Vector<TypedVar *>;
+ $$ = new std::vector<TypedVar *>;
}
| typed_var
{
- $$ = new Vector<TypedVar *>;
+ $$ = new std::vector<TypedVar *>;
$$->push_back($1);
}
| typed_vars ',' typed_var
@@ -293,7 +293,7 @@
;
field_declarations
- : /* empty */ { $$ = new Vector<CompoundField *>; }
+ : /* empty */ { $$ = new std::vector<CompoundField *>; }
| field_declarations field_declaration
{
$$ = $1;
@@ -360,11 +360,11 @@
enum_values
: /* empty */
{
- $$ = new Vector<EnumValue *>;
+ $$ = new std::vector<EnumValue *>;
}
| enum_value
{
- $$ = new Vector<EnumValue *>;
+ $$ = new std::vector<EnumValue *>;
$$->push_back($1);
}
| enum_values ',' enum_value
diff --git a/main.cpp b/main.cpp
index 0bada61..b881589 100644
--- a/main.cpp
+++ b/main.cpp
@@ -25,10 +25,7 @@
CHECK(fqName.isValid() && fqName.isFullyQualified());
AST *ast = coordinator.parse(fqName);
-
- if (ast == NULL) {
- continue;
- }
+ CHECK(ast != NULL);
Formatter out;
@@ -36,6 +33,8 @@
ast->dump(out);
+ ast->generateCpp();
+
delete ast;
ast = NULL;
}