Home | History | Annotate | Download | only in aidl
      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 <android-base/strings.h>
     10 
     11 #include "aidl_language_y.h"
     12 #include "logging.h"
     13 
     14 #ifdef _WIN32
     15 int isatty(int  fd)
     16 {
     17     return (fd == 0);
     18 }
     19 #endif
     20 
     21 using android::aidl::IoDelegate;
     22 using android::base::Join;
     23 using android::base::Split;
     24 using std::cerr;
     25 using std::endl;
     26 using std::string;
     27 using std::unique_ptr;
     28 
     29 void yylex_init(void **);
     30 void yylex_destroy(void *);
     31 void yyset_in(FILE *f, void *);
     32 int yyparse(Parser*);
     33 YY_BUFFER_STATE yy_scan_buffer(char *, size_t, void *);
     34 void yy_delete_buffer(YY_BUFFER_STATE, void *);
     35 
     36 AidlToken::AidlToken(const std::string& text, const std::string& comments)
     37     : text_(text),
     38       comments_(comments) {}
     39 
     40 AidlType::AidlType(const std::string& name, unsigned line,
     41                    const std::string& comments, bool is_array)
     42     : name_(name),
     43       line_(line),
     44       is_array_(is_array),
     45       comments_(comments) {}
     46 
     47 string AidlType::ToString() const {
     48   return name_ + (is_array_ ? "[]" : "");
     49 }
     50 
     51 AidlArgument::AidlArgument(AidlArgument::Direction direction, AidlType* type,
     52                            std::string name, unsigned line)
     53     : type_(type),
     54       direction_(direction),
     55       direction_specified_(true),
     56       name_(name),
     57       line_(line) {}
     58 
     59 AidlArgument::AidlArgument(AidlType* type, std::string name, unsigned line)
     60     : type_(type),
     61       direction_(AidlArgument::IN_DIR),
     62       direction_specified_(false),
     63       name_(name),
     64       line_(line) {}
     65 
     66 string AidlArgument::ToString() const {
     67   string ret;
     68 
     69   if (direction_specified_) {
     70     switch(direction_) {
     71     case AidlArgument::IN_DIR:
     72       ret += "in ";
     73       break;
     74     case AidlArgument::OUT_DIR:
     75       ret += "out ";
     76       break;
     77     case AidlArgument::INOUT_DIR:
     78       ret += "inout ";
     79       break;
     80     }
     81   }
     82 
     83   ret += type_->ToString();
     84   ret += " ";
     85   ret += name_;
     86 
     87   return ret;
     88 }
     89 
     90 AidlConstant::AidlConstant(std::string name, int32_t value)
     91     : name_(name),
     92       value_(value) {}
     93 
     94 AidlMethod::AidlMethod(bool oneway, AidlType* type, std::string name,
     95                        std::vector<std::unique_ptr<AidlArgument>>* args,
     96                        unsigned line, const std::string& comments, int id)
     97     : oneway_(oneway),
     98       comments_(comments),
     99       type_(type),
    100       name_(name),
    101       line_(line),
    102       arguments_(std::move(*args)),
    103       id_(id) {
    104   has_id_ = true;
    105   delete args;
    106   for (const unique_ptr<AidlArgument>& a : arguments_) {
    107     if (a->IsIn()) { in_arguments_.push_back(a.get()); }
    108     if (a->IsOut()) { out_arguments_.push_back(a.get()); }
    109   }
    110 }
    111 
    112 AidlMethod::AidlMethod(bool oneway, AidlType* type, std::string name,
    113                        std::vector<std::unique_ptr<AidlArgument>>* args,
    114                        unsigned line, const std::string& comments)
    115     : AidlMethod(oneway, type, name, args, line, comments, 0) {
    116   has_id_ = false;
    117 }
    118 
    119 Parser::Parser(const IoDelegate& io_delegate)
    120     : io_delegate_(io_delegate) {
    121   yylex_init(&scanner_);
    122 }
    123 
    124 AidlParcelable::AidlParcelable(AidlQualifiedName* name, unsigned line,
    125                                const std::vector<std::string>& package,
    126                                const std::string& cpp_header)
    127     : name_(name),
    128       line_(line),
    129       package_(package),
    130       cpp_header_(cpp_header) {
    131   // Strip off quotation marks if we actually have a cpp header.
    132   if (cpp_header_.length() >= 2) {
    133     cpp_header_ = cpp_header_.substr(1, cpp_header_.length() - 2);
    134   }
    135 }
    136 
    137 std::string AidlParcelable::GetPackage() const {
    138   return Join(package_, '.');
    139 }
    140 
    141 std::string AidlParcelable::GetCanonicalName() const {
    142   if (package_.empty()) {
    143     return GetName();
    144   }
    145   return GetPackage() + "." + GetName();
    146 }
    147 
    148 AidlInterface::AidlInterface(const std::string& name, unsigned line,
    149                              const std::string& comments, bool oneway,
    150                              std::vector<std::unique_ptr<AidlMember>>* members,
    151                              const std::vector<std::string>& package)
    152     : name_(name),
    153       comments_(comments),
    154       line_(line),
    155       oneway_(oneway),
    156       package_(package) {
    157   for (auto& member : *members) {
    158     AidlMember* local = member.release();
    159     AidlMethod* method = local->AsMethod();
    160     AidlConstant* constant = local->AsConstant();
    161 
    162     if (method) {
    163       methods_.emplace_back(method);
    164     } else if (constant) {
    165       constants_.emplace_back(constant);
    166     } else {
    167       LOG(FATAL) << "Member is neither method nor constant!";
    168     }
    169   }
    170 
    171   delete members;
    172 }
    173 
    174 std::string AidlInterface::GetPackage() const {
    175   return Join(package_, '.');
    176 }
    177 
    178 std::string AidlInterface::GetCanonicalName() const {
    179   if (package_.empty()) {
    180     return GetName();
    181   }
    182   return GetPackage() + "." + GetName();
    183 }
    184 
    185 AidlDocument::AidlDocument(AidlInterface* interface)
    186     : interface_(interface) {}
    187 
    188 AidlQualifiedName::AidlQualifiedName(std::string term,
    189                                      std::string comments)
    190     : terms_({term}),
    191       comments_(comments) {
    192   if (term.find('.') != string::npos) {
    193     terms_ = Split(term, ".");
    194     for (const auto& term: terms_) {
    195       if (term.empty()) {
    196         LOG(FATAL) << "Malformed qualified identifier: '" << term << "'";
    197       }
    198     }
    199   }
    200 }
    201 
    202 void AidlQualifiedName::AddTerm(std::string term) {
    203   terms_.push_back(term);
    204 }
    205 
    206 AidlImport::AidlImport(const std::string& from,
    207                        const std::string& needed_class, unsigned line)
    208     : from_(from),
    209       needed_class_(needed_class),
    210       line_(line) {}
    211 
    212 Parser::~Parser() {
    213   if (raw_buffer_) {
    214     yy_delete_buffer(buffer_, scanner_);
    215     raw_buffer_.reset();
    216   }
    217   yylex_destroy(scanner_);
    218 }
    219 
    220 bool Parser::ParseFile(const string& filename) {
    221   // Make sure we can read the file first, before trashing previous state.
    222   unique_ptr<string> new_buffer = io_delegate_.GetFileContents(filename);
    223   if (!new_buffer) {
    224     LOG(ERROR) << "Error while opening file for parsing: '" << filename << "'";
    225     return false;
    226   }
    227 
    228   // Throw away old parsing state if we have any.
    229   if (raw_buffer_) {
    230     yy_delete_buffer(buffer_, scanner_);
    231     raw_buffer_.reset();
    232   }
    233 
    234   raw_buffer_ = std::move(new_buffer);
    235   // We're going to scan this buffer in place, and yacc demands we put two
    236   // nulls at the end.
    237   raw_buffer_->append(2u, '\0');
    238   filename_ = filename;
    239   package_.reset();
    240   error_ = 0;
    241   document_.reset();
    242 
    243   buffer_ = yy_scan_buffer(&(*raw_buffer_)[0], raw_buffer_->length(), scanner_);
    244 
    245   if (yy::parser(this).parse() != 0 || error_ != 0) {
    246     return false;}
    247 
    248   if (document_.get() != nullptr)
    249     return true;
    250 
    251   LOG(ERROR) << "Parser succeeded but yielded no document!";
    252   return false;
    253 }
    254 
    255 void Parser::ReportError(const string& err, unsigned line) {
    256   cerr << filename_ << ":" << line << ": " << err << endl;
    257   error_ = 1;
    258 }
    259 
    260 std::vector<std::string> Parser::Package() const {
    261   if (!package_) {
    262     return {};
    263   }
    264   return package_->GetTerms();
    265 }
    266 
    267 void Parser::AddImport(AidlQualifiedName* name, unsigned line) {
    268   imports_.emplace_back(new AidlImport(this->FileName(),
    269                                        name->GetDotName(), line));
    270   delete name;
    271 }
    272