blob: 95a336993cd7792d876b88321a89ecac2020cd0c [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
Roshan Pius9d7810a2016-07-28 08:57:50 -07009#include <android-base/parseint.h>
Elliott Hughes0a620672015-12-04 13:53:18 -080010#include <android-base/strings.h>
Christopher Wileyd76067c2015-10-19 17:00:13 -070011
Ying Wang3000e752016-01-11 18:05:59 -080012#include "aidl_language_y.h"
Christopher Wiley4a2884b2015-10-07 11:27:45 -070013#include "logging.h"
Adam Lesinskiffa16862014-01-23 18:17:42 -080014
Casey Dahlin07b9dde2015-09-10 19:13:49 -070015#ifdef _WIN32
16int isatty(int fd)
17{
18 return (fd == 0);
19}
20#endif
21
Christopher Wiley4a2884b2015-10-07 11:27:45 -070022using android::aidl::IoDelegate;
Christopher Wileyd76067c2015-10-19 17:00:13 -070023using android::base::Join;
Christopher Wiley8aa4d9f2015-11-16 19:10:45 -080024using android::base::Split;
Casey Dahlindd691812015-09-09 17:59:06 -070025using std::cerr;
26using std::endl;
Christopher Wiley4a2884b2015-10-07 11:27:45 -070027using std::string;
28using std::unique_ptr;
Adam Lesinskiffa16862014-01-23 18:17:42 -080029
Casey Dahlindd691812015-09-09 17:59:06 -070030void yylex_init(void **);
31void yylex_destroy(void *);
32void yyset_in(FILE *f, void *);
Casey Dahline2507492015-09-14 17:11:20 -070033int yyparse(Parser*);
Christopher Wiley4a2884b2015-10-07 11:27:45 -070034YY_BUFFER_STATE yy_scan_buffer(char *, size_t, void *);
Casey Dahlin89d44842015-09-24 18:45:54 -070035void yy_delete_buffer(YY_BUFFER_STATE, void *);
Casey Dahlindd691812015-09-09 17:59:06 -070036
Casey Dahlincdbbc8c2015-10-14 15:31:04 -070037AidlToken::AidlToken(const std::string& text, const std::string& comments)
38 : text_(text),
39 comments_(comments) {}
Casey Dahlin98a544b2015-10-14 14:22:55 -070040
Casey Dahlinf2d23f72015-10-02 16:19:19 -070041AidlType::AidlType(const std::string& name, unsigned line,
Casey Dahlinf7a421c2015-10-05 17:24:28 -070042 const std::string& comments, bool is_array)
Casey Dahlinf2d23f72015-10-02 16:19:19 -070043 : name_(name),
44 line_(line),
Casey Dahlinf7a421c2015-10-05 17:24:28 -070045 is_array_(is_array),
Casey Dahlinf2d23f72015-10-02 16:19:19 -070046 comments_(comments) {}
47
Casey Dahlin98a544b2015-10-14 14:22:55 -070048string AidlType::ToString() const {
49 return name_ + (is_array_ ? "[]" : "");
Casey Dahlin70078e62015-09-30 17:01:30 -070050}
51
Casey Dahlin0ee37582015-09-30 16:31:55 -070052AidlArgument::AidlArgument(AidlArgument::Direction direction, AidlType* type,
Casey Dahlin308f9d42015-10-05 18:48:42 -070053 std::string name, unsigned line)
Casey Dahlin0ee37582015-09-30 16:31:55 -070054 : type_(type),
Casey Dahlinfd6fb482015-09-30 14:48:18 -070055 direction_(direction),
56 direction_specified_(true),
Casey Dahlin308f9d42015-10-05 18:48:42 -070057 name_(name),
58 line_(line) {}
Casey Dahlinc378c992015-09-29 16:50:40 -070059
Casey Dahlin308f9d42015-10-05 18:48:42 -070060AidlArgument::AidlArgument(AidlType* type, std::string name, unsigned line)
Casey Dahlin0ee37582015-09-30 16:31:55 -070061 : type_(type),
Casey Dahlinfd6fb482015-09-30 14:48:18 -070062 direction_(AidlArgument::IN_DIR),
63 direction_specified_(false),
Casey Dahlin308f9d42015-10-05 18:48:42 -070064 name_(name),
65 line_(line) {}
Casey Dahlinc378c992015-09-29 16:50:40 -070066
67string AidlArgument::ToString() const {
68 string ret;
69
70 if (direction_specified_) {
71 switch(direction_) {
72 case AidlArgument::IN_DIR:
73 ret += "in ";
74 break;
75 case AidlArgument::OUT_DIR:
76 ret += "out ";
77 break;
78 case AidlArgument::INOUT_DIR:
79 ret += "inout ";
80 break;
81 }
82 }
83
Casey Dahlin70078e62015-09-30 17:01:30 -070084 ret += type_->ToString();
Casey Dahlinc378c992015-09-29 16:50:40 -070085 ret += " ";
Casey Dahlind127b502015-09-30 12:51:08 -070086 ret += name_;
Casey Dahlinc378c992015-09-29 16:50:40 -070087
88 return ret;
89}
Casey Dahlinbc7a50a2015-09-28 19:20:50 -070090
Christopher Wileyd6bdd8d2016-05-03 11:23:13 -070091AidlIntConstant::AidlIntConstant(std::string name, int32_t value)
Casey Dahlind40e2fe2015-11-24 14:06:52 -080092 : name_(name),
Roshan Pius3b2203d2016-07-22 16:13:20 -070093 value_(value),
94 is_valid_(true) {}
95
96AidlIntConstant::AidlIntConstant(std::string name,
97 std::string value,
98 unsigned line_number)
99 : name_(name) {
Roshan Pius9d7810a2016-07-28 08:57:50 -0700100 uint32_t unsigned_val;
101 if (!android::base::ParseUint(value.c_str(), &unsigned_val)) {
Roshan Pius3b2203d2016-07-22 16:13:20 -0700102 is_valid_ = false;
103 LOG(ERROR) << "Found invalid int value '" << value
104 << "' on line " << line_number;
105 } else {
Roshan Pius9d7810a2016-07-28 08:57:50 -0700106 // Converting from unsigned to signed integer.
107 value_ = unsigned_val;
Roshan Pius3b2203d2016-07-22 16:13:20 -0700108 is_valid_ = true;
109 }
110}
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800111
Christopher Wileyd6bdd8d2016-05-03 11:23:13 -0700112AidlStringConstant::AidlStringConstant(std::string name,
113 std::string value,
114 unsigned line_number)
115 : name_(name),
116 value_(value) {
117 is_valid_ = true;
118 for (size_t i = 0; i < value_.length(); ++i) {
119 const char& c = value_[i];
120 if (c <= 0x1f || // control characters are < 0x20
121 c >= 0x7f || // DEL is 0x7f
122 c == '\\') { // Disallow backslashes for future proofing.
123 LOG(ERROR) << "Found invalid character at index " << i
124 << " in string constant '" << value_
125 << "' beginning on line " << line_number;
126 is_valid_ = false;
127 break;
128 }
129 }
130}
131
Casey Dahlinf4a93112015-10-05 16:58:09 -0700132AidlMethod::AidlMethod(bool oneway, AidlType* type, std::string name,
133 std::vector<std::unique_ptr<AidlArgument>>* args,
Casey Dahlinfb7da2e2015-10-08 17:26:09 -0700134 unsigned line, const std::string& comments, int id)
Casey Dahlinf4a93112015-10-05 16:58:09 -0700135 : oneway_(oneway),
136 comments_(comments),
137 type_(type),
138 name_(name),
139 line_(line),
140 arguments_(std::move(*args)),
141 id_(id) {
142 has_id_ = true;
143 delete args;
Christopher Wileyad339272015-10-05 19:11:58 -0700144 for (const unique_ptr<AidlArgument>& a : arguments_) {
145 if (a->IsIn()) { in_arguments_.push_back(a.get()); }
146 if (a->IsOut()) { out_arguments_.push_back(a.get()); }
147 }
Casey Dahlinf4a93112015-10-05 16:58:09 -0700148}
149
150AidlMethod::AidlMethod(bool oneway, AidlType* type, std::string name,
151 std::vector<std::unique_ptr<AidlArgument>>* args,
Casey Dahlinfb7da2e2015-10-08 17:26:09 -0700152 unsigned line, const std::string& comments)
Casey Dahlinf4a93112015-10-05 16:58:09 -0700153 : AidlMethod(oneway, type, name, args, line, comments, 0) {
154 has_id_ = false;
155}
Casey Dahlinf2d23f72015-10-02 16:19:19 -0700156
Christopher Wiley4a2884b2015-10-07 11:27:45 -0700157Parser::Parser(const IoDelegate& io_delegate)
158 : io_delegate_(io_delegate) {
159 yylex_init(&scanner_);
160}
161
Steven Moreland787b0432018-07-03 09:00:58 -0700162AidlDefinedType::AidlDefinedType(std::string name, unsigned line,
163 const std::string& comments,
164 const std::vector<std::string>& package)
165 : AidlType(name, line, comments, false /*is_array*/),
166 package_(package) {}
167
168std::string AidlDefinedType::GetPackage() const {
169 return Join(package_, '.');
170}
171
172std::string AidlDefinedType::GetCanonicalName() const {
173 if (package_.empty()) {
174 return GetName();
175 }
176 return GetPackage() + "." + GetName();
177}
178
Casey Dahlin2b2879b2015-10-13 16:59:44 -0700179AidlParcelable::AidlParcelable(AidlQualifiedName* name, unsigned line,
Christopher Wiley8aa4d9f2015-11-16 19:10:45 -0800180 const std::vector<std::string>& package,
181 const std::string& cpp_header)
Steven Moreland787b0432018-07-03 09:00:58 -0700182 : AidlDefinedType(name->GetDotName(), line, "" /*comments*/, package),
183 name_(name),
Christopher Wiley8aa4d9f2015-11-16 19:10:45 -0800184 cpp_header_(cpp_header) {
185 // Strip off quotation marks if we actually have a cpp header.
186 if (cpp_header_.length() >= 2) {
187 cpp_header_ = cpp_header_.substr(1, cpp_header_.length() - 2);
188 }
Casey Dahlin59401da2015-10-09 18:16:45 -0700189}
190
Casey Dahlinfb7da2e2015-10-08 17:26:09 -0700191AidlInterface::AidlInterface(const std::string& name, unsigned line,
192 const std::string& comments, bool oneway,
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800193 std::vector<std::unique_ptr<AidlMember>>* members,
Christopher Wileyd76067c2015-10-19 17:00:13 -0700194 const std::vector<std::string>& package)
Steven Moreland787b0432018-07-03 09:00:58 -0700195 : AidlDefinedType(name, line, comments, package),
196 oneway_(oneway) {
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800197 for (auto& member : *members) {
198 AidlMember* local = member.release();
199 AidlMethod* method = local->AsMethod();
Christopher Wileyd6bdd8d2016-05-03 11:23:13 -0700200 AidlIntConstant* int_constant = local->AsIntConstant();
201 AidlStringConstant* string_constant = local->AsStringConstant();
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800202
203 if (method) {
204 methods_.emplace_back(method);
Christopher Wileyd6bdd8d2016-05-03 11:23:13 -0700205 } else if (int_constant) {
206 int_constants_.emplace_back(int_constant);
207 } else if (string_constant) {
208 string_constants_.emplace_back(string_constant);
Casey Dahlind40e2fe2015-11-24 14:06:52 -0800209 } else {
210 LOG(FATAL) << "Member is neither method nor constant!";
211 }
212 }
213
214 delete members;
Casey Dahlinfb7da2e2015-10-08 17:26:09 -0700215}
216
Casey Dahlinc1f39b42015-11-24 10:34:34 -0800217AidlDocument::AidlDocument(AidlInterface* interface)
218 : interface_(interface) {}
219
Casey Dahlin2b2879b2015-10-13 16:59:44 -0700220AidlQualifiedName::AidlQualifiedName(std::string term,
221 std::string comments)
222 : terms_({term}),
223 comments_(comments) {
Christopher Wiley8aa4d9f2015-11-16 19:10:45 -0800224 if (term.find('.') != string::npos) {
225 terms_ = Split(term, ".");
226 for (const auto& term: terms_) {
227 if (term.empty()) {
228 LOG(FATAL) << "Malformed qualified identifier: '" << term << "'";
229 }
230 }
231 }
Casey Dahlin2b2879b2015-10-13 16:59:44 -0700232}
233
Chih-Hung Hsiehf05cc262016-07-27 11:42:51 -0700234void AidlQualifiedName::AddTerm(const std::string& term) {
Casey Dahlin2b2879b2015-10-13 16:59:44 -0700235 terms_.push_back(term);
236}
237
Casey Dahlin0edf3422015-10-07 12:34:59 -0700238AidlImport::AidlImport(const std::string& from,
239 const std::string& needed_class, unsigned line)
240 : from_(from),
241 needed_class_(needed_class),
242 line_(line) {}
243
Christopher Wiley4a2884b2015-10-07 11:27:45 -0700244Parser::~Parser() {
245 if (raw_buffer_) {
246 yy_delete_buffer(buffer_, scanner_);
247 raw_buffer_.reset();
248 }
249 yylex_destroy(scanner_);
250}
251
252bool Parser::ParseFile(const string& filename) {
253 // Make sure we can read the file first, before trashing previous state.
254 unique_ptr<string> new_buffer = io_delegate_.GetFileContents(filename);
255 if (!new_buffer) {
256 LOG(ERROR) << "Error while opening file for parsing: '" << filename << "'";
257 return false;
258 }
259
260 // Throw away old parsing state if we have any.
261 if (raw_buffer_) {
262 yy_delete_buffer(buffer_, scanner_);
263 raw_buffer_.reset();
264 }
265
266 raw_buffer_ = std::move(new_buffer);
267 // We're going to scan this buffer in place, and yacc demands we put two
268 // nulls at the end.
269 raw_buffer_->append(2u, '\0');
270 filename_ = filename;
Christopher Wileyd76067c2015-10-19 17:00:13 -0700271 package_.reset();
Christopher Wiley4a2884b2015-10-07 11:27:45 -0700272 error_ = 0;
Casey Dahlinc1f39b42015-11-24 10:34:34 -0800273 document_.reset();
Christopher Wiley4a2884b2015-10-07 11:27:45 -0700274
275 buffer_ = yy_scan_buffer(&(*raw_buffer_)[0], raw_buffer_->length(), scanner_);
276
Steven Moreland2ca4fcb2018-06-27 16:01:01 -0700277 if (yy::parser(this).parse() != 0 || error_ != 0)
278 return false;
Christopher Wiley4a2884b2015-10-07 11:27:45 -0700279
Casey Dahlinc1f39b42015-11-24 10:34:34 -0800280 if (document_.get() != nullptr)
281 return true;
282
283 LOG(ERROR) << "Parser succeeded but yielded no document!";
284 return false;
Christopher Wiley4a2884b2015-10-07 11:27:45 -0700285}
286
Christopher Wiley90be4e32015-10-20 14:55:25 -0700287std::vector<std::string> Parser::Package() const {
288 if (!package_) {
289 return {};
290 }
291 return package_->GetTerms();
292}
293
Casey Dahlin2b2879b2015-10-13 16:59:44 -0700294void Parser::AddImport(AidlQualifiedName* name, unsigned line) {
295 imports_.emplace_back(new AidlImport(this->FileName(),
296 name->GetDotName(), line));
297 delete name;
Casey Dahline2507492015-09-14 17:11:20 -0700298}