added c2hal

This is a transpiler which converts C headers to .hal files. Its design
is intended to mirror hidl-gen in order to make it easier for team
members familiar with one to be familiar with the other.

After making c2hal, commands from ~/android/master/:

Build the test.h header:
c2hal -r android.hardware:hardware/interfaces -p android.hardware.baz@1.0 system/tools/hidl/c2hal/test/test.h

Build the simple.h header:
c2hal -r android.hardware:hardware/interfaces -p android.hardware.simple@1.0 system/tools/hidl/c2hal/test/simple.h

Build all headers from libhardware:
python3 system/tools/hidl/c2hal/test/build_all.py ~/android/master/hardware/libhardware/include/hardware/

Build various OpenGl versions:
python3 system/tools/hidl/c2hal/test/build_all.py -g ~/android/master/frameworks/native/opengl/include/EGL/
python3 system/tools/hidl/c2hal/test/build_all.py -g ~/android/master/frameworks/native/opengl/include/ETC1/
python3 system/tools/hidl/c2hal/test/build_all.py -g ~/android/master/frameworks/native/opengl/include/GLES/
python3 system/tools/hidl/c2hal/test/build_all.py -g ~/android/master/frameworks/native/opengl/include/GLES2/
python3 system/tools/hidl/c2hal/test/build_all.py -g ~/android/master/frameworks/native/opengl/include/GLES3/
python3 system/tools/hidl/c2hal/test/build_all.py -g ~/android/master/frameworks/native/opengl/include/KHR/

Change-Id: I5a3b1d6d2350dd7e1ff825deeec212314b49d083
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