1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "c_service_impl_code_emitter.h"
17 #include "util/file.h"
18 #include "util/logger.h"
19
20 namespace OHOS {
21 namespace Idl {
ResolveDirectory(const std::string & targetDirectory)22 bool CServiceImplCodeEmitter::ResolveDirectory(const std::string &targetDirectory)
23 {
24 if (ast_->GetASTFileType() == ASTFileType::AST_IFACE || ast_->GetASTFileType() == ASTFileType::AST_ICALLBACK) {
25 directory_ = GetFileParentPath(targetDirectory);
26 } else {
27 return false;
28 }
29
30 if (!File::CreateParentDir(directory_)) {
31 Logger::E("CServiceImplCodeEmitter", "Create '%s' failed!", directory_.c_str());
32 return false;
33 }
34
35 return true;
36 }
37
EmitCode()38 void CServiceImplCodeEmitter::EmitCode()
39 {
40 switch (mode_) {
41 case GenMode::LOW: {
42 EmitLowServiceImplHeaderFile();
43 EmitLowServiceImplSourceFile();
44 break;
45 }
46 case GenMode::PASSTHROUGH:
47 case GenMode::IPC: {
48 if (interface_->IsSerializable()) {
49 EmitServiceImplHeaderFile();
50 }
51 EmitServiceImplSourceFile();
52 break;
53 }
54 case GenMode::KERNEL: {
55 EmitServiceImplHeaderFile();
56 EmitServiceImplSourceFile();
57 break;
58 }
59 default:
60 break;
61 }
62 }
63
EmitLowServiceImplHeaderFile()64 void CServiceImplCodeEmitter::EmitLowServiceImplHeaderFile()
65 {
66 std::string filePath =
67 File::AdapterPath(StringHelper::Format("%s/%s.h", directory_.c_str(), FileName(implName_).c_str()));
68 File file(filePath, File::WRITE);
69 StringBuilder sb;
70
71 sb.Append("\n");
72 EmitLicense(sb);
73 EmitHeadMacro(sb, implFullName_);
74 EmitLowServiceImplInclusions(sb);
75 sb.Append("\n");
76 EmitHeadExternC(sb);
77 sb.Append("\n");
78 EmitLowServiceImplDefinition(sb);
79 sb.Append("\n");
80 EmitServiceImplExternalMethodsDecl(sb);
81 sb.Append("\n");
82 EmitTailExternC(sb);
83 sb.Append("\n");
84 EmitTailMacro(sb, implFullName_);
85
86 std::string data = sb.ToString();
87 file.WriteData(data.c_str(), data.size());
88 file.Flush();
89 file.Close();
90 }
91
EmitLowServiceImplInclusions(StringBuilder & sb)92 void CServiceImplCodeEmitter::EmitLowServiceImplInclusions(StringBuilder &sb)
93 {
94 HeaderFile::HeaderFileSet headerFiles;
95 headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE, EmitVersionHeaderName(interfaceName_));
96 for (const auto &file : headerFiles) {
97 sb.AppendFormat("%s\n", file.ToString().c_str());
98 }
99 }
100
EmitLowServiceImplDefinition(StringBuilder & sb)101 void CServiceImplCodeEmitter::EmitLowServiceImplDefinition(StringBuilder &sb)
102 {
103 sb.AppendFormat("struct %s {\n", implName_.c_str());
104 sb.Append(TAB).AppendFormat("struct %s super;\n", interfaceName_.c_str());
105 sb.Append(TAB).Append("// please add private data here\n");
106 sb.Append("};\n");
107 }
108
EmitLowServiceImplSourceFile()109 void CServiceImplCodeEmitter::EmitLowServiceImplSourceFile()
110 {
111 std::string filePath =
112 File::AdapterPath(StringHelper::Format("%s/%s.c", directory_.c_str(), FileName(implName_).c_str()));
113 File file(filePath, File::WRITE);
114 StringBuilder sb;
115
116 EmitLicense(sb);
117 EmitServiceImplSourceInclusions(sb);
118 sb.Append("\n");
119 EmitLogTagMacro(sb, FileName(implName_));
120 sb.Append("\n");
121 EmitServiceImplMethodImpls(sb, "");
122 sb.Append("\n");
123 EmitLowServiceImplGetMethod(sb);
124 sb.Append("\n");
125 EmitServiceImplReleaseMethod(sb);
126
127 std::string data = sb.ToString();
128 file.WriteData(data.c_str(), data.size());
129 file.Flush();
130 file.Close();
131 }
132
EmitLowServiceImplGetMethod(StringBuilder & sb)133 void CServiceImplCodeEmitter::EmitLowServiceImplGetMethod(StringBuilder &sb)
134 {
135 sb.AppendFormat("struct %s *%sServiceGet(void)\n", implName_.c_str(), baseName_.c_str());
136 sb.Append("{\n");
137
138 sb.Append(TAB).AppendFormat("struct %s *service = (struct %s *)OsalMemCalloc(sizeof(struct %s));\n",
139 implName_.c_str(), implName_.c_str(), implName_.c_str());
140 sb.Append(TAB).Append("if (service == NULL) {\n");
141 sb.Append(TAB).Append(TAB).Append("HDF_LOGE(\"%s: failed to malloc service object\", __func__);\n");
142 sb.Append(TAB).Append("}\n");
143
144 for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
145 sb.Append(TAB).AppendFormat("service->super.%s = %s%s;\n", method->GetName().c_str(),
146 baseName_.c_str(), method->GetName().c_str());
147 }
148
149 AutoPtr<ASTMethod> method = interface_->GetVersionMethod();
150 sb.Append(TAB).AppendFormat("service->super.%s = %s%s;\n", method->GetName().c_str(),
151 baseName_.c_str(), method->GetName().c_str());
152
153 sb.Append(TAB).Append("return service;\n");
154 sb.Append("}\n");
155 }
156
EmitServiceImplHeaderFile()157 void CServiceImplCodeEmitter::EmitServiceImplHeaderFile()
158 {
159 std::string filePath =
160 File::AdapterPath(StringHelper::Format("%s/%s.h", directory_.c_str(), FileName(baseName_ + "Service").c_str()));
161 File file(filePath, File::WRITE);
162 StringBuilder sb;
163
164 EmitLicense(sb);
165 EmitHeadMacro(sb, implFullName_);
166 sb.Append("\n");
167 EmitServiceImplHeaderInclusions(sb);
168 sb.Append("\n");
169 EmitHeadExternC(sb);
170 if (mode_ == GenMode::KERNEL) {
171 sb.Append("\n");
172 EmitKernelServiceImplDef(sb);
173 } else if (interface_->IsSerializable()) {
174 sb.Append("\n");
175 EmitServiceImplDef(sb);
176 }
177 sb.Append("\n");
178 EmitServiceImplExternalMethodsDecl(sb);
179 sb.Append("\n");
180 EmitTailExternC(sb);
181 sb.Append("\n");
182 EmitTailMacro(sb, implFullName_);
183
184 std::string data = sb.ToString();
185 file.WriteData(data.c_str(), data.size());
186 file.Flush();
187 file.Close();
188 }
189
EmitServiceImplHeaderInclusions(StringBuilder & sb)190 void CServiceImplCodeEmitter::EmitServiceImplHeaderInclusions(StringBuilder &sb)
191 {
192 HeaderFile::HeaderFileSet headerFiles;
193
194 if (mode_ == GenMode::KERNEL) {
195 headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE, EmitVersionHeaderName(stubName_));
196 } else {
197 headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE, EmitVersionHeaderName(interfaceName_));
198 }
199
200 for (const auto &file : headerFiles) {
201 sb.AppendFormat("%s\n", file.ToString().c_str());
202 }
203 }
204
EmitServiceImplExternalMethodsDecl(StringBuilder & sb) const205 void CServiceImplCodeEmitter::EmitServiceImplExternalMethodsDecl(StringBuilder &sb) const
206 {
207 std::string instTypeName;
208 if (mode_ == GenMode::LOW || mode_ == GenMode::KERNEL) {
209 instTypeName = implName_;
210 } else {
211 instTypeName = interface_->IsSerializable() ? interfaceName_ : implName_;
212 }
213 sb.AppendFormat("struct %s *%sServiceGet(void);\n\n", instTypeName.c_str(), baseName_.c_str());
214 sb.AppendFormat("void %sServiceRelease(struct %s *instance);\n", baseName_.c_str(), instTypeName.c_str());
215 }
216
EmitServiceImplSourceFile()217 void CServiceImplCodeEmitter::EmitServiceImplSourceFile()
218 {
219 std::string filePath =
220 File::AdapterPath(StringHelper::Format("%s/%s.c", directory_.c_str(), FileName(implName_).c_str()));
221 File file(filePath, File::WRITE);
222 StringBuilder sb;
223
224 EmitLicense(sb);
225 EmitServiceImplSourceInclusions(sb);
226 sb.Append("\n");
227 EmitLogTagMacro(sb, FileName(implName_));
228 if (mode_ != GenMode::KERNEL && !interface_->IsSerializable()) {
229 sb.Append("\n");
230 EmitServiceImplDef(sb);
231 }
232
233 sb.Append("\n");
234 EmitServiceImplMethodImpls(sb, "");
235 if (mode_ == GenMode::KERNEL) {
236 sb.Append("\n");
237 EmitKernelServiceImplGetMethod(sb);
238 sb.Append("\n");
239 EmitKernelServiceImplReleaseMethod(sb);
240 } else {
241 sb.Append("\n");
242 EmitServiceImplGetMethod(sb);
243 sb.Append("\n");
244 EmitServiceImplReleaseMethod(sb);
245 }
246
247 std::string data = sb.ToString();
248 file.WriteData(data.c_str(), data.size());
249 file.Flush();
250 file.Close();
251 }
252
EmitServiceImplSourceInclusions(StringBuilder & sb)253 void CServiceImplCodeEmitter::EmitServiceImplSourceInclusions(StringBuilder &sb)
254 {
255 HeaderFile::HeaderFileSet headerFiles;
256
257 if (mode_ == GenMode::KERNEL || mode_ == GenMode::LOW || interface_->IsSerializable()) {
258 headerFiles.emplace(HeaderFileType::OWN_HEADER_FILE, EmitVersionHeaderName(implName_));
259 } else {
260 headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE, EmitVersionHeaderName(interfaceName_));
261 }
262 GetSourceOtherLibInclusions(headerFiles);
263
264 for (const auto &file : headerFiles) {
265 sb.AppendFormat("%s\n", file.ToString().c_str());
266 }
267 }
268
GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet & headerFiles) const269 void CServiceImplCodeEmitter::GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles) const
270 {
271 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_base");
272 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_core_log");
273 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "osal_mem");
274 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "securec");
275 }
276
EmitKernelServiceImplDef(StringBuilder & sb) const277 void CServiceImplCodeEmitter::EmitKernelServiceImplDef(StringBuilder &sb) const
278 {
279 sb.AppendFormat("struct %sService {\n", baseName_.c_str());
280 sb.Append(TAB).AppendFormat("struct %sStub stub;\n\n", baseName_.c_str());
281 sb.Append(TAB).Append("// please add private data here\n");
282 sb.Append("};\n");
283 }
284
EmitServiceImplDef(StringBuilder & sb) const285 void CServiceImplCodeEmitter::EmitServiceImplDef(StringBuilder &sb) const
286 {
287 sb.AppendFormat("struct %sService {\n", baseName_.c_str());
288 sb.Append(TAB).AppendFormat("struct %s interface;\n", interfaceName_.c_str());
289 sb.Append("};\n");
290 }
291
EmitServiceImplMethodImpls(StringBuilder & sb,const std::string & prefix) const292 void CServiceImplCodeEmitter::EmitServiceImplMethodImpls(StringBuilder &sb, const std::string &prefix) const
293 {
294 for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
295 EmitServiceImplMethodImpl(method, sb, prefix);
296 sb.Append("\n");
297 }
298
299 EmitServiceImplGetVersionMethod(sb, prefix);
300 }
301
EmitServiceImplMethodImpl(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix) const302 void CServiceImplCodeEmitter::EmitServiceImplMethodImpl(
303 const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const
304 {
305 if (method->GetParameterNumber() == 0) {
306 sb.Append(prefix).AppendFormat("static int32_t %s%s(struct %s *self)\n", baseName_.c_str(),
307 method->GetName().c_str(), interfaceName_.c_str());
308 } else {
309 StringBuilder paramStr;
310 paramStr.Append(prefix).AppendFormat("static int32_t %s%s(struct %s *self, ", baseName_.c_str(),
311 method->GetName().c_str(), interfaceName_.c_str());
312 for (size_t i = 0; i < method->GetParameterNumber(); i++) {
313 AutoPtr<ASTParameter> param = method->GetParameter(i);
314 EmitInterfaceMethodParameter(param, paramStr, "");
315 if (i + 1 < method->GetParameterNumber()) {
316 paramStr.Append(", ");
317 }
318 }
319
320 paramStr.Append(")");
321 sb.Append(SpecificationParam(paramStr, prefix + TAB));
322 sb.Append("\n");
323 }
324
325 sb.Append(prefix).Append("{\n");
326 sb.Append(prefix + TAB).Append("return HDF_SUCCESS;\n");
327 sb.Append(prefix).Append("}\n");
328 }
329
EmitServiceImplGetVersionMethod(StringBuilder & sb,const std::string & prefix) const330 void CServiceImplCodeEmitter::EmitServiceImplGetVersionMethod(StringBuilder &sb, const std::string &prefix) const
331 {
332 AutoPtr<ASTMethod> method = interface_->GetVersionMethod();
333 sb.Append(prefix).AppendFormat("static int32_t %s%s(struct %s *self, ", baseName_.c_str(),
334 method->GetName().c_str(), interfaceName_.c_str());
335 for (size_t i = 0; i < method->GetParameterNumber(); i++) {
336 AutoPtr<ASTParameter> param = method->GetParameter(i);
337 EmitInterfaceMethodParameter(param, sb, "");
338 if (i + 1 < method->GetParameterNumber()) {
339 sb.Append(", ");
340 }
341 }
342 sb.Append(")\n");
343 sb.Append(prefix).Append("{\n");
344 AutoPtr<ASTParameter> majorParam = method->GetParameter(0);
345 sb.Append(prefix + TAB).AppendFormat("*%s = %s;\n", majorParam->GetName().c_str(), majorVerName_.c_str());
346 AutoPtr<ASTParameter> minorParam = method->GetParameter(1);
347 sb.Append(prefix + TAB).AppendFormat("*%s = %s;\n", minorParam->GetName().c_str(), minorVerName_.c_str());
348 sb.Append(prefix + TAB).Append("return HDF_SUCCESS;\n");
349 sb.Append(prefix).Append("}\n");
350 }
351
EmitKernelServiceImplGetMethod(StringBuilder & sb) const352 void CServiceImplCodeEmitter::EmitKernelServiceImplGetMethod(StringBuilder &sb) const
353 {
354 std::string objName = "service";
355 sb.AppendFormat("struct %s *%sGet(void)\n", implName_.c_str(), implName_.c_str());
356 sb.Append("{\n");
357 sb.Append(TAB).AppendFormat("struct %s *%s = (struct %s *)OsalMemCalloc(sizeof(struct %s));\n",
358 implName_.c_str(), objName.c_str(), implName_.c_str(), implName_.c_str());
359 sb.Append(TAB).AppendFormat("if (%s == NULL) {\n", objName.c_str());
360 sb.Append(TAB).Append(TAB).AppendFormat(
361 "HDF_LOGE(\"%%{public}s: malloc %s obj failed!\", __func__);\n", implName_.c_str());
362 sb.Append(TAB).Append(TAB).Append("return NULL;\n");
363 sb.Append(TAB).Append("}\n\n");
364 sb.Append(TAB).AppendFormat("if (!%sStubConstruct(&%s->stub)) {\n", baseName_.c_str(), objName.c_str());
365 sb.Append(TAB).Append(TAB).AppendFormat(
366 "HDF_LOGE(\"%%{public}s: construct %sStub obj failed!\", __func__);\n", baseName_.c_str());
367 sb.Append(TAB).Append(TAB).AppendFormat("OsalMemFree(%s);\n", objName.c_str());
368 sb.Append(TAB).Append(TAB).Append("return NULL;\n");
369 sb.Append(TAB).Append("}\n\n");
370
371 for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
372 sb.Append(TAB).AppendFormat("%s->stub.interface.%s = %s%s;\n", objName.c_str(), method->GetName().c_str(),
373 baseName_.c_str(), method->GetName().c_str());
374 }
375
376 sb.Append(TAB).AppendFormat("return service;\n", objName.c_str());
377 sb.Append("}\n");
378 }
379
EmitServiceImplGetMethod(StringBuilder & sb) const380 void CServiceImplCodeEmitter::EmitServiceImplGetMethod(StringBuilder &sb) const
381 {
382 std::string objName = "service";
383 if (interface_->IsSerializable()) {
384 sb.AppendFormat("struct %s *%sServiceGet(void)\n", interfaceName_.c_str(), baseName_.c_str());
385 } else {
386 sb.AppendFormat("struct %s *%sImplGetInstance(void)\n", interfaceName_.c_str(), baseName_.c_str());
387 }
388
389 sb.Append("{\n");
390 sb.Append(TAB).AppendFormat("struct %s *%s = (struct %s *)OsalMemCalloc(sizeof(struct %s));\n",
391 implName_.c_str(), objName.c_str(), implName_.c_str(), implName_.c_str());
392 sb.Append(TAB).AppendFormat("if (%s == NULL) {\n", objName.c_str());
393 sb.Append(TAB).Append(TAB).AppendFormat(
394 "HDF_LOGE(\"%%{public}s: malloc %s obj failed!\", __func__);\n", implName_.c_str());
395 sb.Append(TAB).Append(TAB).Append("return NULL;\n");
396 sb.Append(TAB).Append("}\n\n");
397 for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
398 sb.Append(TAB).AppendFormat("%s->interface.%s = %s%s;\n", objName.c_str(), method->GetName().c_str(),
399 baseName_.c_str(), method->GetName().c_str());
400 }
401
402 AutoPtr<ASTMethod> method = interface_->GetVersionMethod();
403 sb.Append(TAB).AppendFormat("%s->interface.%s = %s%s;\n", objName.c_str(), method->GetName().c_str(),
404 baseName_.c_str(), method->GetName().c_str());
405
406 sb.Append(TAB).AppendFormat("return &%s->interface;\n", objName.c_str());
407 sb.Append("}\n");
408 }
409
EmitKernelServiceImplReleaseMethod(StringBuilder & sb) const410 void CServiceImplCodeEmitter::EmitKernelServiceImplReleaseMethod(StringBuilder &sb) const
411 {
412 std::string instName = "instance";
413 sb.AppendFormat(
414 "void %sRelease(struct %s *%s)\n", implName_.c_str(), implName_.c_str(), instName.c_str());
415 sb.Append("{\n");
416 sb.Append(TAB).AppendFormat("if (%s == NULL) {\n", instName.c_str());
417 sb.Append(TAB).Append(TAB).Append("return;\n");
418 sb.Append(TAB).Append("}\n\n");
419 sb.Append(TAB).AppendFormat("OsalMemFree(%s);\n", instName.c_str());
420 sb.Append("}\n");
421 }
422
EmitServiceImplReleaseMethod(StringBuilder & sb) const423 void CServiceImplCodeEmitter::EmitServiceImplReleaseMethod(StringBuilder &sb) const
424 {
425 if (mode_ == GenMode::LOW || mode_ == GenMode::KERNEL) {
426 sb.AppendFormat("void %sRelease(struct %s *instance)\n", implName_.c_str(), implName_.c_str());
427 } else {
428 if (interface_->IsSerializable()) {
429 sb.AppendFormat("void %sServiceRelease(struct %s *instance)\n", baseName_.c_str(), interfaceName_.c_str());
430 } else {
431 sb.AppendFormat("void %sImplRelease(struct %s *instance)\n", baseName_.c_str(), interfaceName_.c_str());
432 }
433 }
434 sb.Append("{\n");
435 sb.Append(TAB).Append("if (instance == NULL) {\n");
436 sb.Append(TAB).Append(TAB).Append("return;\n");
437 sb.Append(TAB).Append("}\n");
438 sb.Append(TAB).Append("OsalMemFree(instance);\n");
439 sb.Append("}\n");
440 }
441 } // namespace Idl
442 } // namespace OHOS