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 "codegen/c_custom_types_code_emitter.h"
10 #include "util/file.h"
11 #include "util/logger.h"
12 #include "util/options.h"
13
14 namespace OHOS {
15 namespace HDI {
ResolveDirectory(const String & targetDirectory)16 bool CCustomTypesCodeEmitter::ResolveDirectory(const String& targetDirectory)
17 {
18 if (ast_->GetASTFileType() != ASTFileType::AST_TYPES) {
19 return false;
20 }
21
22 directory_ = GetFilePath(targetDirectory);
23 if (!File::CreateParentDir(directory_)) {
24 Logger::E("CCustomTypesCodeEmitter", "Create '%s' failed!", directory_.string());
25 return false;
26 }
27
28 return true;
29 }
30
EmitCode()31 void CCustomTypesCodeEmitter::EmitCode()
32 {
33 EmitCustomTypesHeaderFile();
34 EmitCustomTypesSourceFile();
35 }
36
EmitCustomTypesHeaderFile()37 void CCustomTypesCodeEmitter::EmitCustomTypesHeaderFile()
38 {
39 String filePath = String::Format("%s/%s.h", directory_.string(), FileName(baseName_).string());
40 File file(filePath, File::WRITE);
41 StringBuilder sb;
42
43 EmitLicense(sb);
44 EmitHeadMacro(sb, baseName_);
45 sb.Append("\n");
46 EmitHeaderInclusions(sb);
47 sb.Append("\n");
48 EmitInterfaceBuffSizeMacro(sb);
49 sb.Append("\n");
50 EmitHeadExternC(sb);
51 sb.Append("\n");
52 EmitCustomTypeDecls(sb);
53 sb.Append("\n");
54 EmitCustomTypeFuncDecl(sb);
55 sb.Append("\n");
56 EmitTailExternC(sb);
57 sb.Append("\n");
58 EmitTailMacro(sb, baseName_);
59
60 String data = sb.ToString();
61 file.WriteData(data.string(), data.GetLength());
62 file.Flush();
63 file.Close();
64 }
65
EmitHeaderInclusions(StringBuilder & sb)66 void CCustomTypesCodeEmitter::EmitHeaderInclusions(StringBuilder& sb)
67 {
68 HeaderFile::HeaderFileSet headerFiles;
69 GetHeaderOtherLibInclusions(headerFiles);
70
71 for (const auto& file : headerFiles) {
72 sb.AppendFormat("%s\n", file.ToString().string());
73 }
74 }
75
GetHeaderOtherLibInclusions(HeaderFile::HeaderFileSet & headerFiles)76 void CCustomTypesCodeEmitter::GetHeaderOtherLibInclusions(HeaderFile::HeaderFileSet& headerFiles)
77 {
78 for (size_t i = 0; i < ast_->GetTypeDefinitionNumber(); i++) {
79 AutoPtr<ASTType> type = ast_->GetTypeDefintion(i);
80 if (type->GetTypeKind() == TypeKind::TYPE_STRUCT) {
81 headerFiles.emplace(HeaderFile(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_sbuf"));
82 break;
83 }
84 }
85 }
86
EmitCustomTypeDecls(StringBuilder & sb)87 void CCustomTypesCodeEmitter::EmitCustomTypeDecls(StringBuilder& sb)
88 {
89 for (size_t i = 0; i < ast_->GetTypeDefinitionNumber(); i++) {
90 AutoPtr<ASTType> type = ast_->GetTypeDefintion(i);
91 EmitCustomTypeDecl(sb, type);
92 if (i + 1 < ast_->GetTypeDefinitionNumber()) {
93 sb.Append("\n");
94 }
95 }
96 }
97
EmitCustomTypeDecl(StringBuilder & sb,const AutoPtr<ASTType> & type)98 void CCustomTypesCodeEmitter::EmitCustomTypeDecl(StringBuilder& sb, const AutoPtr<ASTType>& type)
99 {
100 switch (type->GetTypeKind()) {
101 case TypeKind::TYPE_ENUM: {
102 AutoPtr<ASTEnumType> enumType = dynamic_cast<ASTEnumType*>(type.Get());
103 sb.Append(enumType->EmitCTypeDecl()).Append("\n");
104 break;
105 }
106 case TypeKind::TYPE_STRUCT: {
107 AutoPtr<ASTStructType> structType = dynamic_cast<ASTStructType*>(type.Get());
108 sb.Append(structType->EmitCTypeDecl()).Append("\n");
109 break;
110 }
111 case TypeKind::TYPE_UNION: {
112 AutoPtr<ASTUnionType> unionType = dynamic_cast<ASTUnionType*>(type.Get());
113 sb.Append(unionType->EmitCTypeDecl()).Append("\n");
114 break;
115 }
116 default:
117 break;
118 }
119 }
120
EmitCustomTypeFuncDecl(StringBuilder & sb)121 void CCustomTypesCodeEmitter::EmitCustomTypeFuncDecl(StringBuilder& sb)
122 {
123 for (size_t i = 0; i < ast_->GetTypeDefinitionNumber(); i++) {
124 AutoPtr<ASTType> type = ast_->GetTypeDefintion(i);
125 if (type->GetTypeKind() == TypeKind::TYPE_STRUCT) {
126 AutoPtr<ASTStructType> structType = dynamic_cast<ASTStructType*>(type.Get());
127 EmitCustomTypeMarshallingDecl(sb, structType);
128 sb.Append("\n");
129 EmitCustomTypeUnmarshallingDecl(sb, structType);
130 sb.Append("\n");
131 EmitCustomTypeFreeDecl(sb, structType);
132 if (i + 1 < ast_->GetTypeDefinitionNumber()) {
133 sb.Append("\n");
134 }
135 }
136 }
137 }
138
EmitCustomTypeMarshallingDecl(StringBuilder & sb,const AutoPtr<ASTStructType> & type)139 void CCustomTypesCodeEmitter::EmitCustomTypeMarshallingDecl(StringBuilder& sb,
140 const AutoPtr<ASTStructType>& type)
141 {
142 String objName("dataBlock");
143 sb.AppendFormat("bool %sBlockMarshalling(struct HdfSBuf *data, const %s *%s);\n",
144 type->GetName().string(), type->EmitCType().string(), objName.string());
145 }
146
EmitCustomTypeUnmarshallingDecl(StringBuilder & sb,const AutoPtr<ASTStructType> & type)147 void CCustomTypesCodeEmitter::EmitCustomTypeUnmarshallingDecl(StringBuilder& sb,
148 const AutoPtr<ASTStructType>& type)
149 {
150 String objName("dataBlock");
151 sb.AppendFormat("bool %sBlockUnmarshalling(struct HdfSBuf *data, %s *%s);\n",
152 type->GetName().string(), type->EmitCType().string(), objName.string());
153 }
154
EmitCustomTypeFreeDecl(StringBuilder & sb,const AutoPtr<ASTStructType> & type)155 void CCustomTypesCodeEmitter::EmitCustomTypeFreeDecl(StringBuilder& sb,
156 const AutoPtr<ASTStructType>& type)
157 {
158 String objName("dataBlock");
159 sb.AppendFormat("void %sFree(%s *%s, bool freeSelf);\n",
160 type->GetName().string(), type->EmitCType().string(), objName.string());
161 }
162
EmitCustomTypesSourceFile()163 void CCustomTypesCodeEmitter::EmitCustomTypesSourceFile()
164 {
165 String filePath = String::Format("%s/%s.c", directory_.string(), FileName(baseName_).string());
166 File file(filePath, File::WRITE);
167 StringBuilder sb;
168
169 EmitLicense(sb);
170 EmitSoucreIncludsions(sb);
171 sb.Append("\n");
172 EmitCustomTypeDataProcess(sb);
173
174 String data = sb.ToString();
175 file.WriteData(data.string(), data.GetLength());
176 file.Flush();
177 file.Close();
178 }
179
EmitSoucreIncludsions(StringBuilder & sb)180 void CCustomTypesCodeEmitter::EmitSoucreIncludsions(StringBuilder& sb)
181 {
182 HeaderFile::HeaderFileSet headerFiles;
183 headerFiles.emplace(HeaderFile(HeaderFileType::OWN_HEADER_FILE, EmitVersionHeaderName(baseName_)));
184 GetSourceOtherLibInclusions(headerFiles);
185
186 for (const auto& file : headerFiles) {
187 sb.AppendFormat("%s\n", file.ToString().string());
188 }
189 }
190
GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet & headerFiles)191 void CCustomTypesCodeEmitter::GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet& headerFiles)
192 {
193 headerFiles.emplace(HeaderFile(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_log"));
194 headerFiles.emplace(HeaderFile(HeaderFileType::OTHER_MODULES_HEADER_FILE, "osal_mem"));
195
196 const AST::TypeStringMap& types = ast_->GetTypes();
197 for (const auto& pair : types) {
198 AutoPtr<ASTType> type = pair.second;
199 if (type->GetTypeKind() == TypeKind::TYPE_STRUCT
200 || type->GetTypeKind() == TypeKind::TYPE_UNION) {
201 headerFiles.emplace(HeaderFile(HeaderFileType::OTHER_MODULES_HEADER_FILE, "securec"));
202 break;
203 }
204 }
205 }
206
EmitCustomTypeDataProcess(StringBuilder & sb)207 void CCustomTypesCodeEmitter::EmitCustomTypeDataProcess(StringBuilder& sb)
208 {
209 for (size_t i = 0; i < ast_->GetTypeDefinitionNumber(); i++) {
210 AutoPtr<ASTType> type = ast_->GetTypeDefintion(i);
211 if (type->GetTypeKind() == TypeKind::TYPE_STRUCT) {
212 AutoPtr<ASTStructType> structType = dynamic_cast<ASTStructType*>(type.Get());
213 EmitCustomTypeMarshallingImpl(sb, structType);
214 sb.Append("\n");
215 EmitCustomTypeUnmarshallingImpl(sb, structType);
216 sb.Append("\n");
217 EmitCustomTypeFreeImpl(sb, structType);
218 if (i + 1 < ast_->GetTypeDefinitionNumber()) {
219 sb.Append("\n");
220 }
221 }
222 }
223 }
224
EmitCustomTypeMarshallingImpl(StringBuilder & sb,const AutoPtr<ASTStructType> & type)225 void CCustomTypesCodeEmitter::EmitCustomTypeMarshallingImpl(StringBuilder& sb, const AutoPtr<ASTStructType>& type)
226 {
227 String objName("dataBlock");
228 sb.AppendFormat("bool %sBlockMarshalling(struct HdfSBuf *data, const %s *%s)\n",
229 type->GetName().string(), type->EmitCType().string(), objName.string());
230 sb.Append("{\n");
231
232 for (size_t i = 0; i < type->GetMemberNumber(); i++) {
233 AutoPtr<ASTType> memberType = type->GetMemberType(i);
234 if (isKernelCode_) {
235 if (memberType->GetTypeKind() == TypeKind::TYPE_ARRAY ||
236 memberType->GetTypeKind() == TypeKind::TYPE_LIST) {
237 sb.Append(g_tab).Append("uint32_t i = 0;\n");
238 break;
239 }
240 }
241 }
242
243 for (size_t i = 0; i < type->GetMemberNumber(); i++) {
244 String memberName = type->GetMemberName(i);
245 AutoPtr<ASTType> memberType = type->GetMemberType(i);
246 String name = String::Format("%s->%s", objName.string(), memberName.string());
247 memberType->EmitCMarshalling(name, sb, g_tab);
248 sb.Append("\n");
249 }
250
251 sb.Append(g_tab).Append("return true;\n");
252 sb.Append("}\n");
253 }
254
EmitCustomTypeUnmarshallingImpl(StringBuilder & sb,const AutoPtr<ASTStructType> & type)255 void CCustomTypesCodeEmitter::EmitCustomTypeUnmarshallingImpl(StringBuilder& sb, const AutoPtr<ASTStructType>& type)
256 {
257 String objName("dataBlock");
258 freeObjStatements_.clear();
259
260 sb.AppendFormat("bool %sBlockUnmarshalling(struct HdfSBuf *data, %s *%s)\n",
261 type->GetName().string(), type->EmitCType().string(), objName.string());
262 sb.Append("{\n");
263
264 if (isKernelCode_) {
265 for (size_t i = 0; i < type->GetMemberNumber(); i++) {
266 AutoPtr<ASTType> memberType = type->GetMemberType(i);
267 if (memberType->GetTypeKind() == TypeKind::TYPE_ARRAY ||
268 memberType->GetTypeKind() == TypeKind::TYPE_LIST) {
269 sb.Append(g_tab).Append("uint32_t i = 0;\n");
270 break;
271 }
272 }
273 }
274
275 sb.Append(g_tab).AppendFormat("if (%s == NULL) {\n", objName.string());
276 sb.Append(g_tab).Append(g_tab).Append("return false;\n");
277 sb.Append(g_tab).Append("}\n");
278
279 for (size_t i = 0; i < type->GetMemberNumber(); i++) {
280 AutoPtr<ASTType> memberType = type->GetMemberType(i);
281 EmitMemberUnmarshalling(memberType, objName, type->GetMemberName(i), sb, g_tab);
282 }
283
284 sb.Append(g_tab).AppendFormat("return true;\n");
285 sb.AppendFormat("%s:\n", errorsLabelName_);
286 EmitCustomTypeMemoryRecycle(type, objName, sb, g_tab);
287
288 sb.Append(g_tab).Append("return false;\n");
289 sb.Append("}\n");
290 }
291
EmitMemberUnmarshalling(const AutoPtr<ASTType> & type,const String & name,const String & memberName,StringBuilder & sb,const String & prefix)292 void CCustomTypesCodeEmitter::EmitMemberUnmarshalling(const AutoPtr<ASTType>& type, const String& name,
293 const String& memberName, StringBuilder& sb, const String& prefix)
294 {
295 String varName = String::Format("%s->%s", name.string(), memberName.string());
296 switch (type->GetTypeKind()) {
297 case TypeKind::TYPE_STRING: {
298 String tmpName = String::Format("%sCp", memberName.string());
299 type->EmitCUnMarshalling(tmpName, errorsLabelName_, sb, g_tab, freeObjStatements_);
300
301 if (Options::GetInstance().DoGenerateKernelCode()) {
302 sb.Append(g_tab).AppendFormat("%s = (char*)OsalMemCalloc(strlen(%s) + 1);\n",
303 varName.string(), tmpName.string());
304 sb.Append(g_tab).AppendFormat("if (%s == NULL) {\n", varName.string());
305 sb.Append(g_tab).Append(g_tab).AppendFormat("goto %s;\n", errorsLabelName_);
306 sb.Append(g_tab).Append("}\n");
307
308 sb.Append(g_tab).AppendFormat("if (strcpy_s(%s, (strlen(%s) + 1), %s) != HDF_SUCCESS) {\n",
309 varName.string(), tmpName.string(), tmpName.string());
310 sb.Append(g_tab).Append(g_tab).AppendFormat("goto %s;\n", errorsLabelName_);
311 sb.Append(g_tab).Append("}\n");
312 } else {
313 sb.Append(g_tab).AppendFormat("%s = strdup(%s);\n", varName.string(), tmpName.string());
314 }
315
316 sb.Append(g_tab).AppendFormat("if (%s == NULL) {\n", varName.string());
317 sb.Append(g_tab).Append(g_tab).AppendFormat("goto %s;\n", errorsLabelName_);
318 sb.Append(g_tab).Append("}\n");
319 sb.Append("\n");
320 break;
321 }
322 case TypeKind::TYPE_STRUCT: {
323 String paramName = String::Format("&%s", varName.string());
324 type->EmitCUnMarshalling(paramName, errorsLabelName_, sb, g_tab, freeObjStatements_);
325 sb.Append("\n");
326 break;
327 }
328 case TypeKind::TYPE_UNION: {
329 String tmpName = String::Format("%sCp", memberName.string());
330 type->EmitCUnMarshalling(tmpName, errorsLabelName_, sb, g_tab, freeObjStatements_);
331 sb.Append(g_tab).AppendFormat("(void)memcpy_s(&%s, sizeof(%s), %s, sizeof(%s));\n",
332 varName.string(), type->EmitCType().string(),
333 tmpName.string(), type->EmitCType().string());
334 sb.Append("\n");
335 break;
336 }
337 case TypeKind::TYPE_ARRAY:
338 case TypeKind::TYPE_LIST: {
339 EmitArrayMemberUnmarshalling(type, memberName, varName, sb, g_tab);
340 sb.Append("\n");
341 break;
342 }
343 default: {
344 type->EmitCUnMarshalling(varName, errorsLabelName_, sb, g_tab, freeObjStatements_);
345 sb.Append("\n");
346 }
347 }
348 }
349
EmitArrayMemberUnmarshalling(const AutoPtr<ASTType> & type,const String & memberName,const String & varName,StringBuilder & sb,const String & prefix)350 void CCustomTypesCodeEmitter::EmitArrayMemberUnmarshalling(const AutoPtr<ASTType>& type, const String& memberName,
351 const String& varName, StringBuilder& sb, const String& prefix)
352 {
353 String tmpName = String::Format("%sCp", memberName.string());
354 AutoPtr<ASTType> elementType = nullptr;
355 if (type->GetTypeKind() == TypeKind::TYPE_ARRAY) {
356 AutoPtr<ASTArrayType> arrayType = dynamic_cast<ASTArrayType*>(type.Get());
357 elementType = arrayType->GetElementType();
358 } else {
359 AutoPtr<ASTListType> listType = dynamic_cast<ASTListType*>(type.Get());
360 elementType = listType->GetElementType();
361 }
362
363 sb.Append(prefix).AppendFormat("%s* %s = NULL;\n", elementType->EmitCType().string(), tmpName.string());
364 sb.Append(prefix).AppendFormat("uint32_t %sLen = 0;\n", tmpName.string());
365 type->EmitCUnMarshalling(tmpName, errorsLabelName_, sb, prefix, freeObjStatements_);
366 sb.Append(prefix).AppendFormat("%s = %s;\n", varName.string(), tmpName.string());
367 sb.Append(prefix).AppendFormat("%sLen = %sLen;\n", varName.string(), tmpName.string());
368 }
369
EmitCustomTypeFreeImpl(StringBuilder & sb,const AutoPtr<ASTStructType> & type)370 void CCustomTypesCodeEmitter::EmitCustomTypeFreeImpl(StringBuilder& sb, const AutoPtr<ASTStructType>& type)
371 {
372 String objName("dataBlock");
373 sb.AppendFormat("void %sFree(%s *%s, bool freeSelf)\n",
374 type->GetName().string(), type->EmitCType().string(), objName.string());
375 sb.Append("{\n");
376
377 if (isKernelCode_) {
378 for (size_t i = 0; i < type->GetMemberNumber(); i++) {
379 AutoPtr<ASTType> memberType = type->GetMemberType(i);
380 if (NeedEmitInitVar(memberType)) {
381 sb.Append(g_tab).Append("uint32_t i = 0;\n");
382 break;
383 }
384 }
385 }
386
387 sb.Append(g_tab).AppendFormat("if (%s == NULL) {\n", objName.string());
388 sb.Append(g_tab).Append(g_tab).Append("return;\n");
389 sb.Append(g_tab).Append("}\n");
390 sb.Append("\n");
391
392 EmitCustomTypeMemoryRecycle(type, objName, sb, g_tab);
393
394 sb.Append(g_tab).Append("if (freeSelf) {\n");
395 sb.Append(g_tab).Append(g_tab).Append("OsalMemFree(dataBlock);\n");
396 sb.Append(g_tab).Append("}\n");
397 sb.Append("}\n");
398 }
399
NeedEmitInitVar(const AutoPtr<ASTType> & type)400 bool CCustomTypesCodeEmitter::NeedEmitInitVar(const AutoPtr<ASTType>& type)
401 {
402 if (type == nullptr) {
403 return false;
404 }
405
406 if (type->IsArrayType()) {
407 AutoPtr<ASTArrayType> ArrType = dynamic_cast<ASTArrayType*>(type.Get());
408 AutoPtr<ASTType> elementType = ArrType->GetElementType();
409 if (elementType->IsStringType() || elementType->IsStructType()) {
410 return true;
411 }
412 } else if (type->IsListType()) {
413 AutoPtr<ASTListType> ListType = dynamic_cast<ASTListType*>(type.Get());
414 AutoPtr<ASTType> elementType = ListType->GetElementType();
415 if (elementType->IsStringType() || elementType->IsStructType()) {
416 return true;
417 }
418 }
419
420 return false;
421 }
422
EmitCustomTypeMemoryRecycle(const AutoPtr<ASTStructType> & type,const String & name,StringBuilder & sb,const String & prefix)423 void CCustomTypesCodeEmitter::EmitCustomTypeMemoryRecycle(const AutoPtr<ASTStructType>& type, const String& name,
424 StringBuilder& sb, const String& prefix)
425 {
426 for (size_t i = 0; i < type->GetMemberNumber(); i++) {
427 AutoPtr<ASTType> memberType = type->GetMemberType(i);
428 String memberName = type->GetMemberName(i);
429 String varName = String::Format("%s->%s", name.string(), memberName.string());
430 switch (memberType->GetTypeKind()) {
431 case TypeKind::TYPE_STRING:
432 case TypeKind::TYPE_STRUCT:
433 case TypeKind::TYPE_ARRAY:
434 case TypeKind::TYPE_LIST:
435 memberType->EmitMemoryRecycle(varName, false, false, sb, prefix);
436 sb.Append("\n");
437 break;
438 default:
439 break;
440 }
441 }
442 }
443 } // namespace HDI
444 } // namespace OHOS