• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
generateCppImpl(const std::string & outputPath) const35 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 
generateFetchSymbol(Formatter & out,const std::string & ifaceName) const45 void AST::generateFetchSymbol(Formatter &out, const std::string& ifaceName) const {
46     out << "HIDL_FETCH_" << ifaceName;
47 }
48 
generateStubImplMethod(Formatter & out,const std::string & className,const Method * method) const49 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 
generateStubImplHeader(const std::string & outputPath) const82 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 
generateStubImplSource(const std::string & outputPath) const169 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