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