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_service_impl_code_emitter.h"
10 #include "util/file.h"
11 #include "util/logger.h"
12
13 namespace OHOS {
14 namespace HDI {
ResolveDirectory(const std::string & targetDirectory)15 bool CServiceImplCodeEmitter::ResolveDirectory(const std::string &targetDirectory)
16 {
17 if (ast_->GetASTFileType() == ASTFileType::AST_IFACE || ast_->GetASTFileType() == ASTFileType::AST_ICALLBACK) {
18 directory_ = GetFileParentPath(targetDirectory);
19 } else {
20 return false;
21 }
22
23 if (!File::CreateParentDir(directory_)) {
24 Logger::E("CServiceImplCodeEmitter", "Create '%s' failed!", directory_.c_str());
25 return false;
26 }
27
28 return true;
29 }
30
EmitCode()31 void CServiceImplCodeEmitter::EmitCode()
32 {
33 if (isKernelCode_ || interface_->IsSerializable()) {
34 EmitServiceImplHeaderFile();
35 }
36
37 EmitServiceImplSourceFile();
38 }
39
EmitServiceImplHeaderFile()40 void CServiceImplCodeEmitter::EmitServiceImplHeaderFile()
41 {
42 std::string filePath =
43 File::AdapterPath(StringHelper::Format("%s/%s.h", directory_.c_str(), FileName(baseName_ + "Service").c_str()));
44 File file(filePath, File::WRITE);
45 StringBuilder sb;
46
47 EmitLicense(sb);
48 EmitHeadMacro(sb, implFullName_);
49 sb.Append("\n");
50 EmitServiceImplHeaderInclusions(sb);
51 sb.Append("\n");
52 EmitHeadExternC(sb);
53 if (isKernelCode_) {
54 sb.Append("\n");
55 EmitKernelServiceImplDef(sb);
56 } else if (interface_->IsSerializable()) {
57 sb.Append("\n");
58 EmitServiceImplDef(sb);
59 }
60 sb.Append("\n");
61 EmitServiceImplConstructDecl(sb);
62 sb.Append("\n");
63 EmitTailExternC(sb);
64 sb.Append("\n");
65 EmitTailMacro(sb, implFullName_);
66
67 std::string data = sb.ToString();
68 file.WriteData(data.c_str(), data.size());
69 file.Flush();
70 file.Close();
71 }
72
EmitServiceImplHeaderInclusions(StringBuilder & sb)73 void CServiceImplCodeEmitter::EmitServiceImplHeaderInclusions(StringBuilder &sb)
74 {
75 HeaderFile::HeaderFileSet headerFiles;
76
77 if (isKernelCode_) {
78 headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE, EmitVersionHeaderName(stubName_));
79 } else {
80 headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE, EmitVersionHeaderName(interfaceName_));
81 }
82
83 for (const auto &file : headerFiles) {
84 sb.AppendFormat("%s\n", file.ToString().c_str());
85 }
86 }
87
EmitServiceImplConstructDecl(StringBuilder & sb)88 void CServiceImplCodeEmitter::EmitServiceImplConstructDecl(StringBuilder &sb)
89 {
90 std::string instTypeName = interface_->IsSerializable() ? interfaceName_ : implName_;
91 sb.AppendFormat("struct %s *%sServiceGet(void);\n\n", instTypeName.c_str(), baseName_.c_str());
92 sb.AppendFormat("void %sServiceRelease(struct %s *instance);\n", baseName_.c_str(), instTypeName.c_str());
93 }
94
EmitServiceImplSourceFile()95 void CServiceImplCodeEmitter::EmitServiceImplSourceFile()
96 {
97 std::string filePath =
98 File::AdapterPath(StringHelper::Format("%s/%s.c", directory_.c_str(), FileName(implName_).c_str()));
99 File file(filePath, File::WRITE);
100 StringBuilder sb;
101
102 EmitLicense(sb);
103 EmitServiceImplSourceInclusions(sb);
104 sb.Append("\n");
105 EmitLogTagMacro(sb, FileName(implName_));
106 if (!isKernelCode_ && !interface_->IsSerializable()) {
107 sb.Append("\n");
108 EmitServiceImplDef(sb);
109 }
110
111 sb.Append("\n");
112 EmitServiceImplMethodImpls(sb, "");
113 if (isKernelCode_) {
114 sb.Append("\n");
115 EmitKernelServiceImplGetMethod(sb);
116 sb.Append("\n");
117 EmitKernelServiceImplReleaseMethod(sb);
118 } else {
119 sb.Append("\n");
120 EmitServiceImplGetMethod(sb);
121 sb.Append("\n");
122 EmitServiceImplReleaseMethod(sb);
123 }
124
125 std::string data = sb.ToString();
126 file.WriteData(data.c_str(), data.size());
127 file.Flush();
128 file.Close();
129 }
130
EmitServiceImplSourceInclusions(StringBuilder & sb)131 void CServiceImplCodeEmitter::EmitServiceImplSourceInclusions(StringBuilder &sb)
132 {
133 HeaderFile::HeaderFileSet headerFiles;
134
135 if (isKernelCode_ || interface_->IsSerializable()) {
136 headerFiles.emplace(HeaderFileType::OWN_HEADER_FILE, EmitVersionHeaderName(implName_));
137 } else {
138 headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE, EmitVersionHeaderName(interfaceName_));
139 }
140 GetSourceOtherLibInclusions(headerFiles);
141
142 for (const auto &file : headerFiles) {
143 sb.AppendFormat("%s\n", file.ToString().c_str());
144 }
145 }
146
GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet & headerFiles)147 void CServiceImplCodeEmitter::GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles)
148 {
149 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_base");
150 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_log");
151 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "osal_mem");
152 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "securec");
153 }
154
EmitKernelServiceImplDef(StringBuilder & sb)155 void CServiceImplCodeEmitter::EmitKernelServiceImplDef(StringBuilder &sb)
156 {
157 sb.AppendFormat("struct %sService {\n", baseName_.c_str());
158 sb.Append(TAB).AppendFormat("struct %sStub stub;\n\n", baseName_.c_str());
159 sb.Append(TAB).Append("// please add private data here\n");
160 sb.Append("};\n");
161 }
162
EmitServiceImplDef(StringBuilder & sb)163 void CServiceImplCodeEmitter::EmitServiceImplDef(StringBuilder &sb)
164 {
165 sb.AppendFormat("struct %sService {\n", baseName_.c_str());
166 sb.Append(TAB).AppendFormat("struct %s interface;\n", interfaceName_.c_str());
167 sb.Append("};\n");
168 }
169
EmitServiceImplMethodImpls(StringBuilder & sb,const std::string & prefix)170 void CServiceImplCodeEmitter::EmitServiceImplMethodImpls(StringBuilder &sb, const std::string &prefix)
171 {
172 for (size_t i = 0; i < interface_->GetMethodNumber(); i++) {
173 AutoPtr<ASTMethod> method = interface_->GetMethod(i);
174 EmitServiceImplMethodImpl(method, sb, prefix);
175 if (i + 1 < interface_->GetMethodNumber()) {
176 sb.Append("\n");
177 }
178 }
179
180 sb.Append("\n");
181 EmitServiceImplGetVersionMethod(sb, prefix);
182 }
183
EmitServiceImplMethodImpl(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix)184 void CServiceImplCodeEmitter::EmitServiceImplMethodImpl(
185 const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix)
186 {
187 if (method->GetParameterNumber() == 0) {
188 sb.Append(prefix).AppendFormat("static int32_t %s%s(struct %s *self)\n", baseName_.c_str(),
189 method->GetName().c_str(), interfaceName_.c_str());
190 } else {
191 StringBuilder paramStr;
192 paramStr.Append(prefix).AppendFormat("static int32_t %s%s(struct %s *self, ", baseName_.c_str(),
193 method->GetName().c_str(), interfaceName_.c_str());
194 for (size_t i = 0; i < method->GetParameterNumber(); i++) {
195 AutoPtr<ASTParameter> param = method->GetParameter(i);
196 EmitInterfaceMethodParameter(param, paramStr, "");
197 if (i + 1 < method->GetParameterNumber()) {
198 paramStr.Append(", ");
199 }
200 }
201
202 paramStr.Append(")");
203 sb.Append(SpecificationParam(paramStr, prefix + TAB));
204 sb.Append("\n");
205 }
206
207 sb.Append(prefix).Append("{\n");
208 sb.Append(prefix + TAB).Append("return HDF_SUCCESS;\n");
209 sb.Append(prefix).Append("}\n");
210 }
211
EmitServiceImplGetVersionMethod(StringBuilder & sb,const std::string & prefix)212 void CServiceImplCodeEmitter::EmitServiceImplGetVersionMethod(StringBuilder &sb, const std::string &prefix)
213 {
214 AutoPtr<ASTMethod> method = interface_->GetVersionMethod();
215 sb.Append(prefix).AppendFormat("static int32_t %s%s(struct %s *self, ", baseName_.c_str(),
216 method->GetName().c_str(), interfaceName_.c_str());
217 for (size_t i = 0; i < method->GetParameterNumber(); i++) {
218 AutoPtr<ASTParameter> param = method->GetParameter(i);
219 EmitInterfaceMethodParameter(param, sb, "");
220 if (i + 1 < method->GetParameterNumber()) {
221 sb.Append(", ");
222 }
223 }
224 sb.Append(")\n");
225 sb.Append(prefix).Append("{\n");
226 AutoPtr<ASTParameter> majorParam = method->GetParameter(0);
227 sb.Append(prefix + TAB).AppendFormat("*%s = %s;\n", majorParam->GetName().c_str(), majorVerName_.c_str());
228 AutoPtr<ASTParameter> minorParam = method->GetParameter(1);
229 sb.Append(prefix + TAB).AppendFormat("*%s = %s;\n", minorParam->GetName().c_str(), minorVerName_.c_str());
230 sb.Append(prefix + TAB).Append("return HDF_SUCCESS;\n");
231 sb.Append(prefix).Append("}\n");
232 }
233
EmitKernelServiceImplGetMethod(StringBuilder & sb)234 void CServiceImplCodeEmitter::EmitKernelServiceImplGetMethod(StringBuilder &sb)
235 {
236 std::string objName = "service";
237 sb.AppendFormat("struct %s *%sGet(void)\n", implName_.c_str(), implName_.c_str());
238 sb.Append("{\n");
239 sb.Append(TAB).AppendFormat("struct %s *%s = (struct %s *)OsalMemCalloc(sizeof(struct %s));\n",
240 implName_.c_str(), objName.c_str(), implName_.c_str(), implName_.c_str());
241 sb.Append(TAB).AppendFormat("if (%s == NULL) {\n", objName.c_str());
242 sb.Append(TAB).Append(TAB).AppendFormat(
243 "HDF_LOGE(\"%%{public}s: malloc %s obj failed!\", __func__);\n", implName_.c_str());
244 sb.Append(TAB).Append(TAB).Append("return NULL;\n");
245 sb.Append(TAB).Append("}\n\n");
246 sb.Append(TAB).AppendFormat("if (!%sStubConstruct(&%s->stub)) {\n", baseName_.c_str(), objName.c_str());
247 sb.Append(TAB).Append(TAB).AppendFormat(
248 "HDF_LOGE(\"%%{public}s: construct %sStub obj failed!\", __func__);\n", baseName_.c_str());
249 sb.Append(TAB).Append(TAB).AppendFormat("OsalMemFree(%s);\n", objName.c_str());
250 sb.Append(TAB).Append(TAB).Append("return NULL;\n");
251 sb.Append(TAB).Append("}\n\n");
252
253 for (size_t i = 0; i < interface_->GetMethodNumber(); i++) {
254 AutoPtr<ASTMethod> method = interface_->GetMethod(i);
255 sb.Append(TAB).AppendFormat("%s->stub.interface.%s = %s%s;\n", objName.c_str(), method->GetName().c_str(),
256 baseName_.c_str(), method->GetName().c_str());
257 }
258
259 sb.Append(TAB).AppendFormat("return service;\n", objName.c_str());
260 sb.Append("}\n");
261 }
262
EmitServiceImplGetMethod(StringBuilder & sb)263 void CServiceImplCodeEmitter::EmitServiceImplGetMethod(StringBuilder &sb)
264 {
265 std::string objName = "service";
266 if (interface_->IsSerializable()) {
267 sb.AppendFormat("struct %s *%sServiceGet(void)\n", interfaceName_.c_str(), baseName_.c_str());
268 } else {
269 sb.AppendFormat("struct %s *%sImplGetInstance(void)\n", interfaceName_.c_str(), baseName_.c_str());
270 }
271
272 sb.Append("{\n");
273 sb.Append(TAB).AppendFormat("struct %s *%s = (struct %s *)OsalMemCalloc(sizeof(struct %s));\n",
274 implName_.c_str(), objName.c_str(), implName_.c_str(), implName_.c_str());
275 sb.Append(TAB).AppendFormat("if (%s == NULL) {\n", objName.c_str());
276 sb.Append(TAB).Append(TAB).AppendFormat(
277 "HDF_LOGE(\"%%{public}s: malloc %s obj failed!\", __func__);\n", implName_.c_str());
278 sb.Append(TAB).Append(TAB).Append("return NULL;\n");
279 sb.Append(TAB).Append("}\n\n");
280
281 for (size_t i = 0; i < interface_->GetMethodNumber(); i++) {
282 AutoPtr<ASTMethod> method = interface_->GetMethod(i);
283 sb.Append(TAB).AppendFormat("%s->interface.%s = %s%s;\n", objName.c_str(), method->GetName().c_str(),
284 baseName_.c_str(), method->GetName().c_str());
285 }
286
287 AutoPtr<ASTMethod> method = interface_->GetVersionMethod();
288 sb.Append(TAB).AppendFormat("%s->interface.%s = %s%s;\n", objName.c_str(), method->GetName().c_str(),
289 baseName_.c_str(), method->GetName().c_str());
290
291 sb.Append(TAB).AppendFormat("return &%s->interface;\n", objName.c_str());
292 sb.Append("}\n");
293 }
294
EmitKernelServiceImplReleaseMethod(StringBuilder & sb)295 void CServiceImplCodeEmitter::EmitKernelServiceImplReleaseMethod(StringBuilder &sb)
296 {
297 std::string instName = "instance";
298 sb.AppendFormat(
299 "void %sRelease(struct %s *%s)\n", implName_.c_str(), implName_.c_str(), instName.c_str());
300 sb.Append("{\n");
301 sb.Append(TAB).AppendFormat("if (%s == NULL) {\n", instName.c_str());
302 sb.Append(TAB).Append(TAB).Append("return;\n");
303 sb.Append(TAB).Append("}\n\n");
304 sb.Append(TAB).AppendFormat("OsalMemFree(%s);\n", instName.c_str());
305 sb.Append("}\n");
306 }
307
EmitServiceImplReleaseMethod(StringBuilder & sb)308 void CServiceImplCodeEmitter::EmitServiceImplReleaseMethod(StringBuilder &sb)
309 {
310 if (interface_->IsSerializable()) {
311 sb.AppendFormat("void %sServiceRelease(struct %s *instance)\n", baseName_.c_str(), interfaceName_.c_str());
312 } else {
313 sb.AppendFormat("void %sImplRelease(struct %s *instance)\n", baseName_.c_str(), interfaceName_.c_str());
314 }
315 sb.Append("{\n");
316 sb.Append(TAB).Append("if (instance == NULL) {\n");
317 sb.Append(TAB).Append(TAB).Append("return;\n");
318 sb.Append(TAB).Append("}\n");
319 sb.Append(TAB).Append("OsalMemFree(instance);\n");
320 sb.Append("}\n");
321 }
322 } // namespace HDI
323 } // namespace OHOS