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