| /* |
| * 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 "Coordinator.h" |
| #include "EnumType.h" |
| #include "Interface.h" |
| #include "Method.h" |
| #include "ScalarType.h" |
| #include "Scope.h" |
| |
| #include <algorithm> |
| #include <hidl-util/Formatter.h> |
| #include <android-base/logging.h> |
| #include <string> |
| #include <vector> |
| #include <set> |
| |
| namespace android { |
| |
| status_t AST::generateCppImpl(const std::string &outputPath) const { |
| status_t err = generateStubImplHeader(outputPath); |
| |
| if (err == OK) { |
| err = generateStubImplSource(outputPath); |
| } |
| |
| return err; |
| } |
| |
| void AST::generateFetchSymbol(Formatter &out, const std::string& ifaceName) const { |
| out << "HIDL_FETCH_" << ifaceName; |
| } |
| |
| status_t AST::generateStubImplMethod(Formatter &out, |
| const std::string &className, |
| const Method *method) const { |
| |
| // ignore HIDL reserved methods -- implemented in IFoo already. |
| if (method->isHidlReserved()) { |
| return OK; |
| } |
| |
| method->generateCppSignature(out, className, false /* specifyNamespaces */); |
| |
| out << " {\n"; |
| |
| out.indent(); |
| out << "// TODO implement\n"; |
| |
| const TypedVar *elidedReturn = method->canElideCallback(); |
| |
| if (elidedReturn == nullptr) { |
| out << "return Void();\n"; |
| } else { |
| out << "return " |
| << elidedReturn->type().getCppResultType() |
| << " {};\n"; |
| } |
| |
| out.unindent(); |
| |
| out << "}\n\n"; |
| |
| return OK; |
| } |
| |
| status_t AST::generateStubImplHeader(const std::string &outputPath) const { |
| std::string ifaceName; |
| if (!AST::isInterface(&ifaceName)) { |
| // types.hal does not get a stub header. |
| return OK; |
| } |
| |
| const Interface *iface = mRootScope->getInterface(); |
| |
| const std::string baseName = iface->getBaseName(); |
| |
| std::string path = outputPath; |
| path.append(baseName); |
| path.append(".h"); |
| |
| CHECK(Coordinator::MakeParentHierarchy(path)); |
| FILE *file = fopen(path.c_str(), "w"); |
| |
| if (file == NULL) { |
| return -errno; |
| } |
| |
| Formatter out(file); |
| |
| const std::string guard = makeHeaderGuard(baseName, false /* indicateGenerated */); |
| |
| out << "#ifndef " << guard << "\n"; |
| out << "#define " << guard << "\n\n"; |
| |
| generateCppPackageInclude(out, mPackage, "I" + baseName); |
| |
| out << "#include <hidl/MQDescriptor.h>\n"; |
| out << "#include <hidl/Status.h>\n\n"; |
| |
| enterLeaveNamespace(out, true /* enter */); |
| out << "namespace implementation {\n\n"; |
| |
| // this is namespace aware code and doesn't require post-processing |
| out.setNamespace(""); |
| |
| std::vector<const Interface *> chain = iface->typeChain(); |
| |
| std::set<const FQName> usedTypes{}; |
| |
| for (auto it = chain.rbegin(); it != chain.rend(); ++it) { |
| const Interface *superInterface = *it; |
| superInterface->addNamedTypesToSet(usedTypes); |
| } |
| |
| for (const auto &tuple : iface->allMethodsFromRoot()) { |
| const Method *method = tuple.method(); |
| for(const auto & arg : method->args()) { |
| arg->type().addNamedTypesToSet(usedTypes); |
| } |
| for(const auto & results : method->results()) { |
| results->type().addNamedTypesToSet(usedTypes); |
| } |
| } |
| |
| std::set<const FQName> topLevelTypes{}; |
| |
| for (const auto &name : usedTypes) { |
| topLevelTypes.insert(name.getTopLevelType()); |
| } |
| |
| for (const FQName &name : topLevelTypes) { |
| out << "using " << name.cppName() << ";\n"; |
| } |
| |
| out << "using ::android::hardware::hidl_array;\n"; |
| out << "using ::android::hardware::hidl_string;\n"; |
| out << "using ::android::hardware::hidl_vec;\n"; |
| out << "using ::android::hardware::Return;\n"; |
| out << "using ::android::hardware::Void;\n"; |
| out << "using ::android::sp;\n"; |
| |
| out << "\n"; |
| |
| out << "struct " |
| << baseName |
| << " : public " |
| << ifaceName |
| << " {\n"; |
| |
| out.indent(); |
| |
| status_t err = generateMethods(out, [&](const Method *method, const Interface *) { |
| // ignore HIDL reserved methods -- implemented in IFoo already. |
| if (method->isHidlReserved()) { |
| return OK; |
| } |
| method->generateCppSignature(out, "" /* className */, |
| false /* specifyNamespaces */); |
| out << " override;\n"; |
| return OK; |
| }); |
| |
| if (err != OK) { |
| return err; |
| } |
| |
| out.unindent(); |
| |
| out << "};\n\n"; |
| |
| out << "extern \"C\" " |
| << ifaceName |
| << "* "; |
| generateFetchSymbol(out, ifaceName); |
| out << "(const char* name);\n\n"; |
| |
| out << "} // namespace implementation\n"; |
| enterLeaveNamespace(out, false /* leave */); |
| |
| out << "\n#endif // " << guard << "\n"; |
| |
| return OK; |
| } |
| |
| status_t AST::generateStubImplSource(const std::string &outputPath) const { |
| std::string ifaceName; |
| if (!AST::isInterface(&ifaceName)) { |
| // types.hal does not get a stub header. |
| return OK; |
| } |
| |
| const Interface *iface = mRootScope->getInterface(); |
| const std::string baseName = iface->getBaseName(); |
| |
| std::string path = outputPath; |
| path.append(baseName); |
| path.append(".cpp"); |
| |
| CHECK(Coordinator::MakeParentHierarchy(path)); |
| FILE *file = fopen(path.c_str(), "w"); |
| |
| if (file == NULL) { |
| return -errno; |
| } |
| |
| Formatter out(file); |
| |
| out << "#include \"" << baseName << ".h\"\n\n"; |
| |
| enterLeaveNamespace(out, true /* enter */); |
| out << "namespace implementation {\n\n"; |
| |
| // this is namespace aware code and doesn't require post-processing |
| out.setNamespace(""); |
| |
| status_t err = generateMethods(out, [&](const Method *method, const Interface *) { |
| return generateStubImplMethod(out, baseName, method); |
| }); |
| |
| out << ifaceName |
| << "* "; |
| generateFetchSymbol(out, ifaceName); |
| out << "(const char* /* name */) {\n"; |
| out.indent(); |
| out << "return new " << baseName << "();\n"; |
| out.unindent(); |
| out << "}\n\n"; |
| |
| out << "} // namespace implementation\n"; |
| enterLeaveNamespace(out, false /* leave */); |
| |
| return OK; |
| } |
| |
| } // namespace android |