• 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 "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