1 #include "aidl_language.h"
2 #include "aidl_typenames.h"
3
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <algorithm>
8 #include <cassert>
9 #include <iostream>
10 #include <set>
11 #include <sstream>
12 #include <string>
13 #include <utility>
14
15 #include <android-base/parsedouble.h>
16 #include <android-base/parseint.h>
17 #include <android-base/strings.h>
18
19 #include "aidl_language_y.h"
20 #include "logging.h"
21 #include "type_java.h"
22 #include "type_namespace.h"
23
24 #ifdef _WIN32
isatty(int fd)25 int isatty(int fd)
26 {
27 return (fd == 0);
28 }
29 #endif
30
31 using android::aidl::IoDelegate;
32 using android::base::Join;
33 using android::base::Split;
34 using std::cerr;
35 using std::endl;
36 using std::pair;
37 using std::set;
38 using std::string;
39 using std::unique_ptr;
40 using std::vector;
41
42 void yylex_init(void **);
43 void yylex_destroy(void *);
44 void yyset_in(FILE *f, void *);
45 int yyparse(Parser*);
46 YY_BUFFER_STATE yy_scan_buffer(char *, size_t, void *);
47 void yy_delete_buffer(YY_BUFFER_STATE, void *);
48
AidlToken(const std::string & text,const std::string & comments)49 AidlToken::AidlToken(const std::string& text, const std::string& comments)
50 : text_(text),
51 comments_(comments) {}
52
AidlLocation(const std::string & file,Point begin,Point end)53 AidlLocation::AidlLocation(const std::string& file, Point begin, Point end)
54 : file_(file), begin_(begin), end_(end) {}
55
operator <<(std::ostream & os,const AidlLocation & l)56 std::ostream& operator<<(std::ostream& os, const AidlLocation& l) {
57 os << l.file_ << ":" << l.begin_.line << "." << l.begin_.column << "-";
58 if (l.begin_.line != l.end_.line) {
59 os << l.end_.line << ".";
60 }
61 os << l.end_.column;
62 return os;
63 }
64
AidlNode(const AidlLocation & location)65 AidlNode::AidlNode(const AidlLocation& location) : location_(location) {}
66
PrintLocation() const67 std::string AidlNode::PrintLocation() const {
68 std::stringstream ss;
69 ss << location_.file_ << ":" << location_.begin_.line;
70 return ss.str();
71 }
72
AidlError(bool fatal)73 AidlError::AidlError(bool fatal) : os_(std::cerr), fatal_(fatal) {
74 os_ << "ERROR: ";
75 }
76
77 static const string kNullable("nullable");
78 static const string kUtf8InCpp("utf8InCpp");
79 static const string kUnsupportedAppUsage("UnsupportedAppUsage");
80 static const string kSystemApi("SystemApi");
81 static const string kStableParcelable("JavaOnlyStableParcelable");
82
83 static const set<string> kAnnotationNames{kNullable, kUtf8InCpp, kUnsupportedAppUsage, kSystemApi,
84 kStableParcelable};
85
Parse(const AidlLocation & location,const string & name)86 AidlAnnotation* AidlAnnotation::Parse(const AidlLocation& location, const string& name) {
87 if (kAnnotationNames.find(name) == kAnnotationNames.end()) {
88 std::ostringstream stream;
89 stream << "'" << name << "' is not a recognized annotation. ";
90 stream << "It must be one of:";
91 for (const string& kv : kAnnotationNames) {
92 stream << " " << kv;
93 }
94 stream << ".";
95 AIDL_ERROR(location) << stream.str();
96 return nullptr;
97 }
98 return new AidlAnnotation(location, name);
99 }
100
AidlAnnotation(const AidlLocation & location,const string & name)101 AidlAnnotation::AidlAnnotation(const AidlLocation& location, const string& name)
102 : AidlNode(location), name_(name) {}
103
HasAnnotation(const vector<AidlAnnotation> & annotations,const string & name)104 static bool HasAnnotation(const vector<AidlAnnotation>& annotations, const string& name) {
105 for (const auto& a : annotations) {
106 if (a.GetName() == name) {
107 return true;
108 }
109 }
110 return false;
111 }
112
AidlAnnotatable(const AidlLocation & location)113 AidlAnnotatable::AidlAnnotatable(const AidlLocation& location) : AidlNode(location) {}
114
IsNullable() const115 bool AidlAnnotatable::IsNullable() const {
116 return HasAnnotation(annotations_, kNullable);
117 }
118
IsUtf8InCpp() const119 bool AidlAnnotatable::IsUtf8InCpp() const {
120 return HasAnnotation(annotations_, kUtf8InCpp);
121 }
122
IsUnsupportedAppUsage() const123 bool AidlAnnotatable::IsUnsupportedAppUsage() const {
124 return HasAnnotation(annotations_, kUnsupportedAppUsage);
125 }
126
IsSystemApi() const127 bool AidlAnnotatable::IsSystemApi() const {
128 return HasAnnotation(annotations_, kSystemApi);
129 }
130
IsStableParcelable() const131 bool AidlAnnotatable::IsStableParcelable() const {
132 return HasAnnotation(annotations_, kStableParcelable);
133 }
134
ToString() const135 string AidlAnnotatable::ToString() const {
136 vector<string> ret;
137 for (const auto& a : annotations_) {
138 ret.emplace_back(a.ToString());
139 }
140 std::sort(ret.begin(), ret.end());
141 return Join(ret, " ");
142 }
143
AidlTypeSpecifier(const AidlLocation & location,const string & unresolved_name,bool is_array,vector<unique_ptr<AidlTypeSpecifier>> * type_params,const string & comments)144 AidlTypeSpecifier::AidlTypeSpecifier(const AidlLocation& location, const string& unresolved_name,
145 bool is_array,
146 vector<unique_ptr<AidlTypeSpecifier>>* type_params,
147 const string& comments)
148 : AidlAnnotatable(location),
149 unresolved_name_(unresolved_name),
150 is_array_(is_array),
151 type_params_(type_params),
152 comments_(comments) {}
153
ArrayBase() const154 AidlTypeSpecifier AidlTypeSpecifier::ArrayBase() const {
155 AIDL_FATAL_IF(!is_array_, this);
156
157 AidlTypeSpecifier arrayBase = *this;
158 arrayBase.is_array_ = false;
159 return arrayBase;
160 }
161
ToString() const162 string AidlTypeSpecifier::ToString() const {
163 string ret = GetName();
164 if (IsGeneric()) {
165 vector<string> arg_names;
166 for (const auto& ta : GetTypeParameters()) {
167 arg_names.emplace_back(ta->ToString());
168 }
169 ret += "<" + Join(arg_names, ",") + ">";
170 }
171 if (IsArray()) {
172 ret += "[]";
173 }
174 return ret;
175 }
176
Signature() const177 string AidlTypeSpecifier::Signature() const {
178 string ret = ToString();
179 string annotations = AidlAnnotatable::ToString();
180 if (annotations != "") {
181 ret = annotations + " " + ret;
182 }
183 return ret;
184 }
185
Resolve(android::aidl::AidlTypenames & typenames)186 bool AidlTypeSpecifier::Resolve(android::aidl::AidlTypenames& typenames) {
187 assert(!IsResolved());
188 pair<string, bool> result = typenames.ResolveTypename(unresolved_name_);
189 if (result.second) {
190 fully_qualified_name_ = result.first;
191 }
192 return result.second;
193 }
194
CheckValid(const AidlTypenames & typenames) const195 bool AidlTypeSpecifier::CheckValid(const AidlTypenames& typenames) const {
196 if (IsGeneric()) {
197 const string& type_name = GetName();
198 const int num = GetTypeParameters().size();
199 if (type_name == "List") {
200 if (num > 1) {
201 AIDL_ERROR(this) << " List cannot have type parameters more than one, but got "
202 << "'" << ToString() << "'";
203 return false;
204 }
205 } else if (type_name == "Map") {
206 if (num != 0 && num != 2) {
207 AIDL_ERROR(this) << "Map must have 0 or 2 type parameters, but got "
208 << "'" << ToString() << "'";
209 return false;
210 }
211 }
212 }
213
214 if (GetName() == "void") {
215 if (IsArray() || IsNullable() || IsUtf8InCpp()) {
216 AIDL_ERROR(this) << "void type cannot be an array or nullable or utf8 string";
217 return false;
218 }
219 }
220
221 if (IsArray()) {
222 const auto definedType = typenames.TryGetDefinedType(GetName());
223 if (definedType != nullptr && definedType->AsInterface() != nullptr) {
224 AIDL_ERROR(this) << "Binder type cannot be an array";
225 return false;
226 }
227 }
228
229 if (IsNullable()) {
230 if (AidlTypenames::IsPrimitiveTypename(GetName()) && !IsArray()) {
231 AIDL_ERROR(this) << "Primitive type cannot get nullable annotation";
232 return false;
233 }
234 }
235 return true;
236 }
237
AidlConstantValueDecorator(const AidlTypeSpecifier &,const std::string & raw_value)238 std::string AidlConstantValueDecorator(const AidlTypeSpecifier& /*type*/,
239 const std::string& raw_value) {
240 return raw_value;
241 }
242
AidlVariableDeclaration(const AidlLocation & location,AidlTypeSpecifier * type,const std::string & name)243 AidlVariableDeclaration::AidlVariableDeclaration(const AidlLocation& location,
244 AidlTypeSpecifier* type, const std::string& name)
245 : AidlVariableDeclaration(location, type, name, nullptr /*default_value*/) {}
246
AidlVariableDeclaration(const AidlLocation & location,AidlTypeSpecifier * type,const std::string & name,AidlConstantValue * default_value)247 AidlVariableDeclaration::AidlVariableDeclaration(const AidlLocation& location,
248 AidlTypeSpecifier* type, const std::string& name,
249 AidlConstantValue* default_value)
250 : AidlNode(location), type_(type), name_(name), default_value_(default_value) {}
251
CheckValid(const AidlTypenames & typenames) const252 bool AidlVariableDeclaration::CheckValid(const AidlTypenames& typenames) const {
253 bool valid = true;
254 valid &= type_->CheckValid(typenames);
255
256 if (default_value_ == nullptr) return valid;
257 valid &= default_value_->CheckValid();
258
259 if (!valid) return false;
260
261 return !ValueString(AidlConstantValueDecorator).empty();
262 }
263
ToString() const264 string AidlVariableDeclaration::ToString() const {
265 string ret = type_->Signature() + " " + name_;
266 if (default_value_ != nullptr) {
267 ret += " = " + ValueString(AidlConstantValueDecorator);
268 }
269 return ret;
270 }
271
Signature() const272 string AidlVariableDeclaration::Signature() const {
273 return type_->Signature() + " " + name_;
274 }
275
ValueString(const ConstantValueDecorator & decorator) const276 std::string AidlVariableDeclaration::ValueString(const ConstantValueDecorator& decorator) const {
277 if (default_value_ != nullptr) {
278 return GetDefaultValue()->As(GetType(), decorator);
279 } else {
280 return "";
281 }
282 }
283
AidlArgument(const AidlLocation & location,AidlArgument::Direction direction,AidlTypeSpecifier * type,const std::string & name)284 AidlArgument::AidlArgument(const AidlLocation& location, AidlArgument::Direction direction,
285 AidlTypeSpecifier* type, const std::string& name)
286 : AidlVariableDeclaration(location, type, name),
287 direction_(direction),
288 direction_specified_(true) {}
289
AidlArgument(const AidlLocation & location,AidlTypeSpecifier * type,const std::string & name)290 AidlArgument::AidlArgument(const AidlLocation& location, AidlTypeSpecifier* type,
291 const std::string& name)
292 : AidlVariableDeclaration(location, type, name),
293 direction_(AidlArgument::IN_DIR),
294 direction_specified_(false) {}
295
GetDirectionSpecifier() const296 string AidlArgument::GetDirectionSpecifier() const {
297 string ret;
298 if (direction_specified_) {
299 switch(direction_) {
300 case AidlArgument::IN_DIR:
301 ret += "in ";
302 break;
303 case AidlArgument::OUT_DIR:
304 ret += "out ";
305 break;
306 case AidlArgument::INOUT_DIR:
307 ret += "inout ";
308 break;
309 }
310 }
311 return ret;
312 }
313
ToString() const314 string AidlArgument::ToString() const {
315 return GetDirectionSpecifier() + AidlVariableDeclaration::ToString();
316 }
317
Signature() const318 std::string AidlArgument::Signature() const {
319 class AidlInterface;
320 class AidlInterface;
321 class AidlParcelable;
322 class AidlStructuredParcelable;
323 class AidlParcelable;
324 class AidlStructuredParcelable;
325 return GetDirectionSpecifier() + AidlVariableDeclaration::Signature();
326 }
327
AidlMember(const AidlLocation & location)328 AidlMember::AidlMember(const AidlLocation& location) : AidlNode(location) {}
329
AidlConstantValue(const AidlLocation & location,Type type,const std::string & checked_value)330 AidlConstantValue::AidlConstantValue(const AidlLocation& location, Type type,
331 const std::string& checked_value)
332 : AidlNode(location), type_(type), value_(checked_value) {
333 CHECK(!value_.empty() || type_ == Type::ERROR);
334 CHECK(type_ != Type::ARRAY);
335 }
336
AidlConstantValue(const AidlLocation & location,Type type,std::vector<std::unique_ptr<AidlConstantValue>> * values)337 AidlConstantValue::AidlConstantValue(const AidlLocation& location, Type type,
338 std::vector<std::unique_ptr<AidlConstantValue>>* values)
339 : AidlNode(location), type_(type), values_(std::move(*values)) {}
340
isValidLiteralChar(char c)341 static bool isValidLiteralChar(char c) {
342 return !(c <= 0x1f || // control characters are < 0x20
343 c >= 0x7f || // DEL is 0x7f
344 c == '\\'); // Disallow backslashes for future proofing.
345 }
346
Boolean(const AidlLocation & location,bool value)347 AidlConstantValue* AidlConstantValue::Boolean(const AidlLocation& location, bool value) {
348 return new AidlConstantValue(location, Type::BOOLEAN, value ? "true" : "false");
349 }
350
Character(const AidlLocation & location,char value)351 AidlConstantValue* AidlConstantValue::Character(const AidlLocation& location, char value) {
352 if (!isValidLiteralChar(value)) {
353 AIDL_ERROR(location) << "Invalid character literal " << value;
354 return new AidlConstantValue(location, Type::ERROR, "");
355 }
356 return new AidlConstantValue(location, Type::CHARACTER, std::string("'") + value + "'");
357 }
358
Floating(const AidlLocation & location,const std::string & value)359 AidlConstantValue* AidlConstantValue::Floating(const AidlLocation& location,
360 const std::string& value) {
361 return new AidlConstantValue(location, Type::FLOATING, value);
362 }
363
Hex(const AidlLocation & location,const std::string & value)364 AidlConstantValue* AidlConstantValue::Hex(const AidlLocation& location, const std::string& value) {
365 return new AidlConstantValue(location, Type::HEXIDECIMAL, value);
366 }
367
Integral(const AidlLocation & location,const std::string & value)368 AidlConstantValue* AidlConstantValue::Integral(const AidlLocation& location,
369 const std::string& value) {
370 return new AidlConstantValue(location, Type::INTEGRAL, value);
371 }
372
Array(const AidlLocation & location,std::vector<std::unique_ptr<AidlConstantValue>> * values)373 AidlConstantValue* AidlConstantValue::Array(
374 const AidlLocation& location, std::vector<std::unique_ptr<AidlConstantValue>>* values) {
375 return new AidlConstantValue(location, Type::ARRAY, values);
376 }
377
String(const AidlLocation & location,const std::string & value)378 AidlConstantValue* AidlConstantValue::String(const AidlLocation& location,
379 const std::string& value) {
380 for (size_t i = 0; i < value.length(); ++i) {
381 if (!isValidLiteralChar(value[i])) {
382 AIDL_ERROR(location) << "Found invalid character at index " << i << " in string constant '"
383 << value << "'";
384 return new AidlConstantValue(location, Type::ERROR, "");
385 }
386 }
387
388 return new AidlConstantValue(location, Type::STRING, value);
389 }
390
CheckValid() const391 bool AidlConstantValue::CheckValid() const {
392 // error always logged during creation
393 return type_ != AidlConstantValue::Type::ERROR;
394 }
395
TrimIfSuffix(const string & str,const string & suffix)396 static string TrimIfSuffix(const string& str, const string& suffix) {
397 if (str.size() > suffix.size() &&
398 0 == str.compare(str.size() - suffix.size(), suffix.size(), suffix)) {
399 return str.substr(0, str.size() - suffix.size());
400 }
401 return str;
402 }
403
As(const AidlTypeSpecifier & type,const ConstantValueDecorator & decorator) const404 string AidlConstantValue::As(const AidlTypeSpecifier& type,
405 const ConstantValueDecorator& decorator) const {
406 if (type.IsGeneric()) {
407 AIDL_ERROR(type) << "Generic type cannot be specified with a constant literal.";
408 return "";
409 }
410
411 const std::string& type_string = type.GetName();
412
413 if ((type_ == Type::ARRAY) != type.IsArray()) {
414 goto mismatch_error;
415 }
416
417 switch (type_) {
418 case AidlConstantValue::Type::ARRAY: {
419 vector<string> raw_values;
420 raw_values.reserve(values_.size());
421
422 bool success = true;
423 for (const auto& value : values_) {
424 const AidlTypeSpecifier& array_base = type.ArrayBase();
425 const std::string raw_value = value->As(array_base, decorator);
426
427 success &= !raw_value.empty();
428 raw_values.push_back(decorator(array_base, raw_value));
429 }
430 if (!success) {
431 AIDL_ERROR(this) << "Default value must be a literal array of " << type_string << ".";
432 return "";
433 }
434 return decorator(type, "{" + Join(raw_values, ", ") + "}");
435 }
436 case AidlConstantValue::Type::BOOLEAN:
437 if (type_string == "boolean") return decorator(type, value_);
438 goto mismatch_error;
439 case AidlConstantValue::Type::CHARACTER:
440 if (type_string == "char") return decorator(type, value_);
441 goto mismatch_error;
442 case AidlConstantValue::Type::FLOATING: {
443 bool is_float_literal = value_.back() == 'f';
444 const std::string raw_value = TrimIfSuffix(value_, "f");
445
446 if (type_string == "double") {
447 double parsed_value;
448 if (!android::base::ParseDouble(raw_value, &parsed_value)) goto parse_error;
449 return decorator(type, std::to_string(parsed_value));
450 }
451 if (is_float_literal && type_string == "float") {
452 float parsed_value;
453 if (!android::base::ParseFloat(raw_value, &parsed_value)) goto parse_error;
454 return decorator(type, std::to_string(parsed_value) + "f");
455 }
456 goto mismatch_error;
457 }
458 case AidlConstantValue::Type::HEXIDECIMAL:
459 // For historical reasons, a hexidecimal int needs to have the specified bits interpreted
460 // as the signed type, so the other types are made consistent with it.
461 if (type_string == "byte") {
462 uint8_t unsigned_value;
463 if (!android::base::ParseUint<uint8_t>(value_, &unsigned_value)) goto parse_error;
464 return decorator(type, std::to_string((int8_t)unsigned_value));
465 }
466 if (type_string == "int") {
467 uint32_t unsigned_value;
468 if (!android::base::ParseUint<uint32_t>(value_, &unsigned_value)) goto parse_error;
469 return decorator(type, std::to_string((int32_t)unsigned_value));
470 }
471 if (type_string == "long") {
472 uint64_t unsigned_value;
473 if (!android::base::ParseUint<uint64_t>(value_, &unsigned_value)) goto parse_error;
474 return decorator(type, std::to_string((int64_t)unsigned_value));
475 }
476 goto mismatch_error;
477 case AidlConstantValue::Type::INTEGRAL:
478 if (type_string == "byte") {
479 if (!android::base::ParseInt<int8_t>(value_, nullptr)) goto parse_error;
480 return decorator(type, value_);
481 }
482 if (type_string == "int") {
483 if (!android::base::ParseInt<int32_t>(value_, nullptr)) goto parse_error;
484 return decorator(type, value_);
485 }
486 if (type_string == "long") {
487 if (!android::base::ParseInt<int64_t>(value_, nullptr)) goto parse_error;
488 return decorator(type, value_);
489 }
490 goto mismatch_error;
491 case AidlConstantValue::Type::STRING:
492 if (type_string == "String") return decorator(type, value_);
493 goto mismatch_error;
494 default:
495 AIDL_FATAL(this) << "Unrecognized constant value type";
496 }
497
498 mismatch_error:
499 AIDL_ERROR(this) << "Expecting type " << type_string << " but constant is " << ToString(type_);
500 return "";
501 parse_error:
502 AIDL_ERROR(this) << "Could not parse " << value_ << " as " << type_string;
503 return "";
504 }
505
ToString(Type type)506 string AidlConstantValue::ToString(Type type) {
507 switch (type) {
508 case Type::ARRAY:
509 return "a literal array";
510 case Type::BOOLEAN:
511 return "a literal boolean";
512 case Type::CHARACTER:
513 return "a literal char";
514 case Type::FLOATING:
515 return "a floating-point literal";
516 case Type::HEXIDECIMAL:
517 return "a hexidecimal literal";
518 case Type::INTEGRAL:
519 return "an integral literal";
520 case Type::STRING:
521 return "a literal string";
522 case Type::ERROR:
523 LOG(FATAL) << "aidl internal error: error type failed to halt program";
524 return "";
525 default:
526 LOG(FATAL) << "aidl internal error: unknown constant type: " << static_cast<int>(type);
527 return ""; // not reached
528 }
529 }
530
AidlConstantDeclaration(const AidlLocation & location,AidlTypeSpecifier * type,const std::string & name,AidlConstantValue * value)531 AidlConstantDeclaration::AidlConstantDeclaration(const AidlLocation& location,
532 AidlTypeSpecifier* type, const std::string& name,
533 AidlConstantValue* value)
534 : AidlMember(location), type_(type), name_(name), value_(value) {}
535
CheckValid(const AidlTypenames & typenames) const536 bool AidlConstantDeclaration::CheckValid(const AidlTypenames& typenames) const {
537 bool valid = true;
538 valid &= type_->CheckValid(typenames);
539 valid &= value_->CheckValid();
540 if (!valid) return false;
541
542 const static set<string> kSupportedConstTypes = {"String", "int"};
543 if (kSupportedConstTypes.find(type_->ToString()) == kSupportedConstTypes.end()) {
544 AIDL_ERROR(this) << "Constant of type " << type_->ToString() << " is not supported.";
545 return false;
546 }
547
548 return !ValueString(AidlConstantValueDecorator).empty();
549 }
550
ToString() const551 string AidlConstantDeclaration::ToString() const {
552 return "const " + type_->ToString() + " " + name_ + " = " +
553 ValueString(AidlConstantValueDecorator);
554 }
555
Signature() const556 string AidlConstantDeclaration::Signature() const {
557 return type_->Signature() + " " + name_;
558 }
559
AidlMethod(const AidlLocation & location,bool oneway,AidlTypeSpecifier * type,const std::string & name,std::vector<std::unique_ptr<AidlArgument>> * args,const std::string & comments)560 AidlMethod::AidlMethod(const AidlLocation& location, bool oneway, AidlTypeSpecifier* type,
561 const std::string& name, std::vector<std::unique_ptr<AidlArgument>>* args,
562 const std::string& comments)
563 : AidlMethod(location, oneway, type, name, args, comments, 0, true) {
564 has_id_ = false;
565 }
566
AidlMethod(const AidlLocation & location,bool oneway,AidlTypeSpecifier * type,const std::string & name,std::vector<std::unique_ptr<AidlArgument>> * args,const std::string & comments,int id,bool is_user_defined)567 AidlMethod::AidlMethod(const AidlLocation& location, bool oneway, AidlTypeSpecifier* type,
568 const std::string& name, std::vector<std::unique_ptr<AidlArgument>>* args,
569 const std::string& comments, int id, bool is_user_defined)
570 : AidlMember(location),
571 oneway_(oneway),
572 comments_(comments),
573 type_(type),
574 name_(name),
575 arguments_(std::move(*args)),
576 id_(id),
577 is_user_defined_(is_user_defined) {
578 has_id_ = true;
579 delete args;
580 for (const unique_ptr<AidlArgument>& a : arguments_) {
581 if (a->IsIn()) { in_arguments_.push_back(a.get()); }
582 if (a->IsOut()) { out_arguments_.push_back(a.get()); }
583 }
584 }
585
586
Signature() const587 string AidlMethod::Signature() const {
588 vector<string> arg_signatures;
589 for (const auto& arg : GetArguments()) {
590 arg_signatures.emplace_back(arg->GetType().ToString());
591 }
592 return GetName() + "(" + Join(arg_signatures, ", ") + ")";
593 }
594
ToString() const595 string AidlMethod::ToString() const {
596 vector<string> arg_strings;
597 for (const auto& arg : GetArguments()) {
598 arg_strings.emplace_back(arg->Signature());
599 }
600 string ret = (IsOneway() ? "oneway " : "") + GetType().Signature() + " " + GetName() + "(" +
601 Join(arg_strings, ", ") + ")";
602 if (HasId()) {
603 ret += " = " + std::to_string(GetId());
604 }
605 return ret;
606 }
607
AidlDefinedType(const AidlLocation & location,const std::string & name,const std::string & comments,const std::vector<std::string> & package)608 AidlDefinedType::AidlDefinedType(const AidlLocation& location, const std::string& name,
609 const std::string& comments,
610 const std::vector<std::string>& package)
611 : AidlAnnotatable(location), name_(name), comments_(comments), package_(package) {}
612
GetPackage() const613 std::string AidlDefinedType::GetPackage() const {
614 return Join(package_, '.');
615 }
616
GetCanonicalName() const617 std::string AidlDefinedType::GetCanonicalName() const {
618 if (package_.empty()) {
619 return GetName();
620 }
621 return GetPackage() + "." + GetName();
622 }
623
AidlParcelable(const AidlLocation & location,AidlQualifiedName * name,const std::vector<std::string> & package,const std::string & comments,const std::string & cpp_header)624 AidlParcelable::AidlParcelable(const AidlLocation& location, AidlQualifiedName* name,
625 const std::vector<std::string>& package, const std::string& comments,
626 const std::string& cpp_header)
627 : AidlDefinedType(location, name->GetDotName(), comments, package),
628 name_(name),
629 cpp_header_(cpp_header) {
630 // Strip off quotation marks if we actually have a cpp header.
631 if (cpp_header_.length() >= 2) {
632 cpp_header_ = cpp_header_.substr(1, cpp_header_.length() - 2);
633 }
634 }
635
CheckValid(const AidlTypenames &) const636 bool AidlParcelable::CheckValid(const AidlTypenames&) const {
637 static const std::set<string> allowed{kStableParcelable};
638 for (const auto& v : GetAnnotations()) {
639 if (allowed.find(v.GetName()) == allowed.end()) {
640 std::ostringstream stream;
641 stream << "Unstructured parcelable can contain only";
642 for (const string& kv : allowed) {
643 stream << " " << kv;
644 }
645 stream << ".";
646 AIDL_ERROR(this) << stream.str();
647 return false;
648 }
649 }
650
651 return true;
652 }
653
Write(CodeWriter * writer) const654 void AidlParcelable::Write(CodeWriter* writer) const {
655 writer->Write("parcelable %s ;\n", GetName().c_str());
656 }
657
AidlStructuredParcelable(const AidlLocation & location,AidlQualifiedName * name,const std::vector<std::string> & package,const std::string & comments,std::vector<std::unique_ptr<AidlVariableDeclaration>> * variables)658 AidlStructuredParcelable::AidlStructuredParcelable(
659 const AidlLocation& location, AidlQualifiedName* name, const std::vector<std::string>& package,
660 const std::string& comments, std::vector<std::unique_ptr<AidlVariableDeclaration>>* variables)
661 : AidlParcelable(location, name, package, comments, "" /*cpp_header*/),
662 variables_(std::move(*variables)) {}
663
Write(CodeWriter * writer) const664 void AidlStructuredParcelable::Write(CodeWriter* writer) const {
665 writer->Write("parcelable %s {\n", GetName().c_str());
666 writer->Indent();
667 for (const auto& field : GetFields()) {
668 writer->Write("%s;\n", field->ToString().c_str());
669 }
670 writer->Dedent();
671 writer->Write("}\n");
672 }
673
CheckValid(const AidlTypenames & typenames) const674 bool AidlStructuredParcelable::CheckValid(const AidlTypenames& typenames) const {
675 for (const auto& v : GetFields()) {
676 if (!(v->CheckValid(typenames))) {
677 return false;
678 }
679 }
680
681 return true;
682 }
683
AidlInterface(const AidlLocation & location,const std::string & name,const std::string & comments,bool oneway,std::vector<std::unique_ptr<AidlMember>> * members,const std::vector<std::string> & package)684 AidlInterface::AidlInterface(const AidlLocation& location, const std::string& name,
685 const std::string& comments, bool oneway,
686 std::vector<std::unique_ptr<AidlMember>>* members,
687 const std::vector<std::string>& package)
688 : AidlDefinedType(location, name, comments, package) {
689 for (auto& member : *members) {
690 AidlMember* local = member.release();
691 AidlMethod* method = local->AsMethod();
692 AidlConstantDeclaration* constant = local->AsConstantDeclaration();
693
694 CHECK(method == nullptr || constant == nullptr);
695
696 if (method) {
697 method->ApplyInterfaceOneway(oneway);
698 methods_.emplace_back(method);
699 } else if (constant) {
700 constants_.emplace_back(constant);
701 } else {
702 AIDL_FATAL(this) << "Member is neither method nor constant!";
703 }
704 }
705
706 delete members;
707 }
708
Write(CodeWriter * writer) const709 void AidlInterface::Write(CodeWriter* writer) const {
710 writer->Write("interface %s {\n", GetName().c_str());
711 writer->Indent();
712 for (const auto& method : GetMethods()) {
713 writer->Write("%s;\n", method->ToString().c_str());
714 }
715 for (const auto& constdecl : GetConstantDeclarations()) {
716 writer->Write("%s;\n", constdecl->ToString().c_str());
717 }
718 writer->Dedent();
719 writer->Write("}\n");
720 }
721
CheckValid(const AidlTypenames & typenames) const722 bool AidlInterface::CheckValid(const AidlTypenames& typenames) const {
723 // Has to be a pointer due to deleting copy constructor. No idea why.
724 map<string, const AidlMethod*> method_names;
725 for (const auto& m : GetMethods()) {
726 if (!m->GetType().CheckValid(typenames)) {
727 return false;
728 }
729
730 if (m->IsOneway() && m->GetType().GetName() != "void") {
731 AIDL_ERROR(m) << "oneway method '" << m->GetName() << "' cannot return a value";
732 return false;
733 }
734
735 set<string> argument_names;
736 for (const auto& arg : m->GetArguments()) {
737 auto it = argument_names.find(arg->GetName());
738 if (it != argument_names.end()) {
739 AIDL_ERROR(m) << "method '" << m->GetName() << "' has duplicate argument name '"
740 << arg->GetName() << "'";
741 return false;
742 }
743 argument_names.insert(arg->GetName());
744
745 if (!arg->GetType().CheckValid(typenames)) {
746 return false;
747 }
748
749 if (m->IsOneway() && arg->IsOut()) {
750 AIDL_ERROR(m) << "oneway method '" << m->GetName() << "' cannot have out parameters";
751 return false;
752 }
753 }
754
755 auto it = method_names.find(m->GetName());
756 // prevent duplicate methods
757 if (it == method_names.end()) {
758 method_names[m->GetName()] = m.get();
759 } else {
760 AIDL_ERROR(m) << "attempt to redefine method " << m->GetName() << ":";
761 AIDL_ERROR(it->second) << "previously defined here.";
762 return false;
763 }
764
765 static set<string> reserved_methods{"asBinder()", "getInterfaceVersion()",
766 "getTransactionName(int)"};
767
768 if (reserved_methods.find(m->Signature()) != reserved_methods.end()) {
769 AIDL_ERROR(m) << " method " << m->Signature() << " is reserved for internal use." << endl;
770 return false;
771 }
772 }
773
774 bool success = true;
775 set<string> constant_names;
776 for (const std::unique_ptr<AidlConstantDeclaration>& constant : GetConstantDeclarations()) {
777 if (constant_names.count(constant->GetName()) > 0) {
778 LOG(ERROR) << "Found duplicate constant name '" << constant->GetName() << "'";
779 success = false;
780 }
781 constant_names.insert(constant->GetName());
782 success = success && constant->CheckValid(typenames);
783 }
784
785 return success;
786 }
787
AidlQualifiedName(const AidlLocation & location,const std::string & term,const std::string & comments)788 AidlQualifiedName::AidlQualifiedName(const AidlLocation& location, const std::string& term,
789 const std::string& comments)
790 : AidlNode(location), terms_({term}), comments_(comments) {
791 if (term.find('.') != string::npos) {
792 terms_ = Split(term, ".");
793 for (const auto& subterm : terms_) {
794 if (subterm.empty()) {
795 AIDL_FATAL(this) << "Malformed qualified identifier: '" << term << "'";
796 }
797 }
798 }
799 }
800
AddTerm(const std::string & term)801 void AidlQualifiedName::AddTerm(const std::string& term) {
802 terms_.push_back(term);
803 }
804
AidlImport(const AidlLocation & location,const std::string & needed_class)805 AidlImport::AidlImport(const AidlLocation& location, const std::string& needed_class)
806 : AidlNode(location), needed_class_(needed_class) {}
807
Parse(const std::string & filename,const android::aidl::IoDelegate & io_delegate,AidlTypenames & typenames)808 std::unique_ptr<Parser> Parser::Parse(const std::string& filename,
809 const android::aidl::IoDelegate& io_delegate,
810 AidlTypenames& typenames) {
811 // Make sure we can read the file first, before trashing previous state.
812 unique_ptr<string> raw_buffer = io_delegate.GetFileContents(filename);
813 if (raw_buffer == nullptr) {
814 AIDL_ERROR(filename) << "Error while opening file for parsing";
815 return nullptr;
816 }
817
818 // We're going to scan this buffer in place, and yacc demands we put two
819 // nulls at the end.
820 raw_buffer->append(2u, '\0');
821
822 std::unique_ptr<Parser> parser(new Parser(filename, *raw_buffer, typenames));
823
824 if (yy::parser(parser.get()).parse() != 0 || parser->HasError()) return nullptr;
825
826 return parser;
827 }
828
Package() const829 std::vector<std::string> Parser::Package() const {
830 if (!package_) {
831 return {};
832 }
833 return package_->GetTerms();
834 }
835
AddImport(AidlImport * import)836 void Parser::AddImport(AidlImport* import) {
837 imports_.emplace_back(import);
838 }
839
Resolve()840 bool Parser::Resolve() {
841 bool success = true;
842 for (AidlTypeSpecifier* typespec : unresolved_typespecs_) {
843 if (!typespec->Resolve(typenames_)) {
844 AIDL_ERROR(typespec) << "Failed to resolve '" << typespec->GetUnresolvedName() << "'";
845 success = false;
846 // don't stop to show more errors if any
847 }
848 }
849 return success;
850 }
851
Parser(const std::string & filename,std::string & raw_buffer,android::aidl::AidlTypenames & typenames)852 Parser::Parser(const std::string& filename, std::string& raw_buffer,
853 android::aidl::AidlTypenames& typenames)
854 : filename_(filename), typenames_(typenames) {
855 yylex_init(&scanner_);
856 buffer_ = yy_scan_buffer(&raw_buffer[0], raw_buffer.length(), scanner_);
857 }
858
~Parser()859 Parser::~Parser() {
860 yy_delete_buffer(buffer_, scanner_);
861 yylex_destroy(scanner_);
862 }
863