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