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