1 /*
2 * Copyright (c) 2021-2023 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_code_emitter.h"
10 #include "util/options.h"
11
12 namespace OHOS {
13 namespace HDI {
GetStdlibInclusions(HeaderFile::HeaderFileSet & headerFiles)14 void CCodeEmitter::GetStdlibInclusions(HeaderFile::HeaderFileSet &headerFiles)
15 {
16 const AST::TypeStringMap &types = ast_->GetTypes();
17 for (const auto &pair : types) {
18 AutoPtr<ASTType> type = pair.second;
19 if (type->IsNativeBufferType()) {
20 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "base/buffer_util");
21 }
22 }
23 }
24
GetImportInclusions(HeaderFile::HeaderFileSet & headerFiles)25 void CCodeEmitter::GetImportInclusions(HeaderFile::HeaderFileSet &headerFiles)
26 {
27 for (const auto &importPair : ast_->GetImports()) {
28 AutoPtr<AST> importAst = importPair.second;
29 std::string fileName = PackageToFilePath(importAst->GetFullName());
30 headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE, fileName);
31 }
32 }
33
EmitInterfaceMethodParameter(const AutoPtr<ASTParameter> & parameter,StringBuilder & sb,const std::string & prefix) const34 void CCodeEmitter::EmitInterfaceMethodParameter(
35 const AutoPtr<ASTParameter> ¶meter, StringBuilder &sb, const std::string &prefix) const
36 {
37 sb.Append(prefix).Append(parameter->EmitCParameter());
38 }
39
EmitMethodNeedLoopVar(const AutoPtr<ASTMethod> & method,bool needRW,bool needFree,StringBuilder & sb,const std::string & prefix) const40 void CCodeEmitter::EmitMethodNeedLoopVar(
41 const AutoPtr<ASTMethod> &method, bool needRW, bool needFree, StringBuilder &sb, const std::string &prefix) const
42 {
43 if (mode_ != GenMode::KERNEL) {
44 return;
45 }
46
47 for (size_t i = 0; i < method->GetParameterNumber(); i++) {
48 AutoPtr<ASTParameter> param = method->GetParameter(i);
49 if (EmitNeedLoopVar(param->GetType(), needRW, needFree)) {
50 sb.Append(prefix).Append("uint32_t i = 0;\n");
51 break;
52 }
53 }
54 }
55
EmitNeedLoopVar(const AutoPtr<ASTType> & type,bool needRW,bool needFree) const56 bool CCodeEmitter::EmitNeedLoopVar(const AutoPtr<ASTType> &type, bool needRW, bool needFree) const
57 {
58 if (type == nullptr) {
59 return false;
60 }
61
62 auto rwNeedLoopVar = [needRW](const AutoPtr<ASTType> &elementType) -> bool {
63 if (!needRW) {
64 return false;
65 }
66
67 if (elementType->IsPod()) {
68 return elementType->IsBooleanType() ? true : false;
69 }
70
71 return elementType->IsStringType() ? false : true;
72 };
73
74 auto freeNeedLoopVar = [needFree](const AutoPtr<ASTType> &elementType) -> bool {
75 if (!needFree) {
76 return false;
77 }
78 return elementType->IsPod() ? false : true;
79 };
80
81 if (type->IsArrayType()) {
82 AutoPtr<ASTArrayType> arrType = dynamic_cast<ASTArrayType *>(type.Get());
83 if (rwNeedLoopVar(arrType->GetElementType()) || freeNeedLoopVar(arrType->GetElementType())) {
84 return true;
85 }
86 } else if (type->IsListType()) {
87 AutoPtr<ASTListType> listType = dynamic_cast<ASTListType *>(type.Get());
88 if (rwNeedLoopVar(listType->GetElementType()) || freeNeedLoopVar(listType->GetElementType())) {
89 return true;
90 }
91 }
92
93 return false;
94 }
95
EmitErrorHandle(const AutoPtr<ASTMethod> & method,const std::string & gotoLabel,bool isClient,StringBuilder & sb,const std::string & prefix) const96 void CCodeEmitter::EmitErrorHandle(const AutoPtr<ASTMethod> &method, const std::string &gotoLabel, bool isClient,
97 StringBuilder &sb, const std::string &prefix) const
98 {
99 if (!isClient) {
100 sb.Append(prefix).AppendFormat("%s:\n", gotoLabel.c_str());
101 for (size_t i = 0; i < method->GetParameterNumber(); i++) {
102 AutoPtr<ASTParameter> param = method->GetParameter(i);
103 AutoPtr<ASTType> paramType = param->GetType();
104 paramType->EmitMemoryRecycle(param->GetName(), true, sb, prefix + TAB);
105 }
106 return;
107 }
108 }
109
EmitLicense(StringBuilder & sb)110 void CCodeEmitter::EmitLicense(StringBuilder &sb)
111 {
112 if (ast_->GetLicense().empty()) {
113 return;
114 }
115 sb.Append(ast_->GetLicense()).Append("\n\n");
116 }
117
EmitHeadMacro(StringBuilder & sb,const std::string & fullName) const118 void CCodeEmitter::EmitHeadMacro(StringBuilder &sb, const std::string &fullName) const
119 {
120 std::string macroName = MacroName(fullName);
121 sb.Append("#ifndef ").Append(macroName).Append("\n");
122 sb.Append("#define ").Append(macroName).Append("\n");
123 }
124
EmitTailMacro(StringBuilder & sb,const std::string & fullName) const125 void CCodeEmitter::EmitTailMacro(StringBuilder &sb, const std::string &fullName) const
126 {
127 std::string macroName = MacroName(fullName);
128 sb.Append("#endif // ").Append(macroName);
129 }
130
EmitHeadExternC(StringBuilder & sb) const131 void CCodeEmitter::EmitHeadExternC(StringBuilder &sb) const
132 {
133 sb.Append("#ifdef __cplusplus\n");
134 sb.Append("extern \"C\" {\n");
135 sb.Append("#endif /* __cplusplus */\n");
136 }
137
EmitTailExternC(StringBuilder & sb) const138 void CCodeEmitter::EmitTailExternC(StringBuilder &sb) const
139 {
140 sb.Append("#ifdef __cplusplus\n");
141 sb.Append("}\n");
142 sb.Append("#endif /* __cplusplus */\n");
143 }
144
MacroName(const std::string & name) const145 std::string CCodeEmitter::MacroName(const std::string &name) const
146 {
147 if (name.empty()) {
148 return name;
149 }
150
151 std::string macro = StringHelper::StrToUpper(StringHelper::Replace(name, '.', '_')) + "_H";
152 return macro;
153 }
154
SpecificationParam(StringBuilder & paramSb,const std::string & prefix) const155 std::string CCodeEmitter::SpecificationParam(StringBuilder ¶mSb, const std::string &prefix) const
156 {
157 size_t maxLineLen = 120;
158 size_t replaceLen = 2;
159 std::string paramStr = paramSb.ToString();
160 size_t preIndex = 0;
161 size_t curIndex = 0;
162
163 std::string insertStr = StringHelper::Format("\n%s", prefix.c_str());
164 for (; curIndex < paramStr.size(); curIndex++) {
165 if (curIndex == maxLineLen && preIndex > 0) {
166 StringHelper::Replace(paramStr, preIndex, replaceLen, ",");
167 paramStr.insert(preIndex + 1, insertStr);
168 } else {
169 if (paramStr[curIndex] == ',') {
170 preIndex = curIndex;
171 }
172 }
173 }
174 return paramStr;
175 }
176 } // namespace HDI
177 } // namespace OHOS