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_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 switch (mode_) {
34 case GenMode::LOW: {
35 EmitLowServiceImplHeaderFile();
36 EmitLowServiceImplSourceFile();
37 break;
38 }
39 case GenMode::PASSTHROUGH:
40 case GenMode::IPC: {
41 if (interface_->IsSerializable()) {
42 EmitServiceImplHeaderFile();
43 }
44 EmitServiceImplSourceFile();
45 break;
46 }
47 case GenMode::KERNEL: {
48 EmitServiceImplHeaderFile();
49 EmitServiceImplSourceFile();
50 break;
51 }
52 default:
53 break;
54 }
55 }
56
EmitLowServiceImplHeaderFile()57 void CServiceImplCodeEmitter::EmitLowServiceImplHeaderFile()
58 {
59 std::string filePath =
60 File::AdapterPath(StringHelper::Format("%s/%s.h", directory_.c_str(), FileName(implName_).c_str()));
61 File file(filePath, File::WRITE);
62 StringBuilder sb;
63
64 sb.Append("\n");
65 EmitLicense(sb);
66 EmitHeadMacro(sb, implFullName_);
67 EmitLowServiceImplInclusions(sb);
68 sb.Append("\n");
69 EmitHeadExternC(sb);
70 sb.Append("\n");
71 EmitLowServiceImplDefinition(sb);
72 sb.Append("\n");
73 EmitServiceImplExternalMethodsDecl(sb);
74 sb.Append("\n");
75 EmitTailExternC(sb);
76 sb.Append("\n");
77 EmitTailMacro(sb, implFullName_);
78
79 std::string data = sb.ToString();
80 file.WriteData(data.c_str(), data.size());
81 file.Flush();
82 file.Close();
83 }
84
EmitLowServiceImplInclusions(StringBuilder & sb)85 void CServiceImplCodeEmitter::EmitLowServiceImplInclusions(StringBuilder &sb)
86 {
87 HeaderFile::HeaderFileSet headerFiles;
88 headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE, EmitVersionHeaderName(interfaceName_));
89 for (const auto &file : headerFiles) {
90 sb.AppendFormat("%s\n", file.ToString().c_str());
91 }
92 }
93
EmitLowServiceImplDefinition(StringBuilder & sb)94 void CServiceImplCodeEmitter::EmitLowServiceImplDefinition(StringBuilder &sb)
95 {
96 sb.AppendFormat("struct %s {\n", implName_.c_str());
97 sb.Append(TAB).AppendFormat("struct %s super;\n", interfaceName_.c_str());
98 sb.Append(TAB).Append("// please add private data here\n");
99 sb.Append("};\n");
100 }
101
EmitLowServiceImplSourceFile()102 void CServiceImplCodeEmitter::EmitLowServiceImplSourceFile()
103 {
104 std::string filePath =
105 File::AdapterPath(StringHelper::Format("%s/%s.c", directory_.c_str(), FileName(implName_).c_str()));
106 File file(filePath, File::WRITE);
107 StringBuilder sb;
108
109 EmitLicense(sb);
110 EmitServiceImplSourceInclusions(sb);
111 sb.Append("\n");
112 EmitLogTagMacro(sb, FileName(implName_));
113 sb.Append("\n");
114 EmitServiceImplMethodImpls(sb, "");
115 sb.Append("\n");
116 EmitLowServiceImplGetMethod(sb);
117 sb.Append("\n");
118 EmitServiceImplReleaseMethod(sb);
119
120 std::string data = sb.ToString();
121 file.WriteData(data.c_str(), data.size());
122 file.Flush();
123 file.Close();
124 }
125
EmitLowServiceImplGetMethod(StringBuilder & sb)126 void CServiceImplCodeEmitter::EmitLowServiceImplGetMethod(StringBuilder &sb)
127 {
128 sb.AppendFormat("struct %s *%sServiceGet(void)\n", implName_.c_str(), baseName_.c_str());
129 sb.Append("{\n");
130
131 sb.Append(TAB).AppendFormat("struct %s *service = (struct %s *)OsalMemCalloc(sizeof(struct %s));\n",
132 implName_.c_str(), implName_.c_str(), implName_.c_str());
133 sb.Append(TAB).Append("if (service == NULL) {\n");
134 sb.Append(TAB).Append(TAB).Append("HDF_LOGE(\"%s: failed to malloc service object\", __func__);\n");
135 sb.Append(TAB).Append("}\n");
136
137 for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
138 sb.Append(TAB).AppendFormat("service->super.%s = %s%s;\n", method->GetName().c_str(),
139 baseName_.c_str(), method->GetName().c_str());
140 }
141
142 AutoPtr<ASTMethod> method = interface_->GetVersionMethod();
143 sb.Append(TAB).AppendFormat("service->super.%s = %s%s;\n", method->GetName().c_str(),
144 baseName_.c_str(), method->GetName().c_str());
145
146 sb.Append(TAB).Append("return service;\n");
147 sb.Append("}\n");
148 }
149
EmitServiceImplHeaderFile()150 void CServiceImplCodeEmitter::EmitServiceImplHeaderFile()
151 {
152 std::string filePath =
153 File::AdapterPath(StringHelper::Format("%s/%s.h", directory_.c_str(), FileName(baseName_ + "Service").c_str()));
154 File file(filePath, File::WRITE);
155 StringBuilder sb;
156
157 EmitLicense(sb);
158 EmitHeadMacro(sb, implFullName_);
159 sb.Append("\n");
160 EmitServiceImplHeaderInclusions(sb);
161 sb.Append("\n");
162 EmitHeadExternC(sb);
163 if (mode_ == GenMode::KERNEL) {
164 sb.Append("\n");
165 EmitKernelServiceImplDef(sb);
166 } else if (interface_->IsSerializable()) {
167 sb.Append("\n");
168 EmitServiceImplDef(sb);
169 }
170 sb.Append("\n");
171 EmitServiceImplExternalMethodsDecl(sb);
172 sb.Append("\n");
173 EmitTailExternC(sb);
174 sb.Append("\n");
175 EmitTailMacro(sb, implFullName_);
176
177 std::string data = sb.ToString();
178 file.WriteData(data.c_str(), data.size());
179 file.Flush();
180 file.Close();
181 }
182
EmitServiceImplHeaderInclusions(StringBuilder & sb)183 void CServiceImplCodeEmitter::EmitServiceImplHeaderInclusions(StringBuilder &sb)
184 {
185 HeaderFile::HeaderFileSet headerFiles;
186
187 if (mode_ == GenMode::KERNEL) {
188 headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE, EmitVersionHeaderName(stubName_));
189 } else {
190 headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE, EmitVersionHeaderName(interfaceName_));
191 }
192
193 for (const auto &file : headerFiles) {
194 sb.AppendFormat("%s\n", file.ToString().c_str());
195 }
196 }
197
EmitServiceImplExternalMethodsDecl(StringBuilder & sb) const198 void CServiceImplCodeEmitter::EmitServiceImplExternalMethodsDecl(StringBuilder &sb) const
199 {
200 std::string instTypeName;
201 if (mode_ == GenMode::LOW || mode_ == GenMode::KERNEL) {
202 instTypeName = implName_;
203 } else {
204 instTypeName = interface_->IsSerializable() ? interfaceName_ : implName_;
205 }
206 sb.AppendFormat("struct %s *%sServiceGet(void);\n\n", instTypeName.c_str(), baseName_.c_str());
207 sb.AppendFormat("void %sServiceRelease(struct %s *instance);\n", baseName_.c_str(), instTypeName.c_str());
208 }
209
EmitServiceImplSourceFile()210 void CServiceImplCodeEmitter::EmitServiceImplSourceFile()
211 {
212 std::string filePath =
213 File::AdapterPath(StringHelper::Format("%s/%s.c", directory_.c_str(), FileName(implName_).c_str()));
214 File file(filePath, File::WRITE);
215 StringBuilder sb;
216
217 EmitLicense(sb);
218 EmitServiceImplSourceInclusions(sb);
219 sb.Append("\n");
220 EmitLogTagMacro(sb, FileName(implName_));
221 if (mode_ != GenMode::KERNEL && !interface_->IsSerializable()) {
222 sb.Append("\n");
223 EmitServiceImplDef(sb);
224 }
225
226 sb.Append("\n");
227 EmitServiceImplMethodImpls(sb, "");
228 if (mode_ == GenMode::KERNEL) {
229 sb.Append("\n");
230 EmitKernelServiceImplGetMethod(sb);
231 sb.Append("\n");
232 EmitKernelServiceImplReleaseMethod(sb);
233 } else {
234 sb.Append("\n");
235 EmitServiceImplGetMethod(sb);
236 sb.Append("\n");
237 EmitServiceImplReleaseMethod(sb);
238 }
239
240 std::string data = sb.ToString();
241 file.WriteData(data.c_str(), data.size());
242 file.Flush();
243 file.Close();
244 }
245
EmitServiceImplSourceInclusions(StringBuilder & sb)246 void CServiceImplCodeEmitter::EmitServiceImplSourceInclusions(StringBuilder &sb)
247 {
248 HeaderFile::HeaderFileSet headerFiles;
249
250 if (mode_ == GenMode::KERNEL || mode_ == GenMode::LOW || interface_->IsSerializable()) {
251 headerFiles.emplace(HeaderFileType::OWN_HEADER_FILE, EmitVersionHeaderName(implName_));
252 } else {
253 headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE, EmitVersionHeaderName(interfaceName_));
254 }
255 GetSourceOtherLibInclusions(headerFiles);
256
257 for (const auto &file : headerFiles) {
258 sb.AppendFormat("%s\n", file.ToString().c_str());
259 }
260 }
261
GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet & headerFiles) const262 void CServiceImplCodeEmitter::GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles) const
263 {
264 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_base");
265 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_core_log");
266 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "osal_mem");
267 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "securec");
268 }
269
EmitKernelServiceImplDef(StringBuilder & sb) const270 void CServiceImplCodeEmitter::EmitKernelServiceImplDef(StringBuilder &sb) const
271 {
272 sb.AppendFormat("struct %sService {\n", baseName_.c_str());
273 sb.Append(TAB).AppendFormat("struct %sStub stub;\n\n", baseName_.c_str());
274 sb.Append(TAB).Append("// please add private data here\n");
275 sb.Append("};\n");
276 }
277
EmitServiceImplDef(StringBuilder & sb) const278 void CServiceImplCodeEmitter::EmitServiceImplDef(StringBuilder &sb) const
279 {
280 sb.AppendFormat("struct %sService {\n", baseName_.c_str());
281 sb.Append(TAB).AppendFormat("struct %s interface;\n", interfaceName_.c_str());
282 sb.Append("};\n");
283 }
284
EmitServiceImplMethodImpls(StringBuilder & sb,const std::string & prefix) const285 void CServiceImplCodeEmitter::EmitServiceImplMethodImpls(StringBuilder &sb, const std::string &prefix) const
286 {
287 for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
288 EmitServiceImplMethodImpl(method, sb, prefix);
289 sb.Append("\n");
290 }
291
292 EmitServiceImplGetVersionMethod(sb, prefix);
293 }
294
EmitServiceImplMethodImpl(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix) const295 void CServiceImplCodeEmitter::EmitServiceImplMethodImpl(
296 const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const
297 {
298 if (method->GetParameterNumber() == 0) {
299 sb.Append(prefix).AppendFormat("static int32_t %s%s(struct %s *self)\n", baseName_.c_str(),
300 method->GetName().c_str(), interfaceName_.c_str());
301 } else {
302 StringBuilder paramStr;
303 paramStr.Append(prefix).AppendFormat("static int32_t %s%s(struct %s *self, ", baseName_.c_str(),
304 method->GetName().c_str(), interfaceName_.c_str());
305 for (size_t i = 0; i < method->GetParameterNumber(); i++) {
306 AutoPtr<ASTParameter> param = method->GetParameter(i);
307 EmitInterfaceMethodParameter(param, paramStr, "");
308 if (i + 1 < method->GetParameterNumber()) {
309 paramStr.Append(", ");
310 }
311 }
312
313 paramStr.Append(")");
314 sb.Append(SpecificationParam(paramStr, prefix + TAB));
315 sb.Append("\n");
316 }
317
318 sb.Append(prefix).Append("{\n");
319 sb.Append(prefix + TAB).Append("return HDF_SUCCESS;\n");
320 sb.Append(prefix).Append("}\n");
321 }
322
EmitServiceImplGetVersionMethod(StringBuilder & sb,const std::string & prefix) const323 void CServiceImplCodeEmitter::EmitServiceImplGetVersionMethod(StringBuilder &sb, const std::string &prefix) const
324 {
325 AutoPtr<ASTMethod> method = interface_->GetVersionMethod();
326 sb.Append(prefix).AppendFormat("static int32_t %s%s(struct %s *self, ", baseName_.c_str(),
327 method->GetName().c_str(), interfaceName_.c_str());
328 for (size_t i = 0; i < method->GetParameterNumber(); i++) {
329 AutoPtr<ASTParameter> param = method->GetParameter(i);
330 EmitInterfaceMethodParameter(param, sb, "");
331 if (i + 1 < method->GetParameterNumber()) {
332 sb.Append(", ");
333 }
334 }
335 sb.Append(")\n");
336 sb.Append(prefix).Append("{\n");
337 AutoPtr<ASTParameter> majorParam = method->GetParameter(0);
338 sb.Append(prefix + TAB).AppendFormat("*%s = %s;\n", majorParam->GetName().c_str(), majorVerName_.c_str());
339 AutoPtr<ASTParameter> minorParam = method->GetParameter(1);
340 sb.Append(prefix + TAB).AppendFormat("*%s = %s;\n", minorParam->GetName().c_str(), minorVerName_.c_str());
341 sb.Append(prefix + TAB).Append("return HDF_SUCCESS;\n");
342 sb.Append(prefix).Append("}\n");
343 }
344
EmitKernelServiceImplGetMethod(StringBuilder & sb) const345 void CServiceImplCodeEmitter::EmitKernelServiceImplGetMethod(StringBuilder &sb) const
346 {
347 std::string objName = "service";
348 sb.AppendFormat("struct %s *%sGet(void)\n", implName_.c_str(), implName_.c_str());
349 sb.Append("{\n");
350 sb.Append(TAB).AppendFormat("struct %s *%s = (struct %s *)OsalMemCalloc(sizeof(struct %s));\n",
351 implName_.c_str(), objName.c_str(), implName_.c_str(), implName_.c_str());
352 sb.Append(TAB).AppendFormat("if (%s == NULL) {\n", objName.c_str());
353 sb.Append(TAB).Append(TAB).AppendFormat(
354 "HDF_LOGE(\"%%{public}s: malloc %s obj failed!\", __func__);\n", implName_.c_str());
355 sb.Append(TAB).Append(TAB).Append("return NULL;\n");
356 sb.Append(TAB).Append("}\n\n");
357 sb.Append(TAB).AppendFormat("if (!%sStubConstruct(&%s->stub)) {\n", baseName_.c_str(), objName.c_str());
358 sb.Append(TAB).Append(TAB).AppendFormat(
359 "HDF_LOGE(\"%%{public}s: construct %sStub obj failed!\", __func__);\n", baseName_.c_str());
360 sb.Append(TAB).Append(TAB).AppendFormat("OsalMemFree(%s);\n", objName.c_str());
361 sb.Append(TAB).Append(TAB).Append("return NULL;\n");
362 sb.Append(TAB).Append("}\n\n");
363
364 for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
365 sb.Append(TAB).AppendFormat("%s->stub.interface.%s = %s%s;\n", objName.c_str(), method->GetName().c_str(),
366 baseName_.c_str(), method->GetName().c_str());
367 }
368
369 sb.Append(TAB).AppendFormat("return service;\n", objName.c_str());
370 sb.Append("}\n");
371 }
372
EmitServiceImplGetMethod(StringBuilder & sb) const373 void CServiceImplCodeEmitter::EmitServiceImplGetMethod(StringBuilder &sb) const
374 {
375 std::string objName = "service";
376 if (interface_->IsSerializable()) {
377 sb.AppendFormat("struct %s *%sServiceGet(void)\n", interfaceName_.c_str(), baseName_.c_str());
378 } else {
379 sb.AppendFormat("struct %s *%sImplGetInstance(void)\n", interfaceName_.c_str(), baseName_.c_str());
380 }
381
382 sb.Append("{\n");
383 sb.Append(TAB).AppendFormat("struct %s *%s = (struct %s *)OsalMemCalloc(sizeof(struct %s));\n",
384 implName_.c_str(), objName.c_str(), implName_.c_str(), implName_.c_str());
385 sb.Append(TAB).AppendFormat("if (%s == NULL) {\n", objName.c_str());
386 sb.Append(TAB).Append(TAB).AppendFormat(
387 "HDF_LOGE(\"%%{public}s: malloc %s obj failed!\", __func__);\n", implName_.c_str());
388 sb.Append(TAB).Append(TAB).Append("return NULL;\n");
389 sb.Append(TAB).Append("}\n\n");
390 for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
391 sb.Append(TAB).AppendFormat("%s->interface.%s = %s%s;\n", objName.c_str(), method->GetName().c_str(),
392 baseName_.c_str(), method->GetName().c_str());
393 }
394
395 AutoPtr<ASTMethod> method = interface_->GetVersionMethod();
396 sb.Append(TAB).AppendFormat("%s->interface.%s = %s%s;\n", objName.c_str(), method->GetName().c_str(),
397 baseName_.c_str(), method->GetName().c_str());
398
399 sb.Append(TAB).AppendFormat("return &%s->interface;\n", objName.c_str());
400 sb.Append("}\n");
401 }
402
EmitKernelServiceImplReleaseMethod(StringBuilder & sb) const403 void CServiceImplCodeEmitter::EmitKernelServiceImplReleaseMethod(StringBuilder &sb) const
404 {
405 std::string instName = "instance";
406 sb.AppendFormat(
407 "void %sRelease(struct %s *%s)\n", implName_.c_str(), implName_.c_str(), instName.c_str());
408 sb.Append("{\n");
409 sb.Append(TAB).AppendFormat("if (%s == NULL) {\n", instName.c_str());
410 sb.Append(TAB).Append(TAB).Append("return;\n");
411 sb.Append(TAB).Append("}\n\n");
412 sb.Append(TAB).AppendFormat("OsalMemFree(%s);\n", instName.c_str());
413 sb.Append("}\n");
414 }
415
EmitServiceImplReleaseMethod(StringBuilder & sb) const416 void CServiceImplCodeEmitter::EmitServiceImplReleaseMethod(StringBuilder &sb) const
417 {
418 if (mode_ == GenMode::LOW || mode_ == GenMode::KERNEL) {
419 sb.AppendFormat("void %sRelease(struct %s *instance)\n", implName_.c_str(), implName_.c_str());
420 } else {
421 if (interface_->IsSerializable()) {
422 sb.AppendFormat("void %sServiceRelease(struct %s *instance)\n", baseName_.c_str(), interfaceName_.c_str());
423 } else {
424 sb.AppendFormat("void %sImplRelease(struct %s *instance)\n", baseName_.c_str(), interfaceName_.c_str());
425 }
426 }
427 sb.Append("{\n");
428 sb.Append(TAB).Append("if (instance == NULL) {\n");
429 sb.Append(TAB).Append(TAB).Append("return;\n");
430 sb.Append(TAB).Append("}\n");
431 sb.Append(TAB).Append("OsalMemFree(instance);\n");
432 sb.Append("}\n");
433 }
434 } // namespace HDI
435 } // namespace OHOS