blob: 4f58c50f0206c719ba105946ba04333c26ab160e [file] [log] [blame]
Christopher Wileyeb1acc12015-09-16 11:25:13 -07001/*
2 * Copyright (C) 2015, 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 "generate_cpp.h"
Casey Dahlina834dd42015-09-23 11:52:15 -070018#include "parse_helpers.h"
Christopher Wiley9a8e1d92015-09-19 10:34:33 -070019
Casey Dahlin082f1d12015-09-21 14:06:25 -070020#include <cctype>
Christopher Wiley9a8e1d92015-09-19 10:34:33 -070021#include <memory>
Casey Dahlin082f1d12015-09-21 14:06:25 -070022#include <random>
Christopher Wiley9a8e1d92015-09-19 10:34:33 -070023#include <string>
24
Christopher Wileye3550c62015-09-29 13:26:10 -070025#include <base/stringprintf.h>
26
Casey Dahlina834dd42015-09-23 11:52:15 -070027#include "aidl_language.h"
Christopher Wiley9a8e1d92015-09-19 10:34:33 -070028#include "ast_cpp.h"
29#include "code_writer.h"
Christopher Wileyeb1acc12015-09-16 11:25:13 -070030#include "logging.h"
31
Christopher Wileye3550c62015-09-29 13:26:10 -070032using android::base::StringPrintf;
Christopher Wiley9a8e1d92015-09-19 10:34:33 -070033using std::string;
Casey Dahlin082f1d12015-09-21 14:06:25 -070034using std::unique_ptr;
Casey Dahlina834dd42015-09-23 11:52:15 -070035using std::vector;
Christopher Wiley9a8e1d92015-09-19 10:34:33 -070036
Christopher Wileyeb1acc12015-09-16 11:25:13 -070037namespace android {
38namespace aidl {
Christopher Wileyf944e792015-09-29 10:00:46 -070039namespace cpp {
Casey Dahlina834dd42015-09-23 11:52:15 -070040namespace internals {
Christopher Wiley0c732db2015-09-29 14:36:44 -070041namespace {
Christopher Wileyeb1acc12015-09-16 11:25:13 -070042
Christopher Wiley0c732db2015-09-29 14:36:44 -070043const char kAndroidStatusLiteral[] = "android::status_t";
44const char kIBinderHeader[] = "binder/IBinder.h";
45const char kIInterfaceHeader[] = "binder/IInterface.h";
Casey Dahlin082f1d12015-09-21 14:06:25 -070046
Christopher Wiley0c732db2015-09-29 14:36:44 -070047string UpperCase(const std::string& s) {
48 string result = s;
49 for (char& c : result)
50 c = toupper(c);
51 return result;
Casey Dahlina834dd42015-09-23 11:52:15 -070052}
Casey Dahlin082f1d12015-09-21 14:06:25 -070053
Casey Dahlin0ee37582015-09-30 16:31:55 -070054string GetCPPVarDec(const TypeNamespace& types, const AidlType& type,
Christopher Wileye3550c62015-09-29 13:26:10 -070055 const string& var_name, bool use_pointer) {
Casey Dahlinf2d23f72015-10-02 16:19:19 -070056 const Type* cpp_type = types.Find(type.GetName());
Christopher Wileye3550c62015-09-29 13:26:10 -070057 if (cpp_type == nullptr) {
58 // We should have caught this in type resolution.
59 LOG(FATAL) << "internal error";
60 }
61 return StringPrintf("%s%s %s%s",
62 cpp_type->CppType().c_str(),
63 (use_pointer) ? "*" : "",
64 var_name.c_str(),
Casey Dahlinf7a421c2015-10-05 17:24:28 -070065 type.IsArray() ? "[]" : "");
Casey Dahlina834dd42015-09-23 11:52:15 -070066}
67
Casey Dahlin5c69deb2015-10-01 14:44:12 -070068unique_ptr<Declaration> BuildMethodDecl(const AidlMethod& method,
Christopher Wiley0c732db2015-09-29 14:36:44 -070069 const TypeNamespace& types,
70 bool for_interface) {
71 vector<string> args;
Casey Dahlinf4a93112015-10-05 16:58:09 -070072 for (const unique_ptr<AidlArgument>& arg : method.GetArguments()) {
Christopher Wiley0c732db2015-09-29 14:36:44 -070073 args.push_back(GetCPPVarDec(
Casey Dahlin0ee37582015-09-30 16:31:55 -070074 types, arg->GetType(), arg->GetName(),
Casey Dahlinc378c992015-09-29 16:50:40 -070075 AidlArgument::OUT_DIR & arg->GetDirection()));
Christopher Wiley0c732db2015-09-29 14:36:44 -070076 }
77
Casey Dahlinf4a93112015-10-05 16:58:09 -070078 string return_arg = GetCPPVarDec(types, method.GetType(), "_aidl_return", true);
Christopher Wiley0c732db2015-09-29 14:36:44 -070079 args.push_back(return_arg);
80
81 uint32_t modifiers = 0;
82 if (for_interface) {
83 modifiers |= MethodDecl::IS_VIRTUAL;
84 modifiers |= MethodDecl::IS_PURE_VIRTUAL;
85 } else {
86 modifiers |= MethodDecl::IS_OVERRIDE;
87 }
88
89 return unique_ptr<Declaration>{
90 new MethodDecl{kAndroidStatusLiteral,
Casey Dahlinf4a93112015-10-05 16:58:09 -070091 method.GetName(),
Christopher Wiley0c732db2015-09-29 14:36:44 -070092 args,
93 modifiers}};
94}
95
96unique_ptr<CppNamespace> NestInNamespaces(unique_ptr<Declaration> decl) {
97 using N = CppNamespace;
98 using NPtr = unique_ptr<N>;
99 return NPtr{new N{"android", NPtr{new N{"generated", std::move(decl)}}}};
100}
101
102} // namespace
103
104enum class ClassNames { BASE, CLIENT, SERVER, INTERFACE };
105
Casey Dahlin1ae2bc52015-10-07 18:49:10 -0700106string ClassName(const AidlInterface& interface, ClassNames type) {
Casey Dahlinfb7da2e2015-10-08 17:26:09 -0700107 string c_name = interface.GetName();
Christopher Wiley0c732db2015-09-29 14:36:44 -0700108
109 if (c_name.length() >= 2 && c_name[0] == 'I' && isupper(c_name[1]))
110 c_name = c_name.substr(1);
111
112 switch (type) {
113 case ClassNames::CLIENT:
114 c_name = "Bp" + c_name;
115 break;
116 case ClassNames::SERVER:
117 c_name = "Bn" + c_name;
118 break;
119 case ClassNames::INTERFACE:
120 c_name = "I" + c_name;
121 break;
122 case ClassNames::BASE:
123 break;
124 }
125 return c_name;
126}
127
Christopher Wileye3550c62015-09-29 13:26:10 -0700128unique_ptr<Document> BuildClientSource(const TypeNamespace& types,
Casey Dahlin1ae2bc52015-10-07 18:49:10 -0700129 const AidlInterface& parsed_doc) {
Christopher Wiley0c732db2015-09-29 14:36:44 -0700130 unique_ptr<CppNamespace> ns{new CppNamespace{"android"}};
Christopher Wileyf944e792015-09-29 10:00:46 -0700131 return unique_ptr<Document>{new CppSource{ {}, std::move(ns)}};
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700132}
133
Christopher Wileye3550c62015-09-29 13:26:10 -0700134unique_ptr<Document> BuildServerSource(const TypeNamespace& types,
Casey Dahlin1ae2bc52015-10-07 18:49:10 -0700135 const AidlInterface& parsed_doc) {
Christopher Wiley0c732db2015-09-29 14:36:44 -0700136 unique_ptr<CppNamespace> ns{new CppNamespace{"android"}};
Christopher Wileyf944e792015-09-29 10:00:46 -0700137 return unique_ptr<Document>{new CppSource{ {}, std::move(ns)}};
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700138}
139
Christopher Wileye3550c62015-09-29 13:26:10 -0700140unique_ptr<Document> BuildInterfaceSource(const TypeNamespace& types,
Casey Dahlin1ae2bc52015-10-07 18:49:10 -0700141 const AidlInterface& parsed_doc) {
Christopher Wiley1dd458d2015-09-30 11:05:52 -0700142 const string i_name = ClassName(parsed_doc, ClassNames::INTERFACE);
143 const string bp_name = ClassName(parsed_doc, ClassNames::CLIENT);
144 vector<string> include_list{i_name + ".h", bp_name + ".h"};
145
146 string fq_name = i_name;
Casey Dahlinfb7da2e2015-10-08 17:26:09 -0700147 if (!parsed_doc.GetPackage().empty()) {
148 fq_name = StringPrintf("%s.%s", parsed_doc.GetPackage().c_str(), i_name.c_str());
Christopher Wiley1dd458d2015-09-30 11:05:52 -0700149 }
150
151 unique_ptr<ConstructorDecl> meta_if{new ConstructorDecl{
152 "IMPLEMENT_META_INTERFACE",
153 {ClassName(parsed_doc, ClassNames::BASE), '"' + fq_name + '"'}
154 }};
155
156 return unique_ptr<Document>{new CppSource{
157 include_list,
158 NestInNamespaces(std::move(meta_if))}};
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700159}
160
Christopher Wileye3550c62015-09-29 13:26:10 -0700161unique_ptr<Document> BuildClientHeader(const TypeNamespace& types,
Casey Dahlin1ae2bc52015-10-07 18:49:10 -0700162 const AidlInterface& parsed_doc) {
Christopher Wiley0c732db2015-09-29 14:36:44 -0700163 const string i_name = ClassName(parsed_doc, ClassNames::INTERFACE);
164 const string bp_name = ClassName(parsed_doc, ClassNames::CLIENT);
Casey Dahlina834dd42015-09-23 11:52:15 -0700165
Christopher Wiley0c732db2015-09-29 14:36:44 -0700166 unique_ptr<ConstructorDecl> constructor{new ConstructorDecl(bp_name, {})};
Christopher Wileyf944e792015-09-29 10:00:46 -0700167 unique_ptr<ConstructorDecl> destructor{
Christopher Wiley0c732db2015-09-29 14:36:44 -0700168 new ConstructorDecl("~" + bp_name, {})};
Casey Dahlina834dd42015-09-23 11:52:15 -0700169
Christopher Wileyf944e792015-09-29 10:00:46 -0700170 vector<unique_ptr<Declaration>> publics;
Casey Dahlina834dd42015-09-23 11:52:15 -0700171 publics.push_back(std::move(constructor));
172 publics.push_back(std::move(destructor));
173
Casey Dahlinfb7da2e2015-10-08 17:26:09 -0700174 for (const auto& item : parsed_doc.GetMethods()) {
Casey Dahlin5c69deb2015-10-01 14:44:12 -0700175 publics.push_back(BuildMethodDecl(*item, types, false));
Casey Dahlina834dd42015-09-23 11:52:15 -0700176 }
177
Christopher Wileyf944e792015-09-29 10:00:46 -0700178 unique_ptr<ClassDecl> bp_class{
179 new ClassDecl{bp_name,
180 "public android::BpInterface<" + i_name + ">",
181 std::move(publics),
182 {}
Casey Dahlina834dd42015-09-23 11:52:15 -0700183 }};
184
Christopher Wiley0c732db2015-09-29 14:36:44 -0700185 return unique_ptr<Document>{new CppHeader{
186 bp_name + "_H",
187 {kIBinderHeader,
188 kIInterfaceHeader,
189 "utils/Errors.h",
190 i_name + ".h"},
191 NestInNamespaces(std::move(bp_class))}};
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700192}
193
Christopher Wileye3550c62015-09-29 13:26:10 -0700194unique_ptr<Document> BuildServerHeader(const TypeNamespace& types,
Casey Dahlin1ae2bc52015-10-07 18:49:10 -0700195 const AidlInterface& parsed_doc) {
Christopher Wiley0c732db2015-09-29 14:36:44 -0700196 const string i_name = ClassName(parsed_doc, ClassNames::INTERFACE);
197 const string bn_name = ClassName(parsed_doc, ClassNames::SERVER);
Casey Dahlin082f1d12015-09-21 14:06:25 -0700198
Christopher Wileyf944e792015-09-29 10:00:46 -0700199 unique_ptr<Declaration> on_transact{
Christopher Wiley0c732db2015-09-29 14:36:44 -0700200 new MethodDecl(kAndroidStatusLiteral, "onTransact",
Christopher Wileyf944e792015-09-29 10:00:46 -0700201 { "uint32_t code",
202 "const android::Parcel& data",
203 "android::Parcel* reply",
204 "uint32_t flags = 0"
205 })};
Casey Dahlin082f1d12015-09-21 14:06:25 -0700206
Christopher Wileyf944e792015-09-29 10:00:46 -0700207 std::vector<unique_ptr<Declaration>> publics;
Casey Dahlinb7d0f7f2015-09-22 17:21:08 -0700208 publics.push_back(std::move(on_transact));
209
Christopher Wileyf944e792015-09-29 10:00:46 -0700210 unique_ptr<ClassDecl> bn_class{
211 new ClassDecl{bn_name,
212 "public android::BnInterface<" + i_name + ">",
213 std::move(publics),
214 {}
Casey Dahlinb7d0f7f2015-09-22 17:21:08 -0700215 }};
Casey Dahlin082f1d12015-09-21 14:06:25 -0700216
Christopher Wiley0c732db2015-09-29 14:36:44 -0700217 return unique_ptr<Document>{new CppHeader{
218 bn_name + "_H",
219 {"binder/IInterface.h",
220 i_name + ".h"},
221 NestInNamespaces(std::move(bn_class))}};
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700222}
223
Christopher Wileye3550c62015-09-29 13:26:10 -0700224unique_ptr<Document> BuildInterfaceHeader(const TypeNamespace& types,
Casey Dahlin1ae2bc52015-10-07 18:49:10 -0700225 const AidlInterface& parsed_doc) {
Christopher Wiley0c732db2015-09-29 14:36:44 -0700226 unique_ptr<ClassDecl> if_class{
227 new ClassDecl{ClassName(parsed_doc, ClassNames::INTERFACE),
228 "public android::IInterface"}};
229 if_class->AddPublic(unique_ptr<Declaration>{
230 new ConstructorDecl{
231 "DECLARE_META_INTERFACE",
232 {ClassName(parsed_doc, ClassNames::BASE)}}});
233
234 unique_ptr<Enum> call_enum{new Enum{"Call"}};
Casey Dahlinfb7da2e2015-10-08 17:26:09 -0700235 for (const auto& method : parsed_doc.GetMethods()) {
Casey Dahlin5c69deb2015-10-01 14:44:12 -0700236 if_class->AddPublic(BuildMethodDecl(*method, types, true));
Christopher Wiley0c732db2015-09-29 14:36:44 -0700237 call_enum->AddValue(
Casey Dahlinf4a93112015-10-05 16:58:09 -0700238 UpperCase(method->GetName()),
Christopher Wiley0c732db2015-09-29 14:36:44 -0700239 StringPrintf("android::IBinder::FIRST_CALL_TRANSACTION + %d",
Casey Dahlinf4a93112015-10-05 16:58:09 -0700240 method->GetId()));
Christopher Wiley0c732db2015-09-29 14:36:44 -0700241 }
242 if_class->AddPublic(std::move(call_enum));
243
244 return unique_ptr<Document>{new CppSource{
245 {kIBinderHeader,
246 kIInterfaceHeader},
247 NestInNamespaces(std::move(if_class))}};
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700248}
249
Christopher Wileyf944e792015-09-29 10:00:46 -0700250bool GenerateCppForFile(const std::string& name, unique_ptr<Document> doc) {
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700251 if (!doc) {
252 return false;
253 }
254 unique_ptr<CodeWriter> writer = GetFileWriter(name);
255 doc->Write(writer.get());
256 return true;
257}
258
Casey Dahlina834dd42015-09-23 11:52:15 -0700259} // namespace internals
260
261using namespace internals;
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700262
Christopher Wileye3550c62015-09-29 13:26:10 -0700263bool GenerateCpp(const CppOptions& options,
264 const TypeNamespace& types,
Casey Dahlin1ae2bc52015-10-07 18:49:10 -0700265 const AidlInterface& parsed_doc) {
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700266 bool success = true;
267
268 success &= GenerateCppForFile(options.ClientCppFileName(),
Christopher Wileye3550c62015-09-29 13:26:10 -0700269 BuildClientSource(types, parsed_doc));
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700270 success &= GenerateCppForFile(options.ClientHeaderFileName(),
Christopher Wileye3550c62015-09-29 13:26:10 -0700271 BuildClientHeader(types, parsed_doc));
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700272 success &= GenerateCppForFile(options.ServerCppFileName(),
Christopher Wileye3550c62015-09-29 13:26:10 -0700273 BuildServerSource(types, parsed_doc));
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700274 success &= GenerateCppForFile(options.ServerHeaderFileName(),
Christopher Wileye3550c62015-09-29 13:26:10 -0700275 BuildServerHeader(types, parsed_doc));
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700276 success &= GenerateCppForFile(options.InterfaceCppFileName(),
Christopher Wileye3550c62015-09-29 13:26:10 -0700277 BuildInterfaceSource(types, parsed_doc));
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700278 success &= GenerateCppForFile(options.InterfaceHeaderFileName(),
Christopher Wileye3550c62015-09-29 13:26:10 -0700279 BuildInterfaceHeader(types, parsed_doc));
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700280
281 return success;
Christopher Wileyeb1acc12015-09-16 11:25:13 -0700282}
283
Christopher Wileyf944e792015-09-29 10:00:46 -0700284} // namespace cpp
Christopher Wileyeb1acc12015-09-16 11:25:13 -0700285} // namespace aidl
Christopher Wileyf944e792015-09-29 10:00:46 -0700286} // namespace android