aidl_language.cpp revision 90be4e3fe6d16ea8e8263b80989ef2ab4e6ef9c6
1#include "aidl_language.h" 2 3#include <iostream> 4#include <stdio.h> 5#include <stdlib.h> 6#include <string.h> 7#include <string> 8 9#include <base/strings.h> 10 11#include "aidl_language_y.hpp" 12#include "logging.h" 13 14#ifdef _WIN32 15int isatty(int fd) 16{ 17 return (fd == 0); 18} 19#endif 20 21using android::aidl::IoDelegate; 22using android::base::Join; 23using std::cerr; 24using std::endl; 25using std::string; 26using std::unique_ptr; 27 28void yylex_init(void **); 29void yylex_destroy(void *); 30void yyset_in(FILE *f, void *); 31int yyparse(Parser*); 32YY_BUFFER_STATE yy_scan_buffer(char *, size_t, void *); 33void yy_delete_buffer(YY_BUFFER_STATE, void *); 34 35AidlToken::AidlToken(const std::string& text, const std::string& comments) 36 : text_(text), 37 comments_(comments) {} 38 39AidlType::AidlType(const std::string& name, unsigned line, 40 const std::string& comments, bool is_array) 41 : name_(name), 42 line_(line), 43 is_array_(is_array), 44 comments_(comments) {} 45 46string AidlType::ToString() const { 47 return name_ + (is_array_ ? "[]" : ""); 48} 49 50AidlArgument::AidlArgument(AidlArgument::Direction direction, AidlType* type, 51 std::string name, unsigned line) 52 : type_(type), 53 direction_(direction), 54 direction_specified_(true), 55 name_(name), 56 line_(line) {} 57 58AidlArgument::AidlArgument(AidlType* type, std::string name, unsigned line) 59 : type_(type), 60 direction_(AidlArgument::IN_DIR), 61 direction_specified_(false), 62 name_(name), 63 line_(line) {} 64 65string AidlArgument::ToString() const { 66 string ret; 67 68 if (direction_specified_) { 69 switch(direction_) { 70 case AidlArgument::IN_DIR: 71 ret += "in "; 72 break; 73 case AidlArgument::OUT_DIR: 74 ret += "out "; 75 break; 76 case AidlArgument::INOUT_DIR: 77 ret += "inout "; 78 break; 79 } 80 } 81 82 ret += type_->ToString(); 83 ret += " "; 84 ret += name_; 85 86 return ret; 87} 88 89AidlMethod::AidlMethod(bool oneway, AidlType* type, std::string name, 90 std::vector<std::unique_ptr<AidlArgument>>* args, 91 unsigned line, const std::string& comments, int id) 92 : oneway_(oneway), 93 comments_(comments), 94 type_(type), 95 name_(name), 96 line_(line), 97 arguments_(std::move(*args)), 98 id_(id) { 99 has_id_ = true; 100 delete args; 101 for (const unique_ptr<AidlArgument>& a : arguments_) { 102 if (a->IsIn()) { in_arguments_.push_back(a.get()); } 103 if (a->IsOut()) { out_arguments_.push_back(a.get()); } 104 } 105} 106 107AidlMethod::AidlMethod(bool oneway, AidlType* type, std::string name, 108 std::vector<std::unique_ptr<AidlArgument>>* args, 109 unsigned line, const std::string& comments) 110 : AidlMethod(oneway, type, name, args, line, comments, 0) { 111 has_id_ = false; 112} 113 114Parser::Parser(const IoDelegate& io_delegate) 115 : io_delegate_(io_delegate) { 116 yylex_init(&scanner_); 117} 118 119AidlParcelable::AidlParcelable(AidlQualifiedName* name, unsigned line, 120 const std::vector<std::string>& package) 121 : AidlParcelable(name->GetDotName(), line, package) { 122 delete name; 123} 124 125AidlParcelable::AidlParcelable(const std::string& name, unsigned line, 126 const std::vector<std::string>& package) 127 : name_(name), 128 line_(line), 129 package_(package) { 130 item_type = USER_DATA_TYPE; 131} 132 133std::string AidlParcelable::GetPackage() const { 134 return Join(package_, '.'); 135} 136 137AidlInterface::AidlInterface(const std::string& name, unsigned line, 138 const std::string& comments, bool oneway, 139 std::vector<std::unique_ptr<AidlMethod>>* methods, 140 const std::vector<std::string>& package) 141 : name_(name), 142 comments_(comments), 143 line_(line), 144 oneway_(oneway), 145 methods_(std::move(*methods)), 146 package_(package) { 147 item_type = INTERFACE_TYPE_BINDER; 148 delete methods; 149} 150 151std::string AidlInterface::GetPackage() const { 152 return Join(package_, '.'); 153} 154 155std::string AidlInterface::GetCanonicalName() const { 156 if (package_.empty()) { 157 return GetName(); 158 } 159 return GetPackage() + "." + GetName(); 160} 161 162AidlQualifiedName::AidlQualifiedName(std::string term, 163 std::string comments) 164 : terms_({term}), 165 comments_(comments) { 166} 167 168void AidlQualifiedName::AddTerm(std::string term) { 169 terms_.push_back(term); 170} 171 172AidlImport::AidlImport(const std::string& from, 173 const std::string& needed_class, unsigned line) 174 : from_(from), 175 needed_class_(needed_class), 176 line_(line) {} 177 178Parser::~Parser() { 179 if (raw_buffer_) { 180 yy_delete_buffer(buffer_, scanner_); 181 raw_buffer_.reset(); 182 } 183 yylex_destroy(scanner_); 184} 185 186bool Parser::ParseFile(const string& filename) { 187 // Make sure we can read the file first, before trashing previous state. 188 unique_ptr<string> new_buffer = io_delegate_.GetFileContents(filename); 189 if (!new_buffer) { 190 LOG(ERROR) << "Error while opening file for parsing: '" << filename << "'"; 191 return false; 192 } 193 194 // Throw away old parsing state if we have any. 195 if (raw_buffer_) { 196 yy_delete_buffer(buffer_, scanner_); 197 raw_buffer_.reset(); 198 } 199 200 raw_buffer_ = std::move(new_buffer); 201 // We're going to scan this buffer in place, and yacc demands we put two 202 // nulls at the end. 203 raw_buffer_->append(2u, '\0'); 204 filename_ = filename; 205 package_.reset(); 206 error_ = 0; 207 document_ = nullptr; 208 209 buffer_ = yy_scan_buffer(&(*raw_buffer_)[0], raw_buffer_->length(), scanner_); 210 211 int ret = yy::parser(this).parse(); 212 213 return ret == 0 && error_ == 0; 214} 215 216void Parser::ReportError(const string& err, unsigned line) { 217 cerr << filename_ << ":" << line << ": " << err << endl; 218 error_ = 1; 219} 220 221std::vector<std::string> Parser::Package() const { 222 if (!package_) { 223 return {}; 224 } 225 return package_->GetTerms(); 226} 227 228void Parser::AddImport(AidlQualifiedName* name, unsigned line) { 229 imports_.emplace_back(new AidlImport(this->FileName(), 230 name->GetDotName(), line)); 231 delete name; 232} 233