• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     constexpr uint32_t elementPerLine = 8;
123 
124     if (index == 0) {
125         ofs_ << "#define " << arrName << "_data {";
126     }
127 
128     if (index % elementPerLine == 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 % elementPerLine == 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> &current, 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> &current, 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> &current)
281 {
282     if (arraySize != 0) {
283         GenArray(arrayName, arraySize, arrayType, current);
284     } else {
285         ofs_ << " " << current->IntegerValue() << std::endl;
286     }
287 }