blob: 93a62827c6949d4b1e4c12748bd06a2405241821 [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
Christopher Wileye3550c62015-09-29 13:26:10 -070054string GetCPPVarDec(const TypeNamespace& types, const type_type* type,
55 const string& var_name, bool use_pointer) {
56 const Type* cpp_type = types.Find(type->type.data);
57 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(),
65 type->Brackets().c_str());
Casey Dahlina834dd42015-09-23 11:52:15 -070066}
67
Christopher Wiley0c732db2015-09-29 14:36:44 -070068unique_ptr<Declaration> BuildMethodDecl(const method_type* method,
69 const TypeNamespace& types,
70 bool for_interface) {
71 vector<string> args;
72 for (const unique_ptr<AidlArgument>& arg : *method->args) {
73 args.push_back(GetCPPVarDec(
74 types, &arg->type, arg->name.Literal(),
75 OUT_PARAMETER & convert_direction(arg->direction.data)));
76 }
77
78 string return_arg = GetCPPVarDec(types, &method->type, "_aidl_return", true);
79 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,
91 method->name.Literal(),
92 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
106string ClassName(const interface_type& interface, ClassNames type) {
107 string c_name = interface.name.Literal();
108
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,
129 const interface_type& 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,
135 const interface_type& 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,
141 const interface_type& parsed_doc) {
Christopher Wiley0c732db2015-09-29 14:36:44 -0700142 unique_ptr<CppNamespace> ns{new CppNamespace{"android"}};
Christopher Wileyf944e792015-09-29 10:00:46 -0700143 return unique_ptr<Document>{new CppSource{ {}, std::move(ns)}};
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700144}
145
Christopher Wileye3550c62015-09-29 13:26:10 -0700146unique_ptr<Document> BuildClientHeader(const TypeNamespace& types,
147 const interface_type& parsed_doc) {
Christopher Wiley0c732db2015-09-29 14:36:44 -0700148 const string i_name = ClassName(parsed_doc, ClassNames::INTERFACE);
149 const string bp_name = ClassName(parsed_doc, ClassNames::CLIENT);
Casey Dahlina834dd42015-09-23 11:52:15 -0700150
Christopher Wiley0c732db2015-09-29 14:36:44 -0700151 unique_ptr<ConstructorDecl> constructor{new ConstructorDecl(bp_name, {})};
Christopher Wileyf944e792015-09-29 10:00:46 -0700152 unique_ptr<ConstructorDecl> destructor{
Christopher Wiley0c732db2015-09-29 14:36:44 -0700153 new ConstructorDecl("~" + bp_name, {})};
Casey Dahlina834dd42015-09-23 11:52:15 -0700154
Christopher Wileyf944e792015-09-29 10:00:46 -0700155 vector<unique_ptr<Declaration>> publics;
Casey Dahlina834dd42015-09-23 11:52:15 -0700156 publics.push_back(std::move(constructor));
157 publics.push_back(std::move(destructor));
158
Christopher Wileye3550c62015-09-29 13:26:10 -0700159 for (method_type *item = parsed_doc.interface_items;
Casey Dahlina834dd42015-09-23 11:52:15 -0700160 item;
161 item = item->next) {
Christopher Wiley0c732db2015-09-29 14:36:44 -0700162 publics.push_back(BuildMethodDecl(item, types, false));
Casey Dahlina834dd42015-09-23 11:52:15 -0700163 }
164
Christopher Wileyf944e792015-09-29 10:00:46 -0700165 unique_ptr<ClassDecl> bp_class{
166 new ClassDecl{bp_name,
167 "public android::BpInterface<" + i_name + ">",
168 std::move(publics),
169 {}
Casey Dahlina834dd42015-09-23 11:52:15 -0700170 }};
171
Christopher Wiley0c732db2015-09-29 14:36:44 -0700172 return unique_ptr<Document>{new CppHeader{
173 bp_name + "_H",
174 {kIBinderHeader,
175 kIInterfaceHeader,
176 "utils/Errors.h",
177 i_name + ".h"},
178 NestInNamespaces(std::move(bp_class))}};
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700179}
180
Christopher Wileye3550c62015-09-29 13:26:10 -0700181unique_ptr<Document> BuildServerHeader(const TypeNamespace& types,
182 const interface_type& parsed_doc) {
Christopher Wiley0c732db2015-09-29 14:36:44 -0700183 const string i_name = ClassName(parsed_doc, ClassNames::INTERFACE);
184 const string bn_name = ClassName(parsed_doc, ClassNames::SERVER);
Casey Dahlin082f1d12015-09-21 14:06:25 -0700185
Christopher Wileyf944e792015-09-29 10:00:46 -0700186 unique_ptr<Declaration> on_transact{
Christopher Wiley0c732db2015-09-29 14:36:44 -0700187 new MethodDecl(kAndroidStatusLiteral, "onTransact",
Christopher Wileyf944e792015-09-29 10:00:46 -0700188 { "uint32_t code",
189 "const android::Parcel& data",
190 "android::Parcel* reply",
191 "uint32_t flags = 0"
192 })};
Casey Dahlin082f1d12015-09-21 14:06:25 -0700193
Christopher Wileyf944e792015-09-29 10:00:46 -0700194 std::vector<unique_ptr<Declaration>> publics;
Casey Dahlinb7d0f7f2015-09-22 17:21:08 -0700195 publics.push_back(std::move(on_transact));
196
Christopher Wileyf944e792015-09-29 10:00:46 -0700197 unique_ptr<ClassDecl> bn_class{
198 new ClassDecl{bn_name,
199 "public android::BnInterface<" + i_name + ">",
200 std::move(publics),
201 {}
Casey Dahlinb7d0f7f2015-09-22 17:21:08 -0700202 }};
Casey Dahlin082f1d12015-09-21 14:06:25 -0700203
Christopher Wiley0c732db2015-09-29 14:36:44 -0700204 return unique_ptr<Document>{new CppHeader{
205 bn_name + "_H",
206 {"binder/IInterface.h",
207 i_name + ".h"},
208 NestInNamespaces(std::move(bn_class))}};
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700209}
210
Christopher Wileye3550c62015-09-29 13:26:10 -0700211unique_ptr<Document> BuildInterfaceHeader(const TypeNamespace& types,
212 const interface_type& parsed_doc) {
Christopher Wiley0c732db2015-09-29 14:36:44 -0700213 unique_ptr<ClassDecl> if_class{
214 new ClassDecl{ClassName(parsed_doc, ClassNames::INTERFACE),
215 "public android::IInterface"}};
216 if_class->AddPublic(unique_ptr<Declaration>{
217 new ConstructorDecl{
218 "DECLARE_META_INTERFACE",
219 {ClassName(parsed_doc, ClassNames::BASE)}}});
220
221 unique_ptr<Enum> call_enum{new Enum{"Call"}};
222 for (const method_type* method = parsed_doc.interface_items;
223 method;
224 method = method->next) {
225 if_class->AddPublic(BuildMethodDecl(method, types, true));
226 call_enum->AddValue(
227 UpperCase(method->name.data),
228 StringPrintf("android::IBinder::FIRST_CALL_TRANSACTION + %d",
229 method->assigned_id));
230 }
231 if_class->AddPublic(std::move(call_enum));
232
233 return unique_ptr<Document>{new CppSource{
234 {kIBinderHeader,
235 kIInterfaceHeader},
236 NestInNamespaces(std::move(if_class))}};
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700237}
238
Christopher Wileyf944e792015-09-29 10:00:46 -0700239bool GenerateCppForFile(const std::string& name, unique_ptr<Document> doc) {
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700240 if (!doc) {
241 return false;
242 }
243 unique_ptr<CodeWriter> writer = GetFileWriter(name);
244 doc->Write(writer.get());
245 return true;
246}
247
Casey Dahlina834dd42015-09-23 11:52:15 -0700248} // namespace internals
249
250using namespace internals;
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700251
Christopher Wileye3550c62015-09-29 13:26:10 -0700252bool GenerateCpp(const CppOptions& options,
253 const TypeNamespace& types,
254 const interface_type& parsed_doc) {
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700255 bool success = true;
256
257 success &= GenerateCppForFile(options.ClientCppFileName(),
Christopher Wileye3550c62015-09-29 13:26:10 -0700258 BuildClientSource(types, parsed_doc));
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700259 success &= GenerateCppForFile(options.ClientHeaderFileName(),
Christopher Wileye3550c62015-09-29 13:26:10 -0700260 BuildClientHeader(types, parsed_doc));
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700261 success &= GenerateCppForFile(options.ServerCppFileName(),
Christopher Wileye3550c62015-09-29 13:26:10 -0700262 BuildServerSource(types, parsed_doc));
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700263 success &= GenerateCppForFile(options.ServerHeaderFileName(),
Christopher Wileye3550c62015-09-29 13:26:10 -0700264 BuildServerHeader(types, parsed_doc));
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700265 success &= GenerateCppForFile(options.InterfaceCppFileName(),
Christopher Wileye3550c62015-09-29 13:26:10 -0700266 BuildInterfaceSource(types, parsed_doc));
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700267 success &= GenerateCppForFile(options.InterfaceHeaderFileName(),
Christopher Wileye3550c62015-09-29 13:26:10 -0700268 BuildInterfaceHeader(types, parsed_doc));
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700269
270 return success;
Christopher Wileyeb1acc12015-09-16 11:25:13 -0700271}
272
Christopher Wileyf944e792015-09-29 10:00:46 -0700273} // namespace cpp
Christopher Wileyeb1acc12015-09-16 11:25:13 -0700274} // namespace aidl
Christopher Wileyf944e792015-09-29 10:00:46 -0700275} // namespace android