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
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