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