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