blob: 59d6d62ead74eed73927966a2f1e269f459f4ca4 [file] [log] [blame]
Adam Lesinskiffa16862014-01-23 18:17:42 -08001#include "aidl_language.h"
Jiyong Park1deecc32018-07-17 01:14:41 +09002#include "aidl_typenames.h"
Christopher Wileyf690be52015-09-14 15:19:10 -07003
Adam Lesinskiffa16862014-01-23 18:17:42 -08004#include <stdio.h>
Adam Lesinskiffa16862014-01-23 18:17:42 -08005#include <stdlib.h>
Christopher Wiley4a2884b2015-10-07 11:27:45 -07006#include <string.h>
Jiyong Park1deecc32018-07-17 01:14:41 +09007#include <cassert>
8#include <iostream>
Casey Dahlindd691812015-09-09 17:59:06 -07009#include <string>
Jiyong Park1deecc32018-07-17 01:14:41 +090010#include <utility>
Christopher Wileyf690be52015-09-14 15:19:10 -070011
Roshan Pius9d7810a2016-07-28 08:57:50 -070012#include <android-base/parseint.h>
Elliott Hughes0a620672015-12-04 13:53:18 -080013#include <android-base/strings.h>
Christopher Wileyd76067c2015-10-19 17:00:13 -070014
Ying Wang3000e752016-01-11 18:05:59 -080015#include "aidl_language_y.h"
Christopher Wiley4a2884b2015-10-07 11:27:45 -070016#include "logging.h"
Adam Lesinskiffa16862014-01-23 18:17:42 -080017
Casey Dahlin07b9dde2015-09-10 19:13:49 -070018#ifdef _WIN32
19int isatty(int fd)
20{
21 return (fd == 0);
22}
23#endif
24
Christopher Wiley4a2884b2015-10-07 11:27:45 -070025using android::aidl::IoDelegate;
Christopher Wileyd76067c2015-10-19 17:00:13 -070026using android::base::Join;
Christopher Wiley8aa4d9f2015-11-16 19:10:45 -080027using android::base::Split;
Casey Dahlindd691812015-09-09 17:59:06 -070028using std::cerr;
29using std::endl;
Jiyong Park1deecc32018-07-17 01:14:41 +090030using std::pair;
Christopher Wiley4a2884b2015-10-07 11:27:45 -070031using std::string;
32using std::unique_ptr;
Jiyong Parkccf00f82018-07-17 01:39:23 +090033using std::vector;
Adam Lesinskiffa16862014-01-23 18:17:42 -080034
Casey Dahlindd691812015-09-09 17:59:06 -070035void yylex_init(void **);
36void yylex_destroy(void *);
37void yyset_in(FILE *f, void *);
Casey Dahline2507492015-09-14 17:11:20 -070038int yyparse(Parser*);
Christopher Wiley4a2884b2015-10-07 11:27:45 -070039YY_BUFFER_STATE yy_scan_buffer(char *, size_t, void *);
Casey Dahlin89d44842015-09-24 18:45:54 -070040void yy_delete_buffer(YY_BUFFER_STATE, void *);
Casey Dahlindd691812015-09-09 17:59:06 -070041
Casey Dahlincdbbc8c2015-10-14 15:31:04 -070042AidlToken::AidlToken(const std::string& text, const std::string& comments)
43 : text_(text),
44 comments_(comments) {}
Casey Dahlin98a544b2015-10-14 14:22:55 -070045
Jiyong Park1deecc32018-07-17 01:14:41 +090046AidlTypeSpecifier::AidlTypeSpecifier(const string& unresolved_name, bool is_array,
47 vector<unique_ptr<AidlTypeSpecifier>>* type_params,
48 unsigned line, const string& comments)
49 : unresolved_name_(unresolved_name),
Casey Dahlinf7a421c2015-10-05 17:24:28 -070050 is_array_(is_array),
Jiyong Park1deecc32018-07-17 01:14:41 +090051 type_params_(type_params),
52 line_(line),
Casey Dahlinf2d23f72015-10-02 16:19:19 -070053 comments_(comments) {}
54
Jiyong Park1deecc32018-07-17 01:14:41 +090055string AidlTypeSpecifier::ToString() const {
56 string ret = GetName();
57 if (IsGeneric()) {
58 vector<string> arg_names;
59 for (const auto& ta : GetTypeParameters()) {
Jiyong Parkccf00f82018-07-17 01:39:23 +090060 arg_names.emplace_back(ta->ToString());
61 }
Jiyong Park1deecc32018-07-17 01:14:41 +090062 ret += "<" + Join(arg_names, ",") + ">";
Jiyong Parkccf00f82018-07-17 01:39:23 +090063 }
Jiyong Park1deecc32018-07-17 01:14:41 +090064 if (IsArray()) {
65 ret += "[]";
66 }
67 return ret;
Jiyong Parkccf00f82018-07-17 01:39:23 +090068}
69
Jiyong Park1deecc32018-07-17 01:14:41 +090070bool AidlTypeSpecifier::Resolve(android::aidl::AidlTypenames& typenames) {
71 assert(!IsResolved());
72 pair<string, bool> result = typenames.ResolveTypename(unresolved_name_);
73 if (result.second) {
74 fully_qualified_name_ = result.first;
Jiyong Parkccf00f82018-07-17 01:39:23 +090075 }
Jiyong Park1deecc32018-07-17 01:14:41 +090076 return result.second;
Casey Dahlin70078e62015-09-30 17:01:30 -070077}
78
Jiyong Parkd59a10d2018-07-18 11:12:55 +090079AidlVariableDeclaration::AidlVariableDeclaration(AidlTypeSpecifier* type, std::string name,
80 unsigned line)
Steven Moreland5557f1c2018-07-02 13:50:23 -070081 : type_(type), name_(name), line_(line) {}
82
83string AidlVariableDeclaration::ToString() const {
84 return type_->ToString() + " " + name_;
85}
86
Jiyong Parkd59a10d2018-07-18 11:12:55 +090087AidlArgument::AidlArgument(AidlArgument::Direction direction, AidlTypeSpecifier* type,
88 std::string name, unsigned line)
Steven Moreland5557f1c2018-07-02 13:50:23 -070089 : AidlVariableDeclaration(type, name, line),
Casey Dahlinfd6fb482015-09-30 14:48:18 -070090 direction_(direction),
Steven Moreland5557f1c2018-07-02 13:50:23 -070091 direction_specified_(true) {}
Casey Dahlinc378c992015-09-29 16:50:40 -070092
Jiyong Parkd59a10d2018-07-18 11:12:55 +090093AidlArgument::AidlArgument(AidlTypeSpecifier* type, std::string name, unsigned line)
Steven Moreland5557f1c2018-07-02 13:50:23 -070094 : AidlVariableDeclaration(type, name, line),
Casey Dahlinfd6fb482015-09-30 14:48:18 -070095 direction_(AidlArgument::IN_DIR),
Steven Moreland5557f1c2018-07-02 13:50:23 -070096 direction_specified_(false) {}
Casey Dahlinc378c992015-09-29 16:50:40 -070097
98string AidlArgument::ToString() const {
99 string ret;
100
101 if (direction_specified_) {
102 switch(direction_) {
103 case AidlArgument::IN_DIR:
104 ret += "in ";
105 break;
106 case AidlArgument::OUT_DIR:
107 ret += "out ";
108 break;
109 case AidlArgument::INOUT_DIR:
110 ret += "inout ";
111 break;
112 }
113 }
114
Steven Moreland5557f1c2018-07-02 13:50:23 -0700115 ret += AidlVariableDeclaration::ToString();
Casey Dahlinc378c992015-09-29 16:50:40 -0700116
117 return ret;
118}
Casey Dahlinbc7a50a2015-09-28 19:20:50 -0700119
Christopher Wileyd6bdd8d2016-05-03 11:23:13 -0700120AidlIntConstant::AidlIntConstant(std::string name, int32_t value)
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800121 : name_(name),
Roshan Pius3b2203d2016-07-22 16:13:20 -0700122 value_(value),
123 is_valid_(true) {}
124
125AidlIntConstant::AidlIntConstant(std::string name,
126 std::string value,
127 unsigned line_number)
128 : name_(name) {
Roshan Pius9d7810a2016-07-28 08:57:50 -0700129 uint32_t unsigned_val;
130 if (!android::base::ParseUint(value.c_str(), &unsigned_val)) {
Roshan Pius3b2203d2016-07-22 16:13:20 -0700131 is_valid_ = false;
132 LOG(ERROR) << "Found invalid int value '" << value
133 << "' on line " << line_number;
134 } else {
Roshan Pius9d7810a2016-07-28 08:57:50 -0700135 // Converting from unsigned to signed integer.
136 value_ = unsigned_val;
Roshan Pius3b2203d2016-07-22 16:13:20 -0700137 is_valid_ = true;
138 }
139}
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800140
Christopher Wileyd6bdd8d2016-05-03 11:23:13 -0700141AidlStringConstant::AidlStringConstant(std::string name,
142 std::string value,
143 unsigned line_number)
144 : name_(name),
145 value_(value) {
146 is_valid_ = true;
147 for (size_t i = 0; i < value_.length(); ++i) {
148 const char& c = value_[i];
149 if (c <= 0x1f || // control characters are < 0x20
150 c >= 0x7f || // DEL is 0x7f
151 c == '\\') { // Disallow backslashes for future proofing.
152 LOG(ERROR) << "Found invalid character at index " << i
153 << " in string constant '" << value_
154 << "' beginning on line " << line_number;
155 is_valid_ = false;
156 break;
157 }
158 }
159}
160
Jiyong Parkd59a10d2018-07-18 11:12:55 +0900161AidlMethod::AidlMethod(bool oneway, AidlTypeSpecifier* type, std::string name,
162 std::vector<std::unique_ptr<AidlArgument>>* args, unsigned line,
163 const std::string& comments, int id)
Casey Dahlinf4a93112015-10-05 16:58:09 -0700164 : oneway_(oneway),
165 comments_(comments),
166 type_(type),
167 name_(name),
168 line_(line),
169 arguments_(std::move(*args)),
170 id_(id) {
171 has_id_ = true;
172 delete args;
Christopher Wileyad339272015-10-05 19:11:58 -0700173 for (const unique_ptr<AidlArgument>& a : arguments_) {
174 if (a->IsIn()) { in_arguments_.push_back(a.get()); }
175 if (a->IsOut()) { out_arguments_.push_back(a.get()); }
176 }
Casey Dahlinf4a93112015-10-05 16:58:09 -0700177}
178
Jiyong Parkd59a10d2018-07-18 11:12:55 +0900179AidlMethod::AidlMethod(bool oneway, AidlTypeSpecifier* type, std::string name,
180 std::vector<std::unique_ptr<AidlArgument>>* args, unsigned line,
181 const std::string& comments)
Casey Dahlinf4a93112015-10-05 16:58:09 -0700182 : AidlMethod(oneway, type, name, args, line, comments, 0) {
183 has_id_ = false;
184}
Casey Dahlinf2d23f72015-10-02 16:19:19 -0700185
Jiyong Park1deecc32018-07-17 01:14:41 +0900186Parser::Parser(const IoDelegate& io_delegate, android::aidl::AidlTypenames* typenames)
187 : io_delegate_(io_delegate), typenames_(typenames) {
Christopher Wiley4a2884b2015-10-07 11:27:45 -0700188 yylex_init(&scanner_);
189}
190
Jiyong Parkd59a10d2018-07-18 11:12:55 +0900191AidlDefinedType::AidlDefinedType(std::string name, unsigned line, const std::string& comments,
Steven Moreland787b0432018-07-03 09:00:58 -0700192 const std::vector<std::string>& package)
Jiyong Park1deecc32018-07-17 01:14:41 +0900193 : name_(name), line_(line), comments_(comments), package_(package) {}
Steven Moreland787b0432018-07-03 09:00:58 -0700194
195std::string AidlDefinedType::GetPackage() const {
196 return Join(package_, '.');
197}
198
199std::string AidlDefinedType::GetCanonicalName() const {
200 if (package_.empty()) {
201 return GetName();
202 }
203 return GetPackage() + "." + GetName();
204}
205
Casey Dahlin2b2879b2015-10-13 16:59:44 -0700206AidlParcelable::AidlParcelable(AidlQualifiedName* name, unsigned line,
Christopher Wiley8aa4d9f2015-11-16 19:10:45 -0800207 const std::vector<std::string>& package,
208 const std::string& cpp_header)
Steven Moreland787b0432018-07-03 09:00:58 -0700209 : AidlDefinedType(name->GetDotName(), line, "" /*comments*/, package),
210 name_(name),
Christopher Wiley8aa4d9f2015-11-16 19:10:45 -0800211 cpp_header_(cpp_header) {
212 // Strip off quotation marks if we actually have a cpp header.
213 if (cpp_header_.length() >= 2) {
214 cpp_header_ = cpp_header_.substr(1, cpp_header_.length() - 2);
215 }
Casey Dahlin59401da2015-10-09 18:16:45 -0700216}
217
Steven Moreland5557f1c2018-07-02 13:50:23 -0700218AidlStructuredParcelable::AidlStructuredParcelable(
219 AidlQualifiedName* name, unsigned line, const std::vector<std::string>& package,
220 std::vector<std::unique_ptr<AidlVariableDeclaration>>* variables)
221 : AidlParcelable(name, line, package, "" /*cpp_header*/), variables_(std::move(*variables)) {}
222
Casey Dahlinfb7da2e2015-10-08 17:26:09 -0700223AidlInterface::AidlInterface(const std::string& name, unsigned line,
224 const std::string& comments, bool oneway,
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800225 std::vector<std::unique_ptr<AidlMember>>* members,
Christopher Wileyd76067c2015-10-19 17:00:13 -0700226 const std::vector<std::string>& package)
Steven Moreland787b0432018-07-03 09:00:58 -0700227 : AidlDefinedType(name, line, comments, package),
228 oneway_(oneway) {
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800229 for (auto& member : *members) {
230 AidlMember* local = member.release();
231 AidlMethod* method = local->AsMethod();
Christopher Wileyd6bdd8d2016-05-03 11:23:13 -0700232 AidlIntConstant* int_constant = local->AsIntConstant();
233 AidlStringConstant* string_constant = local->AsStringConstant();
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800234
235 if (method) {
236 methods_.emplace_back(method);
Christopher Wileyd6bdd8d2016-05-03 11:23:13 -0700237 } else if (int_constant) {
238 int_constants_.emplace_back(int_constant);
239 } else if (string_constant) {
240 string_constants_.emplace_back(string_constant);
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800241 } else {
242 LOG(FATAL) << "Member is neither method nor constant!";
243 }
244 }
245
246 delete members;
Casey Dahlinfb7da2e2015-10-08 17:26:09 -0700247}
248
Steven Morelandc258abc2018-07-10 14:03:38 -0700249AidlDefinedType* AidlDocument::ReleaseDefinedType() {
250 if (defined_types_.size() == 0) {
Steven Moreland5557f1c2018-07-02 13:50:23 -0700251 return nullptr;
252 }
253
Steven Morelandc258abc2018-07-10 14:03:38 -0700254 if (defined_types_.size() > 1) {
255 LOG(ERROR) << "AIDL only supports compiling one defined type per file.";
256 return nullptr;
Steven Moreland5557f1c2018-07-02 13:50:23 -0700257 }
258
Steven Morelandc258abc2018-07-10 14:03:38 -0700259 return defined_types_[0].release();
Steven Moreland5557f1c2018-07-02 13:50:23 -0700260}
261
Casey Dahlin2b2879b2015-10-13 16:59:44 -0700262AidlQualifiedName::AidlQualifiedName(std::string term,
263 std::string comments)
264 : terms_({term}),
265 comments_(comments) {
Christopher Wiley8aa4d9f2015-11-16 19:10:45 -0800266 if (term.find('.') != string::npos) {
267 terms_ = Split(term, ".");
268 for (const auto& term: terms_) {
269 if (term.empty()) {
270 LOG(FATAL) << "Malformed qualified identifier: '" << term << "'";
271 }
272 }
273 }
Casey Dahlin2b2879b2015-10-13 16:59:44 -0700274}
275
Chih-Hung Hsiehf05cc262016-07-27 11:42:51 -0700276void AidlQualifiedName::AddTerm(const std::string& term) {
Casey Dahlin2b2879b2015-10-13 16:59:44 -0700277 terms_.push_back(term);
278}
279
Casey Dahlin0edf3422015-10-07 12:34:59 -0700280AidlImport::AidlImport(const std::string& from,
281 const std::string& needed_class, unsigned line)
282 : from_(from),
283 needed_class_(needed_class),
284 line_(line) {}
285
Christopher Wiley4a2884b2015-10-07 11:27:45 -0700286Parser::~Parser() {
287 if (raw_buffer_) {
288 yy_delete_buffer(buffer_, scanner_);
289 raw_buffer_.reset();
290 }
291 yylex_destroy(scanner_);
292}
293
294bool Parser::ParseFile(const string& filename) {
295 // Make sure we can read the file first, before trashing previous state.
296 unique_ptr<string> new_buffer = io_delegate_.GetFileContents(filename);
297 if (!new_buffer) {
298 LOG(ERROR) << "Error while opening file for parsing: '" << filename << "'";
299 return false;
300 }
301
302 // Throw away old parsing state if we have any.
303 if (raw_buffer_) {
304 yy_delete_buffer(buffer_, scanner_);
305 raw_buffer_.reset();
306 }
307
308 raw_buffer_ = std::move(new_buffer);
309 // We're going to scan this buffer in place, and yacc demands we put two
310 // nulls at the end.
311 raw_buffer_->append(2u, '\0');
312 filename_ = filename;
Christopher Wileyd76067c2015-10-19 17:00:13 -0700313 package_.reset();
Christopher Wiley4a2884b2015-10-07 11:27:45 -0700314 error_ = 0;
Casey Dahlinc1f39b42015-11-24 10:34:34 -0800315 document_.reset();
Christopher Wiley4a2884b2015-10-07 11:27:45 -0700316
317 buffer_ = yy_scan_buffer(&(*raw_buffer_)[0], raw_buffer_->length(), scanner_);
318
Steven Moreland2ca4fcb2018-06-27 16:01:01 -0700319 if (yy::parser(this).parse() != 0 || error_ != 0)
320 return false;
Christopher Wiley4a2884b2015-10-07 11:27:45 -0700321
Jiyong Park1deecc32018-07-17 01:14:41 +0900322 if (document_.get() == nullptr) {
323 LOG(ERROR) << "Parser succeeded but yielded no document!";
324 return false;
325 }
326 return true;
Christopher Wiley4a2884b2015-10-07 11:27:45 -0700327}
328
Christopher Wiley90be4e32015-10-20 14:55:25 -0700329std::vector<std::string> Parser::Package() const {
330 if (!package_) {
331 return {};
332 }
333 return package_->GetTerms();
334}
335
Casey Dahlin2b2879b2015-10-13 16:59:44 -0700336void Parser::AddImport(AidlQualifiedName* name, unsigned line) {
337 imports_.emplace_back(new AidlImport(this->FileName(),
338 name->GetDotName(), line));
339 delete name;
Casey Dahline2507492015-09-14 17:11:20 -0700340}
Jiyong Park1deecc32018-07-17 01:14:41 +0900341
342bool Parser::Resolve() {
343 bool success = true;
344 for (AidlTypeSpecifier* typespec : unresolved_typespecs_) {
345 if (!typespec->Resolve(*typenames_)) {
346 LOG(ERROR) << "Failed to resolve '" << typespec->GetUnresolvedName() << "' at "
347 << this->FileName() << ":" << typespec->GetLine();
348 success = false;
349 // don't stop to show more errors if any
350 }
351 }
352 return success;
353}