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