• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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> &current, 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> &current, 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> &current)
284 {
285     if (arraySize != 0) {
286         GenArray(arrayName, arraySize, arrayType, current);
287     } else {
288         ofs_ << " " << current->IntegerValue() << std::endl;
289     }
290 }