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