blob: 5e7928c24225463851f889c2ecdd028b33174e2f [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>
Steven Morelandf1a35f72016-08-17 08:41:49 -070032#include <sys/stat.h>
33
34namespace android {
35
36AST::AST(const std::string &path,
37 const std::string &outputDir,
38 const std::string &package,
39 bool isOpenGl)
Yi Kong56758da2018-07-24 16:21:37 -070040 : mScanner(nullptr),
Steven Morelandf1a35f72016-08-17 08:41:49 -070041 mPath(path),
42 mOutputDir(outputDir),
43 mPackage(package),
44 mIsOpenGl(isOpenGl)
45 {}
46
47AST::~AST() {
48 delete mExpression;
49
Yi Kong56758da2018-07-24 16:21:37 -070050 if(mDeclarations != nullptr) {
Steven Morelandf1a35f72016-08-17 08:41:49 -070051 for(auto* decl : *mDeclarations) {
52 delete decl;
53 }
54 }
55 delete mDeclarations;
56
Yi Kong56758da2018-07-24 16:21:37 -070057 if(mInterfaces != nullptr) {
Steven Morelandf1a35f72016-08-17 08:41:49 -070058 for(auto* inter : *mInterfaces) {
59 delete inter;
60 }
61 }
62 delete mInterfaces;
63
Yi Kong56758da2018-07-24 16:21:37 -070064 if(mIncludes != nullptr) {
Steven Morelandf1a35f72016-08-17 08:41:49 -070065 for(auto* incl : *mIncludes) {
66 delete incl;
67 }
68 }
69 delete mIncludes;
70}
71
72void *AST::scanner() {
73 return mScanner;
74}
75
76void AST::setScanner(void *scanner) {
77 mScanner = scanner;
78}
79
80bool AST::isOpenGl() const {
81 return mIsOpenGl;
82}
83
84const std::string& AST::getFilename() const {
85 return mPath;
86}
87
88void AST::setDeclarations(std::vector<Declaration *> *declarations) {
Yifan Hong3449bba2016-09-30 10:19:11 -070089 // 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
Steven Morelandf1a35f72016-08-17 08:41:49 -070096 mDeclarations = declarations;
97}
98
99void AST::setIncludes(std::vector<Include *> *includes) {
100 mIncludes = includes;
101}
102
103Expression *AST::getExpression() const {
104 return mExpression;
105}
106void AST::setExpression(Expression *expression) {
107 mExpression = expression;
108}
109
110const Scope<Define *> &AST::getDefinesScope() const {
111 return mDefinesScope;
112}
113
114Scope<Define *> &AST::getDefinesScope() {
115 return mDefinesScope;
116}
117
118void AST::processContents() {
Yi Kong56758da2018-07-24 16:21:37 -0700119 CHECK(mDeclarations != nullptr);
Steven Morelandf1a35f72016-08-17 08:41:49 -0700120
121 for (auto &declaration : *mDeclarations) {
Yi Kong56758da2018-07-24 16:21:37 -0700122 CHECK(declaration != nullptr);
Steven Morelandf1a35f72016-08-17 08:41:49 -0700123
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 */
138void 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 */
157void 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
184void 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
199void 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
Yi Kong56758da2018-07-24 16:21:37 -0700212 define->setExpression(nullptr);
Steven Morelandf1a35f72016-08-17 08:41:49 -0700213
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
235status_t AST::generateCode() const {
Yi Kong56758da2018-07-24 16:21:37 -0700236 CHECK(mDeclarations != nullptr);
Steven Morelandf1a35f72016-08-17 08:41:49 -0700237
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
257status_t AST::generateFile(CompositeDeclaration* declaration) const {
258 std::string fileName = declaration->getInterfaceName() + ".hal";
259
260 FILE *file = fopen((getFileDir() + fileName).c_str(), "w");
261
Yi Kong56758da2018-07-24 16:21:37 -0700262 if(file == nullptr) {
Steven Morelandf1a35f72016-08-17 08:41:49 -0700263 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
276status_t AST::generateTypesFile() const {
277 if (mDeclarations->empty()) {
278 return OK;
279 }
280
281 FILE *file = fopen((getFileDir() + "types.hal").c_str(), "w");
282
Yi Kong56758da2018-07-24 16:21:37 -0700283 if(file == nullptr) {
Steven Morelandf1a35f72016-08-17 08:41:49 -0700284 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
301void AST::generateIncludes(Formatter &out) const {
302 for (auto &include : *mIncludes) {
303 include->generateSource(out);
304 out << "\n";
305 }
306}
307
308void AST::generatePackageLine(Formatter &out) const {
309 out << "package "
310 << mPackage
311 << ";\n\n";
312}
313
314bool MakeParentHierarchy(const std::string &path) {
315 static const mode_t kMode = 0755;
316
317 size_t start = 1; // Ignore leading '/'
318 size_t slashPos;
Chih-Hung Hsieh8c90cc52017-08-03 14:51:13 -0700319 while ((slashPos = path.find('/', start)) != std::string::npos) {
Steven Morelandf1a35f72016-08-17 08:41:49 -0700320 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
342const std::string AST::getFileDir() const {
343 CHECK(MakeParentHierarchy(mOutputDir));
344 return mOutputDir;
345}
346
Yifan Hong3449bba2016-09-30 10:19:11 -0700347} // namespace android