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