aidl_language.cpp revision ad3392747003a30928da6cd206e41f66398c2062
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 113AidlInterface::AidlInterface(const std::string& name, unsigned line, 114 const std::string& comments, bool oneway, 115 std::vector<std::unique_ptr<AidlMethod>>* methods, 116 const std::string& package) 117 : name_(name), 118 comments_(comments), 119 line_(line), 120 oneway_(oneway), 121 methods_(std::move(*methods)), 122 package_(package) { 123 item_type = INTERFACE_TYPE_BINDER; 124 delete methods; 125} 126 127AidlImport::AidlImport(const std::string& from, 128 const std::string& needed_class, unsigned line) 129 : from_(from), 130 needed_class_(needed_class), 131 line_(line) {} 132 133Parser::~Parser() { 134 if (raw_buffer_) { 135 yy_delete_buffer(buffer_, scanner_); 136 raw_buffer_.reset(); 137 } 138 yylex_destroy(scanner_); 139} 140 141bool Parser::ParseFile(const string& filename) { 142 // Make sure we can read the file first, before trashing previous state. 143 unique_ptr<string> new_buffer = io_delegate_.GetFileContents(filename); 144 if (!new_buffer) { 145 LOG(ERROR) << "Error while opening file for parsing: '" << filename << "'"; 146 return false; 147 } 148 149 // Throw away old parsing state if we have any. 150 if (raw_buffer_) { 151 yy_delete_buffer(buffer_, scanner_); 152 raw_buffer_.reset(); 153 } 154 155 raw_buffer_ = std::move(new_buffer); 156 // We're going to scan this buffer in place, and yacc demands we put two 157 // nulls at the end. 158 raw_buffer_->append(2u, '\0'); 159 filename_ = filename; 160 package_.clear(); 161 error_ = 0; 162 document_ = nullptr; 163 164 buffer_ = yy_scan_buffer(&(*raw_buffer_)[0], raw_buffer_->length(), scanner_); 165 166 int ret = yy::parser(this).parse(); 167 168 return ret == 0 && error_ == 0; 169} 170 171void Parser::ReportError(const string& err) { 172 /* FIXME: We're printing out the line number as -1. We used to use yylineno 173 * (which was NEVER correct even before reentrant parsing). Now we'll need 174 * another way. 175 */ 176 cerr << filename_ << ":" << -1 << ": " << err << endl; 177 error_ = 1; 178} 179 180void Parser::AddImport(std::vector<std::string>* terms, unsigned line) { 181 std::string data; 182 bool first = true; 183 184 /* NOTE: This string building code is duplicated from below. We haven't 185 * factored it out into a function because it's hoped that when import_info 186 * becomes a class we won't need this anymore. 187 **/ 188 for (const auto& term : *terms) { 189 if (first) 190 data = term; 191 else 192 data += '.' + term; 193 } 194 195 imports_.emplace_back(new AidlImport(this->FileName(), data, line)); 196 197 delete terms; 198} 199 200void Parser::SetPackage(std::vector<std::string> *terms) { 201 bool first = true; 202 203 for (const auto& term : *terms) { 204 if (first) 205 package_ = term; 206 else 207 package_ += '.' + term; 208 } 209 210 delete terms; 211} 212