Christopher Wiley | eb1acc1 | 2015-09-16 11:25:13 -0700 | [diff] [blame] | 1 | /* |
| 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 Dahlin | a834dd4 | 2015-09-23 11:52:15 -0700 | [diff] [blame^] | 18 | #include "parse_helpers.h" |
Christopher Wiley | 9a8e1d9 | 2015-09-19 10:34:33 -0700 | [diff] [blame] | 19 | |
Casey Dahlin | 082f1d1 | 2015-09-21 14:06:25 -0700 | [diff] [blame] | 20 | #include <cctype> |
Christopher Wiley | 9a8e1d9 | 2015-09-19 10:34:33 -0700 | [diff] [blame] | 21 | #include <memory> |
Casey Dahlin | 082f1d1 | 2015-09-21 14:06:25 -0700 | [diff] [blame] | 22 | #include <random> |
Christopher Wiley | 9a8e1d9 | 2015-09-19 10:34:33 -0700 | [diff] [blame] | 23 | #include <string> |
| 24 | |
Casey Dahlin | a834dd4 | 2015-09-23 11:52:15 -0700 | [diff] [blame^] | 25 | #include "aidl_language.h" |
Christopher Wiley | 9a8e1d9 | 2015-09-19 10:34:33 -0700 | [diff] [blame] | 26 | #include "ast_cpp.h" |
| 27 | #include "code_writer.h" |
Christopher Wiley | eb1acc1 | 2015-09-16 11:25:13 -0700 | [diff] [blame] | 28 | #include "logging.h" |
| 29 | |
Christopher Wiley | 9a8e1d9 | 2015-09-19 10:34:33 -0700 | [diff] [blame] | 30 | using std::string; |
Casey Dahlin | 082f1d1 | 2015-09-21 14:06:25 -0700 | [diff] [blame] | 31 | using std::unique_ptr; |
Casey Dahlin | a834dd4 | 2015-09-23 11:52:15 -0700 | [diff] [blame^] | 32 | using std::vector; |
Christopher Wiley | 9a8e1d9 | 2015-09-19 10:34:33 -0700 | [diff] [blame] | 33 | |
Christopher Wiley | eb1acc1 | 2015-09-16 11:25:13 -0700 | [diff] [blame] | 34 | namespace android { |
| 35 | namespace aidl { |
Casey Dahlin | a834dd4 | 2015-09-23 11:52:15 -0700 | [diff] [blame^] | 36 | namespace internals { |
Christopher Wiley | eb1acc1 | 2015-09-16 11:25:13 -0700 | [diff] [blame] | 37 | |
Casey Dahlin | a834dd4 | 2015-09-23 11:52:15 -0700 | [diff] [blame^] | 38 | string StrippedLiteral(const buffer_type& buffer) { |
| 39 | std::string i_name = buffer.Literal(); |
Casey Dahlin | 082f1d1 | 2015-09-21 14:06:25 -0700 | [diff] [blame] | 40 | |
Casey Dahlin | a834dd4 | 2015-09-23 11:52:15 -0700 | [diff] [blame^] | 41 | string c_name; |
Casey Dahlin | 082f1d1 | 2015-09-21 14:06:25 -0700 | [diff] [blame] | 42 | |
Casey Dahlin | a834dd4 | 2015-09-23 11:52:15 -0700 | [diff] [blame^] | 43 | 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 Dahlin | 082f1d1 | 2015-09-21 14:06:25 -0700 | [diff] [blame] | 47 | |
Casey Dahlin | a834dd4 | 2015-09-23 11:52:15 -0700 | [diff] [blame^] | 48 | return c_name; |
| 49 | } |
Casey Dahlin | 082f1d1 | 2015-09-21 14:06:25 -0700 | [diff] [blame] | 50 | |
Casey Dahlin | a834dd4 | 2015-09-23 11:52:15 -0700 | [diff] [blame^] | 51 | string 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 | |
| 64 | string GetCPPVarDec(type_type* type, string name, |
| 65 | int direction) { |
| 66 | return GetCPPType(type) + ((OUT_PARAMETER & direction) ? "* " : " ") + |
| 67 | name + type->Brackets(); |
Casey Dahlin | 082f1d1 | 2015-09-21 14:06:25 -0700 | [diff] [blame] | 68 | } |
| 69 | |
Christopher Wiley | 9a8e1d9 | 2015-09-19 10:34:33 -0700 | [diff] [blame] | 70 | unique_ptr<CppDocument> BuildClientSource(interface_type* parsed_doc) { |
Casey Dahlin | b7d0f7f | 2015-09-22 17:21:08 -0700 | [diff] [blame] | 71 | unique_ptr<CppNamespace> ns{new CppNamespace{"android", {}}}; |
| 72 | return unique_ptr<CppDocument>{new CppSource{ {}, std::move(ns)}}; |
Christopher Wiley | 9a8e1d9 | 2015-09-19 10:34:33 -0700 | [diff] [blame] | 73 | } |
| 74 | |
| 75 | unique_ptr<CppDocument> BuildServerSource(interface_type* parsed_doc) { |
Casey Dahlin | b7d0f7f | 2015-09-22 17:21:08 -0700 | [diff] [blame] | 76 | unique_ptr<CppNamespace> ns{new CppNamespace{"android", {}}}; |
| 77 | return unique_ptr<CppDocument>{new CppSource{ {}, std::move(ns)}}; |
Christopher Wiley | 9a8e1d9 | 2015-09-19 10:34:33 -0700 | [diff] [blame] | 78 | } |
| 79 | |
| 80 | unique_ptr<CppDocument> BuildInterfaceSource(interface_type* parsed_doc) { |
Casey Dahlin | b7d0f7f | 2015-09-22 17:21:08 -0700 | [diff] [blame] | 81 | unique_ptr<CppNamespace> ns{new CppNamespace{"android", {}}}; |
| 82 | return unique_ptr<CppDocument>{new CppSource{ {}, std::move(ns)}}; |
Christopher Wiley | 9a8e1d9 | 2015-09-19 10:34:33 -0700 | [diff] [blame] | 83 | } |
| 84 | |
| 85 | unique_ptr<CppDocument> BuildClientHeader(interface_type* parsed_doc) { |
Casey Dahlin | a834dd4 | 2015-09-23 11:52:15 -0700 | [diff] [blame^] | 86 | 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 Wiley | 9a8e1d9 | 2015-09-19 10:34:33 -0700 | [diff] [blame] | 150 | } |
| 151 | |
| 152 | unique_ptr<CppDocument> BuildServerHeader(interface_type* parsed_doc) { |
Casey Dahlin | a834dd4 | 2015-09-23 11:52:15 -0700 | [diff] [blame^] | 153 | string i_name = parsed_doc->name.Literal();; |
| 154 | string c_name = StrippedLiteral(parsed_doc->name); |
Casey Dahlin | 082f1d1 | 2015-09-21 14:06:25 -0700 | [diff] [blame] | 155 | string bn_name = "Bn" + c_name; |
| 156 | |
Casey Dahlin | b7d0f7f | 2015-09-22 17:21:08 -0700 | [diff] [blame] | 157 | unique_ptr<CppDeclaration> on_transact{ |
Casey Dahlin | 082f1d1 | 2015-09-21 14:06:25 -0700 | [diff] [blame] | 158 | 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 Dahlin | b7d0f7f | 2015-09-22 17:21:08 -0700 | [diff] [blame] | 163 | })}; |
Casey Dahlin | 082f1d1 | 2015-09-21 14:06:25 -0700 | [diff] [blame] | 164 | |
Casey Dahlin | b7d0f7f | 2015-09-22 17:21:08 -0700 | [diff] [blame] | 165 | std::vector<unique_ptr<CppDeclaration>> publics; |
| 166 | publics.push_back(std::move(on_transact)); |
| 167 | |
| 168 | unique_ptr<CppClassDeclaration> bn_class{ |
Casey Dahlin | 082f1d1 | 2015-09-21 14:06:25 -0700 | [diff] [blame] | 169 | new CppClassDeclaration{bn_name, |
| 170 | "public android::BnInterface<" + i_name + ">", |
Casey Dahlin | b7d0f7f | 2015-09-22 17:21:08 -0700 | [diff] [blame] | 171 | std::move(publics), |
Casey Dahlin | 082f1d1 | 2015-09-21 14:06:25 -0700 | [diff] [blame] | 172 | {} |
Casey Dahlin | b7d0f7f | 2015-09-22 17:21:08 -0700 | [diff] [blame] | 173 | }}; |
Casey Dahlin | 082f1d1 | 2015-09-21 14:06:25 -0700 | [diff] [blame] | 174 | |
Casey Dahlin | b7d0f7f | 2015-09-22 17:21:08 -0700 | [diff] [blame] | 175 | 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 Dahlin | 082f1d1 | 2015-09-21 14:06:25 -0700 | [diff] [blame] | 179 | |
Casey Dahlin | a834dd4 | 2015-09-23 11:52:15 -0700 | [diff] [blame^] | 180 | unique_ptr<CppDocument> bn_header{new CppHeader{bn_name + "_H", |
Casey Dahlin | 082f1d1 | 2015-09-21 14:06:25 -0700 | [diff] [blame] | 181 | {"binder/IInterface.h", |
| 182 | i_name + ".h"}, |
Casey Dahlin | b7d0f7f | 2015-09-22 17:21:08 -0700 | [diff] [blame] | 183 | std::move(ns) }}; |
Casey Dahlin | 082f1d1 | 2015-09-21 14:06:25 -0700 | [diff] [blame] | 184 | |
| 185 | return bn_header; |
Christopher Wiley | 9a8e1d9 | 2015-09-19 10:34:33 -0700 | [diff] [blame] | 186 | } |
| 187 | |
| 188 | unique_ptr<CppDocument> BuildInterfaceHeader(interface_type* parsed_doc) { |
Casey Dahlin | b7d0f7f | 2015-09-22 17:21:08 -0700 | [diff] [blame] | 189 | unique_ptr<CppNamespace> ns{new CppNamespace{"android", {}}}; |
| 190 | return unique_ptr<CppDocument>{new CppSource{ {}, std::move(ns)}}; |
Christopher Wiley | 9a8e1d9 | 2015-09-19 10:34:33 -0700 | [diff] [blame] | 191 | } |
| 192 | |
| 193 | bool 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 Dahlin | a834dd4 | 2015-09-23 11:52:15 -0700 | [diff] [blame^] | 202 | } // namespace internals |
| 203 | |
| 204 | using namespace internals; |
Christopher Wiley | 9a8e1d9 | 2015-09-19 10:34:33 -0700 | [diff] [blame] | 205 | |
| 206 | bool 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 Wiley | eb1acc1 | 2015-09-16 11:25:13 -0700 | [diff] [blame] | 223 | } |
| 224 | |
| 225 | } // namespace android |
| 226 | } // namespace aidl |