blob: e2ae13cccb4bf369dcec7a05d1cc5a1b26fd6123 [file] [log] [blame]
Steven Morelandf1a35f72016-08-17 08:41:49 -07001/*
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"
Yifan Hong3449bba2016-09-30 10:19:11 -070024#include "VarDeclaration.h"
Steven Morelandf1a35f72016-08-17 08:41:49 -070025#include "Define.h"
26#include "Include.h"
Yifan Hong3449bba2016-09-30 10:19:11 -070027#include "Note.h"
Steven Morelandf1a35f72016-08-17 08:41:49 -070028
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) {
Yifan Hong3449bba2016-09-30 10:19:11 -070090 // 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
Steven Morelandf1a35f72016-08-17 08:41:49 -070097 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
Yifan Hong3449bba2016-09-30 10:19:11 -0700348} // namespace android