1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "AST.h" 18 19 #include "Coordinator.h" 20 #include "EnumType.h" 21 #include "Interface.h" 22 #include "Method.h" 23 #include "ScalarType.h" 24 #include "Scope.h" 25 26 #include <algorithm> 27 #include <hidl-util/Formatter.h> 28 #include <android-base/logging.h> 29 #include <string> 30 #include <vector> 31 #include <set> 32 33 namespace android { 34 35 status_t AST::generateCppImpl(const std::string &outputPath) const { 36 status_t err = generateStubImplHeader(outputPath); 37 38 if (err == OK) { 39 err = generateStubImplSource(outputPath); 40 } 41 42 return err; 43 } 44 45 void AST::generateFetchSymbol(Formatter &out, const std::string& ifaceName) const { 46 out << "HIDL_FETCH_" << ifaceName; 47 } 48 49 status_t AST::generateStubImplMethod(Formatter &out, 50 const std::string &className, 51 const Method *method) const { 52 53 // ignore HIDL reserved methods -- implemented in IFoo already. 54 if (method->isHidlReserved()) { 55 return OK; 56 } 57 58 method->generateCppSignature(out, className, false /* specifyNamespaces */); 59 60 out << " {\n"; 61 62 out.indent(); 63 out << "// TODO implement\n"; 64 65 const TypedVar *elidedReturn = method->canElideCallback(); 66 67 if (elidedReturn == nullptr) { 68 out << "return Void();\n"; 69 } else { 70 out << "return " 71 << elidedReturn->type().getCppResultType() 72 << " {};\n"; 73 } 74 75 out.unindent(); 76 77 out << "}\n\n"; 78 79 return OK; 80 } 81 82 status_t AST::generateStubImplHeader(const std::string &outputPath) const { 83 if (!AST::isInterface()) { 84 // types.hal does not get a stub header. 85 return OK; 86 } 87 88 const Interface* iface = mRootScope.getInterface(); 89 const std::string baseName = iface->getBaseName(); 90 91 std::string path = outputPath; 92 path.append(baseName); 93 path.append(".h"); 94 95 CHECK(Coordinator::MakeParentHierarchy(path)); 96 FILE *file = fopen(path.c_str(), "w"); 97 98 if (file == NULL) { 99 return -errno; 100 } 101 102 Formatter out(file); 103 104 const std::string guard = makeHeaderGuard(baseName, false /* indicateGenerated */); 105 106 out << "#ifndef " << guard << "\n"; 107 out << "#define " << guard << "\n\n"; 108 109 generateCppPackageInclude(out, mPackage, iface->localName()); 110 111 out << "#include <hidl/MQDescriptor.h>\n"; 112 out << "#include <hidl/Status.h>\n\n"; 113 114 enterLeaveNamespace(out, true /* enter */); 115 out << "namespace implementation {\n\n"; 116 117 out << "using ::android::hardware::hidl_array;\n"; 118 out << "using ::android::hardware::hidl_memory;\n"; 119 out << "using ::android::hardware::hidl_string;\n"; 120 out << "using ::android::hardware::hidl_vec;\n"; 121 out << "using ::android::hardware::Return;\n"; 122 out << "using ::android::hardware::Void;\n"; 123 out << "using ::android::sp;\n"; 124 125 out << "\n"; 126 127 out << "struct " 128 << baseName 129 << " : public " 130 << iface->localName() 131 << " {\n"; 132 133 out.indent(); 134 135 status_t err = generateMethods(out, [&](const Method *method, const Interface *) { 136 // ignore HIDL reserved methods -- implemented in IFoo already. 137 if (method->isHidlReserved()) { 138 return OK; 139 } 140 method->generateCppSignature(out, "" /* className */, 141 false /* specifyNamespaces */); 142 out << " override;\n"; 143 return OK; 144 }); 145 146 if (err != OK) { 147 return err; 148 } 149 150 out.unindent(); 151 152 out << "};\n\n"; 153 154 out << "// FIXME: most likely delete, this is only for passthrough implementations\n" 155 << "// extern \"C\" " 156 << iface->localName() 157 << "* "; 158 generateFetchSymbol(out, iface->localName()); 159 out << "(const char* name);\n\n"; 160 161 out << "} // namespace implementation\n"; 162 enterLeaveNamespace(out, false /* leave */); 163 164 out << "\n#endif // " << guard << "\n"; 165 166 return OK; 167 } 168 169 status_t AST::generateStubImplSource(const std::string &outputPath) const { 170 if (!AST::isInterface()) { 171 // types.hal does not get a stub header. 172 return OK; 173 } 174 175 const Interface* iface = mRootScope.getInterface(); 176 const std::string baseName = iface->getBaseName(); 177 178 std::string path = outputPath; 179 path.append(baseName); 180 path.append(".cpp"); 181 182 CHECK(Coordinator::MakeParentHierarchy(path)); 183 FILE *file = fopen(path.c_str(), "w"); 184 185 if (file == NULL) { 186 return -errno; 187 } 188 189 Formatter out(file); 190 191 out << "#include \"" << baseName << ".h\"\n\n"; 192 193 enterLeaveNamespace(out, true /* enter */); 194 out << "namespace implementation {\n\n"; 195 196 status_t err = generateMethods(out, [&](const Method *method, const Interface *) { 197 return generateStubImplMethod(out, baseName, method); 198 }); 199 200 if (err != OK) { 201 return err; 202 } 203 204 out.setLinePrefix("//"); 205 out << iface->localName() 206 << "* "; 207 generateFetchSymbol(out, iface->localName()); 208 out << "(const char* /* name */) {\n"; 209 out.indent(); 210 out << "return new " << baseName << "();\n"; 211 out.unindent(); 212 out << "}\n\n"; 213 out.unsetLinePrefix(); 214 215 out << "} // namespace implementation\n"; 216 enterLeaveNamespace(out, false /* leave */); 217 218 return OK; 219 } 220 221 } // namespace android 222