Keeping track of imported names, resolve enum storage types, some finetuning.
diff --git a/AST.cpp b/AST.cpp
index 7c02f1d..26da2bd 100644
--- a/AST.cpp
+++ b/AST.cpp
@@ -141,7 +141,7 @@
     return mScopePath.top();
 }
 
-Type *AST::lookupType(const char *name) const {
+Type *AST::lookupType(const char *name) {
     FQName fqName(name);
     CHECK(fqName.isValid());
 
@@ -166,7 +166,13 @@
 
     // LOG(INFO) << "lookupType now looking for " << fqName.string();
 
-    return mCoordinator->lookupType(fqName);
+    Type *resultType = mCoordinator->lookupType(fqName);
+
+    if (resultType) {
+        mImportedNames.insert(fqName);
+    }
+
+    return resultType;
 }
 
 Type *AST::lookupTypeInternal(const std::string &namePath) const {
diff --git a/AST.h b/AST.h
index a159c59..c0fe6b0 100644
--- a/AST.h
+++ b/AST.h
@@ -3,6 +3,7 @@
 #define AST_H_
 
 #include <android-base/macros.h>
+#include <set>
 #include <string>
 #include <utils/Vector.h>
 
@@ -38,7 +39,7 @@
     // Look up a type by FQName, "pure" names, i.e. those without package
     // or version are first looked up in the current scope chain.
     // After that lookup proceeds to imports.
-    Type *lookupType(const char *name) const;
+    Type *lookupType(const char *name);
 
     // Takes dot-separated path components to a type possibly inside this AST.
     // Name resolution goes from root scope downwards, i.e. the path must be
@@ -58,6 +59,16 @@
 
     FQName mPackage;
 
+    std::set<FQName> mImportedNames;
+
+    static void GetPackageComponents(
+            const FQName &fqName, std::vector<std::string> *components);
+
+    static void GetPackageAndVersionComponents(
+            const FQName &fqName,
+            std::vector<std::string> *components,
+            bool cpp_compatible);
+
     void getPackageComponents(std::vector<std::string> *components) const;
 
     void getPackageAndVersionComponents(
diff --git a/Android.mk b/Android.mk
index a66daf5..3c6e843 100644
--- a/Android.mk
+++ b/Android.mk
@@ -41,5 +41,4 @@
 
 include $(BUILD_HOST_EXECUTABLE)
 
-include $(call all-makefiles-under,$(LOCAL_PATH))
-
+# include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/CompoundType.cpp b/CompoundType.cpp
index a96c7e2..d079f96 100644
--- a/CompoundType.cpp
+++ b/CompoundType.cpp
@@ -274,7 +274,7 @@
                 "parcel",
                 !isReader /* parcelObjIsPointer */,
                 isReader,
-                ErrorMode_Goto,
+                ErrorMode_Return,
                 "parentHandle",
                 "parentOffset + offsetof(" + name() + ", " + field->name() + ")");
     }
diff --git a/EnumType.cpp b/EnumType.cpp
index 506c796..40948b5 100644
--- a/EnumType.cpp
+++ b/EnumType.cpp
@@ -3,6 +3,8 @@
 #include "Formatter.h"
 #include "ScalarType.h"
 
+#include <android-base/logging.h>
+
 namespace android {
 
 EnumValue::EnumValue(const char *name, const char *value)
@@ -60,6 +62,10 @@
     out << "};\n\n";
 }
 
+const ScalarType *EnumType::resolveToScalarType() const {
+    return mStorageType->resolveToScalarType();
+}
+
 std::string EnumType::getCppType(StorageMode, std::string *extra) const {
     extra->clear();
 
@@ -73,17 +79,29 @@
         bool parcelObjIsPointer,
         bool isReader,
         ErrorMode mode) const {
-    mStorageType->emitReaderWriter(
-            out, name, parcelObj, parcelObjIsPointer, isReader, mode);
+    const ScalarType *scalarType = mStorageType->resolveToScalarType();
+    CHECK(scalarType != NULL);
+
+    scalarType->emitReaderWriterWithCast(
+            out,
+            name,
+            parcelObj,
+            parcelObjIsPointer,
+            isReader,
+            mode,
+            true /* needsCast */);
 }
 
 status_t EnumType::emitTypeDeclarations(Formatter &out) const {
+    const ScalarType *scalarType = mStorageType->resolveToScalarType();
+    CHECK(scalarType != NULL);
+
     std::string extra;
 
     out << "enum class "
         << name()
         << " : "
-        << mStorageType->getCppType(&extra)
+        << ((Type *)scalarType)->getCppType(&extra)
         << " {\n";
 
     out.indent();
diff --git a/EnumType.h b/EnumType.h
index a0d866a..a587727 100644
--- a/EnumType.h
+++ b/EnumType.h
@@ -30,6 +30,8 @@
 
     void dump(Formatter &out) const override;
 
+    const ScalarType *resolveToScalarType() const override;
+
     std::string getCppType(StorageMode mode, std::string *extra) const override;
 
     void emitReaderWriter(
diff --git a/HandleType.cpp b/HandleType.cpp
index ea5d665..9e55638 100644
--- a/HandleType.cpp
+++ b/HandleType.cpp
@@ -121,8 +121,11 @@
         out.indent();
         out.indent();
 
-        out << name
-            << (nameIsPointer ? "->" : ".")
+        const std::string nameDeref =
+            nameIsPointer ? ("(*" + name + ")") : name;
+
+        out << nameDeref
+            << "->"
             << "handle(),\n"
             << parentName
             << ",\n"
diff --git a/RefType.cpp b/RefType.cpp
index c71d1d7..fcb8604 100644
--- a/RefType.cpp
+++ b/RefType.cpp
@@ -9,6 +9,10 @@
       mReferencedType(type) {
 }
 
+const ScalarType *RefType::resolveToScalarType() const {
+    return mReferencedType->resolveToScalarType();
+}
+
 const Type *RefType::referencedType() const {
     return mReferencedType;
 }
diff --git a/RefType.h b/RefType.h
index 87e2194..c5b7b3c 100644
--- a/RefType.h
+++ b/RefType.h
@@ -11,6 +11,8 @@
 
     void dump(Formatter &out) const override;
 
+    const ScalarType *resolveToScalarType() const override;
+
     const Type *referencedType() const;
 
     std::string getCppType(StorageMode mode, std::string *extra) const override;
diff --git a/ScalarType.cpp b/ScalarType.cpp
index c498f8c..14fa4e2 100644
--- a/ScalarType.cpp
+++ b/ScalarType.cpp
@@ -16,6 +16,10 @@
     out << kName[mKind];
 }
 
+const ScalarType *ScalarType::resolveToScalarType() const {
+    return this;
+}
+
 std::string ScalarType::getCppType(StorageMode, std::string *extra) const {
     static const char *const kName[] = {
         "char",
@@ -45,6 +49,24 @@
         bool parcelObjIsPointer,
         bool isReader,
         ErrorMode mode) const {
+    emitReaderWriterWithCast(
+            out,
+            name,
+            parcelObj,
+            parcelObjIsPointer,
+            isReader,
+            mode,
+            false /* needsCast */);
+}
+
+void ScalarType::emitReaderWriterWithCast(
+        Formatter &out,
+        const std::string &name,
+        const std::string &parcelObj,
+        bool parcelObjIsPointer,
+        bool isReader,
+        ErrorMode mode,
+        bool needsCast) const {
     static const char *const kSuffix[] = {
         "Uint8",
         "Uint8",
@@ -70,6 +92,14 @@
         << kSuffix[mKind]
         << "(";
 
+    if (needsCast) {
+        std::string extra;
+
+        out << "("
+            << Type::getCppType(&extra)
+            << (isReader ? " *)" : ")");
+    }
+
     if (isReader) {
         out << "&";
     }
diff --git a/ScalarType.h b/ScalarType.h
index 2bd7cae..61220d6 100644
--- a/ScalarType.h
+++ b/ScalarType.h
@@ -27,6 +27,8 @@
 
     void dump(Formatter &out) const override;
 
+    const ScalarType *resolveToScalarType() const override;
+
     std::string getCppType(StorageMode mode, std::string *extra) const override;
 
     void emitReaderWriter(
@@ -37,6 +39,15 @@
             bool isReader,
             ErrorMode mode) const override;
 
+    void emitReaderWriterWithCast(
+            Formatter &out,
+            const std::string &name,
+            const std::string &parcelObj,
+            bool parcelObjIsPointer,
+            bool isReader,
+            ErrorMode mode,
+            bool needsCast) const;
+
 private:
     Kind mKind;
 
diff --git a/Type.cpp b/Type.cpp
index 5f3c462..548e425 100644
--- a/Type.cpp
+++ b/Type.cpp
@@ -17,6 +17,10 @@
     return false;
 }
 
+const ScalarType *Type::resolveToScalarType() const {
+    return NULL;
+}
+
 std::string Type::getCppType(StorageMode, std::string *) const {
     CHECK(!"Should not be here");
     return std::string();
@@ -64,6 +68,12 @@
             out << "if (_aidl_err != ::android::OK) { break; }\n\n";
             break;
         }
+
+        case ErrorMode_Return:
+        {
+            out << "if (_aidl_err != ::android::OK) { return _aidl_err; }\n\n";
+            break;
+        }
     }
 }
 
@@ -74,16 +84,24 @@
             out << "goto _aidl_error;\n";
             break;
         }
+
         case ErrorMode_Break:
         {
             out << "break;\n";
             break;
         }
+
         case ErrorMode_Ignore:
         {
             out << "/* ignoring _aidl_error! */";
             break;
         }
+
+        case ErrorMode_Return:
+        {
+            out << "return _aidl_err;\n";
+            break;
+        }
     }
 }
 
