blob: 503e557e75b1c4c735578fc9fe379e91baf289d2 [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
Casey Dahlina834dd42015-09-23 11:52:15 -070025#include "aidl_language.h"
Christopher Wiley9a8e1d92015-09-19 10:34:33 -070026#include "ast_cpp.h"
27#include "code_writer.h"
Christopher Wileyeb1acc12015-09-16 11:25:13 -070028#include "logging.h"
29
Christopher Wiley9a8e1d92015-09-19 10:34:33 -070030using std::string;
Casey Dahlin082f1d12015-09-21 14:06:25 -070031using std::unique_ptr;
Casey Dahlina834dd42015-09-23 11:52:15 -070032using std::vector;
Christopher Wiley9a8e1d92015-09-19 10:34:33 -070033
Christopher Wileyeb1acc12015-09-16 11:25:13 -070034namespace android {
35namespace aidl {
Casey Dahlina834dd42015-09-23 11:52:15 -070036namespace internals {
Christopher Wileyeb1acc12015-09-16 11:25:13 -070037
Casey Dahlina834dd42015-09-23 11:52:15 -070038string StrippedLiteral(const buffer_type& buffer) {
39 std::string i_name = buffer.Literal();
Casey Dahlin082f1d12015-09-21 14:06:25 -070040
Casey Dahlina834dd42015-09-23 11:52:15 -070041 string c_name;
Casey Dahlin082f1d12015-09-21 14:06:25 -070042
Casey Dahlina834dd42015-09-23 11:52:15 -070043 if (i_name.length() >= 2 && i_name[0] == 'I' && isupper(i_name[1]))
44 c_name = i_name.substr(1);
45 else
46 c_name = i_name;
Casey Dahlin082f1d12015-09-21 14:06:25 -070047
Casey Dahlina834dd42015-09-23 11:52:15 -070048 return c_name;
49}
Casey Dahlin082f1d12015-09-21 14:06:25 -070050
Casey Dahlina834dd42015-09-23 11:52:15 -070051string GetCPPType(type_type *type) {
52 string lit = type->type.Literal();
53
54 if (lit == "int")
55 return "int32_t";
56 else if (lit == "long")
57 return "int64_t";
58 else
59 LOG(FATAL) << "Type not yet supported";
60
61 return "int";
62}
63
64string GetCPPVarDec(type_type* type, string name,
65 int direction) {
66 return GetCPPType(type) + ((OUT_PARAMETER & direction) ? "* " : " ") +
67 name + type->Brackets();
Casey Dahlin082f1d12015-09-21 14:06:25 -070068}
69
Christopher Wiley9a8e1d92015-09-19 10:34:33 -070070unique_ptr<CppDocument> BuildClientSource(interface_type* parsed_doc) {
Casey Dahlinb7d0f7f2015-09-22 17:21:08 -070071 unique_ptr<CppNamespace> ns{new CppNamespace{"android", {}}};
72 return unique_ptr<CppDocument>{new CppSource{ {}, std::move(ns)}};
Christopher Wiley9a8e1d92015-09-19 10:34:33 -070073}
74
75unique_ptr<CppDocument> BuildServerSource(interface_type* parsed_doc) {
Casey Dahlinb7d0f7f2015-09-22 17:21:08 -070076 unique_ptr<CppNamespace> ns{new CppNamespace{"android", {}}};
77 return unique_ptr<CppDocument>{new CppSource{ {}, std::move(ns)}};
Christopher Wiley9a8e1d92015-09-19 10:34:33 -070078}
79
80unique_ptr<CppDocument> BuildInterfaceSource(interface_type* parsed_doc) {
Casey Dahlinb7d0f7f2015-09-22 17:21:08 -070081 unique_ptr<CppNamespace> ns{new CppNamespace{"android", {}}};
82 return unique_ptr<CppDocument>{new CppSource{ {}, std::move(ns)}};
Christopher Wiley9a8e1d92015-09-19 10:34:33 -070083}
84
85unique_ptr<CppDocument> BuildClientHeader(interface_type* parsed_doc) {
Casey Dahlina834dd42015-09-23 11:52:15 -070086 string i_name = parsed_doc->name.Literal();
87 string c_name = StrippedLiteral(parsed_doc->name);
88 string bp_name = "Bp" + c_name;
89
90 unique_ptr<CppMacroOrConstructorDeclaration> constructor{
91 new CppMacroOrConstructorDeclaration(bp_name, {}, false, false)};
92
93 unique_ptr<CppMacroOrConstructorDeclaration> destructor{
94 new CppMacroOrConstructorDeclaration("~" + bp_name, {}, false, false)};
95
96 vector<unique_ptr<CppDeclaration>> publics;
97 publics.push_back(std::move(constructor));
98 publics.push_back(std::move(destructor));
99
100 for (interface_item_type *item = parsed_doc->interface_items;
101 item;
102 item = item->next) {
103 if (item->item_type != METHOD_TYPE) {
104 LOG(FATAL) << "Unknown interface item type";
105 return nullptr;
106 }
107
108 method_type *m_item = (method_type *)item;
109
110 string method_name = m_item->name.Literal();
111 string return_arg = GetCPPVarDec(&m_item->type, "_aidl_return",
112 OUT_PARAMETER);
113
114 vector<string> args;
115
116 for (arg_type *arg = m_item->args; arg; arg = arg->next)
117 args.push_back(GetCPPVarDec(&arg->type, arg->name.Literal(),
118 convert_direction(arg->direction.data)));
119
120 args.push_back(return_arg);
121
122 unique_ptr<CppDeclaration> meth {
123 new CppMethodDeclaration("android::status_t", method_name,
124 args, false, true)
125 };
126
127 publics.push_back(std::move(meth));
128 }
129
130 unique_ptr<CppClassDeclaration> bp_class{
131 new CppClassDeclaration{bp_name,
132 "public android::BpInterface<" + i_name + ">",
133 std::move(publics),
134 {}
135 }};
136
137 vector<unique_ptr<CppDeclaration>> bp_class_vec;
138 bp_class_vec.push_back(std::move(bp_class));
139
140 unique_ptr<CppNamespace> ns {new CppNamespace{"android", std::move(bp_class_vec)}};
141
142 unique_ptr<CppDocument> bp_header{new CppHeader{bp_name + "_H",
143 {"binder/IBinder.h",
144 "binder/IInterface.h",
145 "utils/Errors.h",
146 i_name + ".h"},
147 std::move(ns) }};
148
149 return bp_header;
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700150}
151
152unique_ptr<CppDocument> BuildServerHeader(interface_type* parsed_doc) {
Casey Dahlina834dd42015-09-23 11:52:15 -0700153 string i_name = parsed_doc->name.Literal();;
154 string c_name = StrippedLiteral(parsed_doc->name);
Casey Dahlin082f1d12015-09-21 14:06:25 -0700155 string bn_name = "Bn" + c_name;
156
Casey Dahlinb7d0f7f2015-09-22 17:21:08 -0700157 unique_ptr<CppDeclaration> on_transact{
Casey Dahlin082f1d12015-09-21 14:06:25 -0700158 new CppMethodDeclaration("android::status_t", "onTransact",
159 { "uint32_t code",
160 "const android::Parcel& data",
161 "android::Parcel* reply",
162 "uint32_t flags = 0"
Casey Dahlinb7d0f7f2015-09-22 17:21:08 -0700163 })};
Casey Dahlin082f1d12015-09-21 14:06:25 -0700164
Casey Dahlinb7d0f7f2015-09-22 17:21:08 -0700165 std::vector<unique_ptr<CppDeclaration>> publics;
166 publics.push_back(std::move(on_transact));
167
168 unique_ptr<CppClassDeclaration> bn_class{
Casey Dahlin082f1d12015-09-21 14:06:25 -0700169 new CppClassDeclaration{bn_name,
170 "public android::BnInterface<" + i_name + ">",
Casey Dahlinb7d0f7f2015-09-22 17:21:08 -0700171 std::move(publics),
Casey Dahlin082f1d12015-09-21 14:06:25 -0700172 {}
Casey Dahlinb7d0f7f2015-09-22 17:21:08 -0700173 }};
Casey Dahlin082f1d12015-09-21 14:06:25 -0700174
Casey Dahlinb7d0f7f2015-09-22 17:21:08 -0700175 std::vector<unique_ptr<CppDeclaration>> declarations;
176 declarations.push_back(std::move(bn_class));
177
178 unique_ptr<CppNamespace> ns{new CppNamespace{"android", std::move(declarations)}};
Casey Dahlin082f1d12015-09-21 14:06:25 -0700179
Casey Dahlina834dd42015-09-23 11:52:15 -0700180 unique_ptr<CppDocument> bn_header{new CppHeader{bn_name + "_H",
Casey Dahlin082f1d12015-09-21 14:06:25 -0700181 {"binder/IInterface.h",
182 i_name + ".h"},
Casey Dahlinb7d0f7f2015-09-22 17:21:08 -0700183 std::move(ns) }};
Casey Dahlin082f1d12015-09-21 14:06:25 -0700184
185 return bn_header;
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700186}
187
188unique_ptr<CppDocument> BuildInterfaceHeader(interface_type* parsed_doc) {
Casey Dahlinb7d0f7f2015-09-22 17:21:08 -0700189 unique_ptr<CppNamespace> ns{new CppNamespace{"android", {}}};
190 return unique_ptr<CppDocument>{new CppSource{ {}, std::move(ns)}};
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700191}
192
193bool GenerateCppForFile(const std::string& name, unique_ptr<CppDocument> doc) {
194 if (!doc) {
195 return false;
196 }
197 unique_ptr<CodeWriter> writer = GetFileWriter(name);
198 doc->Write(writer.get());
199 return true;
200}
201
Casey Dahlina834dd42015-09-23 11:52:15 -0700202} // namespace internals
203
204using namespace internals;
Christopher Wiley9a8e1d92015-09-19 10:34:33 -0700205
206bool GenerateCpp(const CppOptions& options, interface_type* parsed_doc) {
207 bool success = true;
208
209 success &= GenerateCppForFile(options.ClientCppFileName(),
210 BuildClientSource(parsed_doc));
211 success &= GenerateCppForFile(options.ClientHeaderFileName(),
212 BuildClientHeader(parsed_doc));
213 success &= GenerateCppForFile(options.ServerCppFileName(),
214 BuildServerSource(parsed_doc));
215 success &= GenerateCppForFile(options.ServerHeaderFileName(),
216 BuildServerHeader(parsed_doc));
217 success &= GenerateCppForFile(options.InterfaceCppFileName(),
218 BuildInterfaceSource(parsed_doc));
219 success &= GenerateCppForFile(options.InterfaceHeaderFileName(),
220 BuildInterfaceHeader(parsed_doc));
221
222 return success;
Christopher Wileyeb1acc12015-09-16 11:25:13 -0700223}
224
225} // namespace android
226} // namespace aidl