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 35namespace android { 36 37AST::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 48AST::~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 73void *AST::scanner() { 74 return mScanner; 75} 76 77void AST::setScanner(void *scanner) { 78 mScanner = scanner; 79} 80 81bool AST::isOpenGl() const { 82 return mIsOpenGl; 83} 84 85const std::string& AST::getFilename() const { 86 return mPath; 87} 88 89void 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 100void AST::setIncludes(std::vector<Include *> *includes) { 101 mIncludes = includes; 102} 103 104Expression *AST::getExpression() const { 105 return mExpression; 106} 107void AST::setExpression(Expression *expression) { 108 mExpression = expression; 109} 110 111const Scope<Define *> &AST::getDefinesScope() const { 112 return mDefinesScope; 113} 114 115Scope<Define *> &AST::getDefinesScope() { 116 return mDefinesScope; 117} 118 119void 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 */ 139void 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 */ 158void 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 185void 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 200void 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 236status_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 258status_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 277status_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 302void AST::generateIncludes(Formatter &out) const { 303 for (auto &include : *mIncludes) { 304 include->generateSource(out); 305 out << "\n"; 306 } 307} 308 309void AST::generatePackageLine(Formatter &out) const { 310 out << "package " 311 << mPackage 312 << ";\n\n"; 313} 314 315bool 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 343const std::string AST::getFileDir() const { 344 CHECK(MakeParentHierarchy(mOutputDir)); 345 return mOutputDir; 346} 347 348} // namespace android 349