1 /* 2 * Copyright (C) 2019, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "parser.h" 18 #include "aidl_language_y.h" 19 #include "logging.h" 20 21 void yylex_init(void**); 22 void yylex_destroy(void*); 23 void yyset_in(FILE* f, void*); 24 int yyparse(Parser*); 25 YY_BUFFER_STATE yy_scan_buffer(char*, size_t, void*); 26 void yy_delete_buffer(YY_BUFFER_STATE, void*); 27 28 std::unique_ptr<Parser> Parser::Parse(const std::string& filename, 29 const android::aidl::IoDelegate& io_delegate, 30 AidlTypenames& typenames) { 31 // Make sure we can read the file first, before trashing previous state. 32 unique_ptr<string> raw_buffer = io_delegate.GetFileContents(filename); 33 if (raw_buffer == nullptr) { 34 AIDL_ERROR(filename) << "Error while opening file for parsing"; 35 return nullptr; 36 } 37 38 // We're going to scan this buffer in place, and yacc demands we put two 39 // nulls at the end. 40 raw_buffer->append(2u, '\0'); 41 42 std::unique_ptr<Parser> parser(new Parser(filename, *raw_buffer, typenames)); 43 44 if (yy::parser(parser.get()).parse() != 0 || parser->HasError()) { 45 return nullptr; 46 } 47 48 return parser; 49 } 50 51 void Parser::SetTypeParameters(AidlTypeSpecifier* type, 52 std::vector<std::unique_ptr<AidlTypeSpecifier>>* type_args) { 53 if (type->IsArray()) { 54 AIDL_ERROR(type) << "Must specify type parameters (<>) before array ([])."; 55 AddError(); 56 } 57 if (!type->SetTypeParameters(type_args)) { 58 AIDL_ERROR(type) << "Can only specify one set of type parameters."; 59 AddError(); 60 delete type_args; 61 } 62 } 63 64 class ConstantReferenceResolver : public AidlVisitor { 65 public: 66 ConstantReferenceResolver(const AidlDefinedType* scope, const AidlTypenames& typenames, 67 TypeResolver& resolver, bool* success) 68 : scope_(scope), typenames_(typenames), resolver_(resolver), success_(success) {} 69 void Visit(const AidlConstantReference& v) override { 70 if (IsCircularReference(&v)) { 71 *success_ = false; 72 return; 73 } 74 75 if (v.GetRefType() && !v.GetRefType()->IsResolved()) { 76 if (!resolver_(typenames_.GetDocumentFor(scope_), v.GetRefType().get())) { 77 AIDL_ERROR(v.GetRefType()) << "Unknown type '" << v.GetRefType()->GetName() << "'"; 78 *success_ = false; 79 return; 80 } 81 } 82 const AidlConstantValue* resolved = v.Resolve(scope_); 83 if (!resolved) { 84 AIDL_ERROR(v) << "Unknown reference '" << v.Literal() << "'"; 85 *success_ = false; 86 return; 87 } 88 89 // resolve recursive references 90 Push(&v); 91 VisitTopDown(*this, *resolved); 92 Pop(); 93 } 94 95 private: 96 struct StackElem { 97 const AidlDefinedType* scope; 98 const AidlConstantReference* ref; 99 }; 100 101 void Push(const AidlConstantReference* ref) { 102 stack_.push_back({scope_, ref}); 103 if (ref->GetRefType()) { 104 scope_ = ref->GetRefType()->GetDefinedType(); 105 } 106 } 107 108 void Pop() { 109 scope_ = stack_.back().scope; 110 stack_.pop_back(); 111 } 112 113 bool IsCircularReference(const AidlConstantReference* ref) { 114 auto it = std::find_if(stack_.begin(), stack_.end(), 115 [&](const auto& elem) { return elem.ref == ref; }); 116 if (it == stack_.end()) { 117 return false; 118 } 119 std::vector<std::string> path; 120 while (it != stack_.end()) { 121 path.push_back(it->ref->Literal()); 122 ++it; 123 } 124 path.push_back(ref->Literal()); 125 AIDL_ERROR(ref) << "Found a circular reference: " << android::base::Join(path, " -> "); 126 return true; 127 } 128 129 const AidlDefinedType* scope_; 130 const AidlTypenames& typenames_; 131 TypeResolver& resolver_; 132 bool* success_; 133 std::vector<StackElem> stack_ = {}; 134 }; 135 136 bool Parser::Resolve(TypeResolver& type_resolver) { 137 bool success = true; 138 for (AidlTypeSpecifier* typespec : unresolved_typespecs_) { 139 if (!type_resolver(document_, typespec)) { 140 AIDL_ERROR(typespec) << "Failed to resolve '" << typespec->GetUnresolvedName() << "'"; 141 success = false; 142 // don't stop to show more errors if any 143 } 144 } 145 146 // resolve "field references" as well. 147 for (const auto& type : document_->DefinedTypes()) { 148 ConstantReferenceResolver ref_resolver{type.get(), typenames_, type_resolver, &success}; 149 VisitTopDown(ref_resolver, *type); 150 } 151 152 return success; 153 } 154 155 Parser::Parser(const std::string& filename, std::string& raw_buffer, 156 android::aidl::AidlTypenames& typenames) 157 : filename_(filename), typenames_(typenames) { 158 yylex_init(&scanner_); 159 buffer_ = yy_scan_buffer(&raw_buffer[0], raw_buffer.length(), scanner_); 160 } 161 162 Parser::~Parser() { 163 yy_delete_buffer(buffer_, scanner_); 164 yylex_destroy(scanner_); 165 } 166