Home | History | Annotate | Download | only in c2hal
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "AST.h"
     18 
     19 #include "FunctionDeclaration.h"
     20 #include "EnumVarDeclaration.h"
     21 #include "Scope.h"
     22 #include "Declaration.h"
     23 #include "CompositeDeclaration.h"
     24 #include "VarDeclaration.h"
     25 #include "Define.h"
     26 #include "Include.h"
     27 #include "Note.h"
     28 
     29 #include <string>
     30 #include <algorithm>
     31 #include <stdlib.h>
     32 #include <sys/dir.h>
     33 #include <sys/stat.h>
     34 
     35 namespace android {
     36 
     37 AST::AST(const std::string &path,
     38          const std::string &outputDir,
     39          const std::string &package,
     40          bool isOpenGl)
     41     : mScanner(NULL),
     42       mPath(path),
     43       mOutputDir(outputDir),
     44       mPackage(package),
     45       mIsOpenGl(isOpenGl)
     46     {}
     47 
     48 AST::~AST() {
     49     delete mExpression;
     50 
     51     if(mDeclarations != NULL) {
     52         for(auto* decl : *mDeclarations) {
     53             delete decl;
     54         }
     55     }
     56     delete mDeclarations;
     57 
     58     if(mInterfaces != NULL) {
     59         for(auto* inter : *mInterfaces) {
     60             delete inter;
     61         }
     62     }
     63     delete mInterfaces;
     64 
     65     if(mIncludes != NULL) {
     66         for(auto* incl : *mIncludes) {
     67             delete incl;
     68         }
     69     }
     70     delete mIncludes;
     71 }
     72 
     73 void *AST::scanner() {
     74     return mScanner;
     75 }
     76 
     77 void AST::setScanner(void *scanner) {
     78     mScanner = scanner;
     79 }
     80 
     81 bool AST::isOpenGl() const {
     82     return mIsOpenGl;
     83 }
     84 
     85 const std::string& AST::getFilename() const {
     86     return mPath;
     87 }
     88 
     89 void AST::setDeclarations(std::vector<Declaration *> *declarations) {
     90     // on the top level, no var declarations are allowed.
     91     for(size_t i = 0; i < declarations->size(); i++) {
     92         if(declarations->at(i)->decType() == VarDeclaration::type()) {
     93             declarations->at(i) = new Note(declarations->at(i));
     94         }
     95     }
     96 
     97     mDeclarations = declarations;
     98 }
     99 
    100 void AST::setIncludes(std::vector<Include *> *includes) {
    101     mIncludes = includes;
    102 }
    103 
    104 Expression *AST::getExpression() const {
    105     return mExpression;
    106 }
    107 void AST::setExpression(Expression *expression) {
    108     mExpression = expression;
    109 }
    110 
    111 const Scope<Define *> &AST::getDefinesScope() const {
    112     return mDefinesScope;
    113 }
    114 
    115 Scope<Define *> &AST::getDefinesScope() {
    116     return mDefinesScope;
    117 }
    118 
    119 void AST::processContents() {
    120     CHECK(mDeclarations != NULL);
    121 
    122     for (auto &declaration : *mDeclarations) {
    123         CHECK(declaration != NULL);
    124 
    125         declaration->processContents(*this);
    126     }
    127 
    128     isolateInterfaces();
    129     isolateGlobalInterface();
    130     isolateIncludes();
    131 
    132     isolateConstants(Expression::Type::U64);
    133     isolateConstants(Expression::Type::S64);
    134     isolateConstants(Expression::Type::U32);
    135     isolateConstants(Expression::Type::S32);
    136 }
    137 
    138 /* take interface-like structs out of the type file */
    139 void AST::isolateInterfaces() {
    140     mInterfaces = new std::vector<CompositeDeclaration*>;
    141 
    142     auto it = mDeclarations->begin();
    143     while (it != mDeclarations->end()) {
    144         if ((*it)->decType() == CompositeDeclaration::type()
    145             && ((CompositeDeclaration *) (*it))->isInterface()) {
    146 
    147             mInterfaces->push_back((CompositeDeclaration *) *it);
    148             it = mDeclarations->erase(it);
    149         } else {
    150             it++;
    151         }
    152     }
    153 }
    154 
    155 /* take global function declarations out of the type file and into a new
    156  * interface
    157  */
    158 void AST::isolateGlobalInterface() {
    159     auto globalFuns = new std::vector<Declaration*>;
    160 
    161     auto it = mDeclarations->begin();
    162     while (it != mDeclarations->end()) {
    163         if ((*it)->decType() == FunctionDeclaration::type()) {
    164 
    165             globalFuns->push_back(*it);
    166             it = mDeclarations->erase(it);
    167         } else {
    168             it++;
    169         }
    170     }
    171 
    172     if (!globalFuns->empty()) {
    173         std::string path = mPackage.substr(0, mPackage.find_first_of('@'));
    174         std::string name = path.substr(path.find_last_of('.') + 1);
    175 
    176         auto interface = new CompositeDeclaration(
    177             Type::Qualifier::STRUCT,
    178             name + "_global_t",
    179             globalFuns);
    180 
    181         mInterfaces->push_back(interface);
    182     }
    183 }
    184 
    185 void AST::isolateIncludes() {
    186     mIncludes = new std::vector<Include*>;
    187 
    188     auto it = mDeclarations->begin();
    189     while (it != mDeclarations->end()) {
    190         if ((*it)->decType() == Include::type()) {
    191 
    192             mIncludes->push_back((Include *) *it);
    193             it = mDeclarations->erase(it);
    194         } else {
    195             it++;
    196         }
    197     }
    198 }
    199 
    200 void AST::isolateConstants(Expression::Type ofType) {
    201     auto constants = new std::vector<Declaration*>;
    202 
    203     auto it = mDeclarations->begin();
    204     while (it != mDeclarations->end()) {
    205         if ((*it)->decType() == Define::type() &&
    206             ((Define *)*it)->getExpressionType() == ofType) {
    207 
    208             Define* define = (Define *)*it;
    209 
    210             auto var = new EnumVarDeclaration(define->getName(),
    211                                               define->getExpression());
    212 
    213             define->setExpression(NULL);
    214 
    215             constants->push_back(var);
    216             it = mDeclarations->erase(it);
    217 
    218             delete define;
    219         } else {
    220             it++;
    221         }
    222     }
    223 
    224     if (!constants->empty()) {
    225         auto constEnum = new CompositeDeclaration(
    226             Type::Qualifier::ENUM,
    227             "Const" + Expression::getTypeDescription(ofType),
    228             constants);
    229 
    230         constEnum->setEnumTypeName(Expression::getTypeName(ofType));
    231 
    232         mDeclarations->insert(mDeclarations->begin(), constEnum);
    233     }
    234 }
    235 
    236 status_t AST::generateCode() const {
    237     CHECK(mDeclarations != NULL);
    238 
    239     status_t err;
    240 
    241     for (auto &interface : *mInterfaces) {
    242         err = generateFile(interface);
    243 
    244         if (err != OK) {
    245             return err;
    246         }
    247     }
    248 
    249     err = generateTypesFile();
    250 
    251     if (err != OK) {
    252         return err;
    253     }
    254 
    255     return OK;
    256 }
    257 
    258 status_t AST::generateFile(CompositeDeclaration* declaration) const {
    259     std::string fileName = declaration->getInterfaceName() + ".hal";
    260 
    261     FILE *file = fopen((getFileDir() + fileName).c_str(), "w");
    262 
    263     if(file == NULL) {
    264         return -errno;
    265     }
    266 
    267     Formatter out(file); // formatter closes out
    268 
    269     generatePackageLine(out);
    270     generateIncludes(out);
    271 
    272     declaration->generateInterface(out);
    273 
    274     return OK;
    275 }
    276 
    277 status_t AST::generateTypesFile() const {
    278     if (mDeclarations->empty()) {
    279         return OK;
    280     }
    281 
    282     FILE *file = fopen((getFileDir() + "types.hal").c_str(), "w");
    283 
    284     if(file == NULL) {
    285         return -errno;
    286     }
    287 
    288     Formatter out(file); // formatter closes out
    289 
    290     generatePackageLine(out);
    291     generateIncludes(out);
    292 
    293     for (auto &declaration : *mDeclarations) {
    294         declaration->generateCommentText(out);
    295         declaration->generateSource(out);
    296         out << "\n";
    297     }
    298 
    299     return OK;
    300 }
    301 
    302 void AST::generateIncludes(Formatter &out) const {
    303     for (auto &include : *mIncludes) {
    304         include->generateSource(out);
    305         out << "\n";
    306     }
    307 }
    308 
    309 void AST::generatePackageLine(Formatter &out) const {
    310     out << "package "
    311         << mPackage
    312         << ";\n\n";
    313 }
    314 
    315 bool MakeParentHierarchy(const std::string &path) {
    316     static const mode_t kMode = 0755;
    317 
    318     size_t start = 1;  // Ignore leading '/'
    319     size_t slashPos;
    320     while ((slashPos = path.find("/", start)) != std::string::npos) {
    321         std::string partial = path.substr(0, slashPos);
    322 
    323         struct stat st;
    324         if (stat(partial.c_str(), &st) < 0) {
    325             if (errno != ENOENT) {
    326                 return false;
    327             }
    328 
    329             int res = mkdir(partial.c_str(), kMode);
    330             if (res < 0) {
    331                 return false;
    332             }
    333         } else if (!S_ISDIR(st.st_mode)) {
    334             return false;
    335         }
    336 
    337         start = slashPos + 1;
    338     }
    339 
    340     return true;
    341 }
    342 
    343 const std::string AST::getFileDir() const {
    344     CHECK(MakeParentHierarchy(mOutputDir));
    345     return mOutputDir;
    346 }
    347 
    348 } // namespace android
    349