Merge "struct fields of type "array" should be declared "final"."
diff --git a/AST.cpp b/AST.cpp
index d13167a..d25e4e1 100644
--- a/AST.cpp
+++ b/AST.cpp
@@ -21,6 +21,7 @@
#include "FQName.h"
#include "HandleType.h"
#include "Interface.h"
+#include "PredefinedType.h"
#include "Scope.h"
#include "TypeDef.h"
@@ -311,4 +312,23 @@
}
}
+bool AST::isJavaCompatible() const {
+ std::string ifaceName;
+ if (!AST::isInterface(&ifaceName)) {
+ for (size_t i = 0; i < mRootScope->countTypes(); ++i) {
+ std::string typeName;
+ const Type *type = mRootScope->typeAt(i, &typeName);
+
+ if (!type->isJavaCompatible()) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ const Interface *iface = mRootScope->getInterface();
+ return iface->isJavaCompatible();
+}
+
} // namespace android;
diff --git a/AST.h b/AST.h
index f77a260..6af5604 100644
--- a/AST.h
+++ b/AST.h
@@ -73,13 +73,18 @@
status_t generateCpp(const std::string &outputPath) const;
- status_t generateJava(const std::string &outputPath) const;
- status_t generateJavaTypes(const std::string &outputPath) const;
+ status_t generateJava(
+ const std::string &outputPath, const char *limitToType) const;
+
+ status_t generateJavaTypes(
+ const std::string &outputPath, const char *limitToType) const;
void getImportedPackages(std::set<FQName> *importSet) const;
status_t generateVts(const std::string &outputPath) const;
+ bool isJavaCompatible() const;
+
private:
Coordinator *mCoordinator;
std::string mPath;
@@ -124,6 +129,7 @@
void enterLeaveNamespace(Formatter &out, bool enter) const;
status_t generateInterfaceHeader(const std::string &outputPath) const;
+ status_t generateHwBinderHeader(const std::string &outputPath) const;
status_t generateStubHeader(const std::string &outputPath) const;
status_t generateProxyHeader(const std::string &outputPath) const;
status_t generateAllSource(const std::string &outputPath) const;
diff --git a/Android.mk b/Android.mk
index 08d6696..ce597f8 100644
--- a/Android.mk
+++ b/Android.mk
@@ -24,6 +24,7 @@
Interface.cpp \
Method.cpp \
NamedType.cpp \
+ PredefinedType.cpp \
ScalarType.cpp \
Scope.cpp \
StringType.cpp \
diff --git a/CompoundType.cpp b/CompoundType.cpp
index a6d5133..74df0a4 100644
--- a/CompoundType.cpp
+++ b/CompoundType.cpp
@@ -577,7 +577,17 @@
}
bool CompoundType::isJavaCompatible() const {
- return mStyle == STYLE_STRUCT && Scope::isJavaCompatible();
+ if (mStyle != STYLE_STRUCT || !Scope::isJavaCompatible()) {
+ return false;
+ }
+
+ for (const auto &field : *mFields) {
+ if (!field->type().isJavaCompatible()) {
+ return false;
+ }
+ }
+
+ return true;
}
void CompoundType::getAlignmentAndSize(size_t *align, size_t *size) const {
diff --git a/ConstantExpression.cpp b/ConstantExpression.cpp
index 0258491..5a5cbf4 100644
--- a/ConstantExpression.cpp
+++ b/ConstantExpression.cpp
@@ -16,33 +16,449 @@
#include "ConstantExpression.h"
+#include <stdio.h>
+#include <string>
#include <utils/String8.h>
+#include <android-base/parseint.h>
+#include <android-base/logging.h>
+#include <sstream>
+
+// The macros are really nasty here. Consider removing
+// as many macros as possible.
+
+#define STREQ(__x__, __y__) (strcmp((__x__), (__y__)) == 0)
+#define OPEQ(__y__) STREQ(op, __y__)
+#define COMPUTE_UNARY(__op__) if(OPEQ(#__op__)) return __op__ val;
+#define COMPUTE_BINARY(__op__) if(OPEQ(#__op__)) return lval __op__ rval;
+#define OP_IS_BIN_ARITHMETIC (OPEQ("+") || OPEQ("-") || OPEQ("*") || OPEQ("/") || OPEQ("%"))
+#define OP_IS_BIN_BITFLIP (OPEQ("|") || OPEQ("^") || OPEQ("&"))
+#define OP_IS_BIN_COMP (OPEQ("<") || OPEQ(">") || OPEQ("<=") || OPEQ(">=") || OPEQ("==") || OPEQ("!="))
+#define OP_IS_BIN_SHIFT (OPEQ(">>") || OPEQ("<<"))
+#define OP_IS_BIN_LOGICAL (OPEQ("||") || OPEQ("&&"))
+#define SK(__x__) ScalarType::Kind::KIND_##__x__
+
+#define SWITCH_KIND(__cond__, __action__, __def__) \
+ switch(__cond__) { \
+ case SK(BOOL): __action__(bool) \
+ case SK(UINT8): __action__(uint8_t) \
+ case SK(INT8): __action__(int8_t) \
+ case SK(UINT16): __action__(uint16_t) \
+ case SK(INT16): __action__(int16_t) \
+ case SK(UINT32): __action__(uint32_t) \
+ case SK(INT32): __action__(int32_t) \
+ case SK(UINT64): __action__(uint64_t) \
+ case SK(INT64): __action__(int64_t) \
+ default: __def__ \
+ } \
namespace android {
-ConstantExpression::ConstantExpression(const char *value)
- : mValue(value) {
+/* See docs at the end for details on integral promotion. */
+ScalarType::Kind integralPromotion(ScalarType::Kind in) {
+ return SK(INT32) < in ? in : SK(INT32); // note that KIND_INT32 < KIND_UINT32
}
-ConstantExpression::ConstantExpression(const ConstantExpression *lval, const char *op, const ConstantExpression* rval)
- : mValue(android::String8::format("(%s %s %s)", lval->c_str(), op, rval->c_str()).string()) {
+/* See docs at the end for details on usual arithmetic conversion. */
+ScalarType::Kind usualArithmeticConversion(ScalarType::Kind lft, ScalarType::Kind rgt) {
+ CHECK(SK(BOOL) <= lft && lft <= SK(UINT64)
+ && SK(BOOL) <= rgt && rgt <= SK(UINT64)
+ && lft != SK(OPAQUE) && rgt != SK(OPAQUE)
+ );
+ // Kinds in concern: bool, (u)int[8|16|32|64]
+ if(lft == rgt) return lft; // easy case
+ if(lft == SK(BOOL)) return rgt;
+ if(rgt == SK(BOOL)) return lft;
+ bool isLftSigned = (lft == SK(INT8)) || (lft == SK(INT16))
+ || (lft == SK(INT32)) || (lft == SK(INT64));
+ bool isRgtSigned = (rgt == SK(INT8)) || (rgt == SK(INT16))
+ || (rgt == SK(INT32)) || (rgt == SK(INT64));
+ if(isLftSigned == isRgtSigned) return lft < rgt ? rgt : lft;
+ ScalarType::Kind unsignedRank = isLftSigned ? rgt : lft;
+ ScalarType::Kind signedRank = isLftSigned ? lft : rgt;
+ if(unsignedRank >= signedRank) return unsignedRank;
+ if(signedRank > unsignedRank) return signedRank;
+
+ // Although there is such rule to return "the unsigned counterpart of
+ // the signed operand", it should not reach here in our HIDL grammar.
+ LOG(FATAL) << "Could not do usual arithmetic conversion for type "
+ << lft << "and" << rgt;
+ switch(signedRank) {
+ case SK(INT8): return SK(UINT8);
+ case SK(INT16): return SK(UINT16);
+ case SK(INT32): return SK(UINT32);
+ case SK(INT64): return SK(UINT64);
+ default: return SK(UINT64);
+ }
}
+
+template <class T>
+T handleUnary(const char *op, T val) {
+ COMPUTE_UNARY(+)
+ COMPUTE_UNARY(-)
+ COMPUTE_UNARY(!)
+ COMPUTE_UNARY(~)
+ // Should not reach here.
+ LOG(FATAL) << "Could not handleUnary for " << op << " " << val;
+ return static_cast<T>(0xdeadbeef);
+}
+
+template <class T>
+T handleBinaryCommon(T lval, const char *op, T rval) {
+ COMPUTE_BINARY(+)
+ COMPUTE_BINARY(-)
+ COMPUTE_BINARY(*)
+ COMPUTE_BINARY(/)
+ COMPUTE_BINARY(%)
+ COMPUTE_BINARY(|)
+ COMPUTE_BINARY(^)
+ COMPUTE_BINARY(&)
+ // comparison operators: return 0 or 1 by nature.
+ COMPUTE_BINARY(==)
+ COMPUTE_BINARY(!=)
+ COMPUTE_BINARY(<)
+ COMPUTE_BINARY(>)
+ COMPUTE_BINARY(<=)
+ COMPUTE_BINARY(>=)
+ // Should not reach here.
+ LOG(FATAL) << "Could not handleBinaryCommon for "
+ << lval << " " << op << " " << rval;
+ return static_cast<T>(0xdeadbeef);
+}
+
+template <class T>
+T handleShift(T lval, const char *op, int64_t rval) {
+ // just cast rval to int64_t and it should fit.
+ COMPUTE_BINARY(>>)
+ COMPUTE_BINARY(<<)
+ // Should not reach here.
+ LOG(FATAL) << "Could not handleShift for"
+ << lval << " " << op << " " << rval;
+ return static_cast<T>(0xdeadbeef);
+}
+
+bool handleLogical(bool lval, const char *op, bool rval) {
+ COMPUTE_BINARY(||);
+ COMPUTE_BINARY(&&);
+ // Should not reach here.
+ LOG(FATAL) << "Could not handleLogical for"
+ << lval << " " << op << " " << rval;
+ return false;
+}
+
+/* Literals. */
+ConstantExpression::ConstantExpression(const char *value,
+ ConstantExpression::ConstExprType type)
+ : mFormatted(value), mType(type) {
+ if(mType == kConstExprUnknown)
+ return;
+ const char* head = value, *tail = head + strlen(value) - 1;
+ bool isLong = false, isUnsigned = false;
+ bool isHex = (value[0] == '0' && (value[1] == 'x' || value[1] == 'X'));
+ while(tail >= head && (*tail == 'u' || *tail == 'U' || *tail == 'l' || *tail == 'L')) {
+ isUnsigned |= *tail == 'u' || *tail == 'U';
+ isLong |= *tail == 'l' || *tail == 'L';
+ tail--;
+ }
+ char *newVal = strndup(value, tail - head + 1);
+ bool parseOK = base::ParseUint(newVal, &mValue);
+ free(newVal);
+ if(!parseOK) {
+ LOG(FATAL) << "Could not parse as integer: " << value;
+ mType = kConstExprUnknown;
+ return;
+ }
+
+ // guess literal type.
+ if(isLong) {
+ if(isUnsigned) // ul
+ mValueKind = SK(UINT64);
+ else // l
+ mValueKind = SK(INT64);
+ } else { // no l suffix
+ if(isUnsigned) { // u
+ if(mValue <= UINT32_MAX)
+ mValueKind = SK(UINT32);
+ else
+ mValueKind = SK(UINT64);
+ } else { // no suffix
+ if(isHex) {
+ if(mValue <= INT32_MAX) // mValue always >= 0
+ mValueKind = SK(INT32);
+ else if(mValue <= UINT32_MAX)
+ mValueKind = SK(UINT32);
+ else if(mValue <= INT64_MAX) // mValue always >= 0
+ mValueKind = SK(INT64);
+ else if(mValue <= UINT64_MAX)
+ mValueKind = SK(UINT64);
+ } else {
+ if(mValue <= INT32_MAX) // mValue always >= 0
+ mValueKind = SK(INT32);
+ else
+ mValueKind = SK(INT64);
+ }
+ }
+ }
+}
+
+/* Unary operations. */
ConstantExpression::ConstantExpression(const char *op, const ConstantExpression *value)
- : mValue(android::String8::format("(%s%s)", op, value->c_str()).string()) {
+ : mFormatted(android::String8::format("(%s%s)", op, value->expr()).string()),
+ mType(kConstExprUnary),
+ mValueKind(value->mValueKind) {
+ if(value->mType == kConstExprUnknown) {
+ mType = kConstExprUnknown;
+ return;
+ }
+#define CASE_UNARY(__type__)\
+ mValue = handleUnary(op, static_cast<__type__>(value->mValue)); return;
+
+ SWITCH_KIND(mValueKind, CASE_UNARY, mType = kConstExprUnknown; return;)
}
+
+/* Binary operations. */
+ConstantExpression::ConstantExpression(const ConstantExpression *lval, const char *op, const ConstantExpression* rval)
+ : mFormatted(android::String8::format("(%s %s %s)", lval->expr(), op, rval->expr()).string()),
+ mType(kConstExprBinary)
+{
+ if(lval->mType == kConstExprUnknown || rval->mType == kConstExprUnknown) {
+ mType = kConstExprUnknown;
+ return;
+ }
+
+ bool isArithmeticOrBitflip = OP_IS_BIN_ARITHMETIC || OP_IS_BIN_BITFLIP;
+
+ // CASE 1: + - * / % | ^ & < > <= >= == !=
+ if(isArithmeticOrBitflip || OP_IS_BIN_COMP) {
+ // promoted kind for both operands.
+ ScalarType::Kind promoted = usualArithmeticConversion(
+ integralPromotion(lval->mValueKind),
+ integralPromotion(rval->mValueKind));
+ // result kind.
+ mValueKind = isArithmeticOrBitflip
+ ? promoted // arithmetic or bitflip operators generates promoted type
+ : SK(BOOL); // comparison operators generates bool
+
+#define CASE_BINARY_COMMON(__type__)\
+ mValue = handleBinaryCommon(static_cast<__type__>(lval->mValue), op, static_cast<__type__>(rval->mValue)); return;
+
+ SWITCH_KIND(promoted, CASE_BINARY_COMMON, mType = kConstExprUnknown; return;)
+ }
+
+ // CASE 2: << >>
+ if(OP_IS_BIN_SHIFT) {
+ mValueKind = integralPromotion(lval->mValueKind);
+ // instead of promoting rval, simply casting it to int64 should also be good.
+ int64_t numBits = rval->cast<int64_t>();
+ if(numBits < 0) {
+ // shifting with negative number of bits is undefined in C. In HIDL it
+ // is defined as shifting into the other direction.
+ op = OPEQ("<<") ? ">>" : "<<";
+ numBits = -numBits;
+ }
+
+#define CASE_SHIFT(__type__)\
+ mValue = handleShift(static_cast<__type__>(lval->mValue), op, numBits); return;
+
+ SWITCH_KIND(mValueKind, CASE_SHIFT, mType = kConstExprUnknown; return;)
+ }
+
+ // CASE 3: && ||
+ if(OP_IS_BIN_LOGICAL) {
+ mValueKind = SK(BOOL);
+ // easy; everything is bool.
+ mValue = handleLogical(lval->mValue, op, rval->mValue);
+ return;
+ }
+
+ mType = kConstExprUnknown;
+}
+
+/* Ternary ?: operation. */
ConstantExpression::ConstantExpression(const ConstantExpression *cond,
const ConstantExpression *trueVal,
const ConstantExpression *falseVal)
- : mValue(android::String8::format("(%s?%s:%s)",
- cond->c_str(), trueVal->c_str(), falseVal->c_str()).string()) {
+ : mFormatted(android::String8::format("(%s?%s:%s)",
+ cond->expr(), trueVal->expr(), falseVal->expr()).string()),
+ mType(kConstExprTernary) {
+ // note: for ?:, unlike arithmetic ops, integral promotion is not necessary.
+ mValueKind = usualArithmeticConversion(trueVal->mValueKind,
+ falseVal->mValueKind);
+
+#define CASE_TERNARY(__type__)\
+ mValue = cond->mValue ? (static_cast<__type__>(trueVal->mValue)) : (static_cast<__type__>(falseVal->mValue)); return;
+
+ SWITCH_KIND(mValueKind, CASE_TERNARY, mType = kConstExprUnknown; return;)
}
-const char *ConstantExpression::c_str() const {
- return mValue.c_str();
+const char *ConstantExpression::expr() const {
+ return mFormatted.c_str();
}
+
+const char *ConstantExpression::description() const {
+ static const char *const kName[] = {
+ "bool",
+ "void *",
+ "int8_t",
+ "uint8_t",
+ "int16_t",
+ "uint16_t",
+ "int32_t",
+ "uint32_t",
+ "int64_t",
+ "uint64_t",
+ "float",
+ "double"
+ };
+ if(mType == kConstExprUnknown)
+ return expr();
+ std::ostringstream os;
+ os << "(" << kName[mValueKind] << ")" << expr();
+ return strdup(os.str().c_str());
+}
+
const char *ConstantExpression::value() const {
- return mValue.c_str();
+ return value0(mValueKind);
}
+const char *ConstantExpression::cppValue(ScalarType::Kind castKind) const {
+ std::string literal(value0(castKind));
+ // this is a hack to translate
+ // enum x : int64_t { y = 1l << 63 };
+ // into
+ // enum class x : int64_t { y = (int64_t)-9223372036854775808ull };
+ // by adding the explicit cast.
+ // Because 9223372036854775808 is uint64_t, and
+ // -(uint64_t)9223372036854775808 == 9223372036854775808 could not
+ // be narrowed to int64_t.
+ if(castKind == SK(INT64) && (int64_t)mValue == INT64_MIN) {
+ std::string extra;
+ return strdup(("("
+ + ScalarType(SK(INT64)).getCppType(android::Type::StorageMode_Stack, &extra) // "int64_t"
+ + ")(" + literal + "ull)").c_str());
+ }
+
+ // add suffix if necessary.
+ if(castKind == SK(UINT32) || castKind == SK(UINT64)) literal += "u";
+ if(castKind == SK(UINT64) || castKind == SK(INT64)) literal += "ll";
+ return strdup(literal.c_str());
+}
+
+const char *ConstantExpression::javaValue(ScalarType::Kind castKind) const {
+ switch(castKind) {
+ case SK(UINT64): return value0(SK(INT64));
+ case SK(UINT32): return value0(SK(INT32));
+ case SK(UINT16): return value0(SK(INT16));
+ case SK(UINT8) : return value0(SK(INT8));
+ case SK(BOOL) :
+ if(mType == kConstExprUnknown)
+ return expr();
+ return this->cast<bool>() ? strdup("true") : strdup("false");
+ default: break;
+ }
+ return value0(castKind);
+}
+
+const char *ConstantExpression::value0(ScalarType::Kind castKind) const {
+ if(mType == kConstExprUnknown)
+ return expr();
+
+#define CASE_STR(__type__) return strdup(std::to_string(this->cast<__type__>()).c_str());
+
+ SWITCH_KIND(castKind, CASE_STR, return expr(); );
+}
+
+template<typename T>
+T ConstantExpression::cast() const {
+ CHECK(mType != kConstExprUnknown);
+
+#define CASE_CAST_T(__type__) return static_cast<T>(static_cast<__type__>(mValue));
+
+ SWITCH_KIND(mValueKind, CASE_CAST_T, CHECK(false); return 0; );
+}
+
+/*
+
+Evaluating expressions in HIDL language
+
+The following rules are mostly like that in:
+http://en.cppreference.com/w/cpp/language/operator_arithmetic
+http://en.cppreference.com/w/cpp/language/operator_logical
+http://en.cppreference.com/w/cpp/language/operator_comparison
+http://en.cppreference.com/w/cpp/language/operator_other
+
+The type of literal is the first type which the value
+can fit from the list of types depending on the suffix and bases.
+
+suffix decimal bases hexadecimal bases
+no suffix int32_t int32_t
+ int64_t uint32_t
+ int64_t
+ uint64_t
+
+u/U uint32_t (same as left)
+ uint64_t
+
+l/L int64_t int64_t
+
+ul/UL/uL/Ul uint64_t uint64_t
+
+
+Note: There are no negative integer literals.
+ -1 is the unary minus applied to 1.
+
+Unary arithmetic and bitwise operators (~ + -):
+ don't change the type of the argument.
+ (so -1u = -(1u) has type uint32_t)
+
+Binary arithmetic and bitwise operators (except shifts) (+ - * / % & | ^):
+1. Integral promotion is first applied on both sides.
+2. If both operands have the same type, no promotion is necessary.
+3. Usual arithmetic conversions.
+
+Integral promotion: if an operand is of a type with less than 32 bits,
+(including bool), it is promoted to int32_t.
+
+Usual arithmetic conversions:
+1. If operands are both signed or both unsigned, lesser conversion rank is
+ converted to greater conversion rank.
+2. Otherwise, if unsigned's rank >= signed's rank, -> unsigned's type
+3. Otherwise, if signed's type can hold all values in unsigned's type,
+ -> signed's type
+4. Otherwise, both converted to the unsigned counterpart of the signed operand's
+ type.
+rank: bool < int8_t < int16_t < int32_t < int64_t
+
+
+Shift operators (<< >>):
+1. Integral promotion is applied on both sides.
+2. For unsigned a, a << b discards bits that shifts out.
+ For signed non-negative a, a << b is legal if no bits shifts out, otherwise error.
+ For signed negative a, a << b gives error.
+3. For unsigned and signed non-negative a, a >> b discards bits that shifts out.
+ For signed negative a, a >> b discards bits that shifts out, and the signed
+ bit gets extended. ("arithmetic right shift")
+4. Shifting with negative number of bits is undefined. (Currently, the
+ parser will shift into the other direction. This behavior may change.)
+5. Shifting with number of bits exceeding the width of the type is undefined.
+ (Currently, 1 << 32 == 1. This behavior may change.)
+
+Logical operators (!, &&, ||):
+1. Convert first operand to bool. (true if non-zero, false otherwise)
+2. If short-circuited, return the result as type bool, value 1 or 0.
+3. Otherwise, convert second operand to bool, evaluate the result, and return
+ the result in the same fashion.
+
+Arithmetic comparison operators (< > <= >= == !=):
+1. Promote operands in the same way as binary arithmetic and bitwise operators.
+ (Integral promotion + Usual arithmetic conversions)
+2. Return type bool, value 0 or 1 the same way as logical operators.
+
+Ternary conditional operator (?:):
+1. Evaluate the conditional and evaluate the operands.
+2. Return type of expression is the type under usual arithmetic conversions on
+ the second and third operand. (No integral promotions necessary.)
+
+*/
+
} // namespace android
diff --git a/ConstantExpression.h b/ConstantExpression.h
index 277b9e5..fe2d572 100644
--- a/ConstantExpression.h
+++ b/ConstantExpression.h
@@ -20,16 +20,25 @@
#include <android-base/macros.h>
#include <string>
+#include "ScalarType.h"
namespace android {
-
/**
* A constant expression is represented by a tree.
*/
struct ConstantExpression {
+
+ enum ConstExprType {
+ kConstExprLiteral,
+ kConstExprUnknown,
+ kConstExprUnary,
+ kConstExprBinary,
+ kConstExprTernary
+ };
+
/* Literals, identifiers */
- ConstantExpression(const char *value);
+ ConstantExpression(const char *value, ConstExprType type);
/* binary operations */
ConstantExpression(const ConstantExpression *value1,
const char *op, const ConstantExpression* value2);
@@ -41,12 +50,33 @@
const ConstantExpression *falseVal);
/* Original expression. */
- const char *c_str() const;
- /* Evaluated result. */
+ const char *expr() const;
+ /* Evaluated result in a string form. */
const char *value() const;
+ /* Evaluated result in a string form, with given contextual kind. */
+ const char *cppValue(ScalarType::Kind castKind) const;
+ /* Evaluated result in a string form, with given contextual kind. */
+ const char *javaValue(ScalarType::Kind castKind) const;
+ /* Original expression with type. */
+ const char *description() const;
private:
- std::string mValue;
+ /* The formatted expression. */
+ std::string mFormatted;
+ /* The type of the expression. Hints on its original form. */
+ ConstExprType mType;
+ /* The kind of the result value.
+ * Is valid only when mType != kConstExprUnknown. */
+ ScalarType::Kind mValueKind;
+ /* The stored result value.
+ * Is valid only when mType != kConstExprUnknown. */
+ uint64_t mValue;
+ /* Return the value casted to the given type.
+ * First cast it according to mValueKind, then cast it to T.
+ * Assumes mType != kConstExprUnknown */
+ template <typename T> T cast() const;
+ /* Helper function for value(ScalarType::Kind) */
+ const char *value0(ScalarType::Kind castKind) const;
DISALLOW_COPY_AND_ASSIGN(ConstantExpression);
};
diff --git a/EnumType.cpp b/EnumType.cpp
index bdae930..fbb8a19 100644
--- a/EnumType.cpp
+++ b/EnumType.cpp
@@ -119,12 +119,19 @@
for (const auto &entry : type->values()) {
out << entry->name();
- const char *value = entry->value();
+ const char *value = entry->cppValue(scalarType->getKind());
if (value != NULL) {
out << " = " << value;
}
- out << ",\n";
+ out << ",";
+
+ const char *comment = entry->comment();
+ if (comment != NULL && strcmp(comment, value) != 0) {
+ out << " // " << comment;
+ }
+
+ out << "\n";
}
}
@@ -188,7 +195,7 @@
<< " "
<< entry->name();
- const char *value = entry->value();
+ const char *value = entry->javaValue(scalarType->getKind());
if (value != NULL) {
out << " = ";
@@ -202,7 +209,14 @@
}
}
- out << ";\n";
+ out << ";";
+
+ const char *comment = entry->comment();
+ if (comment != NULL && strcmp(comment, value) != 0) {
+ out << " // " << comment;
+ }
+
+ out << "\n";
}
}
@@ -240,7 +254,10 @@
}
status_t EnumType::emitVtsAttributeType(Formatter &out) const {
- out << "type: TYPE_ENUM\n" << "predefined_type:\"" << localName() << "\"\n";
+ out << "type: TYPE_ENUM\n"
+ << "predefined_type: \""
+ << localName()
+ << "\"\n";
return OK;
}
@@ -265,7 +282,7 @@
////////////////////////////////////////////////////////////////////////////////
-EnumValue::EnumValue(const char *name, const char *value)
+EnumValue::EnumValue(const char *name, const ConstantExpression *value)
: mName(name),
mValue(value) {
}
@@ -275,7 +292,18 @@
}
const char *EnumValue::value() const {
- return mValue;
+ return mValue ? mValue->value() : nullptr;
+}
+
+const char *EnumValue::cppValue(ScalarType::Kind castKind) const {
+ return mValue ? mValue->cppValue(castKind) : nullptr;
+}
+const char *EnumValue::javaValue(ScalarType::Kind castKind) const {
+ return mValue ? mValue->javaValue(castKind) : nullptr;
+}
+
+const char *EnumValue::comment() const {
+ return mValue ? mValue->description() : nullptr;
}
} // namespace android
diff --git a/EnumType.h b/EnumType.h
index fe36bda..ffe0b49 100644
--- a/EnumType.h
+++ b/EnumType.h
@@ -18,6 +18,7 @@
#define ENUM_TYPE_H_
+#include "ConstantExpression.h"
#include "NamedType.h"
#include <vector>
@@ -77,14 +78,17 @@
};
struct EnumValue {
- EnumValue(const char *name, const char *value = NULL);
+ EnumValue(const char *name, const ConstantExpression *value = nullptr);
std::string name() const;
const char *value() const;
+ const char *cppValue(ScalarType::Kind castKind) const;
+ const char *javaValue(ScalarType::Kind castKind) const;
+ const char *comment() const;
private:
std::string mName;
- const char *mValue;
+ const ConstantExpression *mValue;
DISALLOW_COPY_AND_ASSIGN(EnumValue);
};
diff --git a/Interface.cpp b/Interface.cpp
index 33e8c88..52d960e 100644
--- a/Interface.cpp
+++ b/Interface.cpp
@@ -56,6 +56,11 @@
return *mAnnotationsByName;
}
+std::string Interface::getBaseName() const {
+ // cut off the leading 'I'.
+ return localName().substr(1);
+}
+
std::string Interface::getCppType(StorageMode mode, std::string *extra) const {
extra->clear();
const std::string base = "::android::sp<" + fullName() + ">";
@@ -103,7 +108,9 @@
out << name
<< " = "
- << fullName()
+ << fqName().cppNamespace()
+ << "::IHw"
+ << getBaseName()
<< "::asInterface("
<< binderName
<< ");\n";
@@ -111,14 +118,33 @@
out.unindent();
out << "}\n\n";
} else {
+
+ out << "if (" << name << "->isRemote()) {\n";
+ out.indent();
out << "_hidl_err = ";
out << parcelObjDeref
<< "writeStrongBinder("
- << fullName()
- << "::asBinder("
- << name
- << "));\n";
-
+ << fqName().cppNamespace()
+ << "::IHw"
+ << getBaseName()
+ << "::asBinder(static_cast<"
+ << fqName().cppNamespace()
+ << "::IHw"
+ << getBaseName()
+ << "*>("
+ << name << ".get()"
+ << ")));\n";
+ out.unindent();
+ out << "} else {\n";
+ out.indent();
+ out << "_hidl_err = ";
+ out << parcelObjDeref
+ << "writeStrongBinder("
+ << "new " << fqName().cppNamespace()
+ << "::Bn" << getBaseName() << " "
+ << "(" << name <<"));\n";
+ out.unindent();
+ out << "}\n";
handleError(out, mode);
}
}
@@ -220,7 +246,8 @@
out << "type: TYPE_HIDL_CALLBACK\n"
<< "predefined_type: \""
<< localName()
- << "\"\n";
+ << "\"\n"
+ << "is_callback: true\n";
return OK;
}
@@ -234,6 +261,11 @@
return true;
}
+ if (mSuperType != nullptr && !mSuperType->isJavaCompatible()) {
+ mIsJavaCompatibleInProgress = false;
+ return false;
+ }
+
mIsJavaCompatibleInProgress = true;
if (!Scope::isJavaCompatible()) {
diff --git a/Interface.h b/Interface.h
index 023742c..7d57218 100644
--- a/Interface.h
+++ b/Interface.h
@@ -46,6 +46,8 @@
const AnnotationVector &annotations() const;
+ std::string getBaseName() const;
+
std::string getCppType(StorageMode mode, std::string *extra) const override;
std::string getJavaType() const override;
diff --git a/MODULE_LICENSE_APACHE2 b/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/MODULE_LICENSE_APACHE2
diff --git a/NOTICE b/NOTICE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/PredefinedType.cpp b/PredefinedType.cpp
new file mode 100644
index 0000000..ea557a4
--- /dev/null
+++ b/PredefinedType.cpp
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "PredefinedType.h"
+
+#include "Formatter.h"
+
+#include <android-base/logging.h>
+
+namespace android {
+
+PredefinedType::PredefinedType(const char *name)
+ : mName(name) {
+}
+
+std::string PredefinedType::getCppType(
+ StorageMode mode, std::string *extra) const {
+ extra->clear();
+
+ const std::string base = mName;
+
+ switch (mode) {
+ case StorageMode_Stack:
+ return base;
+
+ case StorageMode_Argument:
+ return "const " + base + "&";
+
+ case StorageMode_Result:
+ return "const " + base + "*";
+ }
+}
+
+std::string PredefinedType::getJavaType() const {
+ CHECK(!"Should not be here");
+ return std::string();
+}
+
+void PredefinedType::emitReaderWriter(
+ Formatter &out,
+ const std::string &name,
+ const std::string &parcelObj,
+ bool parcelObjIsPointer,
+ bool isReader,
+ ErrorMode mode) const {
+ const std::string parentName = "_hidl_" + name + "_parent";
+
+ out << "size_t " << parentName << ";\n\n";
+
+ const std::string parcelObjDeref =
+ parcelObj + (parcelObjIsPointer ? "->" : ".");
+
+ if (isReader) {
+ out << name
+ << " = (const "
+ << mName
+ << " *)"
+ << parcelObjDeref
+ << "readBuffer("
+ << "&"
+ << parentName
+ << ");\n";
+
+ out << "if ("
+ << name
+ << " == nullptr) {\n";
+
+ out.indent();
+
+ out << "_hidl_err = ::android::UNKNOWN_ERROR;\n";
+ handleError2(out, mode);
+
+ out.unindent();
+ out << "}\n\n";
+ } else {
+ out << "_hidl_err = "
+ << parcelObjDeref
+ << "writeBuffer(&"
+ << name
+ << ", sizeof("
+ << name
+ << "), &"
+ << parentName
+ << ");\n";
+
+ handleError(out, mode);
+ }
+
+ emitReaderWriterEmbedded(
+ out,
+ name,
+ isReader /* nameIsPointer */,
+ parcelObj,
+ parcelObjIsPointer,
+ isReader,
+ mode,
+ parentName,
+ "0 /* parentOffset */");
+}
+
+void PredefinedType::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,
+ mName,
+ "" /* childName */);
+}
+
+bool PredefinedType::isJavaCompatible() const {
+ return false;
+}
+
+bool PredefinedType::needsEmbeddedReadWrite() const {
+ return true;
+}
+
+bool PredefinedType::resultNeedsDeref() const {
+ return true;
+}
+
+} // namespace android
+
diff --git a/PredefinedType.h b/PredefinedType.h
new file mode 100644
index 0000000..5915eb3
--- /dev/null
+++ b/PredefinedType.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PREDEFINED_TYPE_H_
+
+#define PREDEFINED_TYPE_H_
+
+#include "Type.h"
+
+namespace android {
+
+struct PredefinedType : public Type {
+ PredefinedType(const char *name);
+
+ std::string getCppType(StorageMode mode, std::string *extra) const override;
+ std::string getJavaType() 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 isJavaCompatible() const override;
+
+ bool needsEmbeddedReadWrite() const override;
+ bool resultNeedsDeref() const override;
+
+private:
+ std::string mName;
+
+ DISALLOW_COPY_AND_ASSIGN(PredefinedType);
+};
+
+} // namespace android
+
+#endif // PREDEFINED_TYPE_H_
diff --git a/ScalarType.cpp b/ScalarType.cpp
index cff91c3..f751ae6 100644
--- a/ScalarType.cpp
+++ b/ScalarType.cpp
@@ -208,11 +208,21 @@
}
status_t ScalarType::emitVtsTypeDeclarations(Formatter &out) const {
- std::string extra;
- out << "type: TYPE_SCALAR\n"
- << "scalar_type: "
- << getCppType(StorageMode_Stack, &extra)
- << "\n";
+ static const char *const kName[] = {
+ "bool_t",
+ "opaque",
+ "int8_t",
+ "uint8_t",
+ "int16_t",
+ "uint16_t",
+ "int32_t",
+ "uint32_t",
+ "int64_t",
+ "uint64_t",
+ "float_t",
+ "double_t"
+ };
+ out << "type: TYPE_SCALAR\n"<< "scalar_type: \""<< kName[mKind]<< "\"\n";
return OK;
}
@@ -235,5 +245,9 @@
*align = *size = kAlign[mKind];
}
+ScalarType::Kind ScalarType::getKind() const {
+ return mKind;
+}
+
} // namespace android
diff --git a/ScalarType.h b/ScalarType.h
index fd9fb67..06892bf 100644
--- a/ScalarType.h
+++ b/ScalarType.h
@@ -78,6 +78,8 @@
void getAlignmentAndSize(size_t *align, size_t *size) const override;
+ Kind getKind() const;
+
private:
Kind mKind;
diff --git a/c2hal/AST.cpp b/c2hal/AST.cpp
new file mode 100644
index 0000000..f803cc1
--- /dev/null
+++ b/c2hal/AST.cpp
@@ -0,0 +1,339 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "AST.h"
+
+#include "FunctionDeclaration.h"
+#include "EnumVarDeclaration.h"
+#include "Scope.h"
+#include "Declaration.h"
+#include "CompositeDeclaration.h"
+#include "Define.h"
+#include "Include.h"
+
+#include <string>
+#include <algorithm>
+#include <stdlib.h>
+#include <sys/dir.h>
+#include <sys/stat.h>
+
+namespace android {
+
+AST::AST(const std::string &path,
+ const std::string &outputDir,
+ const std::string &package,
+ bool isOpenGl)
+ : mScanner(NULL),
+ mPath(path),
+ mOutputDir(outputDir),
+ mPackage(package),
+ mIsOpenGl(isOpenGl)
+ {}
+
+AST::~AST() {
+ delete mExpression;
+
+ if(mDeclarations != NULL) {
+ for(auto* decl : *mDeclarations) {
+ delete decl;
+ }
+ }
+ delete mDeclarations;
+
+ if(mInterfaces != NULL) {
+ for(auto* inter : *mInterfaces) {
+ delete inter;
+ }
+ }
+ delete mInterfaces;
+
+ if(mIncludes != NULL) {
+ for(auto* incl : *mIncludes) {
+ delete incl;
+ }
+ }
+ delete mIncludes;
+}
+
+void *AST::scanner() {
+ return mScanner;
+}
+
+void AST::setScanner(void *scanner) {
+ mScanner = scanner;
+}
+
+bool AST::isOpenGl() const {
+ return mIsOpenGl;
+}
+
+const std::string& AST::getFilename() const {
+ return mPath;
+}
+
+void AST::setDeclarations(std::vector<Declaration *> *declarations) {
+ mDeclarations = declarations;
+}
+
+void AST::setIncludes(std::vector<Include *> *includes) {
+ mIncludes = includes;
+}
+
+Expression *AST::getExpression() const {
+ return mExpression;
+}
+void AST::setExpression(Expression *expression) {
+ mExpression = expression;
+}
+
+const Scope<Define *> &AST::getDefinesScope() const {
+ return mDefinesScope;
+}
+
+Scope<Define *> &AST::getDefinesScope() {
+ return mDefinesScope;
+}
+
+void AST::processContents() {
+ CHECK(mDeclarations != NULL);
+
+ for (auto &declaration : *mDeclarations) {
+ CHECK(declaration != NULL);
+
+ declaration->processContents(*this);
+ }
+
+ isolateInterfaces();
+ isolateGlobalInterface();
+ isolateIncludes();
+
+ isolateConstants(Expression::Type::U64);
+ isolateConstants(Expression::Type::S64);
+ isolateConstants(Expression::Type::U32);
+ isolateConstants(Expression::Type::S32);
+}
+
+/* take interface-like structs out of the type file */
+void AST::isolateInterfaces() {
+ mInterfaces = new std::vector<CompositeDeclaration*>;
+
+ auto it = mDeclarations->begin();
+ while (it != mDeclarations->end()) {
+ if ((*it)->decType() == CompositeDeclaration::type()
+ && ((CompositeDeclaration *) (*it))->isInterface()) {
+
+ mInterfaces->push_back((CompositeDeclaration *) *it);
+ it = mDeclarations->erase(it);
+ } else {
+ it++;
+ }
+ }
+}
+
+/* take global function declarations out of the type file and into a new
+ * interface
+ */
+void AST::isolateGlobalInterface() {
+ auto globalFuns = new std::vector<Declaration*>;
+
+ auto it = mDeclarations->begin();
+ while (it != mDeclarations->end()) {
+ if ((*it)->decType() == FunctionDeclaration::type()) {
+
+ globalFuns->push_back(*it);
+ it = mDeclarations->erase(it);
+ } else {
+ it++;
+ }
+ }
+
+ if (!globalFuns->empty()) {
+ std::string path = mPackage.substr(0, mPackage.find_first_of('@'));
+ std::string name = path.substr(path.find_last_of('.') + 1);
+
+ auto interface = new CompositeDeclaration(
+ Type::Qualifier::STRUCT,
+ name + "_global_t",
+ globalFuns);
+
+ mInterfaces->push_back(interface);
+ }
+}
+
+void AST::isolateIncludes() {
+ mIncludes = new std::vector<Include*>;
+
+ auto it = mDeclarations->begin();
+ while (it != mDeclarations->end()) {
+ if ((*it)->decType() == Include::type()) {
+
+ mIncludes->push_back((Include *) *it);
+ it = mDeclarations->erase(it);
+ } else {
+ it++;
+ }
+ }
+}
+
+void AST::isolateConstants(Expression::Type ofType) {
+ auto constants = new std::vector<Declaration*>;
+
+ auto it = mDeclarations->begin();
+ while (it != mDeclarations->end()) {
+ if ((*it)->decType() == Define::type() &&
+ ((Define *)*it)->getExpressionType() == ofType) {
+
+ Define* define = (Define *)*it;
+
+ auto var = new EnumVarDeclaration(define->getName(),
+ define->getExpression());
+
+ define->setExpression(NULL);
+
+ constants->push_back(var);
+ it = mDeclarations->erase(it);
+
+ delete define;
+ } else {
+ it++;
+ }
+ }
+
+ if (!constants->empty()) {
+ auto constEnum = new CompositeDeclaration(
+ Type::Qualifier::ENUM,
+ "Const" + Expression::getTypeDescription(ofType),
+ constants);
+
+ constEnum->setEnumTypeName(Expression::getTypeName(ofType));
+
+ mDeclarations->insert(mDeclarations->begin(), constEnum);
+ }
+}
+
+status_t AST::generateCode() const {
+ CHECK(mDeclarations != NULL);
+
+ status_t err;
+
+ for (auto &interface : *mInterfaces) {
+ err = generateFile(interface);
+
+ if (err != OK) {
+ return err;
+ }
+ }
+
+ err = generateTypesFile();
+
+ if (err != OK) {
+ return err;
+ }
+
+ return OK;
+}
+
+status_t AST::generateFile(CompositeDeclaration* declaration) const {
+ std::string fileName = declaration->getInterfaceName() + ".hal";
+
+ FILE *file = fopen((getFileDir() + fileName).c_str(), "w");
+
+ if(file == NULL) {
+ return -errno;
+ }
+
+ Formatter out(file); // formatter closes out
+
+ generatePackageLine(out);
+ generateIncludes(out);
+
+ declaration->generateInterface(out);
+
+ return OK;
+}
+
+status_t AST::generateTypesFile() const {
+ if (mDeclarations->empty()) {
+ return OK;
+ }
+
+ FILE *file = fopen((getFileDir() + "types.hal").c_str(), "w");
+
+ if(file == NULL) {
+ return -errno;
+ }
+
+ Formatter out(file); // formatter closes out
+
+ generatePackageLine(out);
+ generateIncludes(out);
+
+ for (auto &declaration : *mDeclarations) {
+ declaration->generateCommentText(out);
+ declaration->generateSource(out);
+ out << "\n";
+ }
+
+ return OK;
+}
+
+void AST::generateIncludes(Formatter &out) const {
+ for (auto &include : *mIncludes) {
+ include->generateSource(out);
+ out << "\n";
+ }
+}
+
+void AST::generatePackageLine(Formatter &out) const {
+ out << "package "
+ << mPackage
+ << ";\n\n";
+}
+
+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;
+}
+
+const std::string AST::getFileDir() const {
+ CHECK(MakeParentHierarchy(mOutputDir));
+ return mOutputDir;
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/c2hal/AST.h b/c2hal/AST.h
new file mode 100644
index 0000000..bc0808a
--- /dev/null
+++ b/c2hal/AST.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AST_H_
+#define AST_H_
+
+#include "../Formatter.h"
+#include "Scope.h"
+#include "Expression.h"
+
+#include <android-base/macros.h>
+#include <android-base/logging.h>
+#include <string>
+#include <vector>
+#include <utils/Errors.h>
+
+namespace android {
+
+struct Include;
+struct Define;
+struct CompositeDeclaration;
+struct Declaration;
+
+struct AST {
+ AST(const std::string &path,
+ const std::string &outputDir,
+ const std::string &package,
+ bool isOpenGl);
+ ~AST();
+
+ void *scanner();
+ void setScanner(void *scanner);
+
+ bool isOpenGl() const;
+
+ const std::string &getFilename() const;
+
+ void setDeclarations(std::vector<Declaration *> *declarations);
+ void setIncludes(std::vector<Include *> *includes);
+
+ Expression *getExpression() const;
+ void setExpression(Expression *expression);
+
+ status_t generateCode() const;
+
+ void processContents();
+
+ const Scope<Define *> &getDefinesScope() const;
+ Scope<Define *> &getDefinesScope();
+
+private:
+ void * mScanner = NULL;
+ std::string mPath;
+ std::string mOutputDir;
+ std::string mPackage;
+
+ bool mIsOpenGl;
+
+ Expression* mExpression = NULL;
+
+ std::vector<Declaration *> *mDeclarations = NULL;
+ std::vector<CompositeDeclaration *> *mInterfaces = NULL;
+ std::vector<Include *> *mIncludes = NULL;
+
+ Scope<Define *> mDefinesScope;
+
+ const std::string getFileDir() const;
+
+ status_t generateFile(CompositeDeclaration* declaration) const;
+ status_t generateTypesFile() const;
+
+ void generateIncludes(Formatter &out) const;
+ void generatePackageLine(Formatter &out) const;
+
+ void isolateInterfaces();
+ void isolateGlobalInterface();
+ void isolateIncludes();
+ void isolateConstants(Expression::Type ofType);
+
+ DISALLOW_COPY_AND_ASSIGN(AST);
+};
+
+} // namespace android
+
+#endif // AST_H_
diff --git a/c2hal/Android.mk b/c2hal/Android.mk
new file mode 100644
index 0000000..828264b
--- /dev/null
+++ b/c2hal/Android.mk
@@ -0,0 +1,35 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := c2hal
+LOCAL_MODULE_CLASS := EXECUTABLES
+# LOCAL_IS_HOST_MODULE := true
+
+LOCAL_SRC_FILES := \
+ ../Formatter.cpp \
+ AST.cpp \
+ c2hal_l.ll \
+ c2hal_y.yy \
+ CompositeDeclaration.cpp \
+ Declaration.cpp \
+ Define.cpp \
+ EnumVarDeclaration.cpp \
+ Expression.cpp \
+ FunctionDeclaration.cpp \
+ Include.cpp \
+ main.cpp \
+ Note.cpp \
+ Type.cpp \
+ TypeDef.cpp \
+ VarDeclaration.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+ libbase \
+ liblog \
+
+LOCAL_STATIC_LIBRARIES := \
+ libutils \
+
+LOCAL_CFLAGS := -O0 -g
+
+include $(BUILD_HOST_EXECUTABLE)
diff --git a/c2hal/CompositeDeclaration.cpp b/c2hal/CompositeDeclaration.cpp
new file mode 100644
index 0000000..135654c
--- /dev/null
+++ b/c2hal/CompositeDeclaration.cpp
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CompositeDeclaration.h"
+#include "FunctionDeclaration.h"
+#include "Declaration.h"
+
+#include <algorithm>
+#include <iostream>
+#include <string>
+#include <sstream>
+
+namespace android {
+
+static std::string capitalize(const std::string in) {
+ std::string out{in};
+
+ if(!out.empty()) {
+ out[0] = toupper(out[0]);
+ }
+
+ return out;
+}
+
+static std::string snakeCaseToCamelCase(const std::string in) {
+ std::istringstream ss(in);
+ std::string word;
+ std::string out;
+
+ while (std::getline(ss, word, '_')) {
+ out += capitalize(word);
+ }
+
+ return out;
+}
+
+CompositeDeclaration::CompositeDeclaration(
+ const Type::Qualifier::Qualification qualifier,
+ const std::string &name,
+ std::vector<android::Declaration *> *fieldDeclarations)
+ : Declaration(name), mQualifier(qualifier), mFieldDeclarations(fieldDeclarations)
+ {}
+
+CompositeDeclaration::~CompositeDeclaration() {
+ if(mFieldDeclarations != NULL) {
+ for(auto* decl : *mFieldDeclarations) {
+ delete decl;
+ }
+ }
+ delete mFieldDeclarations;
+}
+
+
+const Type::Qualifier::Qualification &CompositeDeclaration::getQualifier() const {
+ return mQualifier;
+}
+const std::vector<android::Declaration *>*
+ CompositeDeclaration::getFieldDeclarations() const {
+ return mFieldDeclarations;
+}
+
+void CompositeDeclaration::generateInterface(Formatter &out) const {
+ generateCommentText(out);
+ out << "interface " << getInterfaceName() << " {\n\n";
+
+ generateBody(out);
+
+ out << "};\n";
+}
+
+void CompositeDeclaration::generateSource(Formatter &out) const {
+ CHECK(mQualifier == Type::Qualifier::STRUCT ||
+ mQualifier == Type::Qualifier::UNION ||
+ mQualifier == Type::Qualifier::ENUM);
+
+ out << Type::qualifierText(mQualifier) << " " << getName();
+
+ if (mQualifier == Type::Qualifier::ENUM) {
+ out << " : ";
+
+ if (mEnumTypeName.empty()) {
+ out << "int32_t /* NOTE: type is guessed */";
+ } else {
+ out << mEnumTypeName;
+ }
+
+ }
+
+ out << " {\n";
+
+ generateBody(out);
+
+ out << "};\n";
+}
+
+void CompositeDeclaration::generateBody(Formatter &out) const {
+ out.indent();
+
+ for (auto *declaration : *mFieldDeclarations) {
+ declaration->generateCommentText(out);
+ declaration->generateSource(out);
+ out << "\n";
+ }
+
+ out.unindent();
+}
+
+void CompositeDeclaration::processContents(AST &ast) {
+ for (auto &declaration : *mFieldDeclarations) {
+ declaration->processContents(ast);
+ }
+
+ if (isInterface()) {
+ // move non function fields into a containing struct
+
+ auto nonFpDecs = new std::vector<Declaration*>;
+
+ auto it = mFieldDeclarations->begin();
+ while (it != mFieldDeclarations->end()) {
+ if((*it)->decType() != FunctionDeclaration::type()) {
+ nonFpDecs->push_back(*it);
+ it = mFieldDeclarations->erase(it);
+ } else {
+ it++;
+ }
+ }
+
+ if (!nonFpDecs->empty()) {
+ auto subStruct = new CompositeDeclaration(Type::Qualifier::STRUCT,
+ getName(),
+ nonFpDecs);
+
+ mFieldDeclarations->insert(mFieldDeclarations->begin(), subStruct);
+ }
+ }
+}
+
+std::string CompositeDeclaration::getInterfaceName() const {
+ std::string baseName{getName()};
+
+ if (baseName.length() > 2 &&
+ baseName.substr(baseName.length() - 2) == "_t") {
+
+ baseName = baseName.substr(0, baseName.length() - 2);
+ }
+
+ return "I" + snakeCaseToCamelCase(baseName);
+}
+
+bool CompositeDeclaration::isInterface() const {
+ if (mQualifier != Type::Qualifier::STRUCT) {
+ return false;
+ }
+
+ for (auto &declaration : *mFieldDeclarations) {
+ if (declaration->decType() == FunctionDeclaration::type()) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void CompositeDeclaration::setEnumTypeName(const std::string &name) {
+ CHECK(mQualifier == Type::Qualifier::ENUM);
+
+ mEnumTypeName = name;
+}
+
+} //namespace android
\ No newline at end of file
diff --git a/c2hal/CompositeDeclaration.h b/c2hal/CompositeDeclaration.h
new file mode 100644
index 0000000..a449216
--- /dev/null
+++ b/c2hal/CompositeDeclaration.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef COMPOSITE_DECLARATION_H_
+#define COMPOSITE_DECLARATION_H_
+
+#include "Declaration.h"
+#include "Type.h"
+
+namespace android {
+
+struct CompositeDeclaration : Declaration {
+ CompositeDeclaration(
+ const Type::Qualifier::Qualification qualifier,
+ const std::string &name,
+ std::vector<android::Declaration *> *fieldDeclarations);
+ ~CompositeDeclaration();
+
+ const Type::Qualifier::Qualification &getQualifier() const;
+ const std::vector<android::Declaration *>* getFieldDeclarations() const;
+
+ static std::string type() { return "composite"; }
+ const std::string decType() const override { return type(); }
+
+ void generateSource(Formatter &out) const override;
+ void processContents(AST &ast) override;
+
+ void generateInterface(Formatter &out) const;
+ std::string getInterfaceName() const;
+ bool isInterface() const;
+
+ void setEnumTypeName(const std::string &name);
+
+private:
+ const Type::Qualifier::Qualification mQualifier;
+ std::vector<android::Declaration *> *mFieldDeclarations;
+
+ std::string mEnumTypeName;
+
+ void generateBody(Formatter &out) const;
+
+ DISALLOW_COPY_AND_ASSIGN(CompositeDeclaration);
+};
+
+} // namespace android
+
+#endif // COMPOSITE_DECLARATION_H_
\ No newline at end of file
diff --git a/c2hal/Declaration.cpp b/c2hal/Declaration.cpp
new file mode 100644
index 0000000..8f88ea6
--- /dev/null
+++ b/c2hal/Declaration.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Declaration.h"
+
+#include <regex>
+
+namespace android {
+
+static const std::regex RE_LEADING_SPACES("\n +");
+
+Declaration::Declaration(const std::string &name)
+ : mName(name)
+ {}
+
+Declaration::~Declaration() {}
+
+const std::string& Declaration::getName() const {
+ return mName;
+}
+void Declaration::setName(const std::string &name) {
+ mName = name;
+}
+
+const std::string& Declaration::getComment() const {
+ return mComment;
+}
+void Declaration::setComment(const std::string &comment) {
+ // remove excess leading whitespace
+ mComment = regex_replace(comment, RE_LEADING_SPACES, "\n ");
+}
+
+void Declaration::generateCommentText(Formatter &out) const {
+ if (!mComment.empty()) {
+ out << mComment << "\n";
+ }
+}
+
+void Declaration::generateParameterSource(Formatter &out) const {
+ out << "/* UNKOWN PARAMTER */" << "\n";
+}
+
+} //namespace android
\ No newline at end of file
diff --git a/c2hal/Declaration.h b/c2hal/Declaration.h
new file mode 100644
index 0000000..bd7bce0
--- /dev/null
+++ b/c2hal/Declaration.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef DECLARATION_H_
+#define DECLARATION_H_
+
+#include <android-base/macros.h>
+#include <android-base/logging.h>
+#include <string>
+#include <vector>
+#include "../Formatter.h"
+
+namespace android {
+
+struct AST;
+
+struct Declaration {
+ Declaration(const std::string &name);
+ virtual ~Declaration();
+
+ const std::string &getName() const;
+ void setName(const std::string &name);
+
+ const std::string& getComment() const;
+ void setComment(const std::string &comment);
+
+ std::string getInterfaceName() const;
+
+ void generateCommentText(Formatter &out) const;
+
+ virtual const std::string decType() const = 0;
+
+ /* for example "int test;" */
+ virtual void generateSource(Formatter &out) const = 0;
+
+ /* for example "int test" in fun(int test, float jeff) */
+ virtual void generateParameterSource(Formatter &out) const;
+
+ virtual void processContents(AST &ast) = 0;
+
+private:
+ std::string mName;
+ std::string mComment;
+
+ DISALLOW_COPY_AND_ASSIGN(Declaration);
+};
+
+} // namespace android
+
+#endif // DECLARATION_H_
\ No newline at end of file
diff --git a/c2hal/Define.cpp b/c2hal/Define.cpp
new file mode 100644
index 0000000..02afded
--- /dev/null
+++ b/c2hal/Define.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Define.h"
+
+#include "AST.h"
+
+extern android::status_t parseExpression(android::AST *ast, std::string str);
+
+namespace android {
+
+Define::Define(const std::string &name, const std::string &slurp)
+ : Declaration(name), mSlurp(slurp)
+ {}
+
+Define::~Define() {
+ delete mExpression;
+}
+
+Expression::Type Define::getExpressionType() const {
+ return mExpressionType;
+}
+Expression *Define::getExpression() const {
+ return mExpression;
+}
+void Define::setExpression(Expression* expression) {
+ mExpression = expression;
+}
+
+void Define::generateSource(Formatter &out) const {
+ out << "/* #define " << getName() << " " << mSlurp << " */\n";
+}
+
+void Define::processContents(AST &ast) {
+ status_t res = parseExpression(&ast, mSlurp);
+
+ if (res != 0) {
+ mExpressionType = Expression::Type::UNKOWN;
+ return;
+ }
+
+ mExpression = ast.getExpression();
+ ast.setExpression(NULL);
+
+ mExpressionType = mExpression->getType(ast);
+
+ ast.getDefinesScope().enter(getName(), this);
+}
+
+} //namespace android
\ No newline at end of file
diff --git a/c2hal/Define.h b/c2hal/Define.h
new file mode 100644
index 0000000..e66159d
--- /dev/null
+++ b/c2hal/Define.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef DEFINE_H_
+#define DEFINE_H_
+
+#include <android-base/macros.h>
+#include <android-base/logging.h>
+#include <string>
+#include <vector>
+#include "Declaration.h"
+#include "Expression.h"
+
+namespace android {
+
+struct Define : Declaration {
+ Define(const std::string &name, const std::string &slurp);
+ ~Define();
+
+ static std::string type() { return "define"; }
+ const std::string decType() const override { return type(); }
+
+ void generateSource(Formatter &out) const override;
+ void processContents(AST &ast) override;
+
+ Expression::Type getExpressionType() const;
+ Expression *getExpression() const;
+ void setExpression(Expression* expression);
+
+private:
+ const std::string mSlurp;
+
+ Expression::Type mExpressionType;
+ Expression* mExpression = NULL;
+
+ DISALLOW_COPY_AND_ASSIGN(Define);
+};
+
+} // namespace android
+
+#endif // DEFINE_H_
\ No newline at end of file
diff --git a/c2hal/EnumVarDeclaration.cpp b/c2hal/EnumVarDeclaration.cpp
new file mode 100644
index 0000000..f7c4671
--- /dev/null
+++ b/c2hal/EnumVarDeclaration.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "EnumVarDeclaration.h"
+#include "Expression.h"
+
+namespace android {
+
+EnumVarDeclaration::EnumVarDeclaration(const std::string &name, Expression *expression)
+ : Declaration(name), mExpression(expression)
+ {}
+
+EnumVarDeclaration::~EnumVarDeclaration() {
+ delete mExpression;
+}
+
+Expression *EnumVarDeclaration::getExpression() const {
+ return mExpression;
+}
+
+void EnumVarDeclaration::generateSource(Formatter &out) const {
+ out << getName();
+
+ if(mExpression != NULL) {
+ out << " = " << mExpression->toString();
+ }
+
+ out << ",\n";
+}
+
+void EnumVarDeclaration::processContents(AST &) {
+ // nothing to do
+}
+
+} //namespace android
\ No newline at end of file
diff --git a/c2hal/EnumVarDeclaration.h b/c2hal/EnumVarDeclaration.h
new file mode 100644
index 0000000..10978e0
--- /dev/null
+++ b/c2hal/EnumVarDeclaration.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ENUM_VAR_DECLARATION_H_
+#define ENUM_VAR_DECLARATION_H_
+
+#include <android-base/macros.h>
+#include <android-base/logging.h>
+#include <string>
+#include <vector>
+#include "Declaration.h"
+
+namespace android {
+
+struct Expression;
+
+struct EnumVarDeclaration : Declaration {
+ EnumVarDeclaration(const std::string &name, Expression *expression);
+ ~EnumVarDeclaration();
+
+ static std::string type() { return "enum"; }
+ const std::string decType() const override { return type(); }
+
+ Expression *getExpression() const;
+
+ void generateSource(Formatter &out) const override;
+ void processContents(AST &ast) override;
+
+private:
+ Expression *mExpression = NULL;
+
+ DISALLOW_COPY_AND_ASSIGN(EnumVarDeclaration);
+};
+
+} // namespace android
+
+#endif // ENUM_VAR_DECLARATION_H_
\ No newline at end of file
diff --git a/c2hal/Expression.cpp b/c2hal/Expression.cpp
new file mode 100644
index 0000000..f9c8bb2
--- /dev/null
+++ b/c2hal/Expression.cpp
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Expression.h"
+#include "Define.h"
+#include "AST.h"
+#include "Scope.h"
+
+#include <vector>
+#include <regex>
+
+namespace android {
+
+static const std::regex RE_S32("[^ul]$");
+static const std::regex RE_U32("[^ul]u$");
+static const std::regex RE_S64("[^ul](l|ll)$");
+static const std::regex RE_U64("[^ul](ul|ull)$");
+
+// static
+Expression::Type Expression::integralType(std::string integer) {
+ if (std::regex_search(integer, RE_S32)) {
+ return Type::S32;
+ }
+
+ if (std::regex_search(integer, RE_U32)) {
+ return Type::U32;
+ }
+
+ if (std::regex_search(integer, RE_S64)) {
+ return Type::S64;
+ }
+
+ if (std::regex_search(integer, RE_U64)) {
+ return Type::U64;
+ }
+
+ LOG(WARNING) << "UNKOWN INTEGER LITERAL: " << integer;
+
+ return Type::UNKOWN;
+}
+
+// static
+Expression::Type Expression::coalesceTypes(Type lhs, Type rhs) {
+ // because we are reducing everything to two ranks, we can heavily simplify
+ // conversion rules
+
+#define SIGNED(i) (i & 2) // i & 0b10
+#define MAX_RANK(i) (i | 1) // i | 0b01
+
+ if (lhs == rhs) {
+ return lhs;
+ }
+
+ // lhs != rhs
+ if (SIGNED(lhs) == SIGNED(rhs)) {
+ return (Type)MAX_RANK(lhs);
+ }
+
+ // lhs != rhs && SIGNED(lhs) != SIGNED(rhs)
+ if (lhs == U32 || rhs == U32) {
+ return S64;
+ }
+
+ return Type::UNKOWN;
+
+#undef SIGNED
+#undef MAX_RANK
+
+}
+
+struct ParenthesizedExpression : Expression {
+ ParenthesizedExpression(Expression* inner)
+ : mInner(inner) {}
+ ~ParenthesizedExpression() {
+ delete mInner;
+ }
+
+ virtual Type getType(const AST &ast) {
+ return mInner->getType(ast);
+ }
+ virtual std::string toString() {
+ return "(" + mInner->toString() + ")";
+ }
+
+private:
+ Expression* mInner;
+
+ DISALLOW_COPY_AND_ASSIGN(ParenthesizedExpression);
+};
+
+struct AtomExpression : Expression {
+ AtomExpression(Type type, const std::string &value)
+ : mType(type), mValue(value)
+ {}
+
+ virtual Type getType(const AST &ast) {
+ if (mType != Type::UNKOWN) {
+ return mType;
+ }
+
+ Define *define = ast.getDefinesScope().lookup(mValue);
+
+ if (define == NULL) {
+ return Type::UNKOWN;
+ }
+
+ return define->getExpressionType();
+ }
+ virtual std::string toString() {
+ return mValue;
+ }
+
+private:
+ Type mType;
+ std::string mValue;
+
+ DISALLOW_COPY_AND_ASSIGN(AtomExpression);
+};
+
+struct UnaryExpression : Expression {
+ UnaryExpression(std::string op, Expression* rhs)
+ : mOp(op), mRhs(rhs)
+ {}
+ ~UnaryExpression() {
+ delete mRhs;
+ }
+
+ virtual Type getType(const AST &ast) {
+ return mRhs->getType(ast);
+ }
+ virtual std::string toString() {
+ return mOp + mRhs->toString();
+ }
+
+private:
+ std::string mOp;
+ Expression* mRhs;
+
+ DISALLOW_COPY_AND_ASSIGN(UnaryExpression);
+};
+
+struct BinaryExpression : Expression {
+ BinaryExpression(Expression *lhs, std::string op, Expression* rhs)
+ : mLhs(lhs), mOp(op), mRhs(rhs)
+ {}
+ ~BinaryExpression() {
+ delete mLhs;
+ delete mRhs;
+ }
+
+ virtual Type getType(const AST &ast) {
+ return coalesceTypes(mLhs->getType(ast), mRhs->getType(ast));
+ }
+ virtual std::string toString() {
+ return mLhs->toString() + " " + mOp + " " + mRhs->toString();
+ }
+
+private:
+ Expression* mLhs;
+ std::string mOp;
+ Expression* mRhs;
+
+ DISALLOW_COPY_AND_ASSIGN(BinaryExpression);
+};
+
+struct TernaryExpression : Expression {
+ TernaryExpression(Expression *lhs, Expression *mhs, Expression* rhs)
+ : mLhs(lhs), mMhs(mhs), mRhs(rhs)
+ {}
+ ~TernaryExpression() {
+ delete mLhs;
+ delete mMhs;
+ delete mRhs;
+ }
+
+ virtual Type getType(const AST &ast) {
+ return coalesceTypes(mMhs->getType(ast), mRhs->getType(ast));
+ }
+ virtual std::string toString() {
+ return mLhs->toString() + " ? " + mMhs->toString() + " : " + mRhs->toString();
+ }
+
+private:
+ Expression* mLhs;
+ Expression* mMhs;
+ Expression* mRhs;
+
+ DISALLOW_COPY_AND_ASSIGN(TernaryExpression);
+};
+
+struct ArraySubscript : Expression {
+ ArraySubscript(std::string id, Expression* subscript)
+ : mId(id), mSubscript(subscript)
+ {}
+ ~ArraySubscript() {
+ delete mSubscript;
+ }
+
+ virtual Type getType(const AST &) {
+ return Type::UNKOWN;
+ }
+ virtual std::string toString() {
+ return mId + "[" + mSubscript->toString() + "]";
+ }
+
+private:
+ std::string mId;
+ Expression* mSubscript;
+
+ DISALLOW_COPY_AND_ASSIGN(ArraySubscript);
+};
+
+struct FunctionCall : Expression {
+ FunctionCall(std::string id, std::vector<Expression *> *args)
+ : mId(id), mArgs(args)
+ {}
+ ~FunctionCall() {
+ if(mArgs != NULL) {
+ for(auto* args : *mArgs) {
+ delete args;
+ }
+ }
+ delete mArgs;
+ }
+
+ virtual Type getType(const AST &) {
+ return Type::UNKOWN;
+ }
+ virtual std::string toString() {
+ std::string out = mId + "(";
+
+ for (auto it = mArgs->begin(); it != mArgs->end(); ++it) {
+ if (it != mArgs->begin()) {
+ out += ", ";
+ }
+
+ out += (*it)->toString();
+ }
+
+ return out;
+ }
+
+private:
+ std::string mId;
+ std::vector<Expression *> *mArgs;
+
+ DISALLOW_COPY_AND_ASSIGN(FunctionCall);
+};
+
+// static
+Expression *Expression::parenthesize(Expression *inner) {
+ return new ParenthesizedExpression(inner);
+}
+
+// static
+Expression *Expression::atom(Type type, const std::string &value) {
+ return new AtomExpression(type, value);
+}
+
+// static
+Expression *Expression::unary(std::string op, Expression *rhs) {
+ return new UnaryExpression(op, rhs);
+}
+
+// static
+Expression *Expression::binary(Expression *lhs, std::string op, Expression *rhs) {
+ return new BinaryExpression(lhs, op, rhs);
+}
+
+// static
+Expression *Expression::ternary(Expression *lhs, Expression *mhs, Expression *rhs) {
+ return new TernaryExpression(lhs, mhs, rhs);
+}
+
+// static
+Expression *Expression::arraySubscript(std::string id, Expression *subscript) {
+ return new ArraySubscript(id, subscript);
+}
+
+// static
+Expression *Expression::functionCall(std::string id, std::vector<Expression *> *args) {
+ return new FunctionCall(id, args);
+}
+
+
+} //namespace android
\ No newline at end of file
diff --git a/c2hal/Expression.h b/c2hal/Expression.h
new file mode 100644
index 0000000..13ac96d
--- /dev/null
+++ b/c2hal/Expression.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef EXPRESSION_H_
+#define EXPRESSION_H_
+
+#include <android-base/macros.h>
+#include <android-base/logging.h>
+#include <string>
+
+namespace android {
+
+struct AST;
+struct Define;
+
+struct Expression {
+ Expression() {}
+ virtual ~Expression() {}
+
+ enum Type {
+ S32 = 0, // 0b00
+ S64 = 1, // 0b01
+ U32 = 2, // 0b10
+ U64 = 3, // 0b11
+ UNKOWN = -1
+ };
+
+ static std::string getTypeDescription(Type type) {
+ switch (type) {
+ case S32: return "S32";
+ case S64: return "S64";
+ case U32: return "U32";
+ case U64: return "U64";
+ case UNKOWN:
+ default:
+ return "UNKOWN";
+ }
+ }
+
+ static std::string getTypeName(Type type) {
+ switch (type) {
+ case S32: return "int32_t";
+ case S64: return "int64_t";
+ case U32: return "uint32_t";
+ case U64: return "uint64_t";
+ case UNKOWN:
+ default:
+ return "/* UNKOWN */";
+ }
+ }
+
+ static Type integralType(std::string integer);
+ static Type coalesceTypes(Type lhs, Type rhs);
+
+ static Expression *parenthesize(Expression *inner);
+ static Expression *atom(Type type, const std::string &value);
+ static Expression *unary(std::string op, Expression *rhs);
+ static Expression *binary(Expression *lhs, std::string op, Expression *rhs);
+ static Expression *ternary(Expression *lhs, Expression *mhs, Expression *rhs);
+ static Expression *arraySubscript(std::string id, Expression *subscript);
+ static Expression *functionCall(std::string id, std::vector<Expression *> *args);
+
+ virtual Type getType(const AST &scope) = 0;
+ virtual std::string toString() = 0;
+
+private:
+
+ DISALLOW_COPY_AND_ASSIGN(Expression);
+};
+
+} // namespace android
+
+#endif // EXPRESSION_H_
\ No newline at end of file
diff --git a/c2hal/FunctionDeclaration.cpp b/c2hal/FunctionDeclaration.cpp
new file mode 100644
index 0000000..3129fee
--- /dev/null
+++ b/c2hal/FunctionDeclaration.cpp
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "FunctionDeclaration.h"
+#include "VarDeclaration.h"
+#include "Type.h"
+
+namespace android {
+
+FunctionDeclaration::FunctionDeclaration(Type* type,
+ const std::string &name,
+ std::vector<Declaration *> *params)
+ : Declaration(name),
+ mType(type),
+ mParams(params)
+ {}
+
+FunctionDeclaration::~FunctionDeclaration() {
+ delete mType;
+
+ if(mParams != NULL) {
+ for(auto* param : *mParams) {
+ delete param;
+ }
+ }
+ delete mParams;
+}
+
+
+const Type* FunctionDeclaration::getType() const {
+ return mType;
+}
+
+void FunctionDeclaration::generateSource(Formatter &out) const {
+ out << getName();
+
+ generateParams(out);
+
+ if (!getType()->isVoid()) {
+ out << " generates ("
+ << getType()->decorateName(getName() + "_ret")
+ << ")";
+ }
+
+ out << ";\n";
+}
+
+void FunctionDeclaration::generateParameterSource(Formatter &out) const {
+ out << getType()->decorateName("(*" + getName() + ")");
+
+ generateParams(out);
+}
+
+void FunctionDeclaration::processContents(AST &) {
+ if (mParams->size() == 1 &&
+ (*mParams)[0]->decType() == VarDeclaration::type()) {
+
+ VarDeclaration* var = (VarDeclaration *)(*mParams)[0];
+ if (var->getType()->isVoid()) {
+ mParams->clear();
+ }
+ }
+}
+
+void FunctionDeclaration::generateParams(Formatter &out) const {
+ out << "(";
+
+ for (auto it = mParams->begin(); it != mParams->end(); ++it) {
+ if (it != mParams->begin()) {
+ out << ", ";
+ }
+
+ (*it)->generateParameterSource(out);
+ }
+
+ out << ")";
+}
+
+} //namespace android
\ No newline at end of file
diff --git a/c2hal/FunctionDeclaration.h b/c2hal/FunctionDeclaration.h
new file mode 100644
index 0000000..1791102
--- /dev/null
+++ b/c2hal/FunctionDeclaration.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FUNCTION_DECLARATION_H_
+#define FUNCTION_DECLARATION_H_
+
+#include "Declaration.h"
+#include <android-base/macros.h>
+#include <android-base/logging.h>
+
+namespace android {
+
+struct Declaration;
+struct Type;
+
+struct FunctionDeclaration : Declaration {
+ FunctionDeclaration(Type* type,
+ const std::string &name,
+ std::vector<Declaration *> *params);
+ ~FunctionDeclaration();
+
+ const Type * getType() const;
+
+ static std::string type() { return "function"; }
+ const std::string decType() const override { return type(); }
+
+ void generateSource(Formatter &out) const override;
+ void generateParameterSource(Formatter &out) const override;
+ void processContents(AST &ast) override;
+
+private:
+ const Type *mType;
+ std::vector<Declaration *> *mParams;
+
+ void generateParams(Formatter &out) const;
+
+ DISALLOW_COPY_AND_ASSIGN(FunctionDeclaration);
+};
+
+} // namespace android
+
+#endif // FUNCTION_DECLARATION_H_
\ No newline at end of file
diff --git a/c2hal/Include.cpp b/c2hal/Include.cpp
new file mode 100644
index 0000000..8ee72f8
--- /dev/null
+++ b/c2hal/Include.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Include.h"
+
+namespace android {
+
+Include::Include(const std::string &name, bool isLibrary)
+ : Declaration(name), mIsLibrary(isLibrary)
+ {}
+
+Include::~Include() {}
+
+bool Include::isLibrary() const {
+ return mIsLibrary;
+}
+
+void Include::generateSource(Formatter &out) const {
+ out << "// import "
+ << getName();
+
+ if (isLibrary()) {
+ out << "/* library file */";
+ } else {
+ out << "/* local file */";
+ }
+
+ out << "\n";
+}
+
+void Include::processContents(AST &) {
+ // nothing to do
+}
+
+} //namespace android
\ No newline at end of file
diff --git a/c2hal/Include.h b/c2hal/Include.h
new file mode 100644
index 0000000..21988ff
--- /dev/null
+++ b/c2hal/Include.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef INCLUDE_H_
+#define INCLUDE_H_
+
+#include <android-base/macros.h>
+#include <android-base/logging.h>
+#include <string>
+#include "../Formatter.h"
+#include "Declaration.h"
+
+namespace android {
+
+struct Include : Declaration {
+ Include(const std::string &name, bool isLibrary);
+ ~Include();
+
+ static std::string type() { return "include"; }
+ const std::string decType() const override { return type(); }
+
+ void generateSource(Formatter &out) const override;
+ void processContents(AST &ast) override;
+
+ bool isLibrary() const;
+
+private:
+ const bool mIsLibrary;
+
+ DISALLOW_COPY_AND_ASSIGN(Include);
+};
+
+} // namespace android
+
+#endif // INCLUDE_H_
\ No newline at end of file
diff --git a/c2hal/Note.cpp b/c2hal/Note.cpp
new file mode 100644
index 0000000..a9422fc
--- /dev/null
+++ b/c2hal/Note.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Note.h"
+
+namespace android {
+
+Note::Note(const std::string &name)
+ : Declaration(name)
+ {}
+
+Note::~Note() {}
+
+void Note::generateSource(Formatter &out) const {
+ out << "/* NOTE:\n";
+
+ out.indent();
+ out << getName();
+ out.unindent();
+
+ out << "\n*/\n";
+}
+
+void Note::processContents(AST &) {
+ // nothing to do
+}
+
+} //namespace android
\ No newline at end of file
diff --git a/c2hal/Note.h b/c2hal/Note.h
new file mode 100644
index 0000000..679c773
--- /dev/null
+++ b/c2hal/Note.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef NOTE_DECLARATION_H_
+#define NOTE_DECLARATION_H_
+
+#include <android-base/macros.h>
+#include <android-base/logging.h>
+#include <string>
+#include <vector>
+#include "Declaration.h"
+
+namespace android {
+
+/* This class is used to represent declarations or notes
+ * which are otherwise not included in a HIDL HAL
+ */
+struct Note : Declaration {
+ Note(const std::string &name);
+ ~Note();
+
+ static std::string type() { return "note"; }
+ const std::string decType() const override { return type(); }
+
+ void generateSource(Formatter &out) const override;
+ void processContents(AST &ast) override;
+
+private:
+ std::string mExpression;
+
+ DISALLOW_COPY_AND_ASSIGN(Note);
+};
+
+} // namespace android
+
+#endif // NOTE_DECLARATION_H_
\ No newline at end of file
diff --git a/c2hal/Scope.h b/c2hal/Scope.h
new file mode 100644
index 0000000..7ff77ef
--- /dev/null
+++ b/c2hal/Scope.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SCOPE_H_
+#define SCOPE_H_
+
+#include <android-base/macros.h>
+#include <android-base/logging.h>
+#include <string>
+#include <vector>
+#include <map>
+
+namespace android {
+
+/* This class is used to represent declarations or notes
+ * which are otherwise not included in a HIDL HAL
+ */
+template<typename T>
+struct Scope {
+ Scope() {}
+ ~Scope() {}
+
+ void enter(std::string name, T item);
+ void leave(std::string name);
+
+ T lookup(std::string name) const;
+
+private:
+ std::map<std::string, T> mScopeContents;
+
+ DISALLOW_COPY_AND_ASSIGN(Scope);
+};
+
+template<typename T>
+void Scope<T>::enter(std::string name, T item) {
+ auto it = mScopeContents.find(name);
+
+ if (it != mScopeContents.end()) {
+ LOG(WARNING) << "Redeclaring variable in scope: " << name;
+ return;
+ }
+
+ mScopeContents[name] = item;
+}
+
+template<typename T>
+void Scope<T>::leave(std::string name) {
+ auto it = mScopeContents.find(name);
+
+ if (it == mScopeContents.end()) {
+ LOG(WARNING) << "Tried to undefined already undefined value in scope: " << name;
+ return;
+ }
+
+ mScopeContents.erase(it);
+}
+
+template<typename T>
+T Scope<T>::lookup(std::string name) const {
+ auto it = mScopeContents.find(name);
+
+ if (it == mScopeContents.end()) {
+ return NULL;
+ }
+
+ return (*it).second;
+}
+
+} // namespace android
+
+#endif // SCOPE_H_
\ No newline at end of file
diff --git a/c2hal/Type.cpp b/c2hal/Type.cpp
new file mode 100644
index 0000000..28e4618
--- /dev/null
+++ b/c2hal/Type.cpp
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Type.h"
+#include <sstream>
+
+namespace android {
+
+Type::Type(std::vector<Qualifier*> *qualifiers)
+ : mQualifiers(qualifiers)
+ {}
+
+Type::~Type() {
+ delete mArray;
+
+ if(mQualifiers != NULL) {
+ for(auto* qual : *mQualifiers) {
+ delete qual;
+ }
+ }
+ delete mQualifiers;}
+
+
+void Type::setArray(Expression *array) {
+ mArray = array;
+}
+
+const std::string Type::decorateName(const std::string &name) const {
+ std::stringstream ss;
+
+ std::string special = getSpecialTypeName();
+
+ if(special.empty()) {
+ ss << getPreHidlType()
+ << name
+ << getPostHidlType();
+ } else {
+ ss << special
+ << " "
+ << name;
+ }
+
+ return ss.str();
+}
+
+// static
+std::map<std::string, std::string> Type::kCToHidlMap = {
+ { "int", "int32_t" },
+ { "native_handle_t", "handle" },
+
+ // { "hidl_string", "string" },
+ // { "hidl_vec", "vec"},
+};
+
+// static
+const std::string Type::cToHidlType(const std::string &cType) {
+ auto it = kCToHidlMap.find(cType);
+
+ if (it == kCToHidlMap.end()) {
+ return cType;
+ }
+
+ return (*it).second;
+}
+
+const std::string Type::getPreHidlType() const {
+ if (mQualifiers == NULL) {
+ return "";
+ }
+
+ std::stringstream ss;
+
+ for(auto* qualifier : *mQualifiers) {
+ switch(qualifier->qualification) {
+ case Type::Qualifier::STRUCT:
+ case Type::Qualifier::UNION:
+ case Type::Qualifier::ENUM:
+ case Type::Qualifier::POINTER:
+ case Type::Qualifier::CONST:
+ ss << "/* "
+ << Type::qualifierText(qualifier->qualification)
+ << " */ ";
+ break;
+ case Type::Qualifier::ID:
+ ss << cToHidlType(qualifier->id) << " ";
+ break;
+ case Type::Qualifier::GENERICS:
+ ss << "<"
+ << qualifier->generics->decorateName("")
+ << "> ";
+ break;
+ default: {
+ ss << Type::qualifierText(qualifier->qualification)
+ << " ";
+ }
+ }
+ }
+
+ return ss.str();
+}
+
+const std::string Type::getPostHidlType() const {
+ std::stringstream ss;
+
+ if (mArray != NULL) {
+ ss << "[" << mArray->toString() << "]";
+ }
+
+ return ss.str();
+}
+
+const std::string Type::getRawQualifierList() const {
+ if (mQualifiers == NULL) {
+ return "";
+ }
+
+ std::stringstream ss;
+
+ for(auto* qualifier : *mQualifiers) {
+ ss << Type::qualifierText(qualifier->qualification) << " ";
+ }
+
+ return ss.str();
+}
+
+const std::string Type::getSpecialTypeName() const {
+ // this makes for a relatively expensive comparison, but it is
+ // readable until the converstion get nailed down.
+ std::string qualifiers = getRawQualifierList();
+
+ if (qualifiers == "const ID * " ||
+ qualifiers == "ID * ") {
+
+ std::string id = mQualifiers->at(mQualifiers->size() - 2)->id;
+
+ if (id == "char") {
+ return "string";
+ } else {
+ // can't tell if it's a hidl_vec or a pointer
+ // return "vec<" + id + ">";
+ return "";
+ }
+ }
+
+ return "";
+}
+
+bool Type::isVoid() const {
+ if (mQualifiers->size() == 0) {
+ return true;
+ }
+
+ return mQualifiers->size() == 1 &&
+ (*mQualifiers)[0]->qualification == Type::Qualifier::VOID;
+}
+
+
+std::string Type::removeLastId() {
+ if(mQualifiers == NULL || mQualifiers->size() == 0) {
+ return "";
+ }
+
+ Qualifier *last = (*mQualifiers)[mQualifiers->size() - 1];
+
+ if(last == NULL || last->qualification != Qualifier::ID) {
+ return "";
+ }
+
+ std::string ret{last->id};
+
+ mQualifiers->erase(mQualifiers->end() - 1);
+
+ return ret;
+}
+
+} //namespace android
\ No newline at end of file
diff --git a/c2hal/Type.h b/c2hal/Type.h
new file mode 100644
index 0000000..afb1496
--- /dev/null
+++ b/c2hal/Type.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef TYPE_H_
+#define TYPE_H_
+
+#include "Expression.h"
+
+#include <android-base/macros.h>
+#include <android-base/logging.h>
+#include <string>
+#include <vector>
+#include <map>
+
+namespace android {
+
+struct Type {
+
+ struct Qualifier {
+
+ enum Qualification {
+ NONE = 0,
+ STRUCT,
+ UNION,
+ SIGNED,
+ UNSIGNED,
+ VOID,
+ POINTER,
+ CONST,
+ GENERICS,
+ ID,
+ ENUM
+ } qualification;
+
+ union {
+ std::string id;
+ Type *generics;
+ };
+
+ Qualifier(Qualification qualification)
+ : qualification(qualification) {}
+ Qualifier(Qualification qualification, std::string id)
+ : qualification(qualification), id(id) {}
+ Qualifier(Qualification qualification, Type* generics)
+ : qualification(qualification), generics(generics) {}
+
+ ~Qualifier() {
+ if (qualification == GENERICS) {
+ delete generics;
+ }
+ }
+ };
+
+ Type(std::vector<Qualifier*> *qualifiers);
+ ~Type();
+
+ static std::string qualifierText(Qualifier::Qualification qual) {
+ switch(qual) {
+ case Qualifier::STRUCT: return "struct";
+ case Qualifier::UNION: return "union";
+ case Qualifier::ENUM: return "enum";
+ case Qualifier::SIGNED: return "signed";
+ case Qualifier::UNSIGNED: return "unsigned";
+ case Qualifier::VOID: return "void";
+ case Qualifier::POINTER: return "*";
+ case Qualifier::CONST: return "const";
+ case Qualifier::ID: return "ID";
+ case Qualifier::NONE: return "";
+ default: return "/* UNKNOWN TYPE QUALIFIER */";
+ }
+ }
+
+ void setArray(Expression *array);
+
+ const std::string decorateName(const std::string &name) const;
+
+ bool isVoid() const;
+ std::string removeLastId();
+
+private:
+
+ static std::map<std::string, std::string> kCToHidlMap;
+ static const std::string cToHidlType(const std::string &cType);
+
+ const std::string getPreHidlType() const;
+ const std::string getPostHidlType() const;
+
+ const std::string getRawQualifierList() const;
+ const std::string getSpecialTypeName() const;
+
+ std::vector<Qualifier*> *mQualifiers = NULL;
+ Expression *mArray = NULL;
+
+ DISALLOW_COPY_AND_ASSIGN(Type);
+};
+
+} // namespace android
+
+#endif // TYPE_H_
\ No newline at end of file
diff --git a/c2hal/TypeDef.cpp b/c2hal/TypeDef.cpp
new file mode 100644
index 0000000..529bf99
--- /dev/null
+++ b/c2hal/TypeDef.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "TypeDef.h"
+
+namespace android {
+
+TypeDef::TypeDef(const std::string &name, Declaration* declaration)
+ : Declaration(name), mDeclaration(declaration)
+ {}
+
+TypeDef::~TypeDef() {}
+
+void TypeDef::generateSource(Formatter &out) const {
+ out << "typedef ";
+
+ mDeclaration->generateParameterSource(out);
+
+ out << ";\n";
+}
+
+void TypeDef::processContents(AST &ast) {
+ mDeclaration->processContents(ast);
+}
+
+} //namespace android
\ No newline at end of file
diff --git a/c2hal/TypeDef.h b/c2hal/TypeDef.h
new file mode 100644
index 0000000..2f4de5a
--- /dev/null
+++ b/c2hal/TypeDef.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef TYPE_DEF_H_
+#define TYPE_DEF_H_
+
+#include <android-base/macros.h>
+#include <android-base/logging.h>
+#include <string>
+#include <vector>
+#include "Declaration.h"
+
+namespace android {
+
+struct TypeDef : Declaration {
+ TypeDef(const std::string &name, Declaration* declaration);
+ ~TypeDef();
+
+ static std::string type() { return "typedef"; }
+ const std::string decType() const override { return type(); }
+
+ void generateSource(Formatter &out) const override;
+ void processContents(AST &ast) override;
+
+private:
+ Declaration* mDeclaration;
+
+ DISALLOW_COPY_AND_ASSIGN(TypeDef);
+};
+
+} // namespace android
+
+#endif // TYPE_DEF_H_
\ No newline at end of file
diff --git a/c2hal/VarDeclaration.cpp b/c2hal/VarDeclaration.cpp
new file mode 100644
index 0000000..6f5e710
--- /dev/null
+++ b/c2hal/VarDeclaration.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "VarDeclaration.h"
+
+namespace android {
+
+VarDeclaration::VarDeclaration(Type *type, const std::string &name)
+ : Declaration(name),
+ mType(type)
+ {}
+
+VarDeclaration::~VarDeclaration() {
+ delete mType;
+}
+
+Type* VarDeclaration::getType() const {
+ return mType;
+}
+
+void VarDeclaration::generateSource(Formatter &out) const {
+ out << getType()->decorateName(getName())
+ << ";\n";
+}
+
+void VarDeclaration::generateParameterSource(Formatter &out) const {
+ out << getType()->decorateName(getName());
+}
+
+void VarDeclaration::processContents(AST &) {
+ // nothing to do
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/c2hal/VarDeclaration.h b/c2hal/VarDeclaration.h
new file mode 100644
index 0000000..e8ac2b4
--- /dev/null
+++ b/c2hal/VarDeclaration.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef VARDECLARATION_H_
+#define VARDECLARATION_H_
+
+#include "Declaration.h"
+#include "Type.h"
+
+namespace android {
+
+struct VarDeclaration : Declaration{
+ VarDeclaration(Type *type, const std::string &name);
+ ~VarDeclaration();
+
+ Type* getType() const;
+
+ static std::string type() { return "var"; }
+ const std::string decType() const override { return type(); }
+
+ void generateSource(Formatter &out) const override;
+ void generateParameterSource(Formatter &out) const override;
+ void processContents(AST &ast) override;
+
+private:
+ Type *mType;
+
+ DISALLOW_COPY_AND_ASSIGN(VarDeclaration);
+};
+
+} // namespace android
+
+#endif // VARDECLARATION_H_
\ No newline at end of file
diff --git a/c2hal/c2hal_l.ll b/c2hal/c2hal_l.ll
new file mode 100644
index 0000000..089dba6
--- /dev/null
+++ b/c2hal/c2hal_l.ll
@@ -0,0 +1,313 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+D [0-9]
+L [a-zA-Z_]
+AN [a-zA-Z_0-9]
+H [a-fA-F_0-9]
+E [Ee][+-]?{D}+
+FS (f|F|l|L)
+IS (u|U|l|L)*
+S [ \t]
+DOT [.]
+PATH ({DOT}|{AN}|\/|-)+
+ID {L}{AN}*
+
+%{
+
+#include "AST.h"
+#include "Declaration.h"
+#include "Type.h"
+#include "VarDeclaration.h"
+#include "FunctionDeclaration.h"
+#include "CompositeDeclaration.h"
+#include "Define.h"
+#include "Include.h"
+#include "EnumVarDeclaration.h"
+#include "Note.h"
+#include "TypeDef.h"
+#include "Expression.h"
+
+#include <assert.h>
+#include <utils/Errors.h>
+
+#include "c2hal_y.h"
+
+using namespace android;
+
+int check_type(yyscan_t yyscanner, struct yyguts_t *yyg);
+
+// TODO convert to parse params/lex params
+
+extern int start_token;
+
+extern std::string last_comment;
+
+// :(
+extern int numB;
+extern std::string functionText;
+
+extern std::string defineText;
+extern std::string otherText;
+
+extern bool isOpenGl;
+
+#define YY_USER_ACTION yylloc->first_line = yylineno;
+
+#define ID_UNLESS_OPEN_GL(OPEN_GL_CODE) \
+ do { \
+ if (isOpenGl) { \
+ OPEN_GL_CODE \
+ } else { \
+ yylval->str = strdup(yytext); \
+ return ID; \
+ } \
+ } while(0)
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-parameter"
+#pragma clang diagnostic ignored "-Wdeprecated-register"
+
+%}
+
+%option yylineno
+%option reentrant
+%option bison-bridge
+%option bison-locations
+%option extra-type="android::AST *"
+
+%x COMMENT_STATE
+%x INCLUDE_STATE
+%x COPY_DECL_STATE
+%x FUNCTION_STATE
+%x DEFINE_STATE
+%x DEFINE_SLURP_STATE
+
+%%
+%{
+ if (start_token) {
+ int token = start_token;
+ start_token = 0;
+ return token;
+ }
+%}
+
+"\n" { /* needed for yylineno to update */ }
+
+\/\*([^*]|\*+[^*\/])*\*+\/ { last_comment = strdup(yytext); }
+
+"//"[^\r\n]* { /* skip C++ style comment */ }
+
+"__BEGIN_DECLS" { /* macro'd 'extern "C" {' if CPP or nothing */ }
+"__END_DECLS" { /* '}' */ }
+
+"__attribute__((__packed__))" { /* ignore */ }
+"__attribute__((packed))" { /* ignore */ }
+"__attribute__((__deprecated__))" { /* ignore */ }
+
+"EGLAPIENTRYP" { ID_UNLESS_OPEN_GL(return '*';); }
+"EGLAPIENTRY" { ID_UNLESS_OPEN_GL(/* actually is nothing on android */); }
+"GL_APIENTRYP" { ID_UNLESS_OPEN_GL(return '*';); }
+"GL_APIENTRY" { ID_UNLESS_OPEN_GL(/* actually is nothing on android */); }
+"GL_APICALL" { ID_UNLESS_OPEN_GL(/* __attribute__((visibility("default"))) */); }
+
+"#include" { BEGIN(INCLUDE_STATE); return INCLUDE; }
+<INCLUDE_STATE>"<" { return '<'; }
+<INCLUDE_STATE>">" { return '>'; }
+<INCLUDE_STATE>"\"" { return '"'; }
+<INCLUDE_STATE>"\n" { BEGIN(INITIAL); }
+<INCLUDE_STATE>{PATH} { yylval->str = strdup(yytext); return INCLUDE_FILE; }
+<INCLUDE_STATE>. { /* ignore other characters */ }
+
+"static"|"inline" {
+ BEGIN(FUNCTION_STATE);
+ functionText = strdup(yytext);
+ numB = 0;
+ }
+<FUNCTION_STATE>[^{}]+ { functionText += yytext; }
+<FUNCTION_STATE>"{" { functionText += yytext; numB += 1;}
+<FUNCTION_STATE>"}" {
+ functionText += yytext;
+ numB -= 1;
+
+ // Will fail if unbalanced brackets in
+ // strings or comments in the function.
+ if (numB <= 0) {
+ BEGIN(INITIAL);
+ yylval->str = strdup(functionText.c_str());
+ return FUNCTION;
+ }
+ }
+
+"#"{S}*"define" { BEGIN(DEFINE_STATE); return DEFINE; }
+<DEFINE_STATE>{ID} {
+ BEGIN(DEFINE_SLURP_STATE);
+ defineText = "";
+ yylval->str = strdup(yytext);
+ return ID;
+ }
+<DEFINE_STATE>. { /* ignore other characters */ }
+
+<DEFINE_SLURP_STATE>\/\*([^*]|\*+[^*\/])*\*+\/ {
+ defineText += yytext;
+ }
+<DEFINE_SLURP_STATE>[^\\\n] { defineText += yytext; }
+<DEFINE_SLURP_STATE>"\\\n" { defineText += yytext; }
+<DEFINE_SLURP_STATE>"\n" {
+ BEGIN(INITIAL);
+ yylval->str = strdup(defineText.c_str());
+ return DEFINE_SLURP;
+ }
+
+"using" { BEGIN(COPY_DECL_STATE); otherText = strdup(yytext); }
+"#"{S}*{L}+ { BEGIN(COPY_DECL_STATE); otherText = strdup(yytext); }
+<COPY_DECL_STATE>\/\*([^*]|\*+[^*\/])*\*+\/ {
+ otherText += yytext;
+ }
+<COPY_DECL_STATE>[^\\\n] { otherText += yytext; }
+<COPY_DECL_STATE>"\\\n" { otherText += yytext; }
+<COPY_DECL_STATE>"\n" {
+ BEGIN(INITIAL);
+ yylval->str = strdup(otherText.c_str());
+ // decls/macros we want to preserve
+ // in the output, but there is nothing
+ // special to do about them yet
+ return OTHER_STATEMENT;
+ }
+
+"struct" { return STRUCT; }
+"union" { return UNION; }
+"enum" { return ENUM; }
+"const" { return CONST; }
+"typedef" { return TYPEDEF; }
+"void" { return VOID; }
+"unsigned" { return UNSIGNED; }
+"signed" { return SIGNED; }
+"namespace" { return NAMESPACE; }
+"extern" { return EXTERN; }
+"\"C\"" { return C_STRING; }
+
+{ID} { yylval->str = strdup(yytext); return ID; }
+0[xX]{H}+{IS}? { yylval->str = strdup(yytext); return INTEGRAL_VALUE; }
+0{D}+{IS}? { yylval->str = strdup(yytext); return INTEGRAL_VALUE; }
+{D}+{IS}? { yylval->str = strdup(yytext); return INTEGRAL_VALUE; }
+
+{D}+{E}{FS}? { yylval->str = strdup(yytext); return VALUE; }
+{D}+\.{E}?{FS}? { yylval->str = strdup(yytext); return VALUE; }
+{D}*\.{D}+{E}?{FS}? { yylval->str = strdup(yytext); return VALUE; }
+L?\"(\\.|[^\\"])*\" { yylval->str = strdup(yytext); return VALUE; }
+
+"(" { return '('; }
+")" { return ')'; }
+"<" { return '<'; }
+">" { return '>'; }
+"{" { return '{'; }
+"}" { return '}'; }
+"[" { return '['; }
+"]" { return ']'; }
+"?" { return '?'; }
+":" { return ':'; }
+"*" { return '*'; }
+";" { return ';'; }
+"," { return ','; }
+"=" { return '='; }
+"+" { return '+'; }
+"-" { return '-'; }
+"/" { return '/'; }
+"%" { return '%'; }
+"&" { return '&'; }
+"|" { return '|'; }
+"^" { return '^'; }
+"~" { return '~'; }
+"<<" { return LSHIFT; }
+">>" { return RSHIFT; }
+
+"..." { return VARARGS; }
+
+. { /* ignore other characters */ }
+
+%%
+
+#pragma clang diagnostic pop
+
+// allows us to specify what start symbol will be used in the grammar
+int start_token;
+bool should_report_errors;
+
+std::string last_comment;
+
+// this is so frowned upon on so many levels, but here vars are so that we can
+// slurp up function text as a string and don't have to implement
+// the *entire* grammar of C (and C++ in some files) just to parse headers
+int numB;
+std::string functionText;
+
+std::string defineText;
+std::string otherText;
+
+bool isOpenGl;
+
+int yywrap(yyscan_t) {
+ return 1;
+}
+
+status_t parseFile(AST *ast) {
+ FILE *file = fopen(ast->getFilename().c_str(), "rb");
+
+ if (file == NULL) {
+ return -errno;
+ }
+
+ start_token = START_HEADER;
+ isOpenGl = ast->isOpenGl();
+ should_report_errors = true;
+
+ yyscan_t scanner;
+ yylex_init_extra(ast, &scanner);
+ ast->setScanner(scanner);
+
+ yyset_in(file, scanner);
+ int res = yyparse(ast);
+
+ yylex_destroy(scanner);
+ ast->setScanner(NULL);
+
+ fclose(file);
+ file = NULL;
+
+ return res;
+}
+
+status_t parseExpression(AST *ast, std::string str) {
+ start_token = START_EXPR;
+ isOpenGl = ast->isOpenGl();
+ should_report_errors = false;
+
+ yyscan_t scanner;
+ yylex_init_extra(ast, &scanner);
+ ast->setScanner(scanner);
+
+ YY_BUFFER_STATE buf = yy_scan_string(str.c_str(), scanner);
+
+ int res = yyparse(ast);
+
+ yy_delete_buffer(buf, scanner);
+
+ yylex_destroy(scanner);
+ ast->setScanner(NULL);
+
+ return res;
+}
diff --git a/c2hal/c2hal_y.yy b/c2hal/c2hal_y.yy
new file mode 100644
index 0000000..4331025
--- /dev/null
+++ b/c2hal/c2hal_y.yy
@@ -0,0 +1,485 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+%{
+
+#include "AST.h"
+#include "Declaration.h"
+#include "Type.h"
+#include "VarDeclaration.h"
+#include "FunctionDeclaration.h"
+#include "CompositeDeclaration.h"
+#include "Define.h"
+#include "Include.h"
+#include "EnumVarDeclaration.h"
+#include "Note.h"
+#include "TypeDef.h"
+#include "Expression.h"
+
+#include "c2hal_y.h"
+
+#include <stdio.h>
+#include <utils/String8.h>
+#include <algorithm>
+
+using namespace android;
+
+extern int yylex(YYSTYPE *yylval_param, YYLTYPE *llocp, void *);
+
+int yyerror(YYLTYPE *llocp, AST *, const char *s) {
+ extern bool should_report_errors;
+
+ if (!should_report_errors) {
+ return 0;
+ }
+
+ fflush(stdout);
+ LOG(ERROR) << " "
+ << s
+ << " near line "
+ << llocp->first_line;
+
+ return 0;
+}
+
+#define scanner ast->scanner()
+
+std::string get_last_comment() {
+ extern std::string last_comment;
+
+ std::string ret{last_comment};
+
+ // clear the last comment now that it's been taken
+ last_comment = "";
+
+ return ret;
+}
+
+%}
+
+%parse-param { android::AST *ast }
+%lex-param { void *scanner }
+%locations
+%pure-parser
+%glr-parser
+
+%token START_HEADER
+%token START_EXPR
+
+%token STRUCT
+%token UNION
+%token ENUM
+%token CONST
+%token VOID
+%token INCLUDE
+%token DEFINE
+%token TYPEDEF
+%token UNSIGNED
+%token SIGNED
+%token LSHIFT
+%token RSHIFT
+%token VARARGS
+%token NAMESPACE
+%token EXTERN
+%token C_STRING
+
+%left ','
+%right '?' ':'
+%left '|'
+%left '^'
+%left '&'
+%left RSHIFT LSHIFT
+%left '+' '-'
+%left '*' '/' '%'
+%right '~' '!' UMINUS UPLUS
+%left ARRAY_SUBSCRIPT FUNCTION_CALL
+
+%token<str> ID
+%token<str> COMMENT
+%token<str> VALUE
+%token<str> INTEGRAL_VALUE
+%token<str> INCLUDE_FILE
+%token<str> FUNCTION
+%token<str> DEFINE_SLURP
+%token<str> OTHER_STATEMENT
+
+%type<expression> opt_array
+%type<expression> expr
+%type<expressions> args
+%type<type> type
+%type<qualifier> type_qualifier
+%type<qualifiers> type_qualifiers
+%type<declaration> declaration
+%type<declarations> declarations
+%type<composite> struct_or_union_declaration
+%type<composite> enum_declaration
+%type<param> param
+%type<params> params
+%type<qualification> struct_or_union
+%type<str> opt_id
+%type<include> include
+%type<enum_var> enum_var
+%type<declarations> enum_vars
+
+%start parse_selector
+
+%union {
+ const char *str;
+ int count;
+ android::Declaration *declaration;
+ android::CompositeDeclaration *composite;
+ std::vector<android::Declaration *> *declarations;
+ android::EnumVarDeclaration *enum_var;
+ android::Declaration *param;
+ std::vector<android::Declaration *> *params;
+ android::Type *type;
+ android::Type::Qualifier *qualifier;
+ android::Type::Qualifier::Qualification qualification;
+ std::vector<android::Type::Qualifier*> *qualifiers;
+ android::Include *include;
+ std::vector<android::Include *> *includes;
+ android::Expression *expression;
+ std::vector<android::Expression *> *expressions;
+}
+
+%%
+
+parse_selector
+ : START_HEADER header
+ | START_EXPR expr_parser
+ ;
+
+expr_parser
+ : expr
+ {
+ ast->setExpression($1);
+ }
+ ;
+
+header
+ : declarations /* well, we are a header file */
+ {
+ std::reverse($1->begin(), $1->end());
+ ast->setDeclarations($1);
+ }
+ ;
+
+declarations
+ : /* EMPTY */
+ {
+ $$ = new std::vector<Declaration *>;
+ }
+ | declaration declarations
+ {
+ $$ = $2;
+ $$->push_back($1);
+ }
+ | EXTERN C_STRING '{' declarations '}' declarations
+ {
+ $6->push_back(new Note("} // end of extern C"));
+ $6->insert($6->end(), $4->begin(), $4->end());
+ $6->push_back(new Note("extern \"C\" { "));
+ delete $4;
+
+ $$ = $6;
+ }
+ ;
+
+declaration
+ : param ';'
+ {
+ $$ = $1;
+ $$->setComment(get_last_comment());
+ }
+ | struct_or_union_declaration ';'
+ {
+ $$ = $1;
+ }
+ | enum_declaration ';'
+ {
+ $$ = $1;
+ }
+ | TYPEDEF struct_or_union_declaration ';'
+ {
+ // ignore that it is a typedef, for our purposes it doesn't matter
+ $$ = $2;
+ }
+ | TYPEDEF enum_declaration ';'
+ {
+ // ignore that it is a typedef, for our purposes it doesn't matter
+ $$ = $2;
+ }
+ | TYPEDEF param ';' /* looks like 'typedef const int8_t store;' */
+ {
+ $$ = new TypeDef($2->getName(), $2);
+ $$->setComment(get_last_comment());
+ }
+ | DEFINE ID DEFINE_SLURP
+ {
+ $$ = new Define($2, $3);
+ $$->setComment(get_last_comment());
+ }
+ | OTHER_STATEMENT
+ {
+ $$ = new Note($1);
+ $$->setComment(get_last_comment());
+ }
+ | FUNCTION
+ {
+ $$ = new Note($1);
+ $$->setComment(get_last_comment());
+ }
+ | type ID '=' expr ';'
+ {
+ $$ = new Note($1->decorateName($2) + " = " + $4->toString());
+ }
+ | include
+ {
+ $$ = $1;
+ $$->setComment(get_last_comment());
+ }
+ | NAMESPACE ID '{' declarations '}'
+ {
+ $$ = new CompositeDeclaration(Type::Qualifier::STRUCT,
+ $2,
+ $4);
+
+ get_last_comment(); // clear it
+ $$->setComment("/* from namespace declaration */");
+ }
+ ;
+
+include
+ : INCLUDE '<' INCLUDE_FILE '>'
+ {
+ $$ = new Include($3, true /* isLibrary */);
+ }
+ | INCLUDE '"' INCLUDE_FILE '"'
+ {
+ $$ = new Include($3, false /* isLibrary */);
+ }
+ ;
+
+struct_or_union_declaration
+ : struct_or_union opt_id
+ {
+ $<str>$ = strdup(get_last_comment().c_str());
+ }
+ '{' declarations '}' opt_id
+ {
+ std::reverse($5->begin(), $5->end());
+ $$ = new CompositeDeclaration($1, $2, $5);
+ $$->setComment($<str>3);
+
+ if(!std::string($7).empty()) {
+ $$->setName($7);
+ }
+ }
+ ;
+
+enum_declaration
+ : ENUM opt_id
+ {
+ $<str>$ = strdup(get_last_comment().c_str());
+ }
+ '{' enum_vars '}' opt_id
+ {
+ std::reverse($5->begin(), $5->end());
+ $$ = new CompositeDeclaration(Type::Qualifier::ENUM, $2, $5);
+ $$->setComment($<str>3);
+
+ if(!std::string($7).empty()) {
+ $$->setName($7);
+ }
+ }
+ ;
+
+enum_vars
+ : /* EMPTY */
+ {
+ $$ = new std::vector<Declaration *>;
+ }
+ | enum_var /* a comma is optional on the last item */
+ {
+ $$ = new std::vector<Declaration *>;
+ $$->push_back($1);
+ }
+ | enum_var ',' enum_vars
+ {
+ $$ = $3;
+ $$->push_back($1);
+ }
+ ;
+
+enum_var
+ : ID
+ {
+ $$ = new EnumVarDeclaration($1, NULL);
+ $$->setComment(get_last_comment());
+ }
+ | ID '=' expr
+ {
+ $$ = new EnumVarDeclaration($1, $3);
+ $$->setComment(get_last_comment());
+ }
+ ;
+
+params
+ : /* EMPTY */
+ {
+ $$ = new std::vector<Declaration *>;
+ }
+ | param
+ {
+ $$ = new std::vector<Declaration *>;
+ $$->push_back($1);
+ }
+ | param ',' params
+ {
+ $$ = $3;
+ $$->push_back($1);
+ }
+ ;
+
+param
+ : type opt_array
+ {
+ $1->setArray($2);
+
+ // allow for either "const int myvar" or "const int"
+ // as a parameter declaration
+ std::string lastId = $1->removeLastId();
+
+ $$ = new VarDeclaration($1, lastId);
+ }
+ | type '(' '*' ID opt_array ')' '(' params ')'
+ {
+ $1->setArray($5);
+ std::reverse($8->begin(), $8->end());
+ $$ = new FunctionDeclaration($1, $4, $8);
+ }
+ | type ID '(' params ')'
+ {
+ std::reverse($4->begin(), $4->end());
+ $$ = new FunctionDeclaration($1, $2, $4);
+ }
+ | type '(' ID ')' '(' params ')'
+ {
+ std::reverse($6->begin(), $6->end());
+ $$ = new FunctionDeclaration($1, $3, $6);
+ }
+ | VARARGS
+ {
+ $$ = new VarDeclaration(new Type(NULL), "...");
+ }
+ ;
+
+type
+ : type_qualifiers
+ {
+ std::reverse($1->begin(), $1->end());
+ $$ = new Type($1);
+ }
+ ;
+
+type_qualifiers
+ : type_qualifier
+ {
+ $$ = new std::vector<Type::Qualifier *>;
+ $$->push_back($1);
+ }
+ | type_qualifier type_qualifiers
+ {
+ $$ = $2;
+ $$->push_back($1);
+ }
+ ;
+
+opt_id
+ : /* EMPTY */ { $$ = ""; }
+ |
+ ID { $$ = $1; }
+ ;
+
+expr
+ : ID { $$ = Expression::atom(Expression::Type::UNKOWN, $1); }
+ | VALUE { $$ = Expression::atom(Expression::Type::UNKOWN, $1); }
+ | INTEGRAL_VALUE { $$ = Expression::atom(Expression::integralType($1), $1); }
+ | '(' expr ')' { $$ = Expression::parenthesize($2); }
+ | ID '[' expr ']' %prec ARRAY_SUBSCRIPT {
+ $$ = Expression::arraySubscript($1, $3);
+ }
+ | ID '(' args ')' %prec FUNCTION_CALL {
+ std::reverse($3->begin(), $3->end());
+ $$ = Expression::functionCall($1, $3);
+ }
+ | expr '?' expr ':' expr { $$ = Expression::ternary($1, $3, $5); }
+ | expr '+' expr { $$ = Expression::binary($1, "+", $3); }
+ | expr '-' expr { $$ = Expression::binary($1, "-", $3); }
+ | expr '/' expr { $$ = Expression::binary($1, "/", $3); }
+ | expr '*' expr { $$ = Expression::binary($1, "*", $3); }
+ | expr '%' expr { $$ = Expression::binary($1, "%%", $3); }
+ | expr '&' expr { $$ = Expression::binary($1, "&", $3); }
+ | expr '|' expr { $$ = Expression::binary($1, "|", $3); }
+ | expr '^' expr { $$ = Expression::binary($1, "^", $3); }
+ | expr LSHIFT expr { $$ = Expression::binary($1, "<<", $3); }
+ | expr RSHIFT expr { $$ = Expression::binary($1, ">>", $3); }
+ | '~' expr { $$ = Expression::unary("~", $2); }
+ | '-' expr %prec UMINUS { $$ = Expression::unary("-", $2); }
+ | '+' expr %prec UPLUS { $$ = Expression::unary("+", $2); }
+ ;
+
+args
+ : /* empty */
+ {
+ $$ = new std::vector<Expression *>;
+ }
+ | expr
+ {
+ $$ = new std::vector<Expression *>;
+ $$->push_back($1);
+ }
+ | expr ',' args
+ {
+ $$ = $3;
+ $$->push_back($1);
+ }
+ ;
+
+type_qualifier
+ : UNSIGNED { $$ = new Type::Qualifier(Type::Qualifier::UNSIGNED); }
+ | SIGNED { $$ = new Type::Qualifier(Type::Qualifier::SIGNED); }
+ | VOID { $$ = new Type::Qualifier(Type::Qualifier::VOID); }
+ | '*' { $$ = new Type::Qualifier(Type::Qualifier::POINTER); }
+ | CONST { $$ = new Type::Qualifier(Type::Qualifier::CONST); }
+ | ID { $$ = new Type::Qualifier(Type::Qualifier::ID, $1); }
+ | '<' type '>' { $$ = new Type::Qualifier(Type::Qualifier::GENERICS, $2); }
+ | ENUM { $$ = new Type::Qualifier(Type::Qualifier::ENUM); }
+ | struct_or_union { $$ = new Type::Qualifier($1); }
+ ;
+
+struct_or_union
+ : STRUCT { $$ = android::Type::Qualifier::STRUCT; }
+ | UNION { $$ = android::Type::Qualifier::UNION; }
+ ;
+
+opt_array
+ : /* empty */ { $$ = NULL; }
+ | '[' ']' { $$ = Expression::atom(Expression::Type::UNKOWN, " "); }
+ | '[' expr ']' { $$ = $2; }
+ ;
+
+%%
\ No newline at end of file
diff --git a/c2hal/main.cpp b/c2hal/main.cpp
new file mode 100644
index 0000000..d8603f3
--- /dev/null
+++ b/c2hal/main.cpp
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "AST.h"
+
+#include <android-base/logging.h>
+#include <android-base/macros.h>
+#include <set>
+#include <map>
+#include <stdio.h>
+#include <string>
+#include <unistd.h>
+#include <vector>
+#include <utils/Errors.h>
+
+using namespace android;
+
+extern status_t parseFile(android::AST *ast);
+
+static void usage(const char *me) {
+ fprintf(stderr,
+ "usage: %s [-g] -o dir -p package (-r interface-root)+ (header-filepath)+\n",
+ me);
+
+ fprintf(stderr, " -o output path\n");
+ fprintf(stderr, " (example: ~/android/master)\n");
+ fprintf(stderr, " -p package\n");
+ fprintf(stderr, " (example: android.hardware.baz@1.0)\n");
+ fprintf(stderr, " -g (enable open-gl mode) \n");
+ fprintf(stderr, " -r package:path root "
+ "(e.g., android.hardware:hardware/interfaces)\n");
+}
+
+static void addPackageRootToMap(const std::string &val,
+ std::map<std::string, std::string> &packageRootPaths) {
+ auto index = val.find_first_of(':');
+ CHECK(index != std::string::npos);
+
+ auto package = val.substr(0, index);
+ auto path = val.substr(index + 1);
+
+ packageRootPaths[package] = path;
+}
+
+static bool isPathPrefix(const std::string &prefix, const std::string &base) {
+ if (prefix.size() >= base.size()) {
+ LOG(INFO) << "Not long enough";
+ return false;
+ }
+
+ if (base[prefix.size()] != '.') {
+ LOG(INFO) << "not full";
+ return false;
+ }
+
+ return prefix == base.substr(0, prefix.size());
+}
+
+static void applyPackageRootPath(
+ const std::map<std::string, std::string> &packageRootPaths,
+ const std::string &package,
+ std::string &outputPath) {
+
+ auto index = package.find_first_of('@');
+ CHECK(index != std::string::npos);
+
+ auto packagePath = package.substr(0, index);
+ auto packageVersion = package.substr(index + 1);
+
+ for (auto const& pair : packageRootPaths) {
+ const std::string& rootPackage = pair.first;
+ const std::string& rootPath = pair.second;
+
+ if (isPathPrefix(rootPackage, packagePath)) {
+
+ packagePath = packagePath.substr(rootPackage.size() + 1);
+ std::replace(packagePath.begin(), packagePath.end(), '.', '/');
+ packagePath += '/' + packageVersion;
+
+ if (outputPath.empty()) {
+ outputPath = rootPath;
+ }
+
+ outputPath += '/' + packagePath + '/';
+ return;
+ }
+ }
+
+ CHECK(false) << "No package root path provided for package: " << package;
+}
+
+int main(int argc, char **argv) {
+ const char *me = argv[0];
+
+ std::string outputDir;
+ std::string package;
+ std::map<std::string, std::string> packageRootPaths;
+ bool isOpenGl = false;
+
+ int res;
+ while ((res = getopt(argc, argv, "gho:p:r:")) >= 0) {
+ switch (res) {
+ case 'o': {
+ outputDir = optarg;
+ break;
+ }
+ case 'p': {
+ package = optarg;
+ break;
+ }
+ case 'g': {
+ isOpenGl = true;
+ break;
+ }
+ case 'r':
+ {
+ addPackageRootToMap(optarg, packageRootPaths);
+ break;
+ }
+ case 'h':
+ default:
+ {
+ LOG(INFO) << "UNKOWN ARGUMENT: " << optarg;
+ usage(me);
+ exit(1);
+ break;
+ }
+ }
+ }
+
+ // if no arguments are provided, show usage instead of specific errors
+ if (optind == 1) {
+ usage(me);
+ exit(0);
+ }
+
+ applyPackageRootPath(packageRootPaths, package, outputDir);
+
+ if (package.empty()) {
+ LOG(WARNING) << "You must provide a package.";
+ usage(me);
+ exit(0);
+ }
+
+ if (optind == argc) {
+ LOG(WARNING) << "You must provide a header-filepath.";
+ usage(me);
+ exit(0);
+ }
+
+ for(int i = optind; i < argc; i++) {
+ std::string path = argv[i];
+
+ LOG(INFO) << "Processing " << path;
+
+ AST ast(path, outputDir, package, isOpenGl);
+
+ int res = parseFile(&ast);
+
+ if (res != 0) {
+ LOG(ERROR) << "Could not parse: " << res;
+ exit(1);
+ }
+
+ ast.processContents();
+
+ ast.generateCode();
+ }
+
+ return 0;
+}
diff --git a/c2hal/test/build_all.py b/c2hal/test/build_all.py
new file mode 100644
index 0000000..b9faf0b
--- /dev/null
+++ b/c2hal/test/build_all.py
@@ -0,0 +1,87 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+
+from os import listdir
+from os.path import isfile, join as path_join
+from subprocess import call
+import argparse
+
+def main():
+ """this python program tries to build all hardware interfaces from a directory"""
+
+ args = parseArgs()
+
+ path = args.path
+ is_open_gl = args.g
+
+ success, failure = genFiles(path, is_open_gl)
+
+ print("Success: ", ", ".join(success))
+ print("Failure: ", ", ".join(failure))
+
+ ratio = len(success) / (len(success) + len(failure))
+
+ print("%% success = %.2f" % (100 * ratio))
+
+def parseArgs():
+ parser = argparse.ArgumentParser()
+ parser.add_argument("path", help="location of headers to parse", type=str)
+ parser.add_argument("-g", help="enable opengl specific parsing", action="store_true")
+
+ return parser.parse_args()
+
+def genFiles(path, is_open_gl):
+ success = []
+ failure = []
+
+ for header in sorted(headers(path)):
+ fname = header[:-2]
+
+ command = ["c2hal",
+ "-r", "android.hardware:hardware/interfaces",
+ "-p", "android.hardware." + fname + "@1.0"]
+
+ if is_open_gl:
+ command += ["-g"]
+
+ command += [path_join(path, header)]
+
+ res = call(command)
+
+ if res == 0:
+ success += [header]
+ else:
+ failure += [header]
+
+ return success, failure
+
+def headers(path):
+ """all .h files in a directory"""
+ for item in listdir(path):
+ if not isfile(path_join(path, item)):
+ continue
+
+ if not item.endswith(".h"):
+ continue
+
+ yield item
+
+
+
+if __name__ == "__main__":
+ main()
\ No newline at end of file
diff --git a/c2hal/test/simple.h b/c2hal/test/simple.h
new file mode 100644
index 0000000..7f5f69c
--- /dev/null
+++ b/c2hal/test/simple.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SIMPLE_H
+#define SIMPLE_H
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <cutils/native_handle.h>
+
+#include <hardware/hardware.h>
+
+__BEGIN_DECLS
+
+#define FORGROUND_COLOR "#133742"
+#define ACTOR_COLOR "#424242"
+
+/* Simple example */
+typedef struct simple_t {
+ /**
+ * Common methods of the simple device.
+ */
+ struct hw_device_t common;
+
+ /* resolution of the framebuffer's display panel in pixel per inch*/
+ const float xdpi;
+ const float ydpi;
+
+ /* framebuffer's display panel refresh rate in frames per second */
+ const float fps;
+
+ int (*setSwapInterval)(struct simple_t* window,
+ int interval);
+
+ /*
+ * This hook is OPTIONAL.
+ */
+ int (*setUpdateRect)(struct simple_t* window,
+ int left, int top, int width, int height);
+
+} simple_t;
+
+/* Holds pixel coordinates */
+typedef struct {
+ int px;
+ int py;
+
+ /*
+ * If non NULL it will be caused by SurfaceFlinger on dumpsys
+ */
+ void (*dump)(struct simple_t* dev, char *buff, int buff_len);
+
+} simple_location_t;
+
+/** convenience API for coloring */
+
+static inline int showColor(const struct hw_module_t* module,
+ struct simple_t** device) {
+ return module->methods->open(module,
+ FORGROUND_COLOR, (struct simple_t**)device);
+}
+
+static inline int hideColor(struct simple_t* device) {
+ return device->common.close(&device->common);
+}
+
+__END_DECLS
+
+#endif // SIMPLE_H
diff --git a/c2hal/test/test.h b/c2hal/test/test.h
new file mode 100644
index 0000000..8746cfa
--- /dev/null
+++ b/c2hal/test/test.h
@@ -0,0 +1,337 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_FB_INTERFACE_H
+#define ANDROID_FB_INTERFACE_H
+
+
+#include <onelib>
+#include <there/somelib.h>
+#include "mylib.h"
+
+__BEGIN_DECLS
+
+// comments
+
+#define MY_DEFINE 1 \
+ + 1
+#define META(thing1, thing2) thing1 + thing2
+#define VERSION HARDWARE_MODULE_API_VERSION(0, 1)
+#define ONE 1 /* got to
+ get rid of magic numbers */
+
+/* test */
+/** test */
+/* test **/
+/* test / ** ** / test */
+/* test //// ***** test /****/
+
+#define a 1l
+#define b 1l + 2ll
+#define c 1ul + 1l
+#define d 2 + 1l
+#define e 3 + 1ll
+#define f 4 + 3ul
+#define g 1l + 3
+#define h 32u
+#define i 64ull
+#define j 2 + a
+#define k 1u
+#define l k + 1l
+
+/*****************************************************************************/
+typedef enum {
+ A = 47,
+ /* B is a very important value */
+ B,
+ C = 1 + test(19) + test2[21],
+ D = 1 ? 1 : 2
+} onehere;
+
+inline std::string to_string(T value) { return to_string(static_cast<E>(value)); }
+
+const res_t RESULT_ACCESS_DENIED = ~2 | -1;
+const res_t RESULT_INVALID_PARAMETER = 54;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static void fun1() { }
+
+namespace MyNamespace {
+ static void fun2() { }
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+static void fun3() { test; }
+static void fun4() { test; }
+
+#undef ONE
+
+/*****************************************************************************/
+typedef void (*no_arg_fun)(void);
+
+typedef int (*other_fun)(int j);
+
+typedef void (*alarm_cb)(void *data);
+
+typedef void (*special_types)(const native_handle_t* a, int b);
+
+typedef foo_t bar_t;
+
+struct baz_t;
+
+typedef pthread_t (* fun_with_funs)(void (*my_fun)(void *), void* arg);
+
+int (*global_fun_1)(struct framebuffer_device_t* dev, int enable);
+int (*global_fun_2)(struct framebuffer_device_t* dev, int enable);
+
+typedef struct framebuffer_device_t {
+ /**
+ * Common methods of the framebuffer device.
+ */
+ struct hw_device_t common;
+
+ typedef enum another_here {
+ A = 3 | 4,
+ B,
+ C = 4
+ } another_here;
+
+ /* anon struct */
+ struct {
+ float b;
+ };
+
+ struct not_type_defd {
+ double latitude[];
+ double halfLongitude;
+ };
+
+ /* flags describing some attributes of the framebuffer */
+ const uint32_t flags;
+
+ /* dimensions of the framebuffer in pixels */
+ const uint32_t width;
+ const uint32_t height;
+
+ /* frambuffer stride in pixels */
+ const int stride;
+
+ /* framebuffer pixel format */
+ const int format;
+
+ /* resolution of the framebuffer's display panel in pixel per inch*/
+ const float xdpi;
+ const float ydpi;
+
+ /* framebuffer's display panel refresh rate in frames per second */
+ const float fps;
+
+ /* min swap interval supported by this framebuffer */
+ const int minSwapInterval;
+
+ /* max swap interval supported by this framebuffer */
+ const int maxSwapInterval;
+
+ /* Number of framebuffers supported*/
+ const int numFramebuffers;
+
+ int reserved[7];
+
+ /*
+ * requests a specific swap-interval (same definition than EGL)
+ *
+ * Returns 0 on success or -errno on error.
+ */
+ int (*setSwapInterval)(struct framebuffer_device_t* window,
+ int interval);
+
+ /*
+ * This hook is OPTIONAL.
+ *
+ * It is non NULL If the framebuffer driver supports "update-on-demand"
+ * and the given rectangle is the area of the screen that gets
+ * updated during (*post)().
+ *
+ * This is useful on devices that are able to DMA only a portion of
+ * the screen to the display panel, upon demand -- as opposed to
+ * constantly refreshing the panel 60 times per second, for instance.
+ *
+ * Only the area defined by this rectangle is guaranteed to be valid, that
+ * is, the driver is not allowed to post anything outside of this
+ * rectangle.
+ *
+ * The rectangle evaluated during (*post)() and specifies which area
+ * of the buffer passed in (*post)() shall to be posted.
+ *
+ * return -EINVAL if width or height <=0, or if left or top < 0
+ */
+ int (*setUpdateRect)(struct framebuffer_device_t* window,
+ int left, int top, int width, int height);
+
+ /*
+ * Post <buffer> to the display (display it on the screen)
+ * The buffer must have been allocated with the
+ * GRALLOC_USAGE_HW_FB usage flag.
+ * buffer must be the same width and height as the display and must NOT
+ * be locked.
+ *
+ * The buffer is shown during the next VSYNC.
+ *
+ * If the same buffer is posted again (possibly after some other buffer),
+ * post() will block until the the first post is completed.
+ *
+ * Internally, post() is expected to lock the buffer so that a
+ * subsequent call to gralloc_module_t::(*lock)() with USAGE_RENDER or
+ * USAGE_*_WRITE will block until it is safe; that is typically once this
+ * buffer is shown and another buffer has been posted.
+ *
+ * Returns 0 on success or -errno on error.
+ */
+ int (*post)(struct framebuffer_device_t* dev, buffer_handle_t buffer);
+
+
+ /*
+ * The (*compositionComplete)() method must be called after the
+ * compositor has finished issuing GL commands for client buffers.
+ */
+
+ int (*compositionComplete)(struct framebuffer_device_t* dev);
+
+ /*
+ * This hook is OPTIONAL.
+ *
+ * If non NULL it will be caused by SurfaceFlinger on dumpsys
+ */
+ void (*dump)(struct framebuffer_device_t* dev, char *buff, int buff_len);
+
+ /*
+ * (*enableScreen)() is used to either blank (enable=0) or
+ * unblank (enable=1) the screen this framebuffer is attached to.
+ *
+ * Returns 0 on success or -errno on error.
+ */
+ int (*enableScreen)(struct framebuffer_device_t* dev, int enable);
+
+ void* reserved_proc[6];
+
+} framebuffer_device_t;
+
+typedef int context_hub_callback(uint32_t hub_id, const struct hub_message_t *rxed_msg, void *cookie);
+
+typedef struct my_other_t {
+
+ int (*store_meta_data_in_buffers)(struct camera_device *, int enable);
+
+ typedef void (*scan_result_callback)(bt_bdaddr_t* bda, int rssi, vector<uint8_t> adv_data);
+
+ pthread_t (* gps_create_thread)(const char* name, void (*start)(void *), void* arg);
+
+ int (*p1)(struct framebuffer_device_t* dev);
+
+ void (*p2)(struct framebuffer_device_t* dev, char *buff, int buff_len);
+
+ int (*p3)(struct framebuffer_device_t* dev, int enable);
+
+
+ int (*get_supported_activities_list)(struct activity_recognition_module* module,
+ char const* const* *activity_list);
+
+ int (*read_energy_info)();
+ void (*reserved_procs[16 - 4])(void);
+
+} my_other_t;
+
+#define another 4
+
+typedef struct {
+ /** set to sizeof(GpsCallbacks_v1) */
+ size_t size;
+ gps_location_callback location_cb;
+ gps_status_callback status_cb;
+ gps_sv_status_callback sv_status_cb;
+ gps_nmea_callback nmea_cb;
+ gps_set_capabilities set_capabilities_cb;
+ gps_acquire_wakelock acquire_wakelock_cb;
+ gps_release_wakelock release_wakelock_cb;
+ gps_create_thread create_thread_cb;
+ gps_request_utc_time request_utc_time_cb;
+} __attribute__((packed)) GpsCallbacks_v1;
+
+typedef struct one_name {
+ float a;
+} another_name;
+
+typedef struct this_t {
+ int hello;
+} this_t;
+
+typedef union that_t {
+ float a;
+ float c;
+} that_t;
+
+/**
+ * return the frame size (number of bytes per sample) of an output stream.
+ */
+static inline size_t audio_stream_out_frame_size(const struct audio_stream_out *s)
+{
+ size_t chan_samp_sz;
+ audio_format_t format = s->common.get_format(&s->common);
+
+ if (audio_has_proportional_frames(format)) {
+ chan_samp_sz = audio_bytes_per_sample(format);
+ return audio_channel_count_from_out_mask(s->common.get_channels(&s->common)) * chan_samp_sz;
+ }
+
+ return sizeof(int8_t);
+}
+
+/* effective and commanding */
+enum effect_command_e {
+ EFFECT_CMD_INIT, // initialize effect engine
+ EFFECT_CMD_SET_CONFIG, // configure effect engine (see effect_config_t)
+ EFFECT_CMD_RESET, // reset effect engine
+ EFFECT_CMD_ENABLE, // enable effect process
+ EFFECT_CMD_DISABLE, // disable effect process
+ EFFECT_CMD_SET_PARAM, // set parameter immediately (see effect_param_t)
+ EFFECT_CMD_SET_PARAM_DEFERRED, // set parameter deferred
+ EFFECT_CMD_SET_PARAM_COMMIT, // commit previous set parameter deferred
+ EFFECT_CMD_GET_PARAM, // get parameter
+ EFFECT_CMD_SET_DEVICE, // set audio device (see audio.h, audio_devices_t)
+ EFFECT_CMD_SET_VOLUME, // set volume
+ EFFECT_CMD_SET_AUDIO_MODE, // set the audio mode (normal, ring, ...)
+ EFFECT_CMD_SET_CONFIG_REVERSE, // configure effect engine reverse stream(see effect_config_t)
+ EFFECT_CMD_SET_INPUT_DEVICE, // set capture device (see audio.h, audio_devices_t)
+ EFFECT_CMD_GET_CONFIG, // read effect engine configuration
+ EFFECT_CMD_GET_CONFIG_REVERSE, // read configure effect engine reverse stream configuration
+ EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS,// get all supported configurations for a feature.
+ EFFECT_CMD_GET_FEATURE_CONFIG, // get current feature configuration
+ EFFECT_CMD_SET_FEATURE_CONFIG, // set current feature configuration
+ EFFECT_CMD_SET_AUDIO_SOURCE, // set the audio source (see audio.h, audio_source_t)
+ EFFECT_CMD_OFFLOAD, // set if effect thread is an offload one,
+ // send the ioHandle of the effect thread
+ EFFECT_CMD_FIRST_PROPRIETARY = 0x10000 // first proprietary command code
+};
+
+__END_DECLS
+
+#endif
\ No newline at end of file
diff --git a/generateCpp.cpp b/generateCpp.cpp
index e472245..57ed349 100644
--- a/generateCpp.cpp
+++ b/generateCpp.cpp
@@ -49,6 +49,10 @@
}
if (err == OK) {
+ err = generateHwBinderHeader(outputPath);
+ }
+
+ if (err == OK) {
err = generateProxyHeader(outputPath);
}
@@ -158,10 +162,9 @@
}
out << "#include <hidl/HidlSupport.h>\n";
+ out << "#include <hidl/IServiceManager.h>\n";
if (isInterface) {
- out << "#include <hwbinder/IBinder.h>\n";
- out << "#include <hwbinder/IInterface.h>\n";
out << "#include <hwbinder/Status.h>\n";
}
@@ -170,28 +173,27 @@
enterLeaveNamespace(out, true /* enter */);
out << "\n";
+ // cut off the leading 'I'.
+ const std::string baseName = ifaceName.substr(1);
+
if (isInterface) {
out << "struct "
- << ifaceName
- << " : public ";
+ << ifaceName;
const Interface *iface = mRootScope->getInterface();
const Interface *superType = iface->superType();
- if (superType != NULL) {
- out << superType->fullName();
+ if (superType == NULL) {
+ out << " : virtual public RefBase";
} else {
- out << "::android::hardware::IInterface";
+ out << " : public "
+ << superType->fullName();
}
out << " {\n";
out.indent();
- // cut off the leading 'I'.
- const std::string baseName = ifaceName.substr(1);
-
- out << "DECLARE_HWBINDER_META_INTERFACE(" << baseName << ");\n\n";
}
status_t err = emitTypeDeclarations(out);
@@ -204,33 +206,7 @@
const Interface *iface = mRootScope->getInterface();
const Interface *superType = iface->superType();
- out << "enum Call {\n";
- out.indent();
-
- bool first = true;
- for (const auto &method : iface->methods()) {
- out << upcase(method->name());
-
- if (first) {
- out << " = ";
- if (superType != NULL) {
- out << superType->fullName()
- << "::Call::CallCount";
- } else {
- out << "::android::hardware::IBinder::FIRST_CALL_TRANSACTION";
- }
-
- first = false;
- }
-
- out << ",\n";
- }
-
- out << "CallCount\n";
-
- out.unindent();
- out << "};\n\n";
-
+ out << "virtual bool isRemote() const { return false; } \n\n";
bool haveCallbacks = false;
for (const auto &method : iface->methods()) {
const bool returnsValue = !method->results().empty();
@@ -284,6 +260,8 @@
out << ") = 0;\n";
}
+
+ out << "DECLARE_REGISTER_AND_GET_SERVICE(" << baseName << ")\n";
}
if (isInterface) {
@@ -300,12 +278,143 @@
return OK;
}
+status_t AST::generateHwBinderHeader(const std::string &outputPath) const {
+ std::string ifaceName;
+ if(!AST::isInterface(&ifaceName)) {
+ // types.hal does not get an HwBinder header.
+ return OK;
+ }
+
+ // cut off the leading 'I'.
+ const std::string baseName = ifaceName.substr(1);
+
+ const std::string klassName = "IHw" + baseName;
+
+ std::string path = outputPath;
+ path.append(mCoordinator->convertPackageRootToPath(mPackage));
+ path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
+ path.append(klassName + ".h");
+
+ FILE* file = fopen(path.c_str(), "w");
+
+ if (file == NULL) {
+ return -errno;
+ }
+
+ Formatter out(file);
+
+ const std::string guard = makeHeaderGuard(klassName);
+
+ 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";
+
+ for (const auto &item : mImportedNames) {
+ if (item.name() == "types") {
+ continue;
+ }
+
+ out << "#include <";
+
+ std::vector<std::string> components;
+ item.getPackageAndVersionComponents(
+ &components, false /* cpp_compatible */);
+
+ for (const auto &component : components) {
+ out << component << "/";
+ }
+
+ // cut off the leading I
+ const std::string itemBaseName = item.name().substr(1);
+
+ out << "Bn"
+ << itemBaseName
+ << ".h>\n";
+ }
+
+ out << "\n";
+
+ out << "#include <hidl/HidlSupport.h>\n";
+ out << "#include <hwbinder/IBinder.h>\n";
+ out << "#include <hwbinder/IInterface.h>\n";
+ out << "#include <hwbinder/Status.h>\n";
+
+ out << "\n";
+
+ enterLeaveNamespace(out, true /* enter */);
+ out << "\n";
+
+ out << "struct "
+ << klassName
+ << " : public "
+ << ifaceName;
+
+ const Interface *iface = mRootScope->getInterface();
+ const Interface *superType = iface->superType();
+
+ out << ", public ::android::hardware::IInterface";
+
+ out << " {\n";
+
+ out.indent();
+
+ out << "DECLARE_HWBINDER_META_INTERFACE(" << baseName << ");\n\n";
+
+ out << "enum Call {\n";
+ out.indent();
+
+ bool first = true;
+ for (const auto &method : iface->methods()) {
+ out << upcase(method->name());
+
+ if (first) {
+ out << " = ";
+ if (superType != NULL) {
+ out << superType->fqName().cppNamespace()
+ << "::IHw"
+ << superType->getBaseName()
+ << "::Call::CallCount";
+ } else {
+ out << "::android::hardware::IBinder::FIRST_CALL_TRANSACTION";
+ }
+
+ first = false;
+ }
+
+ out << ",\n";
+ }
+
+ out << "CallCount\n";
+
+ out.unindent();
+ out << "};\n\n";
+
+ out.unindent();
+
+ out << "};\n\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::generateHeaderMethodSignatures(
- Formatter &out, bool abstract) const {
+ Formatter &out, bool stub) const {
const Interface *iface = mRootScope->getInterface();
std::vector<const Interface *> chain;
@@ -322,6 +431,9 @@
<< " follow.\n";
for (const auto &method : superInterface->methods()) {
+ if (stub) {
+ out << "inline ";
+ }
const bool returnsValue = !method->results().empty();
const TypedVar *elidedReturn = method->canElideCallback();
@@ -346,7 +458,33 @@
}
out << ") ";
- out << (abstract ? "= 0" : "override");
+ if (stub) {
+ out << " {\n";
+ out.indent();
+ out << "return mImpl->"
+ << method->name()
+ << "(";
+ bool first = true;
+ for (const auto &arg : method->args()) {
+ if (!first) {
+ out << ", ";
+ }
+ first = false;
+ out << arg->name();
+ }
+ if (returnsValue && elidedReturn == nullptr) {
+ if (!method->args().empty()) {
+ out << ", ";
+ }
+
+ out << "_hidl_cb";
+ }
+ out << ");\n";
+ out.unindent();
+ out << "}";
+ } else {
+ out << "override";
+ }
out << ";\n";
}
@@ -365,12 +503,12 @@
// cut off the leading 'I'.
const std::string baseName = ifaceName.substr(1);
+ const std::string klassName = "Bn" + baseName;
std::string path = outputPath;
path.append(mCoordinator->convertPackageRootToPath(mPackage));
path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
- path.append("Bn");
- path.append(baseName);
+ path.append(klassName);
path.append(".h");
CHECK(Coordinator::MakeParentHierarchy(path));
@@ -382,7 +520,7 @@
Formatter out(file);
- const std::string guard = makeHeaderGuard("Bn" + baseName);
+ const std::string guard = makeHeaderGuard(klassName);
out << "#ifndef " << guard << "\n";
out << "#define " << guard << "\n\n";
@@ -395,7 +533,7 @@
for (const auto &component : packageComponents) {
out << component << "/";
}
- out << ifaceName << ".h>\n\n";
+ out << "IHw" << baseName << ".h>\n\n";
enterLeaveNamespace(out, true /* enter */);
out << "\n";
@@ -403,12 +541,15 @@
out << "struct "
<< "Bn"
<< baseName
- << " : public ::android::hardware::BnInterface<"
- << ifaceName
+ << " : public ::android::hardware::BnInterface<I"
+ << baseName << ", IHw" << baseName
<< "> {\n";
out.indent();
-
+ out << "explicit Bn"
+ << baseName
+ << "(const ::android::sp<" << ifaceName << "> &_hidl_impl);"
+ << "\n\n";
out << "::android::status_t onTransact(\n";
out.indent();
out.indent();
@@ -420,8 +561,7 @@
out.unindent();
out.unindent();
- generateHeaderMethodSignatures(out, true); // = 0
-
+ generateHeaderMethodSignatures(out, true); // stub
out.unindent();
out << "};\n\n";
@@ -472,7 +612,7 @@
for (const auto &component : packageComponents) {
out << component << "/";
}
- out << ifaceName << ".h>\n\n";
+ out << "IHw" << baseName << ".h>\n\n";
enterLeaveNamespace(out, true /* enter */);
out << "\n";
@@ -480,8 +620,8 @@
out << "struct "
<< "Bp"
<< baseName
- << " : public ::android::hardware::BpInterface<"
- << ifaceName
+ << " : public ::android::hardware::BpInterface<IHw"
+ << baseName
<< "> {\n";
out.indent();
@@ -491,7 +631,9 @@
<< "(const ::android::sp<::android::hardware::IBinder> &_hidl_impl);"
<< "\n\n";
- generateHeaderMethodSignatures(out, false); // override
+ out << "virtual bool isRemote() const { return true; } \n\n";
+
+ generateHeaderMethodSignatures(out, false); // proxy
out.unindent();
@@ -570,6 +712,10 @@
err = generateStubSource(out, baseName);
}
+ if (err == OK && isInterface) {
+ out << "IMPLEMENT_REGISTER_AND_GET_SERVICE(" << baseName << ")\n";
+ }
+
enterLeaveNamespace(out, false /* enter */);
return err;
@@ -631,7 +777,7 @@
out.indent();
out << ": BpInterface"
- << "<I"
+ << "<IHw"
<< baseName
<< ">(_hidl_impl) {\n";
@@ -684,12 +830,13 @@
out << "::android::hardware::Parcel _hidl_reply;\n";
out << "::android::status_t _hidl_err;\n";
out << "::android::hardware::Status _hidl_status;\n\n";
-
declareCppReaderLocals(out, method->results());
out << "_hidl_err = _hidl_data.writeInterfaceToken("
- << superInterface->fullName()
- << "::getInterfaceDescriptor());\n";
+ << superInterface->fqName().cppNamespace()
+ << "::IHw"
+ << superInterface->getBaseName()
+ << "::descriptor);\n";
out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
@@ -703,9 +850,11 @@
Type::ErrorMode_Goto);
}
- out << "_hidl_err = remote()->transact(I"
- << baseName
- << "::"
+ out << "_hidl_err = remote()->transact("
+ << superInterface->fqName().cppNamespace()
+ << "::IHw"
+ << superInterface->getBaseName()
+ << "::Call::"
<< upcase(method->name())
<< ", _hidl_data, &_hidl_reply";
if (method->isOneway()) {
@@ -798,6 +947,25 @@
const std::string klassName = "Bn" + baseName;
+ out << klassName
+ << "::"
+ << klassName
+ << "(const ::android::sp<I" << baseName <<"> &_hidl_impl)\n";
+
+ out.indent();
+ out.indent();
+
+ out << ": BnInterface"
+ << "<I"
+ << baseName
+ << ", IHw"
+ << baseName
+ << ">(_hidl_impl) {\n";
+
+ out.unindent();
+ out.unindent();
+ out << "}\n\n";
+
out << "::android::status_t " << klassName << "::onTransact(\n";
out.indent();
@@ -812,7 +980,6 @@
out.unindent();
out << "::android::status_t _hidl_err = ::android::OK;\n\n";
-
out << "switch (_hidl_code) {\n";
out.indent();
@@ -829,7 +996,9 @@
for (const auto &method : superInterface->methods()) {
out << "case "
- << superInterface->fullName()
+ << superInterface->fqName().cppNamespace()
+ << "::IHw"
+ << superInterface->getBaseName()
<< "::Call::"
<< upcase(method->name())
<< ":\n{\n";
@@ -852,7 +1021,7 @@
out.indent();
out << "return ::android::hardware::BnInterface<I"
- << baseName
+ << baseName << ", IHw" << baseName
<< ">::onTransact(\n";
out.indent();
@@ -898,8 +1067,10 @@
status_t AST::generateStubSourceForMethod(
Formatter &out, const Interface *iface, const Method *method) const {
out << "if (!_hidl_data.enforceInterface("
- << iface->fullName()
- << "::getInterfaceDescriptor())) {\n";
+ << iface->fqName().cppNamespace()
+ << "::IHw"
+ << iface->getBaseName()
+ << "::descriptor)) {\n";
out.indent();
out << "_hidl_err = ::android::BAD_TYPE;\n";
diff --git a/generateJava.cpp b/generateJava.cpp
index f10ae92..a3c4761 100644
--- a/generateJava.cpp
+++ b/generateJava.cpp
@@ -51,7 +51,8 @@
arg->type().emitJavaReaderWriter(out, parcelObj, arg->name(), isReader);
}
-status_t AST::generateJavaTypes(const std::string &outputPath) const {
+status_t AST::generateJavaTypes(
+ const std::string &outputPath, const char *limitToType) const {
// Splits types.hal up into one java file per declared type.
for (size_t i = 0; i < mRootScope->countTypes(); ++i) {
@@ -62,6 +63,10 @@
continue;
}
+ if ((limitToType != nullptr) && typeName != limitToType) {
+ continue;
+ }
+
std::string path = outputPath;
path.append(mCoordinator->convertPackageRootToPath(mPackage));
path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));
@@ -99,14 +104,9 @@
return OK;
}
-status_t AST::generateJava(const std::string &outputPath) const {
- std::string ifaceName;
- if (!AST::isInterface(&ifaceName)) {
- return generateJavaTypes(outputPath);
- }
-
- const Interface *iface = mRootScope->getInterface();
- if (!iface->isJavaCompatible()) {
+status_t AST::generateJava(
+ const std::string &outputPath, const char *limitToType) const {
+ if (!isJavaCompatible()) {
fprintf(stderr,
"ERROR: This interface is not Java compatible. The Java backend"
" does NOT support union types or native handles.\n");
@@ -114,6 +114,13 @@
return UNKNOWN_ERROR;
}
+ std::string ifaceName;
+ if (!AST::isInterface(&ifaceName)) {
+ return generateJavaTypes(outputPath, limitToType);
+ }
+
+ const Interface *iface = mRootScope->getInterface();
+
// cut off the leading 'I'.
const std::string baseName = ifaceName.substr(1);
diff --git a/generateVts.cpp b/generateVts.cpp
index 0c3ba93..4f3585f 100644
--- a/generateVts.cpp
+++ b/generateVts.cpp
@@ -107,22 +107,6 @@
Formatter out(file);
out << "component_class: HAL_HIDL\n";
-
- // Get the component_type for interface from annotation.
- if (isInterface) {
- const Interface *iface = mRootScope->getInterface();
- Annotation *annotation = iface->annotations().valueFor("hal_type");
- if (annotation != NULL) {
- std::vector<std::string> * values = annotation->params().valueFor(
- "type");
- if (values != NULL) {
- out << "component_type: "
- << removeQuotes(values->at(0))
- << "\n";
- }
- }
- }
-
out << "component_type_version: " << mPackage.version().substr(1) << "\n";
out << "component_name: \""
<< (isInterface ? ifaceName : "types")
diff --git a/hidl-gen_y.yy b/hidl-gen_y.yy
index 4da811d..698f69d 100644
--- a/hidl-gen_y.yy
+++ b/hidl-gen_y.yy
@@ -352,8 +352,8 @@
;
const_expr
- : INTEGER { $$ = new ConstantExpression($1); }
- | IDENTIFIER { $$ = new ConstantExpression($1); }
+ : INTEGER { $$ = new ConstantExpression($1, ConstantExpression::kConstExprLiteral); }
+ | IDENTIFIER { $$ = new ConstantExpression($1, ConstantExpression::kConstExprUnknown); }
| const_expr '?' const_expr ':' const_expr
{
$$ = new ConstantExpression($1, $3, $5);
@@ -570,7 +570,7 @@
enum_value
: IDENTIFIER { $$ = new EnumValue($1); }
- | IDENTIFIER '=' const_expr { $$ = new EnumValue($1, $3->value()); }
+ | IDENTIFIER '=' const_expr { $$ = new EnumValue($1, $3); }
;
enum_values
diff --git a/main.cpp b/main.cpp
index 7fb048e..e7d959a 100644
--- a/main.cpp
+++ b/main.cpp
@@ -18,6 +18,7 @@
#include "Coordinator.h"
#include "Formatter.h"
#include "FQName.h"
+#include "Scope.h"
#include <android-base/logging.h>
#include <set>
@@ -36,7 +37,7 @@
PASS_PACKAGE,
PASS_FULL
};
- ValRes (*validate)(const FQName &);
+ ValRes (*validate)(const FQName &, const std::string &language);
status_t (*generate)(const FQName &fqName,
const char *hidl_gen,
Coordinator *coordinator,
@@ -51,7 +52,19 @@
const std::string &lang) {
CHECK(fqName.isFullyQualified());
- AST *ast = coordinator->parse(fqName);
+ AST *ast;
+ const char *limitToType = nullptr;
+
+ if (fqName.name().find("types.") == 0) {
+ CHECK(lang == "java"); // Already verified in validate().
+
+ limitToType = fqName.name().c_str() + strlen("types.");
+
+ FQName typesName(fqName.package(), fqName.version(), "types");
+ ast = coordinator->parse(typesName);
+ } else {
+ ast = coordinator->parse(fqName);
+ }
if (ast == NULL) {
fprintf(stderr,
@@ -65,7 +78,7 @@
return ast->generateCpp(outputDir);
}
if (lang == "java") {
- return ast->generateJava(outputDir);
+ return ast->generateJava(outputDir, limitToType);
}
if (lang == "vts") {
return ast->generateVts(outputDir);
@@ -109,6 +122,110 @@
return packageFQName.string();
}
+static void generateMakefileSectionForLanguageAndType(
+ Formatter &out,
+ Coordinator *coordinator,
+ const FQName &packageFQName,
+ const FQName &fqName,
+ const char *typeName,
+ bool forJava) {
+ out << "\n"
+ << "\n#"
+ << "\n# Build " << fqName.name() << ".hal";
+
+ if (forJava && typeName != nullptr) {
+ out << " (" << typeName << ")";
+ }
+
+ out << "\n#"
+ << "\nGEN := $(intermediates)/"
+ << coordinator->convertPackageRootToPath(packageFQName)
+ << coordinator->getPackagePath(packageFQName, true /* relative */);
+ if (!forJava) {
+ CHECK(typeName == nullptr);
+
+ if (fqName.name() == "types") {
+ out << "types.cpp";
+ } else {
+ out << fqName.name().substr(1) << "All.cpp";
+ }
+ } else if (typeName == nullptr) {
+ out << fqName.name() << ".java";
+ } else {
+ out << typeName << ".java";
+ }
+
+ out << "\n$(GEN): $(HIDL)";
+ out << "\n$(GEN): PRIVATE_HIDL := $(HIDL)";
+ out << "\n$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/"
+ << fqName.name() << ".hal";
+ out << "\n$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)"
+ << "\n$(GEN): PRIVATE_CUSTOM_TOOL = \\";
+ out.indent();
+ out.indent();
+ out << "\n$(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \\"
+ << "\n-L"
+ << (forJava ? "java" : "c++")
+ << " -r"
+ << coordinator->getPackageRoot(packageFQName) << ":"
+ << coordinator->getPackageRootPath(packageFQName) << " \\\n";
+
+ out << packageFQName.string()
+ << "::"
+ << fqName.name();
+
+ if (forJava && typeName != nullptr) {
+ out << "." << typeName;
+ }
+
+ out << "\n";
+
+ out.unindent();
+ out.unindent();
+
+ out << "\n$(GEN): $(LOCAL_PATH)/" << fqName.name() << ".hal";
+ out << "\n\t$(transform-generated-source)";
+ out << "\nLOCAL_GENERATED_SOURCES += $(GEN)";
+}
+
+static void generateMakefileSectionForLanguage(
+ Formatter &out,
+ Coordinator *coordinator,
+ const FQName &packageFQName,
+ const std::vector<FQName> &packageInterfaces,
+ AST *typesAST,
+ bool forJava) {
+ for (const auto &fqName : packageInterfaces) {
+ if (forJava && fqName.name() == "types") {
+ CHECK(typesAST != nullptr);
+
+ Scope *rootScope = typesAST->scope();
+ for (size_t i = 0; i < rootScope->countTypes(); ++i) {
+ std::string typeName;
+ rootScope->typeAt(i, &typeName);
+
+ generateMakefileSectionForLanguageAndType(
+ out,
+ coordinator,
+ packageFQName,
+ fqName,
+ typeName.c_str(),
+ forJava);
+ }
+
+ continue;
+ }
+
+ generateMakefileSectionForLanguageAndType(
+ out,
+ coordinator,
+ packageFQName,
+ fqName,
+ nullptr /* typeName */,
+ forJava);
+ }
+}
+
static status_t generateMakefileForPackage(
const FQName &packageFQName,
const char *hidl_gen,
@@ -130,6 +247,9 @@
}
std::set<FQName> importedPackages;
+ bool packageIsJavaCompatible = true;
+ AST *typesAST = nullptr;
+
for (const auto &fqName : packageInterfaces) {
AST *ast = coordinator->parse(fqName);
@@ -141,6 +261,14 @@
return UNKNOWN_ERROR;
}
+ if (packageIsJavaCompatible && !ast->isJavaCompatible()) {
+ packageIsJavaCompatible = false;
+ }
+
+ if (fqName.name() == "types") {
+ typesAST = ast;
+ }
+
ast->getImportedPackages(&importedPackages);
}
@@ -170,44 +298,13 @@
<< "HIDL := $(HOST_OUT_EXECUTABLES)/"
<< hidl_gen << "$(HOST_EXECUTABLE_SUFFIX)";
- for (const auto &fqName : packageInterfaces) {
-
- out << "\n"
- << "\n#"
- << "\n# Build " << fqName.name() << ".hal"
- << "\n#";
- out << "\nGEN := $(intermediates)/"
- << coordinator->convertPackageRootToPath(packageFQName)
- << coordinator->getPackagePath(packageFQName, true /* relative */);
- if (fqName.name() == "types") {
- out << "types.cpp";
- } else {
- out << fqName.name().substr(1) << "All.cpp";
- }
-
- out << "\n$(GEN): $(HIDL)";
- out << "\n$(GEN): PRIVATE_HIDL := $(HIDL)";
- out << "\n$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/"
- << fqName.name() << ".hal";
- out << "\n$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)"
- << "\n$(GEN): PRIVATE_CUSTOM_TOOL = \\";
- out.indent();
- out.indent();
- out << "\n$(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \\"
- << "\n-Lc++ -r"
- << coordinator->getPackageRoot(packageFQName) << ":"
- << coordinator->getPackageRootPath(packageFQName) << "\\";
- out << "\n"
- << packageFQName.string()
- << "::$(patsubst %.hal,%,$(notdir $(PRIVATE_DEPS)))"
- << "\n";
- out.unindent();
- out.unindent();
-
- out << "\n$(GEN): $(LOCAL_PATH)/" << fqName.name() << ".hal";
- out << "\n\t$(transform-generated-source)";
- out << "\nLOCAL_GENERATED_SOURCES += $(GEN)";
- }
+ generateMakefileSectionForLanguage(
+ out,
+ coordinator,
+ packageFQName,
+ packageInterfaces,
+ typesAST,
+ false /* forJava */);
out << "\n"
<< "\nLOCAL_EXPORT_C_INCLUDE_DIRS := $(intermediates)"
@@ -224,18 +321,39 @@
out.unindent();
out << "\nLOCAL_MULTILIB := both";
- if (path.find("hardware/interfaces/tests/") != std::string::npos) {
- out << "\nLOCAL_COMPATIBILITY_SUITE := vts"
- << "\n-include test/vts/tools/build/Android.packaging_sharedlib.mk";
- // TODO(yim): b/30589200 remove the above -include line after the
- // build rule change is merged.
- }
out << "\ninclude $(BUILD_SHARED_LIBRARY)\n";
+ if (packageIsJavaCompatible) {
+ out << "\n"
+ << "########################################"
+ << "########################################\n\n";
+
+ out << "include $(CLEAR_VARS)\n"
+ << "LOCAL_MODULE := "
+ << libraryName
+ << "-java\n"
+ << "LOCAL_MODULE_CLASS := JAVA_LIBRARIES\n\n"
+ << "intermediates := $(local-generated-sources-dir)\n\n"
+ << "HIDL := $(HOST_OUT_EXECUTABLES)/"
+ << hidl_gen
+ << "$(HOST_EXECUTABLE_SUFFIX)";
+
+ generateMakefileSectionForLanguage(
+ out,
+ coordinator,
+ packageFQName,
+ packageInterfaces,
+ typesAST,
+ true /* forJava */);
+
+ out << "\ninclude $(BUILD_JAVA_LIBRARY)\n";
+ }
+
return OK;
}
-OutputHandler::ValRes validateForMakefile(const FQName &fqName) {
+OutputHandler::ValRes validateForMakefile(
+ const FQName &fqName, const std::string & /* language */) {
if (fqName.package().empty()) {
fprintf(stderr, "ERROR: Expecting package name\n");
return OutputHandler::FAILED;
@@ -255,7 +373,8 @@
return OutputHandler::PASS_PACKAGE;
}
-OutputHandler::ValRes validateForSource(const FQName &fqName) {
+OutputHandler::ValRes validateForSource(
+ const FQName &fqName, const std::string &language) {
if (fqName.package().empty()) {
fprintf(stderr, "ERROR: Expecting package name\n");
return OutputHandler::FAILED;
@@ -266,9 +385,26 @@
return OutputHandler::FAILED;
}
- return fqName.name().empty() ?
- OutputHandler::PASS_PACKAGE :
- OutputHandler::PASS_FULL;
+ const std::string &name = fqName.name();
+ if (!name.empty()) {
+ if (name.find('.') == std::string::npos) {
+ return OutputHandler::PASS_FULL;
+ }
+
+ if (language != "java" || name.find("types.") != 0) {
+ // When generating java sources for "types.hal", output can be
+ // constrained to just one of the top-level types declared
+ // by using the extended syntax
+ // android.hardware.Foo@1.0::types.TopLevelTypeName.
+ // In all other cases (different language, not 'types') the dot
+ // notation in the name is illegal in this context.
+ return OutputHandler::FAILED;
+ }
+
+ return OutputHandler::PASS_FULL;
+ }
+
+ return OutputHandler::PASS_PACKAGE;
}
static std::vector<OutputHandler> formats = {
@@ -282,12 +418,14 @@
return generateSourcesForFile(fqName,
hidl_gen,
coordinator,
- outputDir, "c++");
+ outputDir,
+ "c++");
} else {
return generateSourcesForPackage(fqName,
hidl_gen,
coordinator,
- outputDir, "c++");
+ outputDir,
+ "c++");
}
}
},
@@ -302,13 +440,15 @@
return generateSourcesForFile(fqName,
hidl_gen,
coordinator,
- outputDir, "java");
+ outputDir,
+ "java");
}
else {
return generateSourcesForPackage(fqName,
hidl_gen,
coordinator,
- outputDir, "java");
+ outputDir,
+ "java");
}
}
},
@@ -460,7 +600,9 @@
exit(1);
}
- OutputHandler::ValRes valid = outputFormat->validate(fqName);
+ OutputHandler::ValRes valid =
+ outputFormat->validate(fqName, outputFormat->mKey);
+
if (valid == OutputHandler::FAILED) {
exit(1);
}
diff --git a/test/data/android/hardware/nfc/1.0/Nfc.vts b/test/data/android/hardware/nfc/1.0/Nfc.vts
index 6d70ff6..4dd78f6 100644
--- a/test/data/android/hardware/nfc/1.0/Nfc.vts
+++ b/test/data/android/hardware/nfc/1.0/Nfc.vts
@@ -1,5 +1,4 @@
component_class: HAL_HIDL
-component_type: NFC
component_type_version: 1.0
component_name: "INfc"
@@ -13,11 +12,12 @@
name: "open"
return_type_hidl: {
type: TYPE_SCALAR
- scalar_type: int32_t
+ scalar_type: "int32_t"
}
arg: {
type: TYPE_HIDL_CALLBACK
predefined_type: "INfcClientCallback"
+ is_callback: true
}
}
@@ -25,7 +25,7 @@
name: "write"
return_type_hidl: {
type: TYPE_SCALAR
- scalar_type: int32_t
+ scalar_type: "int32_t"
}
arg: {
type: TYPE_STRUCT
@@ -37,13 +37,13 @@
name: "core_initialized"
return_type_hidl: {
type: TYPE_SCALAR
- scalar_type: int32_t
+ scalar_type: "int32_t"
}
arg: {
type: TYPE_VECTOR
vector_value: {
type: TYPE_SCALAR
- scalar_type: uint8_t
+ scalar_type: "uint8_t"
}
}
}
@@ -52,7 +52,7 @@
name: "pre_discover"
return_type_hidl: {
type: TYPE_SCALAR
- scalar_type: int32_t
+ scalar_type: "int32_t"
}
}
@@ -60,7 +60,7 @@
name: "close"
return_type_hidl: {
type: TYPE_SCALAR
- scalar_type: int32_t
+ scalar_type: "int32_t"
}
}
@@ -68,7 +68,7 @@
name: "control_granted"
return_type_hidl: {
type: TYPE_SCALAR
- scalar_type: int32_t
+ scalar_type: "int32_t"
}
}
@@ -76,7 +76,7 @@
name: "power_cycle"
return_type_hidl: {
type: TYPE_SCALAR
- scalar_type: int32_t
+ scalar_type: "int32_t"
}
}
diff --git a/test/data/android/hardware/nfc/1.0/NfcClientCallback.vts b/test/data/android/hardware/nfc/1.0/NfcClientCallback.vts
index fb34126..39d1ef8 100644
--- a/test/data/android/hardware/nfc/1.0/NfcClientCallback.vts
+++ b/test/data/android/hardware/nfc/1.0/NfcClientCallback.vts
@@ -1,5 +1,4 @@
component_class: HAL_HIDL
-component_type: NFC
component_type_version: 1.0
component_name: "INfcClientCallback"
@@ -12,11 +11,11 @@
name: "sendEvent"
arg: {
type: TYPE_ENUM
- predefined_type:"nfc_event_t"
+ predefined_type: "nfc_event_t"
}
arg: {
type: TYPE_ENUM
- predefined_type:"nfc_status_t"
+ predefined_type: "nfc_status_t"
}
}
diff --git a/test/data/android/hardware/nfc/1.0/types.vts b/test/data/android/hardware/nfc/1.0/types.vts
index 89a3fba..b8cbb59 100644
--- a/test/data/android/hardware/nfc/1.0/types.vts
+++ b/test/data/android/hardware/nfc/1.0/types.vts
@@ -51,7 +51,7 @@
type: TYPE_VECTOR
vector_value: {
type: TYPE_SCALAR
- scalar_type: uint8_t
+ scalar_type: "uint8_t"
}
}
}
diff --git a/test/data/android/hardware/tests/expression/1.0/BnExpression.h b/test/data/android/hardware/tests/expression/1.0/BnExpression.h
new file mode 100644
index 0000000..99a8137
--- /dev/null
+++ b/test/data/android/hardware/tests/expression/1.0/BnExpression.h
@@ -0,0 +1,32 @@
+#ifndef HIDL_GENERATED_android_hardware_tests_expression_V1_0_BnExpression_H_
+#define HIDL_GENERATED_android_hardware_tests_expression_V1_0_BnExpression_H_
+
+#include <android/hardware/tests/expression/1.0/IHwExpression.h>
+
+namespace android {
+namespace hardware {
+namespace tests {
+namespace expression {
+namespace V1_0 {
+
+struct BnExpression : public ::android::hardware::BnInterface<IExpression, IHwExpression> {
+ explicit BnExpression(const ::android::sp<IExpression> &_hidl_impl);
+
+ ::android::status_t onTransact(
+ uint32_t _hidl_code,
+ const ::android::hardware::Parcel &_hidl_data,
+ ::android::hardware::Parcel *_hidl_reply,
+ uint32_t _hidl_flags = 0,
+ TransactCallback _hidl_cb = nullptr) override;
+
+ // Methods from IExpression follow.
+
+};
+
+} // namespace V1_0
+} // namespace expression
+} // namespace tests
+} // namespace hardware
+} // namespace android
+
+#endif // HIDL_GENERATED_android_hardware_tests_expression_V1_0_BnExpression_H_
diff --git a/test/data/android/hardware/tests/expression/1.0/BpExpression.h b/test/data/android/hardware/tests/expression/1.0/BpExpression.h
new file mode 100644
index 0000000..bb4edae
--- /dev/null
+++ b/test/data/android/hardware/tests/expression/1.0/BpExpression.h
@@ -0,0 +1,27 @@
+#ifndef HIDL_GENERATED_android_hardware_tests_expression_V1_0_BpExpression_H_
+#define HIDL_GENERATED_android_hardware_tests_expression_V1_0_BpExpression_H_
+
+#include <android/hardware/tests/expression/1.0/IHwExpression.h>
+
+namespace android {
+namespace hardware {
+namespace tests {
+namespace expression {
+namespace V1_0 {
+
+struct BpExpression : public ::android::hardware::BpInterface<IHwExpression> {
+ explicit BpExpression(const ::android::sp<::android::hardware::IBinder> &_hidl_impl);
+
+ virtual bool isRemote() const { return true; }
+
+ // Methods from IExpression follow.
+
+};
+
+} // namespace V1_0
+} // namespace expression
+} // namespace tests
+} // namespace hardware
+} // namespace android
+
+#endif // HIDL_GENERATED_android_hardware_tests_expression_V1_0_BpExpression_H_
diff --git a/test/data/android/hardware/tests/expression/1.0/ExpressionAll.cpp b/test/data/android/hardware/tests/expression/1.0/ExpressionAll.cpp
new file mode 100644
index 0000000..6664fa1
--- /dev/null
+++ b/test/data/android/hardware/tests/expression/1.0/ExpressionAll.cpp
@@ -0,0 +1,50 @@
+#include <android/hardware/tests/expression/1.0//BpExpression.h>
+#include <android/hardware/tests/expression/1.0//BnExpression.h>
+
+namespace android {
+namespace hardware {
+namespace tests {
+namespace expression {
+namespace V1_0 {
+
+BpExpression::BpExpression(const ::android::sp<::android::hardware::IBinder> &_hidl_impl)
+ : BpInterface<IHwExpression>(_hidl_impl) {
+}
+
+IMPLEMENT_HWBINDER_META_INTERFACE(Expression, "android.hardware.tests.expression@1.0::IExpression");
+
+BnExpression::BnExpression(const ::android::sp<IExpression> &_hidl_impl)
+ : BnInterface<IExpression, IHwExpression>(_hidl_impl) {
+}
+
+::android::status_t BnExpression::onTransact(
+ uint32_t _hidl_code,
+ const ::android::hardware::Parcel &_hidl_data,
+ ::android::hardware::Parcel *_hidl_reply,
+ uint32_t _hidl_flags,
+ TransactCallback _hidl_cb) {
+ ::android::status_t _hidl_err = ::android::OK;
+
+ switch (_hidl_code) {
+ default:
+ {
+ return ::android::hardware::BnInterface<IExpression, IHwExpression>::onTransact(
+ _hidl_code, _hidl_data, _hidl_reply, _hidl_flags, _hidl_cb);
+ }
+ }
+
+ if (_hidl_err == ::android::UNEXPECTED_NULL) {
+ _hidl_err = ::android::hardware::Status::fromExceptionCode(
+ ::android::hardware::Status::EX_NULL_POINTER)
+ .writeToParcel(_hidl_reply);
+ }
+
+ return _hidl_err;
+}
+
+IMPLEMENT_REGISTER_AND_GET_SERVICE(Expression)
+} // namespace V1_0
+} // namespace expression
+} // namespace tests
+} // namespace hardware
+} // namespace android
diff --git a/test/data/android/hardware/tests/expression/1.0/IExpression.h b/test/data/android/hardware/tests/expression/1.0/IExpression.h
new file mode 100644
index 0000000..a8def3b
--- /dev/null
+++ b/test/data/android/hardware/tests/expression/1.0/IExpression.h
@@ -0,0 +1,142 @@
+#ifndef HIDL_GENERATED_android_hardware_tests_expression_V1_0_IExpression_H_
+#define HIDL_GENERATED_android_hardware_tests_expression_V1_0_IExpression_H_
+
+#include <hidl/HidlSupport.h>
+#include <hidl/IServiceManager.h>
+#include <hwbinder/Status.h>
+#include <utils/NativeHandle.h>
+
+namespace android {
+namespace hardware {
+namespace tests {
+namespace expression {
+namespace V1_0 {
+
+struct IExpression : virtual public RefBase {
+ enum class UInt64LiteralTypeGuessing : uint64_t {
+ noSuffixDec1 = 0ull, // (int32_t)0
+ noSuffixDec2 = 1ull, // (int32_t)1
+ noSuffixDec3 = 18446744073709551615ull, // (int32_t)(-1)
+ noSuffixDec4 = 18446744073709551615ull, // (int32_t)(~0)
+ noSuffixDec5 = 2147483647ull, // (int32_t)2147483647
+ noSuffixDec6 = 18446744071562067968ull, // (int64_t)(-2147483648)
+ noSuffixDec7 = 2147483648ull, // (int64_t)2147483648
+ noSuffixDec8 = 18446744071562067967ull, // (int64_t)(-2147483649)
+ noSuffixDec9 = 0ull, // (int32_t)(~(-1))
+ noSuffixHex1 = 2147483647ull, // (int32_t)0x7fffffff
+ noSuffixHex2 = 2147483648ull, // (uint32_t)0x80000000
+ noSuffixHex3 = 4294967295ull, // (uint32_t)0xffffffff
+ longHex1 = 4294967295ull, // (int64_t)0xffffffffl
+ longHex2 = 68719476735ull, // (int64_t)0xfffffffff
+ longHex3 = 9223372036854775807ull, // (int64_t)0x7fffffffffffffff
+ longHex4 = 9223372036854775808ull, // (uint64_t)0x8000000000000000
+ longHex5 = 18446744073709551615ull, // (uint64_t)0xFFFFFFFFFFFFFFFF
+ };
+
+ enum class SuffixedLiteralTypeGuessing : int32_t {
+ decInt32_1 = 1, // (bool)((~(-1)) == 0)
+ decInt32_2 = 1, // (bool)((-(1 << 31)) == (1 << 31))
+ decInt64_1 = 1, // (bool)((~(-1l)) == 0)
+ decInt64_2 = 1, // (bool)((~4294967295) != 0)
+ decInt64_3 = 1, // (bool)((~4294967295l) != 0)
+ decInt64_4 = 1, // (bool)((-(1l << 63)) == (1l << 63))
+ hexInt32_1 = 1, // (bool)((-0x7fffffff) < 0)
+ hexUInt32_1 = 1, // (bool)((-0x80000000) > 0)
+ hexUInt32_2 = 1, // (bool)((~0xFFFFFFFF) == 0)
+ hexInt64_1 = 1, // (bool)((-0x7FFFFFFFFFFFFFFF) < 0)
+ hexUInt64_1 = 1, // (bool)((-0x8000000000000000) > 0)
+ };
+
+ enum class Int64LiteralTypeGuessing : int64_t {
+ noSuffixDec11 = -2147483648ll, // (int32_t)(1 + 0x7fffffff)
+ noSuffixDec12 = 2147483647ll, // (uint32_t)(0x80000000 - 1)
+ };
+
+ enum class Int32BitShifting : int32_t {
+ int32BitShift1 = -2147483648, // (int32_t)(1 << 31)
+ };
+
+ enum class UInt32BitShifting : uint32_t {
+ uint32BitShift1 = 2147483648u, // (int32_t)(1 << 31)
+ };
+
+ enum class Int64BitShifting : int64_t {
+ int64BitShift1 = (int64_t)(-9223372036854775808ull), // (int64_t)(1l << 63)
+ };
+
+ enum class UInt64BitShifting : uint64_t {
+ uint64BitShift1 = 9223372036854775808ull, // (int64_t)(1l << 63)
+ };
+
+ enum class Precedence : int32_t {
+ literal = 4, // (int32_t)4
+ neg = -4, // (int32_t)(-4)
+ literalL = -4, // (int64_t)(-4L)
+ hex = -1, // (uint32_t)0xffffffff
+ hexLong = -1, // (int64_t)0xffffffffl
+ hexLong2 = -1, // (int64_t)0xfffffffff
+ simpleArithmetic = 5, // (int32_t)(4 + 1)
+ simpleArithmetic2 = 1, // (int32_t)((2 + 3) - 4)
+ simpleBoolExpr = 0, // (bool)(1 == 4)
+ simpleLogical = 1, // (bool)(1 && 1)
+ simpleComp = 1, // (bool)(1 < 2)
+ boolExpr1 = 0, // (bool)(!(((3 != 4) || (((2 < 3) <= 3) > 4)) >= 0))
+ boolExpr = 0, // (bool)((1 == 7) && (!(((3 != 4) || (((2 < 3) <= 3) > 4)) >= 0)))
+ simpleBitShift = 4, // (int32_t)(1 << 2)
+ simpleBitShift2 = 2, // (int32_t)(4 >> 1)
+ simpleBitShiftNeg = 2, // (int32_t)(4 << (-1))
+ simpleArithmeticRightShift = -1, // (int32_t)((1 << 31) >> 31)
+ simpleBitExpr = 5, // (int32_t)(1 | (16 >> 2))
+ bitExpr = 3, // (int32_t)(((~42) & ((1 << 3) | (16 >> 2))) ^ 7)
+ arithmeticExpr = 33, // (int32_t)((2 + 3) - ((4 * (-7)) / (10 % 3)))
+ messyExpr = 2, // (int32_t)(2 + ((-3) & (4 / 7)))
+ paranExpr = 2, // (int32_t)(1 + 1)
+ ternary = 2, // (int32_t)(1?2:3)
+ ternary2 = 3, // (int32_t)((1 && 2)?3:4)
+ complicatedTernary2 = 56, // (int32_t)((((1 - 1) && (2 + 3)) || 5)?(7 * 8):(-3))
+ };
+
+ enum class OperatorSanityCheck : int32_t {
+ plus = 1, // (bool)((1 + 2) == 3)
+ minus = 1, // (bool)((8 - 9) == (-1))
+ product = 1, // (bool)((9 * 9) == 81)
+ division = 1, // (bool)((29 / 3) == 9)
+ mod = 1, // (bool)((29 % 3) == 2)
+ bit_or = 1, // (bool)((0xC0010000 | 0xF00D) == 0xC001F00D)
+ bit_or2 = 1, // (bool)((10 | 6) == 14)
+ bit_and = 1, // (bool)((10 & 6) == 2)
+ bit_xor = 1, // (bool)((10 ^ 6) == 12)
+ lt1 = 1, // (bool)(6 < 10)
+ lt2 = 1, // (bool)((10 < 10) == 0)
+ gt1 = 1, // (bool)((6 > 10) == 0)
+ gt2 = 1, // (bool)((10 > 10) == 0)
+ gte1 = 1, // (bool)(19 >= 10)
+ gte2 = 1, // (bool)(10 >= 10)
+ lte1 = 1, // (bool)(5 <= 10)
+ lte2 = 1, // (bool)((19 <= 10) == 0)
+ ne1 = 1, // (bool)(19 != 10)
+ ne2 = 1, // (bool)((10 != 10) == 0)
+ lshift = 1, // (bool)((22 << 1) == 44)
+ rshift = 1, // (bool)((11 >> 1) == 5)
+ logor1 = 1, // (bool)((1 || 0) == 1)
+ logor2 = 1, // (bool)((1 || 1) == 1)
+ logor3 = 1, // (bool)((0 || 0) == 0)
+ logor4 = 1, // (bool)((0 || 1) == 1)
+ logand1 = 1, // (bool)((1 && 0) == 0)
+ logand2 = 1, // (bool)((1 && 1) == 1)
+ logand3 = 1, // (bool)((0 && 0) == 0)
+ logand4 = 1, // (bool)((0 && 1) == 0)
+ };
+
+ virtual bool isRemote() const { return false; }
+
+ DECLARE_REGISTER_AND_GET_SERVICE(Expression)
+};
+
+} // namespace V1_0
+} // namespace expression
+} // namespace tests
+} // namespace hardware
+} // namespace android
+
+#endif // HIDL_GENERATED_android_hardware_tests_expression_V1_0_IExpression_H_
diff --git a/test/data/android/hardware/tests/expression/1.0/IExpression.java b/test/data/android/hardware/tests/expression/1.0/IExpression.java
new file mode 100644
index 0000000..ebc0bf9
--- /dev/null
+++ b/test/data/android/hardware/tests/expression/1.0/IExpression.java
@@ -0,0 +1,180 @@
+package android.hardware.tests.expression.V1_0;
+
+import android.os.IHwBinder;
+import android.os.IHwInterface;
+import android.os.HwBinder;
+import android.os.HwBlob;
+import android.os.HwParcel;
+
+import java.util.Vector;
+
+public interface IExpression extends IHwInterface {
+ public static final String kInterfaceName = "android.hardware.tests.expression@1.0::IExpression";
+
+ public static IExpression asInterface(IHwBinder binder) {
+ if (binder == null) {
+ return null;
+ }
+
+ IHwInterface iface =
+ binder.queryLocalInterface(kInterfaceName);
+
+ if ((iface != null) && (iface instanceof IExpression)) {
+ return (IExpression)iface;
+ }
+
+ return new IExpression.Proxy(binder);
+ }
+
+ public IHwBinder asBinder();
+
+ public final class UInt64LiteralTypeGuessing {
+ public static final long noSuffixDec1 = 0L; // (int32_t)0
+ public static final long noSuffixDec2 = 1L; // (int32_t)1
+ public static final long noSuffixDec3 = -1L; // (int32_t)(-1)
+ public static final long noSuffixDec4 = -1L; // (int32_t)(~0)
+ public static final long noSuffixDec5 = 2147483647L; // (int32_t)2147483647
+ public static final long noSuffixDec6 = -2147483648L; // (int64_t)(-2147483648)
+ public static final long noSuffixDec7 = 2147483648L; // (int64_t)2147483648
+ public static final long noSuffixDec8 = -2147483649L; // (int64_t)(-2147483649)
+ public static final long noSuffixDec9 = 0L; // (int32_t)(~(-1))
+ public static final long noSuffixHex1 = 2147483647L; // (int32_t)0x7fffffff
+ public static final long noSuffixHex2 = 2147483648L; // (uint32_t)0x80000000
+ public static final long noSuffixHex3 = 4294967295L; // (uint32_t)0xffffffff
+ public static final long longHex1 = 4294967295L; // (int64_t)0xffffffffl
+ public static final long longHex2 = 68719476735L; // (int64_t)0xfffffffff
+ public static final long longHex3 = 9223372036854775807L; // (int64_t)0x7fffffffffffffff
+ public static final long longHex4 = -9223372036854775808L; // (uint64_t)0x8000000000000000
+ public static final long longHex5 = -1L; // (uint64_t)0xFFFFFFFFFFFFFFFF
+ };
+
+ public final class SuffixedLiteralTypeGuessing {
+ public static final int decInt32_1 = 1; // (bool)((~(-1)) == 0)
+ public static final int decInt32_2 = 1; // (bool)((-(1 << 31)) == (1 << 31))
+ public static final int decInt64_1 = 1; // (bool)((~(-1l)) == 0)
+ public static final int decInt64_2 = 1; // (bool)((~4294967295) != 0)
+ public static final int decInt64_3 = 1; // (bool)((~4294967295l) != 0)
+ public static final int decInt64_4 = 1; // (bool)((-(1l << 63)) == (1l << 63))
+ public static final int hexInt32_1 = 1; // (bool)((-0x7fffffff) < 0)
+ public static final int hexUInt32_1 = 1; // (bool)((-0x80000000) > 0)
+ public static final int hexUInt32_2 = 1; // (bool)((~0xFFFFFFFF) == 0)
+ public static final int hexInt64_1 = 1; // (bool)((-0x7FFFFFFFFFFFFFFF) < 0)
+ public static final int hexUInt64_1 = 1; // (bool)((-0x8000000000000000) > 0)
+ };
+
+ public final class Int64LiteralTypeGuessing {
+ public static final long noSuffixDec11 = -2147483648L; // (int32_t)(1 + 0x7fffffff)
+ public static final long noSuffixDec12 = 2147483647L; // (uint32_t)(0x80000000 - 1)
+ };
+
+ public final class Int32BitShifting {
+ public static final int int32BitShift1 = -2147483648; // (int32_t)(1 << 31)
+ };
+
+ public final class UInt32BitShifting {
+ public static final int uint32BitShift1 = -2147483648; // (int32_t)(1 << 31)
+ };
+
+ public final class Int64BitShifting {
+ public static final long int64BitShift1 = -9223372036854775808L; // (int64_t)(1l << 63)
+ };
+
+ public final class UInt64BitShifting {
+ public static final long uint64BitShift1 = -9223372036854775808L; // (int64_t)(1l << 63)
+ };
+
+ public final class Precedence {
+ public static final int literal = 4; // (int32_t)4
+ public static final int neg = -4; // (int32_t)(-4)
+ public static final int literalL = -4; // (int64_t)(-4L)
+ public static final int hex = -1; // (uint32_t)0xffffffff
+ public static final int hexLong = -1; // (int64_t)0xffffffffl
+ public static final int hexLong2 = -1; // (int64_t)0xfffffffff
+ public static final int simpleArithmetic = 5; // (int32_t)(4 + 1)
+ public static final int simpleArithmetic2 = 1; // (int32_t)((2 + 3) - 4)
+ public static final int simpleBoolExpr = 0; // (bool)(1 == 4)
+ public static final int simpleLogical = 1; // (bool)(1 && 1)
+ public static final int simpleComp = 1; // (bool)(1 < 2)
+ public static final int boolExpr1 = 0; // (bool)(!(((3 != 4) || (((2 < 3) <= 3) > 4)) >= 0))
+ public static final int boolExpr = 0; // (bool)((1 == 7) && (!(((3 != 4) || (((2 < 3) <= 3) > 4)) >= 0)))
+ public static final int simpleBitShift = 4; // (int32_t)(1 << 2)
+ public static final int simpleBitShift2 = 2; // (int32_t)(4 >> 1)
+ public static final int simpleBitShiftNeg = 2; // (int32_t)(4 << (-1))
+ public static final int simpleArithmeticRightShift = -1; // (int32_t)((1 << 31) >> 31)
+ public static final int simpleBitExpr = 5; // (int32_t)(1 | (16 >> 2))
+ public static final int bitExpr = 3; // (int32_t)(((~42) & ((1 << 3) | (16 >> 2))) ^ 7)
+ public static final int arithmeticExpr = 33; // (int32_t)((2 + 3) - ((4 * (-7)) / (10 % 3)))
+ public static final int messyExpr = 2; // (int32_t)(2 + ((-3) & (4 / 7)))
+ public static final int paranExpr = 2; // (int32_t)(1 + 1)
+ public static final int ternary = 2; // (int32_t)(1?2:3)
+ public static final int ternary2 = 3; // (int32_t)((1 && 2)?3:4)
+ public static final int complicatedTernary2 = 56; // (int32_t)((((1 - 1) && (2 + 3)) || 5)?(7 * 8):(-3))
+ };
+
+ public final class OperatorSanityCheck {
+ public static final int plus = 1; // (bool)((1 + 2) == 3)
+ public static final int minus = 1; // (bool)((8 - 9) == (-1))
+ public static final int product = 1; // (bool)((9 * 9) == 81)
+ public static final int division = 1; // (bool)((29 / 3) == 9)
+ public static final int mod = 1; // (bool)((29 % 3) == 2)
+ public static final int bit_or = 1; // (bool)((0xC0010000 | 0xF00D) == 0xC001F00D)
+ public static final int bit_or2 = 1; // (bool)((10 | 6) == 14)
+ public static final int bit_and = 1; // (bool)((10 & 6) == 2)
+ public static final int bit_xor = 1; // (bool)((10 ^ 6) == 12)
+ public static final int lt1 = 1; // (bool)(6 < 10)
+ public static final int lt2 = 1; // (bool)((10 < 10) == 0)
+ public static final int gt1 = 1; // (bool)((6 > 10) == 0)
+ public static final int gt2 = 1; // (bool)((10 > 10) == 0)
+ public static final int gte1 = 1; // (bool)(19 >= 10)
+ public static final int gte2 = 1; // (bool)(10 >= 10)
+ public static final int lte1 = 1; // (bool)(5 <= 10)
+ public static final int lte2 = 1; // (bool)((19 <= 10) == 0)
+ public static final int ne1 = 1; // (bool)(19 != 10)
+ public static final int ne2 = 1; // (bool)((10 != 10) == 0)
+ public static final int lshift = 1; // (bool)((22 << 1) == 44)
+ public static final int rshift = 1; // (bool)((11 >> 1) == 5)
+ public static final int logor1 = 1; // (bool)((1 || 0) == 1)
+ public static final int logor2 = 1; // (bool)((1 || 1) == 1)
+ public static final int logor3 = 1; // (bool)((0 || 0) == 0)
+ public static final int logor4 = 1; // (bool)((0 || 1) == 1)
+ public static final int logand1 = 1; // (bool)((1 && 0) == 0)
+ public static final int logand2 = 1; // (bool)((1 && 1) == 1)
+ public static final int logand3 = 1; // (bool)((0 && 0) == 0)
+ public static final int logand4 = 1; // (bool)((0 && 1) == 0)
+ };
+
+ public static final int kOpEnd = IHwBinder.FIRST_CALL_TRANSACTION + 0;
+
+
+ public static final class Proxy implements IExpression {
+ private IHwBinder mRemote;
+
+ public Proxy(IHwBinder remote) {
+ mRemote = remote;
+ }
+
+ public IHwBinder asBinder() {
+ return mRemote;
+ }
+
+ // Methods from ::android::hardware::tests::expression::V1_0::IExpression follow.
+ }
+
+ public static abstract class Stub extends HwBinder implements IExpression {
+ public IHwBinder asBinder() {
+ return this;
+ }
+
+ public IHwInterface queryLocalInterface(String descriptor) {
+ if (kInterfaceName.equals(descriptor)) {
+ return this;
+ }
+ return null;
+ }
+
+ public void onTransact(int code, HwParcel request, final HwParcel reply, int flags) {
+ switch (code) {
+ }
+ }
+ }
+}
diff --git a/test/data/android/hardware/tests/expression/1.0/IHwExpression.h b/test/data/android/hardware/tests/expression/1.0/IHwExpression.h
new file mode 100644
index 0000000..d9ad8aa
--- /dev/null
+++ b/test/data/android/hardware/tests/expression/1.0/IHwExpression.h
@@ -0,0 +1,33 @@
+#ifndef HIDL_GENERATED_android_hardware_tests_expression_V1_0_IHwExpression_H_
+#define HIDL_GENERATED_android_hardware_tests_expression_V1_0_IHwExpression_H_
+
+#include <android/hardware/tests/expression/1.0/IExpression.h>
+
+
+#include <hidl/HidlSupport.h>
+#include <hwbinder/IBinder.h>
+#include <hwbinder/IInterface.h>
+#include <hwbinder/Status.h>
+
+namespace android {
+namespace hardware {
+namespace tests {
+namespace expression {
+namespace V1_0 {
+
+struct IHwExpression : public IExpression, public ::android::hardware::IInterface {
+ DECLARE_HWBINDER_META_INTERFACE(Expression);
+
+ enum Call {
+ CallCount
+ };
+
+};
+
+} // namespace V1_0
+} // namespace expression
+} // namespace tests
+} // namespace hardware
+} // namespace android
+
+#endif // HIDL_GENERATED_android_hardware_tests_expression_V1_0_IHwExpression_H_
diff --git a/test/java_test/Android.mk b/test/java_test/Android.mk
index 84474cc..97a95ec 100644
--- a/test/java_test/Android.mk
+++ b/test/java_test/Android.mk
@@ -5,23 +5,9 @@
LOCAL_MODULE := hidl_test_java_lib
LOCAL_MODULE_STEM := hidl_test_java
LOCAL_MODULE_CLASS := JAVA_LIBRARIES
-
-intermediates := $(local-generated-sources-dir)
-
-HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
-
-GEN := $(intermediates)/android/hardware/tests/baz/1.0/IBaz.java \
- $(intermediates)/android/hardware/tests/baz/1.0/IBazCallback.java \
- $(intermediates)/android/hardware/tests/baz/1.0/IBase.java \
-
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = $(PRIVATE_HIDL) -Ljava -randroid.hardware:hardware/interfaces -o $(PRIVATE_OUTPUT_DIR) android.hardware.tests.baz@1.0
-$(GEN):
- $(transform-generated-source)
-
-LOCAL_GENERATED_SOURCES += $(GEN)
+LOCAL_JAVA_LIBRARIES := \
+ android.hardware.tests.baz@1.0-java \
+ android.hardware.tests.expression@1.0-java
include $(BUILD_JAVA_LIBRARY)
@@ -31,7 +17,11 @@
LOCAL_MODULE := hidl_test_java
LOCAL_MODULE_CLASS := EXECUTABLES
LOCAL_SRC_FILES := hidl_test_java
-LOCAL_REQUIRED_MODULES := hidl_test_java_lib
+
+LOCAL_REQUIRED_MODULES := \
+ hidl_test_java_lib \
+ android.hardware.tests.baz@1.0-java
+
include $(BUILD_PREBUILT)
################################################################################
@@ -48,6 +38,7 @@
libhwbinder \
libutils \
android.hardware.tests.baz@1.0 \
+ android.hardware.tests.expression@1.0
LOCAL_STATIC_LIBRARIES := \
libgtest
diff --git a/test/java_test/hidl_test_java b/test/java_test/hidl_test_java
index 71a16c2..e1171cc 100644
--- a/test/java_test/hidl_test_java
+++ b/test/java_test/hidl_test_java
@@ -1,5 +1,5 @@
base=/system
-export CLASSPATH=$base/framework/hidl_test_java.jar
+export CLASSPATH=$base/framework/hidl_test_java.jar:$base/framework/android.hardware.tests.baz@1.0-java.jar
# Test native server with Java client
hidl_test_java_native -s &
diff --git a/test/java_test/hidl_test_java_native.cpp b/test/java_test/hidl_test_java_native.cpp
index d831435..6ec7263 100644
--- a/test/java_test/hidl_test_java_native.cpp
+++ b/test/java_test/hidl_test_java_native.cpp
@@ -3,9 +3,7 @@
#include <android-base/logging.h>
-#include <android/hardware/tests/baz/1.0/BnBaz.h>
-#include <android/hardware/tests/baz/1.0/BnBazCallback.h>
-#include <android/hardware/tests/baz/1.0/BpBaz.h>
+#include <android/hardware/tests/baz/1.0/IBaz.h>
#include <gtest/gtest.h>
#include <hidl/IServiceManager.h>
@@ -18,16 +16,13 @@
using ::android::hardware::tests::baz::V1_0::IBase;
using ::android::hardware::tests::baz::V1_0::IBaz;
using ::android::hardware::tests::baz::V1_0::IBazCallback;
-using ::android::hardware::tests::baz::V1_0::BnBaz;
-using ::android::hardware::tests::baz::V1_0::BnBazCallback;
-using ::android::hardware::tests::baz::V1_0::BpBaz;
using ::android::hardware::hidl_vec;
using ::android::hardware::hidl_string;
using ::android::hardware::Return;
using ::android::hardware::Status;
-struct BazCallback : public BnBazCallback {
+struct BazCallback : public IBazCallback {
Status heyItsMe(const sp<IBazCallback> &cb) override;
};
@@ -38,7 +33,7 @@
return Status::ok();
}
-struct Baz : public BnBaz {
+struct Baz : public IBaz {
Status someBaseMethod() override;
Status someOtherBaseMethod(
@@ -349,13 +344,8 @@
const hidl_version kVersion = make_hidl_version(1, 0);
- sp<IBinder> service =
- defaultServiceManager()->getService(
- ::android::String16("baz"), kVersion);
+ baz = IBaz::getService(::android::String16("baz"), kVersion);
- CHECK(service != NULL);
-
- baz = IBaz::asInterface(service);
CHECK(baz != NULL);
}
@@ -599,7 +589,7 @@
const hidl_version kVersion = make_hidl_version(1, 0);
- defaultServiceManager()->addService(String16("baz"), baz, kVersion);
+ baz->registerAsService(String16("baz"), kVersion);
ProcessState::self()->startThreadPool();
ProcessState::self()->setThreadPoolMaxThreadCount(0);
diff --git a/test/main.cpp b/test/main.cpp
index 72ec8cd..ae973db 100644
--- a/test/main.cpp
+++ b/test/main.cpp
@@ -30,6 +30,7 @@
using ::android::hardware::tests::foo::V1_0::IFoo;
using ::android::hardware::tests::foo::V1_0::IFooCallback;
using ::android::hardware::tests::bar::V1_0::IBar;
+using ::android::hardware::tests::bar::V1_0::IHwBar;
using ::android::hardware::tests::foo::V1_0::Abc;
using ::android::hardware::Return;
using ::android::hardware::Status;
@@ -39,7 +40,7 @@
using ::android::Mutex;
using ::android::Condition;
-struct FooCallback : public BnFooCallback {
+struct FooCallback : public IFooCallback {
FooCallback() : invokeInfo{}, mLock{}, mCond{} {}
Status heyItsYou(const sp<IFooCallback> &cb) override;
Return<bool> heyItsYouIsntIt(const sp<IFooCallback> &cb) override;
@@ -96,7 +97,7 @@
}
Status FooCallback::reportResults(int64_t ns, reportResults_cb cb) {
- ALOGI("SERVER(FooCallback) reportResults(%" PRId64 ") seconds", nanoseconds_to_seconds(ns));
+ ALOGI("SERVER(FooCallback) reportResults(%" PRId64 " seconds)", nanoseconds_to_seconds(ns));
nsecs_t leftToWaitNs = ns;
mLock.lock();
while (!(invokeInfo[0].invoked && invokeInfo[1].invoked && invokeInfo[2].invoked) &&
@@ -104,10 +105,10 @@
nsecs_t start = systemTime();
::android::status_t rc = mCond.waitRelative(mLock, leftToWaitNs);
if (rc != ::android::OK) {
- ALOGI("SERVER(FooCallback)::reportResults(%" PRId64 ") Condition::waitRelative(%" PRId64 ") returned error (%d)", ns, leftToWaitNs, rc);
+ ALOGI("SERVER(FooCallback)::reportResults(%" PRId64 " ns) Condition::waitRelative(%" PRId64 ") returned error (%d)", ns, leftToWaitNs, rc);
break;
}
- ALOGI("SERVER(FooCallback)::reportResults(%" PRId64 ") Condition::waitRelative was signalled", ns);
+ ALOGI("SERVER(FooCallback)::reportResults(%" PRId64 " ns) Condition::waitRelative was signalled", ns);
leftToWaitNs -= systemTime() - start;
}
mLock.unlock();
@@ -122,7 +123,7 @@
return Status::ok();
}
-struct Bar : public BnBar {
+struct Bar : public IBar {
Status doThis(float param) override;
Return<int32_t> doThatAndReturnSomething(int64_t param) override;
@@ -388,7 +389,7 @@
using namespace android::hardware;
using android::String16;
ALOGI("SERVER(%s) registering", tag);
- defaultServiceManager()->addService(String16(serviceName), server, kVersion);
+ server->registerAsService(String16(serviceName), kVersion);
ALOGI("SERVER(%s) starting", tag);
ProcessState::self()->setThreadPoolMaxThreadCount(0);
ProcessState::self()->startThreadPool();
@@ -410,22 +411,13 @@
using android::String16;
const hidl_version kVersion = make_hidl_version(1, 0);
- service =
- defaultServiceManager()->getService(String16("foo"), kVersion);
- ALOGI("CLIENT Found service foo.");
-
- CHECK(service != NULL);
-
- foo = IFoo::asInterface(service);
+ foo = IFoo::getService(String16("foo"), kVersion);
CHECK(foo != NULL);
- bar = IBar::asInterface(service);
+ bar = IBar::getService(String16("foo"), kVersion);
CHECK(bar != NULL);
- cbService = defaultServiceManager()->getService(String16("foo callback"), kVersion);
- CHECK(cbService != NULL);
-
- fooCb = IFooCallback::asInterface(cbService);
+ fooCb = IFooCallback::getService(String16("foo callback"), kVersion);
CHECK(fooCb != NULL);
ALOGI("Test setup complete");
@@ -574,8 +566,8 @@
// time to execute that we also expect.
const nsecs_t reportResultsNs =
- seconds_to_nanoseconds(2*(FooCallback::DELAY_S +
- FooCallback::TOLERANCE_NS));
+ 2 * FooCallback::DELAY_NS + FooCallback::TOLERANCE_NS;
+
ALOGI("CLIENT: Waiting for up to %" PRId64 " seconds.",
nanoseconds_to_seconds(reportResultsNs));
diff --git a/test/test_output.py b/test/test_output.py
index 09c806b..b435cf0 100644
--- a/test/test_output.py
+++ b/test/test_output.py
@@ -60,8 +60,8 @@
def testAll(self):
"""Run all tests. """
self.TestVtsOutput()
- # Uncomment once we want to test cpp output.
- # self.TestCppOutput()
+ self.TestCppOutput()
+ self.TestJavaOutput()
def TestVtsOutput(self):
"""Runs hidl-gen to generate vts file and verify the output."""
@@ -71,8 +71,15 @@
def TestCppOutput(self):
"""Runs hidl-gen to generate c++ file and verify the output."""
- self.RunTest("c++", "android.hardware.nfc@1.0",
- "android/hardware/nfc/1.0")
+ # self.RunTest("c++", "android.hardware.nfc@1.0",
+ # "android/hardware/nfc/1.0")
+ self.RunTest("c++", "android.hardware.tests.expression@1.0",
+ "android/hardware/tests/expression/1.0")
+ self.assertEqual(self._errors, 0)
+
+ def TestJavaOutput(self):
+ self.RunTest("java", "android.hardware.tests.expression@1.0",
+ "android/hardware/tests/expression/1.0")
self.assertEqual(self._errors, 0)
def RunTest(self, language, fqname, package_path):