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