diff --git a/Type.h b/Type.h
index f7f8509..8e84c55 100644
--- a/Type.h
+++ b/Type.h
@@ -9,6 +9,7 @@
 namespace android {
 
 struct Formatter;
+struct ScalarType;
 
 struct Type {
     Type();
@@ -17,6 +18,7 @@
     virtual void dump(Formatter &out) const = 0;
     virtual bool isScope() const;
     virtual bool isInterface() const;
+    virtual const ScalarType *resolveToScalarType() const;
 
     enum StorageMode {
         StorageMode_Stack,
@@ -36,6 +38,7 @@
         ErrorMode_Ignore,
         ErrorMode_Goto,
         ErrorMode_Break,
+        ErrorMode_Return,
     };
     virtual void emitReaderWriter(
             Formatter &out,
diff --git a/TypeDef.cpp b/TypeDef.cpp
index 163a7e7..94c38cb 100644
--- a/TypeDef.cpp
+++ b/TypeDef.cpp
@@ -9,6 +9,10 @@
       mReferencedType(type) {
 }
 
+const ScalarType *TypeDef::resolveToScalarType() const {
+    return mReferencedType->resolveToScalarType();
+}
+
 const Type *TypeDef::referencedType() const {
     return mReferencedType;
 }
diff --git a/TypeDef.h b/TypeDef.h
index 6e2c54c..7ea7163 100644
--- a/TypeDef.h
+++ b/TypeDef.h
@@ -11,6 +11,8 @@
 
     void dump(Formatter &out) const override;
 
+    const ScalarType *resolveToScalarType() const override;
+
     const Type *referencedType() const;
 
     std::string getCppType(StorageMode mode, std::string *extra) const override;
diff --git a/generateCpp.cpp b/generateCpp.cpp
index 4d80b06..0ab32b8 100644
--- a/generateCpp.cpp
+++ b/generateCpp.cpp
@@ -84,16 +84,21 @@
     return err;
 }
 
-void AST::getPackageComponents(
-        std::vector<std::string> *components) const {
-    SplitString(mPackage.package(), '.', components);
+// static
+void AST::GetPackageComponents(
+        const FQName &fqName,
+        std::vector<std::string> *components) {
+    SplitString(fqName.package(), '.', components);
 }
 
-void AST::getPackageAndVersionComponents(
-        std::vector<std::string> *components, bool cpp_compatible) const {
-    getPackageComponents(components);
+// static
+void AST::GetPackageAndVersionComponents(
+        const FQName &fqName,
+        std::vector<std::string> *components,
+        bool cpp_compatible) {
+    GetPackageComponents(fqName, components);
 
-    const std::string packageVersion = mPackage.version();
+    const std::string packageVersion = fqName.version();
     CHECK(packageVersion[0] == '@');
 
     if (!cpp_compatible) {
@@ -112,6 +117,16 @@
     components->push_back(versionString);
 }
 
+void AST::getPackageComponents(
+        std::vector<std::string> *components) const {
+    GetPackageComponents(mPackage, components);
+}
+
+void AST::getPackageAndVersionComponents(
+        std::vector<std::string> *components, bool cpp_compatible) const {
+    GetPackageAndVersionComponents(mPackage, components, cpp_compatible);
+}
+
 std::string AST::makeHeaderGuard(const std::string &baseName) const {
     std::vector<std::string> packageComponents;
     getPackageAndVersionComponents(
@@ -179,6 +194,25 @@
     out << "#ifndef " << guard << "\n";
     out << "#define " << guard << "\n\n";
 
+    for (const auto &item : mImportedNames) {
+        out << "#include <";
+
+        std::vector<std::string> components;
+        GetPackageAndVersionComponents(
+                item, &components, false /* cpp_compatible */);
+
+        for (const auto &component : components) {
+            out << component << "/";
+        }
+
+        out << item.name()
+            << ".h>\n";
+    }
+
+    if (!mImportedNames.empty()) {
+        out << "\n";
+    }
+
     out << "#include <hwbinder/HidlSupport.h>\n";
 
     if (isInterface) {
@@ -199,7 +233,10 @@
 
         out.indent();
 
-        out << "DECLARE_HWBINDER_META_INTERFACE(" << ifaceName << ");\n\n";
+        // 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);
diff --git a/main.cpp b/main.cpp
index b21d3aa..7869e4b 100644
--- a/main.cpp
+++ b/main.cpp
@@ -16,6 +16,8 @@
 int main(int argc, char **argv) {
     std::string outputDir;
 
+    const char *me = argv[0];
+
     int res;
     while ((res = getopt(argc, argv, "ho:")) >= 0) {
         switch (res) {
@@ -29,7 +31,7 @@
             case 'h':
             default:
             {
-                usage(argv[0]);
+                usage(me);
                 exit(1);
                 break;
             }
@@ -39,8 +41,10 @@
     argc -= optind;
     argv += optind;
 
+    // Valid options are now in argv[0] .. argv[argc - 1].
+
     if (outputDir.empty()) {
-        usage(argv[0]);
+        usage(me);
         exit(1);
     } else {
         const size_t len = outputDir.size();
@@ -60,7 +64,7 @@
 
     Coordinator coordinator(interfacesPath);
 
-    for (int i = 1; i < argc; ++i) {
+    for (int i = 0; i < argc; ++i) {
         FQName fqName(argv[i]);
         CHECK(fqName.isValid() && fqName.isFullyQualified());