• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
AST(const std::string & path,const std::string & outputDir,const std::string & package,bool isOpenGl)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 
~AST()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 
scanner()73 void *AST::scanner() {
74     return mScanner;
75 }
76 
setScanner(void * scanner)77 void AST::setScanner(void *scanner) {
78     mScanner = scanner;
79 }
80 
isOpenGl() const81 bool AST::isOpenGl() const {
82     return mIsOpenGl;
83 }
84 
getFilename() const85 const std::string& AST::getFilename() const {
86     return mPath;
87 }
88 
setDeclarations(std::vector<Declaration * > * declarations)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 
setIncludes(std::vector<Include * > * includes)100 void AST::setIncludes(std::vector<Include *> *includes) {
101     mIncludes = includes;
102 }
103 
getExpression() const104 Expression *AST::getExpression() const {
105     return mExpression;
106 }
setExpression(Expression * expression)107 void AST::setExpression(Expression *expression) {
108     mExpression = expression;
109 }
110 
getDefinesScope() const111 const Scope<Define *> &AST::getDefinesScope() const {
112     return mDefinesScope;
113 }
114 
getDefinesScope()115 Scope<Define *> &AST::getDefinesScope() {
116     return mDefinesScope;
117 }
118 
processContents()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 */
isolateInterfaces()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  */
isolateGlobalInterface()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 
isolateIncludes()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 
isolateConstants(Expression::Type ofType)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 
generateCode() const236 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 
generateFile(CompositeDeclaration * declaration) const258 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 
generateTypesFile() const277 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 
generateIncludes(Formatter & out) const302 void AST::generateIncludes(Formatter &out) const {
303     for (auto &include : *mIncludes) {
304         include->generateSource(out);
305         out << "\n";
306     }
307 }
308 
generatePackageLine(Formatter & out) const309 void AST::generatePackageLine(Formatter &out) const {
310     out << "package "
311         << mPackage
312         << ";\n\n";
313 }
314 
MakeParentHierarchy(const std::string & path)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 
getFileDir() const343 const std::string AST::getFileDir() const {
344     CHECK(MakeParentHierarchy(mOutputDir));
345     return mOutputDir;
346 }
347 
348 } // namespace android
349