blob: 6af55f8c6d1c4a9146bbc0730395e6e0ca083c0f [file] [log] [blame]
Adam Lesinskiffa16862014-01-23 18:17:42 -08001#include "aidl_language.h"
Christopher Wileyf690be52015-09-14 15:19:10 -07002
3#include <iostream>
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>
Casey Dahlindd691812015-09-09 17:59:06 -07007#include <string>
Christopher Wileyf690be52015-09-14 15:19:10 -07008
Elliott Hughes0a620672015-12-04 13:53:18 -08009#include <android-base/strings.h>
Christopher Wileyd76067c2015-10-19 17:00:13 -070010
Ying Wang3000e752016-01-11 18:05:59 -080011#include "aidl_language_y.h"
Christopher Wiley4a2884b2015-10-07 11:27:45 -070012#include "logging.h"
Adam Lesinskiffa16862014-01-23 18:17:42 -080013
Casey Dahlin07b9dde2015-09-10 19:13:49 -070014#ifdef _WIN32
15int isatty(int fd)
16{
17 return (fd == 0);
18}
19#endif
20
Christopher Wiley4a2884b2015-10-07 11:27:45 -070021using android::aidl::IoDelegate;
Christopher Wileyd76067c2015-10-19 17:00:13 -070022using android::base::Join;
Christopher Wiley8aa4d9f2015-11-16 19:10:45 -080023using android::base::Split;
Casey Dahlindd691812015-09-09 17:59:06 -070024using std::cerr;
25using std::endl;
Christopher Wiley4a2884b2015-10-07 11:27:45 -070026using std::string;
27using std::unique_ptr;
Adam Lesinskiffa16862014-01-23 18:17:42 -080028
Casey Dahlindd691812015-09-09 17:59:06 -070029void yylex_init(void **);
30void yylex_destroy(void *);
31void yyset_in(FILE *f, void *);
Casey Dahline2507492015-09-14 17:11:20 -070032int yyparse(Parser*);
Christopher Wiley4a2884b2015-10-07 11:27:45 -070033YY_BUFFER_STATE yy_scan_buffer(char *, size_t, void *);
Casey Dahlin89d44842015-09-24 18:45:54 -070034void yy_delete_buffer(YY_BUFFER_STATE, void *);
Casey Dahlindd691812015-09-09 17:59:06 -070035
Casey Dahlincdbbc8c2015-10-14 15:31:04 -070036AidlToken::AidlToken(const std::string& text, const std::string& comments)
37 : text_(text),
38 comments_(comments) {}
Casey Dahlin98a544b2015-10-14 14:22:55 -070039
Casey Dahlinf2d23f72015-10-02 16:19:19 -070040AidlType::AidlType(const std::string& name, unsigned line,
Casey Dahlinf7a421c2015-10-05 17:24:28 -070041 const std::string& comments, bool is_array)
Casey Dahlinf2d23f72015-10-02 16:19:19 -070042 : name_(name),
43 line_(line),
Casey Dahlinf7a421c2015-10-05 17:24:28 -070044 is_array_(is_array),
Casey Dahlinf2d23f72015-10-02 16:19:19 -070045 comments_(comments) {}
46
Casey Dahlin98a544b2015-10-14 14:22:55 -070047string AidlType::ToString() const {
48 return name_ + (is_array_ ? "[]" : "");
Casey Dahlin70078e62015-09-30 17:01:30 -070049}
50
Casey Dahlin0ee37582015-09-30 16:31:55 -070051AidlArgument::AidlArgument(AidlArgument::Direction direction, AidlType* type,
Casey Dahlin308f9d42015-10-05 18:48:42 -070052 std::string name, unsigned line)
Casey Dahlin0ee37582015-09-30 16:31:55 -070053 : type_(type),
Casey Dahlinfd6fb482015-09-30 14:48:18 -070054 direction_(direction),
55 direction_specified_(true),
Casey Dahlin308f9d42015-10-05 18:48:42 -070056 name_(name),
57 line_(line) {}
Casey Dahlinc378c992015-09-29 16:50:40 -070058
Casey Dahlin308f9d42015-10-05 18:48:42 -070059AidlArgument::AidlArgument(AidlType* type, std::string name, unsigned line)
Casey Dahlin0ee37582015-09-30 16:31:55 -070060 : type_(type),
Casey Dahlinfd6fb482015-09-30 14:48:18 -070061 direction_(AidlArgument::IN_DIR),
62 direction_specified_(false),
Casey Dahlin308f9d42015-10-05 18:48:42 -070063 name_(name),
64 line_(line) {}
Casey Dahlinc378c992015-09-29 16:50:40 -070065
66string AidlArgument::ToString() const {
67 string ret;
68
69 if (direction_specified_) {
70 switch(direction_) {
71 case AidlArgument::IN_DIR:
72 ret += "in ";
73 break;
74 case AidlArgument::OUT_DIR:
75 ret += "out ";
76 break;
77 case AidlArgument::INOUT_DIR:
78 ret += "inout ";
79 break;
80 }
81 }
82
Casey Dahlin70078e62015-09-30 17:01:30 -070083 ret += type_->ToString();
Casey Dahlinc378c992015-09-29 16:50:40 -070084 ret += " ";
Casey Dahlind127b502015-09-30 12:51:08 -070085 ret += name_;
Casey Dahlinc378c992015-09-29 16:50:40 -070086
87 return ret;
88}
Casey Dahlinbc7a50a2015-09-28 19:20:50 -070089
Christopher Wileyd6bdd8d2016-05-03 11:23:13 -070090AidlIntConstant::AidlIntConstant(std::string name, int32_t value)
Casey Dahlind40e2fe2015-11-24 14:06:52 -080091 : name_(name),
Roshan Pius3b2203d2016-07-22 16:13:20 -070092 value_(value),
93 is_valid_(true) {}
94
95AidlIntConstant::AidlIntConstant(std::string name,
96 std::string value,
97 unsigned line_number)
98 : name_(name) {
99 char *end;
100 // Use long long to ensure 0xFFFFFFFF -> -1 works on 32 bit devices.
101 unsigned long long int long_value = std::strtoull(value.c_str(), &end, 16);
102 // Ensure that we parsed the string fully and the value fits in int32.
103 if ((*end != '\0') ||
104 ((long_value == ULLONG_MAX) && (errno == ERANGE)) ||
105 (long_value > std::numeric_limits<uint32_t>::max())) {
106 is_valid_ = false;
107 LOG(ERROR) << "Found invalid int value '" << value
108 << "' on line " << line_number;
109 } else {
110 // Converting from unsigned long to signed integer.
111 value_ = long_value;
112 is_valid_ = true;
113 }
114}
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800115
Christopher Wileyd6bdd8d2016-05-03 11:23:13 -0700116AidlStringConstant::AidlStringConstant(std::string name,
117 std::string value,
118 unsigned line_number)
119 : name_(name),
120 value_(value) {
121 is_valid_ = true;
122 for (size_t i = 0; i < value_.length(); ++i) {
123 const char& c = value_[i];
124 if (c <= 0x1f || // control characters are < 0x20
125 c >= 0x7f || // DEL is 0x7f
126 c == '\\') { // Disallow backslashes for future proofing.
127 LOG(ERROR) << "Found invalid character at index " << i
128 << " in string constant '" << value_
129 << "' beginning on line " << line_number;
130 is_valid_ = false;
131 break;
132 }
133 }
134}
135
Casey Dahlinf4a93112015-10-05 16:58:09 -0700136AidlMethod::AidlMethod(bool oneway, AidlType* type, std::string name,
137 std::vector<std::unique_ptr<AidlArgument>>* args,
Casey Dahlinfb7da2e2015-10-08 17:26:09 -0700138 unsigned line, const std::string& comments, int id)
Casey Dahlinf4a93112015-10-05 16:58:09 -0700139 : oneway_(oneway),
140 comments_(comments),
141 type_(type),
142 name_(name),
143 line_(line),
144 arguments_(std::move(*args)),
145 id_(id) {
146 has_id_ = true;
147 delete args;
Christopher Wileyad339272015-10-05 19:11:58 -0700148 for (const unique_ptr<AidlArgument>& a : arguments_) {
149 if (a->IsIn()) { in_arguments_.push_back(a.get()); }
150 if (a->IsOut()) { out_arguments_.push_back(a.get()); }
151 }
Casey Dahlinf4a93112015-10-05 16:58:09 -0700152}
153
154AidlMethod::AidlMethod(bool oneway, AidlType* type, std::string name,
155 std::vector<std::unique_ptr<AidlArgument>>* args,
Casey Dahlinfb7da2e2015-10-08 17:26:09 -0700156 unsigned line, const std::string& comments)
Casey Dahlinf4a93112015-10-05 16:58:09 -0700157 : AidlMethod(oneway, type, name, args, line, comments, 0) {
158 has_id_ = false;
159}
Casey Dahlinf2d23f72015-10-02 16:19:19 -0700160
Christopher Wiley4a2884b2015-10-07 11:27:45 -0700161Parser::Parser(const IoDelegate& io_delegate)
162 : io_delegate_(io_delegate) {
163 yylex_init(&scanner_);
164}
165
Casey Dahlin2b2879b2015-10-13 16:59:44 -0700166AidlParcelable::AidlParcelable(AidlQualifiedName* name, unsigned line,
Christopher Wiley8aa4d9f2015-11-16 19:10:45 -0800167 const std::vector<std::string>& package,
168 const std::string& cpp_header)
Casey Dahlin59401da2015-10-09 18:16:45 -0700169 : name_(name),
170 line_(line),
Christopher Wiley8aa4d9f2015-11-16 19:10:45 -0800171 package_(package),
172 cpp_header_(cpp_header) {
173 // Strip off quotation marks if we actually have a cpp header.
174 if (cpp_header_.length() >= 2) {
175 cpp_header_ = cpp_header_.substr(1, cpp_header_.length() - 2);
176 }
Casey Dahlin59401da2015-10-09 18:16:45 -0700177}
178
Christopher Wileyd76067c2015-10-19 17:00:13 -0700179std::string AidlParcelable::GetPackage() const {
180 return Join(package_, '.');
181}
182
Casey Dahlinc1f39b42015-11-24 10:34:34 -0800183std::string AidlParcelable::GetCanonicalName() const {
184 if (package_.empty()) {
185 return GetName();
186 }
187 return GetPackage() + "." + GetName();
188}
189
Casey Dahlinfb7da2e2015-10-08 17:26:09 -0700190AidlInterface::AidlInterface(const std::string& name, unsigned line,
191 const std::string& comments, bool oneway,
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800192 std::vector<std::unique_ptr<AidlMember>>* members,
Christopher Wileyd76067c2015-10-19 17:00:13 -0700193 const std::vector<std::string>& package)
Casey Dahlinfb7da2e2015-10-08 17:26:09 -0700194 : name_(name),
195 comments_(comments),
196 line_(line),
197 oneway_(oneway),
Casey Dahlinfb7da2e2015-10-08 17:26:09 -0700198 package_(package) {
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800199 for (auto& member : *members) {
200 AidlMember* local = member.release();
201 AidlMethod* method = local->AsMethod();
Christopher Wileyd6bdd8d2016-05-03 11:23:13 -0700202 AidlIntConstant* int_constant = local->AsIntConstant();
203 AidlStringConstant* string_constant = local->AsStringConstant();
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800204
205 if (method) {
206 methods_.emplace_back(method);
Christopher Wileyd6bdd8d2016-05-03 11:23:13 -0700207 } else if (int_constant) {
208 int_constants_.emplace_back(int_constant);
209 } else if (string_constant) {
210 string_constants_.emplace_back(string_constant);
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800211 } else {
212 LOG(FATAL) << "Member is neither method nor constant!";
213 }
214 }
215
216 delete members;
Casey Dahlinfb7da2e2015-10-08 17:26:09 -0700217}
218
Christopher Wileyd76067c2015-10-19 17:00:13 -0700219std::string AidlInterface::GetPackage() const {
220 return Join(package_, '.');
221}
222
223std::string AidlInterface::GetCanonicalName() const {
224 if (package_.empty()) {
225 return GetName();
226 }
227 return GetPackage() + "." + GetName();
228}
229
Casey Dahlinc1f39b42015-11-24 10:34:34 -0800230AidlDocument::AidlDocument(AidlInterface* interface)
231 : interface_(interface) {}
232
Casey Dahlin2b2879b2015-10-13 16:59:44 -0700233AidlQualifiedName::AidlQualifiedName(std::string term,
234 std::string comments)
235 : terms_({term}),
236 comments_(comments) {
Christopher Wiley8aa4d9f2015-11-16 19:10:45 -0800237 if (term.find('.') != string::npos) {
238 terms_ = Split(term, ".");
239 for (const auto& term: terms_) {
240 if (term.empty()) {
241 LOG(FATAL) << "Malformed qualified identifier: '" << term << "'";
242 }
243 }
244 }
Casey Dahlin2b2879b2015-10-13 16:59:44 -0700245}
246
Chih-Hung Hsiehf05cc262016-07-27 11:42:51 -0700247void AidlQualifiedName::AddTerm(const std::string& term) {
Casey Dahlin2b2879b2015-10-13 16:59:44 -0700248 terms_.push_back(term);
249}
250
Casey Dahlin0edf3422015-10-07 12:34:59 -0700251AidlImport::AidlImport(const std::string& from,
252 const std::string& needed_class, unsigned line)
253 : from_(from),
254 needed_class_(needed_class),
255 line_(line) {}
256
Christopher Wiley4a2884b2015-10-07 11:27:45 -0700257Parser::~Parser() {
258 if (raw_buffer_) {
259 yy_delete_buffer(buffer_, scanner_);
260 raw_buffer_.reset();
261 }
262 yylex_destroy(scanner_);
263}
264
265bool Parser::ParseFile(const string& filename) {
266 // Make sure we can read the file first, before trashing previous state.
267 unique_ptr<string> new_buffer = io_delegate_.GetFileContents(filename);
268 if (!new_buffer) {
269 LOG(ERROR) << "Error while opening file for parsing: '" << filename << "'";
270 return false;
271 }
272
273 // Throw away old parsing state if we have any.
274 if (raw_buffer_) {
275 yy_delete_buffer(buffer_, scanner_);
276 raw_buffer_.reset();
277 }
278
279 raw_buffer_ = std::move(new_buffer);
280 // We're going to scan this buffer in place, and yacc demands we put two
281 // nulls at the end.
282 raw_buffer_->append(2u, '\0');
283 filename_ = filename;
Christopher Wileyd76067c2015-10-19 17:00:13 -0700284 package_.reset();
Christopher Wiley4a2884b2015-10-07 11:27:45 -0700285 error_ = 0;
Casey Dahlinc1f39b42015-11-24 10:34:34 -0800286 document_.reset();
Christopher Wiley4a2884b2015-10-07 11:27:45 -0700287
288 buffer_ = yy_scan_buffer(&(*raw_buffer_)[0], raw_buffer_->length(), scanner_);
289
Casey Dahlinc1f39b42015-11-24 10:34:34 -0800290 if (yy::parser(this).parse() != 0 || error_ != 0) {
291 return false;}
Christopher Wiley4a2884b2015-10-07 11:27:45 -0700292
Casey Dahlinc1f39b42015-11-24 10:34:34 -0800293 if (document_.get() != nullptr)
294 return true;
295
296 LOG(ERROR) << "Parser succeeded but yielded no document!";
297 return false;
Christopher Wiley4a2884b2015-10-07 11:27:45 -0700298}
299
Casey Dahlin98a544b2015-10-14 14:22:55 -0700300void Parser::ReportError(const string& err, unsigned line) {
301 cerr << filename_ << ":" << line << ": " << err << endl;
Casey Dahlindd691812015-09-09 17:59:06 -0700302 error_ = 1;
303}
304
Christopher Wiley90be4e32015-10-20 14:55:25 -0700305std::vector<std::string> Parser::Package() const {
306 if (!package_) {
307 return {};
308 }
309 return package_->GetTerms();
310}
311
Casey Dahlin2b2879b2015-10-13 16:59:44 -0700312void Parser::AddImport(AidlQualifiedName* name, unsigned line) {
313 imports_.emplace_back(new AidlImport(this->FileName(),
314 name->GetDotName(), line));
315 delete name;
Casey Dahline2507492015-09-14 17:11:20 -0700316}