1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8
9 #include <string>
10
11 #include "file.h"
12 #include "logger.h"
13 #include "macro_gen.h"
14
15 using namespace OHOS::Hardware;
16
17 constexpr static const char *FILE_HEAD_COMMENT =
18 "/*\n"
19 " * This is an automatically generated HDF config file. Do not modify it manually.\n"
20 " */\n\n";
21
MacroGen(std::shared_ptr<Ast> ast)22 MacroGen::MacroGen(std::shared_ptr<Ast> ast) : Generator(ast) {}
23
ToUpperString(std::string & str)24 const std::string &MacroGen::ToUpperString(std::string &str)
25 {
26 for (char &c : str) {
27 c = static_cast<char>(toupper(c));
28 }
29
30 return str;
31 }
32
HeaderTopOutput()33 bool MacroGen::HeaderTopOutput()
34 {
35 ofs_ << FILE_HEAD_COMMENT;
36 std::string defMacro = std::string().append("HCS_CONFIG_").append(ToUpperString(outFileName_)).append("_HEADER_H");
37 ofs_ << "#ifndef " << defMacro << '\n';
38 ofs_ << "#define " << defMacro << '\n';
39 ofs_ << "\r\n#include \"hdf_base.h\"\n";
40
41 return true;
42 }
43
HeaderBottomOutput()44 bool MacroGen::HeaderBottomOutput()
45 {
46 std::string defMacro = std::string().append("HCS_CONFIG_").append(ToUpperString(outFileName_)).append("_HEADER_H");
47 ofs_ << "\n#endif // " << defMacro << '\n';
48 ofs_.close();
49 return true;
50 }
51
Output()52 bool MacroGen::Output()
53 {
54 if (!Initialize()) {
55 return false;
56 }
57 if (!TemplateNodeSeparate()) {
58 return false;
59 }
60 if (!HeaderTopOutput()) {
61 return false;
62 }
63
64 if (!NodeWalk()) {
65 return false;
66 }
67 if (!HeaderBottomOutput()) {
68 return false;
69 }
70 return true;
71 }
72
Initialize()73 bool MacroGen::Initialize()
74 {
75 auto opt = Option::Instance();
76 std::string outFileName = Option::Instance().GetOutputName();
77 if (outFileName.empty()) {
78 outFileName = Option::Instance().GetSourceNameBase();
79 }
80 outFileName = Util::File::StripSuffix(outFileName).append(".h");
81 outFileName_ = Util::File::FileNameBase(outFileName);
82 if (outFileName.find(".h") == std::string::npos) {
83 outFileName.append(".h");
84 }
85
86 ofs_.open(outFileName, std::ofstream::out | std::ofstream::binary);
87 if (!ofs_.is_open()) {
88 Logger().Error() << "failed to open output file: " << outFileName;
89 return false;
90 }
91 Logger().Debug() << "output: " << outFileName << outFileName_ << '\n';
92
93 return true;
94 }
95
TemplateNodeSeparate()96 bool MacroGen::TemplateNodeSeparate()
97 {
98 return ast_->WalkBackward([this](std::shared_ptr<AstObject> &object, int32_t depth) {
99 if (object->IsNode() && ConfigNode::CastFrom(object)->GetNodeType() == NODE_TEMPLATE) {
100 object->Separate();
101 return NOERR;
102 }
103 return NOERR;
104 });
105 }
106
GenFullName(int32_t depth,const std::shared_ptr<AstObject> & node,const std::string & sep)107 std::string MacroGen::GenFullName(int32_t depth, const std::shared_ptr<AstObject> &node, const std::string &sep)
108 {
109 std::string name;
110 for (int i = 0; i < depth; i++) {
111 name.append(nodeNameMap_[i]).append(sep);
112 }
113 name.append(node->Name());
114 return name;
115 }
116
GenArray(const std::string & arrName,uint32_t & arrSize,uint32_t type,const std::shared_ptr<AstObject> & node)117 bool MacroGen::GenArray(
118 const std::string &arrName, uint32_t &arrSize, uint32_t type, const std::shared_ptr<AstObject> &node)
119 {
120 static uint32_t index = 0;
121 const uint32_t ELEMENT_PER_LINE = 8;
122
123 if (index == 0) {
124 ofs_ << "#define " << arrName << "_data {";
125 }
126
127 if (index % ELEMENT_PER_LINE == 0) {
128 ofs_ << " \\\n" << TAB;
129 }
130
131 if (type == PARSEROP_STRING) {
132 ofs_ << '"' << node->StringValue() << '"';
133 } else {
134 ofs_ << node->IntegerValue();
135 }
136
137 index++;
138 if (index == arrSize) {
139 index = 0;
140 arrSize = 0;
141 ofs_ << " \\\n}\n";
142 } else {
143 if (index % ELEMENT_PER_LINE == 0) {
144 ofs_ << ",";
145 } else {
146 ofs_ << ", ";
147 }
148 }
149
150 return true;
151 }
152
GenNodeForeach(int32_t depth,const std::shared_ptr<AstObject> & node)153 bool MacroGen::GenNodeForeach(int32_t depth, const std::shared_ptr<AstObject> &node)
154 {
155 std::list<std::string> subList;
156 auto child = node->Child();
157 uint32_t count = 0;
158
159 Logger().Debug() << "node:" << node->Name() << " child:"
160 << " depth:" << depth;
161 while (child != nullptr) {
162 if (child->IsNode()) {
163 Logger().Debug() << " " << child->Name();
164 subList.push_back(GenFullName(depth + 1, child, "_"));
165 count++;
166 }
167 child = child->Next();
168 }
169
170 ofs_ << "// hcs node macros: " << GenFullName(depth, node, "/") << std::endl;
171 ofs_ << "#define " << GenFullName(depth, node, "_").append("_exists 1") << std::endl;
172 if (count) {
173 uint32_t index = count;
174 std::list<std::string>::iterator iter;
175
176 ofs_ << "#define " << GenFullName(depth, node, "_").append("_foreach_child(func)") << " \\\n";
177 for (iter = subList.begin(); iter != subList.end(); iter++) {
178 index--;
179 if (index) {
180 ofs_ << TAB << "func(" << *iter << "); \\\n";
181 } else {
182 ofs_ << TAB << "func(" << *iter << ");\n";
183 }
184 }
185 ofs_ << std::endl;
186
187 index = count;
188 ofs_ << "#define " << GenFullName(depth, node, "_").append("_foreach_child_vargs(func, ...)") << " \\\n";
189 for (iter = subList.begin(); iter != subList.end(); iter++) {
190 index--;
191 if (index) {
192 ofs_ << TAB << "func(" << *iter << ", __VA_ARGS__); \\\n";
193 } else {
194 ofs_ << TAB << "func(" << *iter << ", __VA_ARGS__);\n";
195 }
196 }
197 ofs_ << std::endl;
198 }
199
200 return true;
201 }
202
GenRefObjName(int32_t depth,const std::shared_ptr<AstObject> & object)203 std::string MacroGen::GenRefObjName(int32_t depth, const std::shared_ptr<AstObject> &object)
204 {
205 std::string name(object->StringValue());
206 if (name.find(".") == std::string::npos) {
207 name = GenFullName(depth - 1, object, "_").append(object->StringValue());
208 } else {
209 for (char &c : name) {
210 if (c == '.') {
211 c = '_';
212 }
213 }
214 }
215 return name;
216 }
217
NodeWalk()218 bool MacroGen::NodeWalk()
219 {
220 return ast_->WalkForward([this](std::shared_ptr<AstObject> ¤t, int32_t depth) {
221 auto type = current->Type();
222 static uint32_t arraySize = 0;
223
224 Logger().Debug() << "name,type:[" << current->Name() << "," << type << "] depth:" << depth
225 << " arraySize:" << std::dec << arraySize << '\n';
226 SetTypeData(type, current, arraySize, depth);
227
228 return NOERR;
229 });
230 }
231
SetTypeData(uint32_t type,const std::shared_ptr<AstObject> & current,uint32_t & arraySize,int32_t depth)232 void MacroGen::SetTypeData(uint32_t type, const std::shared_ptr<AstObject> ¤t, uint32_t &arraySize, int32_t depth)
233 {
234 static std::string nodeName;
235 static std::string arrayName;
236 static uint32_t arrayType = 0;
237 switch (type) {
238 case PARSEROP_UINT8:
239 case PARSEROP_UINT16:
240 case PARSEROP_UINT32:
241 case PARSEROP_UINT64: {
242 SetTypeDataUinit64(arrayName, arraySize, arrayType, current);
243 break;
244 }
245 case PARSEROP_STRING:
246 if (arraySize != 0) {
247 GenArray(arrayName, arraySize, arrayType, current);
248 } else {
249 ofs_ << " " << '"' << current->StringValue() << '"' << std::endl;
250 }
251 break;
252 case PARSEROP_CONFTERM:
253 ofs_ << "#define " << GenFullName(depth, current, "_") << "_exists 1" << std::endl;
254 ofs_ << "#define " << GenFullName(depth, current, "_");
255 break;
256 case PARSEROP_CONFNODE: {
257 if (nodeName != current->Name()) {
258 ofs_ << std::endl;
259 }
260 nodeName = current->Name();
261 nodeNameMap_[depth] = nodeName;
262 GenNodeForeach(depth, current);
263 break;
264 }
265 case PARSEROP_ARRAY: {
266 std::shared_ptr<AstObject> parent(current->Parent());
267 arraySize = ConfigArray::CastFrom(current)->ArraySize();
268 arrayType = ConfigArray::CastFrom(current)->ArrayType();
269 ofs_ << "_array_size " << arraySize << std::endl;
270 arrayName = GenFullName(depth - 1, parent, "_");
271 break;
272 }
273 case PARSEROP_NODEREF: {
274 ofs_ << " " << GenRefObjName(depth, current) << std::endl;
275 break;
276 }
277 default:
278 break;
279 }
280 }
281
SetTypeDataUinit64(const std::string & arrayName,uint32_t & arraySize,uint32_t arrayType,const std::shared_ptr<AstObject> & current)282 void MacroGen::SetTypeDataUinit64(
283 const std::string &arrayName, uint32_t &arraySize, uint32_t arrayType, const std::shared_ptr<AstObject> ¤t)
284 {
285 if (arraySize != 0) {
286 GenArray(arrayName, arraySize, arrayType, current);
287 } else {
288 ofs_ << " " << current->IntegerValue() << std::endl;
289 }
290 }