aidl_language.cpp revision b696437d842d59c0cc26411fa3d71cb91897c572
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} 132 133std::string AidlParcelable::GetPackage() const { 134 return Join(package_, '.'); 135} 136 137std::string AidlParcelable::GetCanonicalName() const { 138 if (package_.empty()) { 139 return GetName(); 140 } 141 return GetPackage() + "." + GetName(); 142} 143 144AidlInterface::AidlInterface(const std::string& name, unsigned line, 145 const std::string& comments, bool oneway, 146 std::vector<std::unique_ptr<AidlMethod>>* methods, 147 const std::vector<std::string>& package) 148 : name_(name), 149 comments_(comments), 150 line_(line), 151 oneway_(oneway), 152 methods_(std::move(*methods)), 153 package_(package) { 154 delete methods; 155} 156 157std::string AidlInterface::GetPackage() const { 158 return Join(package_, '.'); 159} 160 161std::string AidlInterface::GetCanonicalName() const { 162 if (package_.empty()) { 163 return GetName(); 164 } 165 return GetPackage() + "." + GetName(); 166} 167 168AidlDocument::AidlDocument(AidlInterface* interface) 169 : interface_(interface) {} 170 171AidlQualifiedName::AidlQualifiedName(std::string term, 172 std::string comments) 173 : terms_({term}), 174 comments_(comments) { 175 if (term.find('.') != string::npos) { 176 terms_ = Split(term, "."); 177 for (const auto& term: terms_) { 178 if (term.empty()) { 179 LOG(FATAL) << "Malformed qualified identifier: '" << term << "'"; 180 } 181 } 182 } 183} 184 185void AidlQualifiedName::AddTerm(std::string term) { 186 terms_.push_back(term); 187} 188 189AidlImport::AidlImport(const std::string& from, 190 const std::string& needed_class, unsigned line) 191 : from_(from), 192 needed_class_(needed_class), 193 line_(line) {} 194 195Parser::~Parser() { 196 if (raw_buffer_) { 197 yy_delete_buffer(buffer_, scanner_); 198 raw_buffer_.reset(); 199 } 200 yylex_destroy(scanner_); 201} 202 203bool Parser::ParseFile(const string& filename) { 204 // Make sure we can read the file first, before trashing previous state. 205 unique_ptr<string> new_buffer = io_delegate_.GetFileContents(filename); 206 if (!new_buffer) { 207 LOG(ERROR) << "Error while opening file for parsing: '" << filename << "'"; 208 return false; 209 } 210 211 // Throw away old parsing state if we have any. 212 if (raw_buffer_) { 213 yy_delete_buffer(buffer_, scanner_); 214 raw_buffer_.reset(); 215 } 216 217 raw_buffer_ = std::move(new_buffer); 218 // We're going to scan this buffer in place, and yacc demands we put two 219 // nulls at the end. 220 raw_buffer_->append(2u, '\0'); 221 filename_ = filename; 222 package_.reset(); 223 error_ = 0; 224 document_.reset(); 225 226 buffer_ = yy_scan_buffer(&(*raw_buffer_)[0], raw_buffer_->length(), scanner_); 227 228 if (yy::parser(this).parse() != 0 || error_ != 0) { 229 return false;} 230 231 if (document_.get() != nullptr) 232 return true; 233 234 LOG(ERROR) << "Parser succeeded but yielded no document!"; 235 return false; 236} 237 238void Parser::ReportError(const string& err, unsigned line) { 239 cerr << filename_ << ":" << line << ": " << err << endl; 240 error_ = 1; 241} 242 243std::vector<std::string> Parser::Package() const { 244 if (!package_) { 245 return {}; 246 } 247 return package_->GetTerms(); 248} 249 250void Parser::AddImport(AidlQualifiedName* name, unsigned line) { 251 imports_.emplace_back(new AidlImport(this->FileName(), 252 name->GetDotName(), line)); 253 delete name; 254} 255