blob: e034613ee1648af1f8d77a676afa129fa232144c [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 Park68bc77a2018-07-19 19:00:45 +09007#include <algorithm>
Jiyong Park1deecc32018-07-17 01:14:41 +09008#include <cassert>
9#include <iostream>
Jiyong Park68bc77a2018-07-19 19:00:45 +090010#include <set>
11#include <sstream>
Casey Dahlindd691812015-09-09 17:59:06 -070012#include <string>
Jiyong Park1deecc32018-07-17 01:14:41 +090013#include <utility>
Christopher Wileyf690be52015-09-14 15:19:10 -070014
Roshan Pius9d7810a2016-07-28 08:57:50 -070015#include <android-base/parseint.h>
Elliott Hughes0a620672015-12-04 13:53:18 -080016#include <android-base/strings.h>
Christopher Wileyd76067c2015-10-19 17:00:13 -070017
Ying Wang3000e752016-01-11 18:05:59 -080018#include "aidl_language_y.h"
Christopher Wiley4a2884b2015-10-07 11:27:45 -070019#include "logging.h"
Adam Lesinskiffa16862014-01-23 18:17:42 -080020
Casey Dahlin07b9dde2015-09-10 19:13:49 -070021#ifdef _WIN32
22int isatty(int fd)
23{
24 return (fd == 0);
25}
26#endif
27
Christopher Wiley4a2884b2015-10-07 11:27:45 -070028using android::aidl::IoDelegate;
Christopher Wileyd76067c2015-10-19 17:00:13 -070029using android::base::Join;
Christopher Wiley8aa4d9f2015-11-16 19:10:45 -080030using android::base::Split;
Casey Dahlindd691812015-09-09 17:59:06 -070031using std::cerr;
32using std::endl;
Jiyong Park1deecc32018-07-17 01:14:41 +090033using std::pair;
Jiyong Park68bc77a2018-07-19 19:00:45 +090034using std::set;
Christopher Wiley4a2884b2015-10-07 11:27:45 -070035using std::string;
36using std::unique_ptr;
Jiyong Parkccf00f82018-07-17 01:39:23 +090037using std::vector;
Adam Lesinskiffa16862014-01-23 18:17:42 -080038
Casey Dahlindd691812015-09-09 17:59:06 -070039void yylex_init(void **);
40void yylex_destroy(void *);
41void yyset_in(FILE *f, void *);
Casey Dahline2507492015-09-14 17:11:20 -070042int yyparse(Parser*);
Christopher Wiley4a2884b2015-10-07 11:27:45 -070043YY_BUFFER_STATE yy_scan_buffer(char *, size_t, void *);
Casey Dahlin89d44842015-09-24 18:45:54 -070044void yy_delete_buffer(YY_BUFFER_STATE, void *);
Casey Dahlindd691812015-09-09 17:59:06 -070045
Casey Dahlincdbbc8c2015-10-14 15:31:04 -070046AidlToken::AidlToken(const std::string& text, const std::string& comments)
47 : text_(text),
48 comments_(comments) {}
Casey Dahlin98a544b2015-10-14 14:22:55 -070049
Jiyong Park68bc77a2018-07-19 19:00:45 +090050static const string kNullable("nullable");
51static const string kUtf8("utf8");
52static const string kUtf8InCpp("utf8InCpp");
53
54static const set<string> kAnnotationNames{kNullable, kUtf8, kUtf8InCpp};
55
56AidlAnnotation::AidlAnnotation(const string& name, string& error) : name_(name) {
57 if (kAnnotationNames.find(name_) == kAnnotationNames.end()) {
58 std::ostringstream stream;
59 stream << "'" << name_ << "' is not a recognized annotation. ";
60 stream << "It must be one of:";
61 for (const string& kv : kAnnotationNames) {
62 stream << " " << kv;
63 }
64 stream << ".";
65 error = stream.str();
66 }
67}
68
69static bool HasAnnotation(const set<unique_ptr<AidlAnnotation>>& annotations, const string& name) {
70 for (const auto& a : annotations) {
71 if (a->GetName() == name) {
72 return true;
73 }
74 }
75 return false;
76}
77
78bool AidlAnnotatable::IsNullable() const {
79 return HasAnnotation(annotations_, kNullable);
80}
81
82bool AidlAnnotatable::IsUtf8() const {
83 return HasAnnotation(annotations_, kUtf8);
84}
85
86bool AidlAnnotatable::IsUtf8InCpp() const {
87 return HasAnnotation(annotations_, kUtf8InCpp);
88}
89
90string AidlAnnotatable::ToString() const {
91 vector<string> ret;
92 for (const auto& a : annotations_) {
93 ret.emplace_back(a->ToString());
94 }
95 std::sort(ret.begin(), ret.end());
96 return Join(ret, " ");
97}
98
Jiyong Park1deecc32018-07-17 01:14:41 +090099AidlTypeSpecifier::AidlTypeSpecifier(const string& unresolved_name, bool is_array,
100 vector<unique_ptr<AidlTypeSpecifier>>* type_params,
101 unsigned line, const string& comments)
102 : unresolved_name_(unresolved_name),
Casey Dahlinf7a421c2015-10-05 17:24:28 -0700103 is_array_(is_array),
Jiyong Park1deecc32018-07-17 01:14:41 +0900104 type_params_(type_params),
105 line_(line),
Casey Dahlinf2d23f72015-10-02 16:19:19 -0700106 comments_(comments) {}
107
Jiyong Park1deecc32018-07-17 01:14:41 +0900108string AidlTypeSpecifier::ToString() const {
109 string ret = GetName();
110 if (IsGeneric()) {
111 vector<string> arg_names;
112 for (const auto& ta : GetTypeParameters()) {
Jiyong Parkccf00f82018-07-17 01:39:23 +0900113 arg_names.emplace_back(ta->ToString());
114 }
Jiyong Park1deecc32018-07-17 01:14:41 +0900115 ret += "<" + Join(arg_names, ",") + ">";
Jiyong Parkccf00f82018-07-17 01:39:23 +0900116 }
Jiyong Park1deecc32018-07-17 01:14:41 +0900117 if (IsArray()) {
118 ret += "[]";
119 }
120 return ret;
Jiyong Parkccf00f82018-07-17 01:39:23 +0900121}
122
Jiyong Park1deecc32018-07-17 01:14:41 +0900123bool AidlTypeSpecifier::Resolve(android::aidl::AidlTypenames& typenames) {
124 assert(!IsResolved());
125 pair<string, bool> result = typenames.ResolveTypename(unresolved_name_);
126 if (result.second) {
127 fully_qualified_name_ = result.first;
Jiyong Parkccf00f82018-07-17 01:39:23 +0900128 }
Jiyong Park1deecc32018-07-17 01:14:41 +0900129 return result.second;
Casey Dahlin70078e62015-09-30 17:01:30 -0700130}
131
Jiyong Parkd59a10d2018-07-18 11:12:55 +0900132AidlVariableDeclaration::AidlVariableDeclaration(AidlTypeSpecifier* type, std::string name,
133 unsigned line)
Steven Moreland5557f1c2018-07-02 13:50:23 -0700134 : type_(type), name_(name), line_(line) {}
135
136string AidlVariableDeclaration::ToString() const {
137 return type_->ToString() + " " + name_;
138}
139
Jiyong Parkd59a10d2018-07-18 11:12:55 +0900140AidlArgument::AidlArgument(AidlArgument::Direction direction, AidlTypeSpecifier* type,
141 std::string name, unsigned line)
Steven Moreland5557f1c2018-07-02 13:50:23 -0700142 : AidlVariableDeclaration(type, name, line),
Casey Dahlinfd6fb482015-09-30 14:48:18 -0700143 direction_(direction),
Steven Moreland5557f1c2018-07-02 13:50:23 -0700144 direction_specified_(true) {}
Casey Dahlinc378c992015-09-29 16:50:40 -0700145
Jiyong Parkd59a10d2018-07-18 11:12:55 +0900146AidlArgument::AidlArgument(AidlTypeSpecifier* type, std::string name, unsigned line)
Steven Moreland5557f1c2018-07-02 13:50:23 -0700147 : AidlVariableDeclaration(type, name, line),
Casey Dahlinfd6fb482015-09-30 14:48:18 -0700148 direction_(AidlArgument::IN_DIR),
Steven Moreland5557f1c2018-07-02 13:50:23 -0700149 direction_specified_(false) {}
Casey Dahlinc378c992015-09-29 16:50:40 -0700150
151string AidlArgument::ToString() const {
152 string ret;
153
154 if (direction_specified_) {
155 switch(direction_) {
156 case AidlArgument::IN_DIR:
157 ret += "in ";
158 break;
159 case AidlArgument::OUT_DIR:
160 ret += "out ";
161 break;
162 case AidlArgument::INOUT_DIR:
163 ret += "inout ";
164 break;
165 }
166 }
167
Steven Moreland5557f1c2018-07-02 13:50:23 -0700168 ret += AidlVariableDeclaration::ToString();
Casey Dahlinc378c992015-09-29 16:50:40 -0700169
170 return ret;
171}
Casey Dahlinbc7a50a2015-09-28 19:20:50 -0700172
Christopher Wileyd6bdd8d2016-05-03 11:23:13 -0700173AidlIntConstant::AidlIntConstant(std::string name, int32_t value)
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800174 : name_(name),
Roshan Pius3b2203d2016-07-22 16:13:20 -0700175 value_(value),
176 is_valid_(true) {}
177
178AidlIntConstant::AidlIntConstant(std::string name,
179 std::string value,
180 unsigned line_number)
181 : name_(name) {
Roshan Pius9d7810a2016-07-28 08:57:50 -0700182 uint32_t unsigned_val;
183 if (!android::base::ParseUint(value.c_str(), &unsigned_val)) {
Roshan Pius3b2203d2016-07-22 16:13:20 -0700184 is_valid_ = false;
185 LOG(ERROR) << "Found invalid int value '" << value
186 << "' on line " << line_number;
187 } else {
Roshan Pius9d7810a2016-07-28 08:57:50 -0700188 // Converting from unsigned to signed integer.
189 value_ = unsigned_val;
Roshan Pius3b2203d2016-07-22 16:13:20 -0700190 is_valid_ = true;
191 }
192}
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800193
Christopher Wileyd6bdd8d2016-05-03 11:23:13 -0700194AidlStringConstant::AidlStringConstant(std::string name,
195 std::string value,
196 unsigned line_number)
197 : name_(name),
198 value_(value) {
199 is_valid_ = true;
200 for (size_t i = 0; i < value_.length(); ++i) {
201 const char& c = value_[i];
202 if (c <= 0x1f || // control characters are < 0x20
203 c >= 0x7f || // DEL is 0x7f
204 c == '\\') { // Disallow backslashes for future proofing.
205 LOG(ERROR) << "Found invalid character at index " << i
206 << " in string constant '" << value_
207 << "' beginning on line " << line_number;
208 is_valid_ = false;
209 break;
210 }
211 }
212}
213
Jiyong Parkd59a10d2018-07-18 11:12:55 +0900214AidlMethod::AidlMethod(bool oneway, AidlTypeSpecifier* type, std::string name,
215 std::vector<std::unique_ptr<AidlArgument>>* args, unsigned line,
216 const std::string& comments, int id)
Casey Dahlinf4a93112015-10-05 16:58:09 -0700217 : oneway_(oneway),
218 comments_(comments),
219 type_(type),
220 name_(name),
221 line_(line),
222 arguments_(std::move(*args)),
223 id_(id) {
224 has_id_ = true;
225 delete args;
Christopher Wileyad339272015-10-05 19:11:58 -0700226 for (const unique_ptr<AidlArgument>& a : arguments_) {
227 if (a->IsIn()) { in_arguments_.push_back(a.get()); }
228 if (a->IsOut()) { out_arguments_.push_back(a.get()); }
229 }
Casey Dahlinf4a93112015-10-05 16:58:09 -0700230}
231
Jiyong Parkd59a10d2018-07-18 11:12:55 +0900232AidlMethod::AidlMethod(bool oneway, AidlTypeSpecifier* type, std::string name,
233 std::vector<std::unique_ptr<AidlArgument>>* args, unsigned line,
234 const std::string& comments)
Casey Dahlinf4a93112015-10-05 16:58:09 -0700235 : AidlMethod(oneway, type, name, args, line, comments, 0) {
236 has_id_ = false;
237}
Casey Dahlinf2d23f72015-10-02 16:19:19 -0700238
Jiyong Park1deecc32018-07-17 01:14:41 +0900239Parser::Parser(const IoDelegate& io_delegate, android::aidl::AidlTypenames* typenames)
240 : io_delegate_(io_delegate), typenames_(typenames) {
Christopher Wiley4a2884b2015-10-07 11:27:45 -0700241 yylex_init(&scanner_);
242}
243
Jiyong Parkd59a10d2018-07-18 11:12:55 +0900244AidlDefinedType::AidlDefinedType(std::string name, unsigned line, const std::string& comments,
Steven Moreland787b0432018-07-03 09:00:58 -0700245 const std::vector<std::string>& package)
Jiyong Park1deecc32018-07-17 01:14:41 +0900246 : name_(name), line_(line), comments_(comments), package_(package) {}
Steven Moreland787b0432018-07-03 09:00:58 -0700247
248std::string AidlDefinedType::GetPackage() const {
249 return Join(package_, '.');
250}
251
252std::string AidlDefinedType::GetCanonicalName() const {
253 if (package_.empty()) {
254 return GetName();
255 }
256 return GetPackage() + "." + GetName();
257}
258
Casey Dahlin2b2879b2015-10-13 16:59:44 -0700259AidlParcelable::AidlParcelable(AidlQualifiedName* name, unsigned line,
Christopher Wiley8aa4d9f2015-11-16 19:10:45 -0800260 const std::vector<std::string>& package,
261 const std::string& cpp_header)
Steven Moreland787b0432018-07-03 09:00:58 -0700262 : AidlDefinedType(name->GetDotName(), line, "" /*comments*/, package),
263 name_(name),
Christopher Wiley8aa4d9f2015-11-16 19:10:45 -0800264 cpp_header_(cpp_header) {
265 // Strip off quotation marks if we actually have a cpp header.
266 if (cpp_header_.length() >= 2) {
267 cpp_header_ = cpp_header_.substr(1, cpp_header_.length() - 2);
268 }
Casey Dahlin59401da2015-10-09 18:16:45 -0700269}
270
Steven Moreland5557f1c2018-07-02 13:50:23 -0700271AidlStructuredParcelable::AidlStructuredParcelable(
272 AidlQualifiedName* name, unsigned line, const std::vector<std::string>& package,
273 std::vector<std::unique_ptr<AidlVariableDeclaration>>* variables)
274 : AidlParcelable(name, line, package, "" /*cpp_header*/), variables_(std::move(*variables)) {}
275
Casey Dahlinfb7da2e2015-10-08 17:26:09 -0700276AidlInterface::AidlInterface(const std::string& name, unsigned line,
277 const std::string& comments, bool oneway,
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800278 std::vector<std::unique_ptr<AidlMember>>* members,
Christopher Wileyd76067c2015-10-19 17:00:13 -0700279 const std::vector<std::string>& package)
Steven Moreland787b0432018-07-03 09:00:58 -0700280 : AidlDefinedType(name, line, comments, package),
281 oneway_(oneway) {
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800282 for (auto& member : *members) {
283 AidlMember* local = member.release();
284 AidlMethod* method = local->AsMethod();
Christopher Wileyd6bdd8d2016-05-03 11:23:13 -0700285 AidlIntConstant* int_constant = local->AsIntConstant();
286 AidlStringConstant* string_constant = local->AsStringConstant();
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800287
288 if (method) {
289 methods_.emplace_back(method);
Christopher Wileyd6bdd8d2016-05-03 11:23:13 -0700290 } else if (int_constant) {
291 int_constants_.emplace_back(int_constant);
292 } else if (string_constant) {
293 string_constants_.emplace_back(string_constant);
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800294 } else {
295 LOG(FATAL) << "Member is neither method nor constant!";
296 }
297 }
298
299 delete members;
Casey Dahlinfb7da2e2015-10-08 17:26:09 -0700300}
301
Steven Morelandc258abc2018-07-10 14:03:38 -0700302AidlDefinedType* AidlDocument::ReleaseDefinedType() {
303 if (defined_types_.size() == 0) {
Steven Moreland5557f1c2018-07-02 13:50:23 -0700304 return nullptr;
305 }
306
Steven Morelandc258abc2018-07-10 14:03:38 -0700307 if (defined_types_.size() > 1) {
308 LOG(ERROR) << "AIDL only supports compiling one defined type per file.";
309 return nullptr;
Steven Moreland5557f1c2018-07-02 13:50:23 -0700310 }
311
Steven Morelandc258abc2018-07-10 14:03:38 -0700312 return defined_types_[0].release();
Steven Moreland5557f1c2018-07-02 13:50:23 -0700313}
314
Casey Dahlin2b2879b2015-10-13 16:59:44 -0700315AidlQualifiedName::AidlQualifiedName(std::string term,
316 std::string comments)
317 : terms_({term}),
318 comments_(comments) {
Christopher Wiley8aa4d9f2015-11-16 19:10:45 -0800319 if (term.find('.') != string::npos) {
320 terms_ = Split(term, ".");
321 for (const auto& term: terms_) {
322 if (term.empty()) {
323 LOG(FATAL) << "Malformed qualified identifier: '" << term << "'";
324 }
325 }
326 }
Casey Dahlin2b2879b2015-10-13 16:59:44 -0700327}
328
Chih-Hung Hsiehf05cc262016-07-27 11:42:51 -0700329void AidlQualifiedName::AddTerm(const std::string& term) {
Casey Dahlin2b2879b2015-10-13 16:59:44 -0700330 terms_.push_back(term);
331}
332
Casey Dahlin0edf3422015-10-07 12:34:59 -0700333AidlImport::AidlImport(const std::string& from,
334 const std::string& needed_class, unsigned line)
335 : from_(from),
336 needed_class_(needed_class),
337 line_(line) {}
338
Christopher Wiley4a2884b2015-10-07 11:27:45 -0700339Parser::~Parser() {
340 if (raw_buffer_) {
341 yy_delete_buffer(buffer_, scanner_);
342 raw_buffer_.reset();
343 }
344 yylex_destroy(scanner_);
345}
346
347bool Parser::ParseFile(const string& filename) {
348 // Make sure we can read the file first, before trashing previous state.
349 unique_ptr<string> new_buffer = io_delegate_.GetFileContents(filename);
350 if (!new_buffer) {
351 LOG(ERROR) << "Error while opening file for parsing: '" << filename << "'";
352 return false;
353 }
354
355 // Throw away old parsing state if we have any.
356 if (raw_buffer_) {
357 yy_delete_buffer(buffer_, scanner_);
358 raw_buffer_.reset();
359 }
360
361 raw_buffer_ = std::move(new_buffer);
362 // We're going to scan this buffer in place, and yacc demands we put two
363 // nulls at the end.
364 raw_buffer_->append(2u, '\0');
365 filename_ = filename;
Christopher Wileyd76067c2015-10-19 17:00:13 -0700366 package_.reset();
Christopher Wiley4a2884b2015-10-07 11:27:45 -0700367 error_ = 0;
Casey Dahlinc1f39b42015-11-24 10:34:34 -0800368 document_.reset();
Christopher Wiley4a2884b2015-10-07 11:27:45 -0700369
370 buffer_ = yy_scan_buffer(&(*raw_buffer_)[0], raw_buffer_->length(), scanner_);
371
Steven Moreland2ca4fcb2018-06-27 16:01:01 -0700372 if (yy::parser(this).parse() != 0 || error_ != 0)
373 return false;
Christopher Wiley4a2884b2015-10-07 11:27:45 -0700374
Jiyong Park1deecc32018-07-17 01:14:41 +0900375 if (document_.get() == nullptr) {
376 LOG(ERROR) << "Parser succeeded but yielded no document!";
377 return false;
378 }
379 return true;
Christopher Wiley4a2884b2015-10-07 11:27:45 -0700380}
381
Christopher Wiley90be4e32015-10-20 14:55:25 -0700382std::vector<std::string> Parser::Package() const {
383 if (!package_) {
384 return {};
385 }
386 return package_->GetTerms();
387}
388
Casey Dahlin2b2879b2015-10-13 16:59:44 -0700389void Parser::AddImport(AidlQualifiedName* name, unsigned line) {
390 imports_.emplace_back(new AidlImport(this->FileName(),
391 name->GetDotName(), line));
392 delete name;
Casey Dahline2507492015-09-14 17:11:20 -0700393}
Jiyong Park1deecc32018-07-17 01:14:41 +0900394
395bool Parser::Resolve() {
396 bool success = true;
397 for (AidlTypeSpecifier* typespec : unresolved_typespecs_) {
398 if (!typespec->Resolve(*typenames_)) {
399 LOG(ERROR) << "Failed to resolve '" << typespec->GetUnresolvedName() << "' at "
400 << this->FileName() << ":" << typespec->GetLine();
401 success = false;
402 // don't stop to show more errors if any
403 }
404 }
405 return success;
406}