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