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_stub_code_emitter.h"
10
11 #include "util/file.h"
12 #include "util/logger.h"
13
14 namespace OHOS {
15 namespace HDI {
ResolveDirectory(const std::string & targetDirectory)16 bool CServiceStubCodeEmitter::ResolveDirectory(const std::string &targetDirectory)
17 {
18 if (ast_->GetASTFileType() == ASTFileType::AST_IFACE || ast_->GetASTFileType() == ASTFileType::AST_ICALLBACK) {
19 directory_ = GetFileParentPath(targetDirectory);
20 } else {
21 return false;
22 }
23
24 if (!File::CreateParentDir(directory_)) {
25 Logger::E("CServiceStubCodeEmitter", "Create '%s' failed!", directory_.c_str());
26 return false;
27 }
28
29 return true;
30 }
31
EmitCode()32 void CServiceStubCodeEmitter::EmitCode()
33 {
34 switch (mode_) {
35 case GenMode::IPC:
36 case GenMode::KERNEL: {
37 EmitServiceStubHeaderFile();
38 EmitServiceStubSourceFile();
39 break;
40 }
41 default:
42 break;
43 }
44 }
45
EmitServiceStubHeaderFile()46 void CServiceStubCodeEmitter::EmitServiceStubHeaderFile()
47 {
48 std::string filePath =
49 File::AdapterPath(StringHelper::Format("%s/%s.h", directory_.c_str(), FileName(stubName_).c_str()));
50 File file(filePath, File::WRITE);
51 StringBuilder sb;
52
53 EmitLicense(sb);
54 EmitHeadMacro(sb, stubFullName_);
55 sb.Append("\n");
56 EmitStubHeaderInclusions(sb);
57 sb.Append("\n");
58 EmitHeadExternC(sb);
59 sb.Append("\n");
60 EmitCbServiceStubDef(sb);
61 if (mode_ == GenMode::KERNEL) {
62 sb.Append("\n");
63 EmitCbServiceStubMethodsDcl(sb);
64 }
65 sb.Append("\n");
66 EmitTailExternC(sb);
67 sb.Append("\n");
68 EmitTailMacro(sb, stubFullName_);
69
70 std::string data = sb.ToString();
71 file.WriteData(data.c_str(), data.size());
72 file.Flush();
73 file.Close();
74 }
75
EmitStubHeaderInclusions(StringBuilder & sb)76 void CServiceStubCodeEmitter::EmitStubHeaderInclusions(StringBuilder &sb)
77 {
78 HeaderFile::HeaderFileSet headerFiles;
79
80 headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE, EmitVersionHeaderName(interfaceName_));
81 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_sbuf");
82
83 if (mode_ != GenMode::KERNEL) {
84 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_remote_service");
85 }
86
87 for (const auto &file : headerFiles) {
88 sb.AppendFormat("%s\n", file.ToString().c_str());
89 }
90 }
91
EmitCbServiceStubDef(StringBuilder & sb) const92 void CServiceStubCodeEmitter::EmitCbServiceStubDef(StringBuilder &sb) const
93 {
94 sb.AppendFormat("struct %sStub {\n", baseName_.c_str());
95 if (mode_ == GenMode::KERNEL) {
96 sb.Append(TAB).AppendFormat("struct %s interface;\n", interfaceName_.c_str());
97 sb.Append(TAB).AppendFormat("int32_t (*OnRemoteRequest)(struct %s *serviceImpl, ", interfaceName_.c_str());
98 sb.Append("int code, struct HdfSBuf *data, struct HdfSBuf *reply);\n");
99 } else {
100 sb.Append(TAB).Append("struct HdfRemoteService *remote;\n");
101 sb.Append(TAB).AppendFormat("struct %s *interface;\n", interfaceName_.c_str());
102 sb.Append(TAB).Append("struct HdfRemoteDispatcher dispatcher;\n");
103 }
104 sb.Append("};\n");
105 }
106
EmitCbServiceStubMethodsDcl(StringBuilder & sb) const107 void CServiceStubCodeEmitter::EmitCbServiceStubMethodsDcl(StringBuilder &sb) const
108 {
109 sb.AppendFormat("bool %sStubConstruct(struct %sStub *stub);\n", baseName_.c_str(), baseName_.c_str());
110 }
111
EmitServiceStubSourceFile()112 void CServiceStubCodeEmitter::EmitServiceStubSourceFile()
113 {
114 std::string filePath =
115 File::AdapterPath(StringHelper::Format("%s/%s.c", directory_.c_str(), FileName(stubName_).c_str()));
116 File file(filePath, File::WRITE);
117 StringBuilder sb;
118
119 EmitLicense(sb);
120 EmitStubSourceInclusions(sb);
121 sb.Append("\n");
122 EmitLogTagMacro(sb, FileName(stubName_));
123 if (mode_ != GenMode::KERNEL && !interface_->IsSerializable()) {
124 sb.Append("\n");
125 EmitExternalMethodImpl(sb);
126 }
127 sb.Append("\n");
128 UtilMethodMap utilMethods;
129 GetUtilMethods(utilMethods);
130 EmitUtilMethods(sb, "", utilMethods, true);
131 sb.Append("\n");
132 EmitUtilMethods(sb, "", utilMethods, false);
133 EmitServiceStubMethodImpls(sb, "");
134
135 if (mode_ == GenMode::KERNEL) {
136 sb.Append("\n");
137 EmitKernelStubOnRequestMethodImpl(sb, "");
138 sb.Append("\n");
139 EmitKernelStubConstruct(sb);
140 } else {
141 sb.Append("\n");
142 EmitStubOnRequestMethodImpl(sb, "");
143 if (!interface_->IsSerializable()) {
144 sb.Append("\n");
145 EmitStubRemoteDispatcher(sb);
146 }
147
148 sb.Append("\n");
149 EmitStubNewInstance(sb);
150 sb.Append("\n");
151 EmitStubReleaseMethod(sb);
152 sb.Append("\n");
153 EmitStubConstructor(sb);
154 sb.Append("\n");
155 EmitStubRegAndUnreg(sb);
156 }
157
158 std::string data = sb.ToString();
159 file.WriteData(data.c_str(), data.size());
160 file.Flush();
161 file.Close();
162 }
163
EmitStubSourceInclusions(StringBuilder & sb)164 void CServiceStubCodeEmitter::EmitStubSourceInclusions(StringBuilder &sb)
165 {
166 HeaderFile::HeaderFileSet headerFiles;
167
168 headerFiles.emplace(HeaderFileType::OWN_HEADER_FILE, EmitVersionHeaderName(stubName_));
169 GetSourceOtherLibInclusions(headerFiles);
170
171 for (const auto &file : headerFiles) {
172 sb.AppendFormat("%s\n", file.ToString().c_str());
173 }
174 }
175
GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet & headerFiles) const176 void CServiceStubCodeEmitter::GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles) const
177 {
178 if (mode_ != GenMode::KERNEL) {
179 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "securec");
180 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_dlist");
181 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "stub_collector");
182
183 if (!interface_->IsSerializable()) {
184 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdi_support");
185 }
186 } else {
187 const AST::TypeStringMap &types = ast_->GetTypes();
188 for (const auto &pair : types) {
189 AutoPtr<ASTType> type = pair.second;
190 if (type->GetTypeKind() == TypeKind::TYPE_STRING || type->GetTypeKind() == TypeKind::TYPE_UNION) {
191 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "securec");
192 break;
193 }
194 }
195 }
196
197 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_base");
198 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_core_log");
199 headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "osal_mem");
200 }
201
EmitExternalMethodImpl(StringBuilder & sb)202 void CServiceStubCodeEmitter::EmitExternalMethodImpl(StringBuilder &sb)
203 {
204 EmitGetMethodImpl(sb);
205 sb.Append("\n");
206 EmitGetInstanceMehtodImpl(sb);
207 sb.Append("\n");
208 EmitReleaseMethodImpl(sb);
209 sb.Append("\n");
210 EmitReleaseInstanceMethodImpl(sb);
211 }
212
EmitGetMethodImpl(StringBuilder & sb) const213 void CServiceStubCodeEmitter::EmitGetMethodImpl(StringBuilder &sb) const
214 {
215 sb.AppendFormat("struct %s *%sGet(bool isStub)\n", interfaceName_.c_str(), interfaceName_.c_str());
216 sb.Append("{\n");
217 sb.Append(TAB).AppendFormat(
218 "return %sGetInstance(\"%s\", isStub);\n", interfaceName_.c_str(), FileName(implName_).c_str());
219 sb.Append("}\n");
220 }
221
EmitGetInstanceMehtodImpl(StringBuilder & sb) const222 void CServiceStubCodeEmitter::EmitGetInstanceMehtodImpl(StringBuilder &sb) const
223 {
224 sb.AppendFormat("struct %s *%sGetInstance(const char *serviceName, bool isStub)\n", interfaceName_.c_str(),
225 interfaceName_.c_str());
226 sb.Append("{\n");
227 sb.Append(TAB).Append("if (!isStub) {\n");
228 sb.Append(TAB).Append(TAB).Append("return NULL;\n");
229 sb.Append(TAB).Append("}\n\n");
230 sb.Append(TAB).AppendFormat("const char *instName = serviceName;\n");
231 sb.Append(TAB).AppendFormat("if (strcmp(serviceName, \"%s\") == 0) {\n", FileName(implName_).c_str());
232 sb.Append(TAB).Append(TAB).Append("instName = \"service\";\n");
233 sb.Append(TAB).Append("}\n");
234 sb.Append(TAB).AppendFormat("return (struct %s *)LoadHdiImpl(%s, instName);\n",
235 interfaceName_.c_str(), interface_->EmitDescMacroName().c_str());
236 sb.Append("}\n");
237 }
238
EmitReleaseMethodImpl(StringBuilder & sb) const239 void CServiceStubCodeEmitter::EmitReleaseMethodImpl(StringBuilder &sb) const
240 {
241 sb.AppendFormat(
242 "void %sRelease(struct %s *instance, bool isStub)\n", interfaceName_.c_str(), interfaceName_.c_str());
243 sb.Append("{\n");
244 sb.Append(TAB).AppendFormat(
245 "%sReleaseInstance(\"%s\", instance, isStub);\n", interfaceName_.c_str(), FileName(implName_).c_str());
246 sb.Append("}\n");
247 }
248
EmitReleaseInstanceMethodImpl(StringBuilder & sb) const249 void CServiceStubCodeEmitter::EmitReleaseInstanceMethodImpl(StringBuilder &sb) const
250 {
251 sb.AppendFormat("void %sReleaseInstance(const char *serviceName, struct %s *instance, bool isStub)\n",
252 interfaceName_.c_str(), interfaceName_.c_str());
253 sb.Append("{\n");
254 sb.Append(TAB).Append("if (serviceName == NULL || !isStub || instance == NULL) {\n");
255 sb.Append(TAB).Append(TAB).Append("return;\n");
256 sb.Append(TAB).Append("}\n");
257 sb.Append(TAB).Append("const char *instName = serviceName;\n");
258 sb.Append(TAB).AppendFormat("if (strcmp(serviceName, \"%s\") == 0) {\n", FileName(implName_).c_str());
259 sb.Append(TAB).Append(TAB).Append("instName = \"service\";\n");
260 sb.Append(TAB).Append("}\n");
261 sb.Append(TAB).AppendFormat("UnloadHdiImpl(%s, instName, instance);\n", interface_->EmitDescMacroName().c_str());
262 sb.Append("}\n");
263 }
264
EmitServiceStubMethodImpls(StringBuilder & sb,const std::string & prefix)265 void CServiceStubCodeEmitter::EmitServiceStubMethodImpls(StringBuilder &sb, const std::string &prefix)
266 {
267 for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
268 EmitServiceStubMethodImpl(method, sb, prefix);
269 sb.Append("\n");
270 }
271
272 EmitStubGetVerMethodImpl(interface_->GetVersionMethod(), sb, prefix);
273 if (mode_ != GenMode::KERNEL) {
274 sb.Append("\n");
275 EmitStubAsObjectMethodImpl(sb, prefix);
276 }
277 }
278
EmitServiceStubMethodImpl(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix) const279 void CServiceStubCodeEmitter::EmitServiceStubMethodImpl(
280 const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const
281 {
282 sb.Append(prefix).AppendFormat(
283 "static int32_t SerStub%s(struct %s *serviceImpl, struct HdfSBuf *%s, struct HdfSBuf *%s)\n",
284 method->GetName().c_str(), interfaceName_.c_str(), dataParcelName_.c_str(), replyParcelName_.c_str());
285 sb.Append(prefix).Append("{\n");
286 sb.Append(prefix + TAB).AppendFormat("int32_t %s = HDF_FAILURE;\n", errorCodeName_.c_str());
287 bool readFlag = NeedFlag(method);
288 if (readFlag) {
289 sb.Append(prefix + TAB).AppendFormat("bool %s = false;\n", flagOfSetMemName_.c_str());
290 }
291
292 // Local variable definitions must precede all execution statements.
293 EmitMethodNeedLoopVar(method, true, true, sb, prefix + TAB);
294
295 if (method->GetParameterNumber() > 0) {
296 for (size_t i = 0; i < method->GetParameterNumber(); i++) {
297 AutoPtr<ASTParameter> param = method->GetParameter(i);
298 EmitStubLocalVariable(param, sb, prefix + TAB);
299 }
300
301 sb.Append("\n");
302 EmitReadFlagVariable(readFlag, sb, prefix + TAB);
303 for (size_t i = 0; i < method->GetParameterNumber(); i++) {
304 AutoPtr<ASTParameter> param = method->GetParameter(i);
305 if (param->GetAttribute() == ParamAttr::PARAM_IN) {
306 EmitReadStubMethodParameter(param, dataParcelName_, finishedLabelName_, sb, prefix + TAB);
307 sb.Append("\n");
308 } else {
309 EmitOutVarMemInitialize(param, dataParcelName_, finishedLabelName_, sb, prefix + TAB);
310 }
311 }
312 }
313
314 EmitStubCallMethod(method, finishedLabelName_, sb, prefix + TAB);
315 sb.Append("\n");
316
317 for (size_t i = 0; i < method->GetParameterNumber(); i++) {
318 AutoPtr<ASTParameter> param = method->GetParameter(i);
319 if (param->GetAttribute() == ParamAttr::PARAM_OUT) {
320 param->EmitCWriteVar(replyParcelName_, errorCodeName_, finishedLabelName_, sb, prefix + TAB);
321 sb.Append("\n");
322 }
323 }
324
325 EmitErrorHandle(method, finishedLabelName_, false, sb, prefix);
326 sb.Append(prefix + TAB).AppendFormat("return %s;\n", errorCodeName_.c_str());
327 sb.Append(prefix).Append("}\n");
328 }
329
EmitReadFlagVariable(bool readFlag,StringBuilder & sb,const std::string & prefix) const330 void CServiceStubCodeEmitter::EmitReadFlagVariable(bool readFlag, StringBuilder &sb, const std::string &prefix) const
331 {
332 if (!readFlag) {
333 return;
334 }
335
336 sb.Append(prefix).AppendFormat(
337 "if (!HdfSbufReadUint8(%s, (uint8_t *)&%s)) {\n", dataParcelName_.c_str(), flagOfSetMemName_.c_str());
338 sb.Append(prefix + TAB).Append("HDF_LOGE(\"%{public}s: read flag of memory setting failed!\", __func__);\n");
339 sb.Append(prefix + TAB).AppendFormat("%s = HDF_ERR_INVALID_PARAM;\n", errorCodeName_.c_str());
340 sb.Append(prefix + TAB).AppendFormat("goto %s;\n", finishedLabelName_);
341 sb.Append(prefix).Append("}\n\n");
342 }
343
EmitStubLocalVariable(const AutoPtr<ASTParameter> & param,StringBuilder & sb,const std::string & prefix) const344 void CServiceStubCodeEmitter::EmitStubLocalVariable(
345 const AutoPtr<ASTParameter> ¶m, StringBuilder &sb, const std::string &prefix) const
346 {
347 AutoPtr<ASTType> type = param->GetType();
348 sb.Append(prefix).Append(param->EmitCLocalVar()).Append("\n");
349 if (type->GetTypeKind() == TypeKind::TYPE_ARRAY || type->GetTypeKind() == TypeKind::TYPE_LIST ||
350 (type->GetTypeKind() == TypeKind::TYPE_STRING && param->GetAttribute() == ParamAttr::PARAM_OUT)) {
351 sb.Append(prefix).AppendFormat("uint32_t %sLen = 0;\n", param->GetName().c_str());
352 }
353 }
354
EmitReadStubMethodParameter(const AutoPtr<ASTParameter> & param,const std::string & parcelName,const std::string & gotoLabel,StringBuilder & sb,const std::string & prefix) const355 void CServiceStubCodeEmitter::EmitReadStubMethodParameter(const AutoPtr<ASTParameter> ¶m,
356 const std::string &parcelName, const std::string &gotoLabel, StringBuilder &sb, const std::string &prefix) const
357 {
358 AutoPtr<ASTType> type = param->GetType();
359
360 if (type->GetTypeKind() == TypeKind::TYPE_STRING) {
361 EmitReadCStringStubMethodParameter(param, parcelName, gotoLabel, sb, prefix, type);
362 } else if (type->GetTypeKind() == TypeKind::TYPE_STRUCT) {
363 sb.Append(prefix).AppendFormat("%s = (%s*)OsalMemCalloc(sizeof(%s));\n", param->GetName().c_str(),
364 type->EmitCType(TypeMode::NO_MODE).c_str(), type->EmitCType(TypeMode::NO_MODE).c_str());
365 sb.Append(prefix).AppendFormat("if (%s == NULL) {\n", param->GetName().c_str());
366 sb.Append(prefix + TAB)
367 .AppendFormat("HDF_LOGE(\"%%{public}s: malloc %s failed\", __func__);\n", param->GetName().c_str());
368 sb.Append(prefix + TAB).AppendFormat("%s = HDF_ERR_MALLOC_FAIL;\n", errorCodeName_.c_str());
369 sb.Append(prefix + TAB).AppendFormat("goto %s;\n", finishedLabelName_);
370 sb.Append(prefix).Append("}\n");
371 type->EmitCStubReadVar(parcelName, param->GetName(), errorCodeName_, gotoLabel, sb, prefix);
372 } else if (type->GetTypeKind() == TypeKind::TYPE_UNION) {
373 std::string cpName = StringHelper::Format("%sCp", param->GetName().c_str());
374 type->EmitCStubReadVar(parcelName, cpName, errorCodeName_, gotoLabel, sb, prefix);
375 sb.Append(prefix).AppendFormat("%s = (%s*)OsalMemCalloc(sizeof(%s));\n", param->GetName().c_str(),
376 type->EmitCType(TypeMode::NO_MODE).c_str(), type->EmitCType(TypeMode::NO_MODE).c_str());
377 sb.Append(prefix).AppendFormat("if (%s == NULL) {\n", param->GetName().c_str());
378 sb.Append(prefix + TAB)
379 .AppendFormat("HDF_LOGE(\"%%{public}s: malloc %s failed\", __func__);\n", param->GetName().c_str());
380 sb.Append(prefix + TAB).AppendFormat("%s = HDF_ERR_MALLOC_FAIL;\n", errorCodeName_.c_str());
381 sb.Append(prefix + TAB).AppendFormat("goto %s;\n", finishedLabelName_);
382 sb.Append(prefix).Append("}\n");
383 sb.Append(prefix).AppendFormat("if (memcpy_s(%s, sizeof(%s), %s, sizeof(%s)) != EOK) {\n",
384 param->GetName().c_str(), type->EmitCType(TypeMode::NO_MODE).c_str(), cpName.c_str(),
385 type->EmitCType(TypeMode::NO_MODE).c_str());
386 sb.Append(prefix + TAB).AppendFormat("HDF_LOGE(\"%%{public}s: failed to memcpy %s\", __func__);\n",
387 param->GetName().c_str());
388 sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n");
389 sb.Append(prefix).Append("}\n");
390 } else if (type->GetTypeKind() == TypeKind::TYPE_ARRAY || type->GetTypeKind() == TypeKind::TYPE_LIST ||
391 type->GetTypeKind() == TypeKind::TYPE_FILEDESCRIPTOR ||
392 type->GetTypeKind() == TypeKind::TYPE_NATIVE_BUFFER || type->GetTypeKind() == TypeKind::TYPE_ENUM ||
393 type->GetTypeKind() == TypeKind::TYPE_INTERFACE) {
394 type->EmitCStubReadVar(parcelName, param->GetName(), errorCodeName_, gotoLabel, sb, prefix);
395 } else {
396 std::string name = StringHelper::Format("&%s", param->GetName().c_str());
397 type->EmitCStubReadVar(parcelName, name, errorCodeName_, gotoLabel, sb, prefix);
398 }
399 }
400
EmitReadCStringStubMethodParameter(const AutoPtr<ASTParameter> & param,const std::string & parcelName,const std::string & gotoLabel,StringBuilder & sb,const std::string & prefix,AutoPtr<ASTType> & type) const401 void CServiceStubCodeEmitter::EmitReadCStringStubMethodParameter(const AutoPtr<ASTParameter> ¶m,
402 const std::string &parcelName, const std::string &gotoLabel, StringBuilder &sb, const std::string &prefix,
403 AutoPtr<ASTType> &type) const
404 {
405 std::string cloneName = StringHelper::Format("%sCp", param->GetName().c_str());
406 type->EmitCStubReadVar(parcelName, cloneName, errorCodeName_, gotoLabel, sb, prefix);
407 if (mode_ == GenMode::KERNEL) {
408 sb.Append("\n");
409 sb.Append(prefix).AppendFormat(
410 "%s = (char*)OsalMemCalloc(strlen(%s) + 1);\n", param->GetName().c_str(), cloneName.c_str());
411 sb.Append(prefix).AppendFormat("if (%s == NULL) {\n", param->GetName().c_str());
412 sb.Append(prefix + TAB).AppendFormat("%s = HDF_ERR_MALLOC_FAIL;\n", errorCodeName_.c_str());
413 sb.Append(prefix + TAB)
414 .AppendFormat("HDF_LOGE(\"%%{public}s: malloc %s failed\", __func__);\n", param->GetName().c_str());
415 sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.c_str());
416 sb.Append(prefix).Append("}\n\n");
417 sb.Append(prefix).AppendFormat("if (strcpy_s(%s, (strlen(%s) + 1), %s) != HDF_SUCCESS) {\n",
418 param->GetName().c_str(), cloneName.c_str(), cloneName.c_str());
419 sb.Append(prefix + TAB)
420 .AppendFormat("HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", param->GetName().c_str());
421 sb.Append(prefix + TAB).AppendFormat("%s = HDF_ERR_INVALID_PARAM;\n", errorCodeName_.c_str());
422 sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.c_str());
423 sb.Append(prefix).Append("}\n");
424 } else {
425 sb.Append(prefix).AppendFormat("%s = strdup(%s);\n", param->GetName().c_str(), cloneName.c_str());
426 }
427 }
428
EmitOutVarMemInitialize(const AutoPtr<ASTParameter> & param,const std::string & parcelName,const std::string & gotoLabel,StringBuilder & sb,const std::string & prefix) const429 void CServiceStubCodeEmitter::EmitOutVarMemInitialize(const AutoPtr<ASTParameter> ¶m, const std::string &parcelName,
430 const std::string &gotoLabel, StringBuilder &sb, const std::string &prefix) const
431 {
432 AutoPtr<ASTType> type = param->GetType();
433 if (type->IsStructType() || type->IsUnionType()) {
434 sb.Append(prefix).AppendFormat("%s = (%s*)OsalMemCalloc(sizeof(%s));\n", param->GetName().c_str(),
435 type->EmitCType(TypeMode::NO_MODE).c_str(), type->EmitCType(TypeMode::NO_MODE).c_str());
436 sb.Append(prefix).AppendFormat("if (%s == NULL) {\n", param->GetName().c_str());
437 sb.Append(prefix + TAB)
438 .AppendFormat("HDF_LOGE(\"%%{public}s: malloc %s failed\", __func__);\n", param->GetName().c_str());
439 sb.Append(prefix + TAB).AppendFormat("%s = HDF_ERR_MALLOC_FAIL;\n", errorCodeName_.c_str());
440 sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.c_str());
441 sb.Append(prefix).Append("}\n\n");
442 } else if (type->IsStringType() || type->IsArrayType() || type->IsListType()) {
443 param->EmitCStubReadOutVar(
444 MAX_BUFF_SIZE_MACRO, flagOfSetMemName_, parcelName, errorCodeName_, gotoLabel, sb, prefix);
445 sb.Append("\n");
446 }
447 }
448
EmitStubCallMethod(const AutoPtr<ASTMethod> & method,const std::string & gotoLabel,StringBuilder & sb,const std::string & prefix) const449 void CServiceStubCodeEmitter::EmitStubCallMethod(
450 const AutoPtr<ASTMethod> &method, const std::string &gotoLabel, StringBuilder &sb, const std::string &prefix) const
451 {
452 sb.Append(prefix).Append("if (serviceImpl == NULL) {\n");
453 sb.Append(prefix + TAB).Append("HDF_LOGE(\"%{public}s: invalid serviceImpl object\", __func__);\n");
454 sb.Append(prefix + TAB).AppendFormat("%s = HDF_ERR_INVALID_OBJECT;\n", errorCodeName_.c_str());
455 sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.c_str());
456 sb.Append(prefix).Append("}\n\n");
457
458 sb.Append(prefix).AppendFormat("if (serviceImpl->%s == NULL) {\n", method->GetName().c_str());
459 sb.Append(prefix + TAB).AppendFormat("HDF_LOGE(\"%%{public}s: invalid interface function %s \", __func__);\n",
460 method->GetName().c_str());
461 sb.Append(prefix + TAB).AppendFormat("%s = HDF_ERR_NOT_SUPPORT;\n", errorCodeName_.c_str());
462 sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.c_str());
463 sb.Append(prefix).Append("}\n\n");
464
465 if (method->GetParameterNumber() == 0) {
466 sb.Append(prefix).AppendFormat(
467 "%s = serviceImpl->%s(serviceImpl);\n", errorCodeName_.c_str(), method->GetName().c_str());
468 } else {
469 sb.Append(prefix).AppendFormat(
470 "%s = serviceImpl->%s(serviceImpl, ", errorCodeName_.c_str(), method->GetName().c_str());
471 for (size_t i = 0; i < method->GetParameterNumber(); i++) {
472 AutoPtr<ASTParameter> param = method->GetParameter(i);
473 EmitCallParameter(sb, param->GetType(), param->GetAttribute(), param->GetName());
474 if (i + 1 < method->GetParameterNumber()) {
475 sb.Append(", ");
476 }
477 }
478 sb.AppendFormat(");\n", method->GetName().c_str());
479 }
480
481 sb.Append(prefix).AppendFormat("if (%s != HDF_SUCCESS) {\n", errorCodeName_.c_str());
482 sb.Append(prefix + TAB)
483 .AppendFormat("HDF_LOGE(\"%%{public}s failed, error code is %%{public}d\", __func__, %s);\n",
484 errorCodeName_.c_str());
485 sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.c_str());
486 sb.Append(prefix).Append("}\n");
487 }
488
EmitCallParameter(StringBuilder & sb,const AutoPtr<ASTType> & type,ParamAttr attribute,const std::string & name) const489 void CServiceStubCodeEmitter::EmitCallParameter(
490 StringBuilder &sb, const AutoPtr<ASTType> &type, ParamAttr attribute, const std::string &name) const
491 {
492 if (attribute == ParamAttr::PARAM_OUT) {
493 if (type->GetTypeKind() == TypeKind::TYPE_STRING || type->GetTypeKind() == TypeKind::TYPE_ARRAY ||
494 type->GetTypeKind() == TypeKind::TYPE_LIST || type->GetTypeKind() == TypeKind::TYPE_STRUCT ||
495 type->GetTypeKind() == TypeKind::TYPE_UNION) {
496 sb.AppendFormat("%s", name.c_str());
497 } else {
498 sb.AppendFormat("&%s", name.c_str());
499 }
500
501 if (type->GetTypeKind() == TypeKind::TYPE_STRING) {
502 sb.AppendFormat(", %sLen", name.c_str());
503 } else if (type->GetTypeKind() == TypeKind::TYPE_ARRAY || type->GetTypeKind() == TypeKind::TYPE_LIST) {
504 sb.AppendFormat(", &%sLen", name.c_str());
505 }
506 } else {
507 sb.AppendFormat("%s", name.c_str());
508 if (type->GetTypeKind() == TypeKind::TYPE_ARRAY || type->GetTypeKind() == TypeKind::TYPE_LIST) {
509 sb.AppendFormat(", %sLen", name.c_str());
510 }
511 }
512 }
513
EmitStubGetVerMethodImpl(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix) const514 void CServiceStubCodeEmitter::EmitStubGetVerMethodImpl(
515 const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const
516 {
517 sb.Append(prefix).AppendFormat(
518 "static int32_t SerStub%s(struct %s *serviceImpl, struct HdfSBuf *%s, struct HdfSBuf *%s)\n",
519 method->GetName().c_str(), interfaceName_.c_str(), dataParcelName_.c_str(), replyParcelName_.c_str());
520 sb.Append(prefix).Append("{\n");
521 sb.Append(prefix + TAB).AppendFormat("int32_t %s = HDF_SUCCESS;\n", errorCodeName_.c_str());
522
523 AutoPtr<ASTType> type = new ASTUintType();
524 type->EmitCWriteVar(replyParcelName_, majorVerName_, errorCodeName_, finishedLabelName_, sb, prefix + TAB);
525 sb.Append("\n");
526 type->EmitCWriteVar(replyParcelName_, minorVerName_, errorCodeName_, finishedLabelName_, sb, prefix + TAB);
527 sb.Append("\n");
528
529 sb.Append(finishedLabelName_).Append(":\n");
530 sb.Append(prefix + TAB).AppendFormat("return %s;\n", errorCodeName_.c_str());
531 sb.Append(prefix).Append("}\n");
532 }
533
EmitStubAsObjectMethodImpl(StringBuilder & sb,const std::string & prefix) const534 void CServiceStubCodeEmitter::EmitStubAsObjectMethodImpl(StringBuilder &sb, const std::string &prefix) const
535 {
536 std::string objName = "self";
537 sb.Append(prefix).AppendFormat("static struct HdfRemoteService *%sStubAsObject(struct %s *%s)\n", baseName_.c_str(),
538 interfaceName_.c_str(), objName.c_str());
539 sb.Append(prefix).Append("{\n");
540
541 if (interface_->IsSerializable()) {
542 sb.Append(prefix + TAB).AppendFormat("if (%s == NULL) {\n", objName.c_str());
543 sb.Append(prefix + TAB + TAB).Append("return NULL;\n");
544 sb.Append(prefix + TAB).Append("}\n");
545 sb.Append(prefix + TAB).AppendFormat(
546 "struct %sStub *stub = CONTAINER_OF(%s, struct %sStub, interface);\n", baseName_.c_str(),
547 objName.c_str(), baseName_.c_str());
548 sb.Append(prefix + TAB).Append("return stub->remote;\n");
549 } else {
550 sb.Append(prefix + TAB).Append("return NULL;\n");
551 }
552
553 sb.Append(prefix).Append("}\n");
554 }
555
EmitKernelStubOnRequestMethodImpl(StringBuilder & sb,const std::string & prefix)556 void CServiceStubCodeEmitter::EmitKernelStubOnRequestMethodImpl(StringBuilder &sb, const std::string &prefix)
557 {
558 std::string implName = "serviceImpl";
559 std::string codeName = "code";
560 std::string funcName = StringHelper::Format("%sOnRemoteRequest", baseName_.c_str());
561 sb.Append(prefix).AppendFormat("static int32_t %s(struct %s *%s, ", funcName.c_str(), interfaceName_.c_str(),
562 implName.c_str());
563 sb.AppendFormat("int %s, struct HdfSBuf *data, struct HdfSBuf *reply)\n", codeName.c_str());
564 sb.Append(prefix).Append("{\n");
565 sb.Append(prefix + TAB).AppendFormat("switch (%s) {\n", codeName.c_str());
566 for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
567 sb.Append(prefix + TAB + TAB).AppendFormat("case %s:\n", EmitMethodCmdID(method).c_str());
568 sb.Append(prefix + TAB + TAB + TAB)
569 .AppendFormat("return SerStub%s(%s, data, reply);\n", method->GetName().c_str(), implName.c_str());
570 }
571
572 AutoPtr<ASTMethod> getVerMethod = interface_->GetVersionMethod();
573 sb.Append(prefix + TAB + TAB).AppendFormat("case %s:\n", EmitMethodCmdID(getVerMethod).c_str());
574 sb.Append(prefix + TAB + TAB + TAB)
575 .AppendFormat("return SerStub%s(%s, data, reply);\n", getVerMethod->GetName().c_str(), implName.c_str());
576
577 sb.Append(prefix + TAB + TAB).Append("default: {\n");
578 sb.Append(prefix + TAB + TAB + TAB)
579 .AppendFormat("HDF_LOGE(\"%%{public}s: not support cmd %%{public}d\", __func__, %s);\n", codeName.c_str());
580 sb.Append(prefix + TAB + TAB + TAB).Append("return HDF_ERR_INVALID_PARAM;\n");
581 sb.Append(prefix + TAB + TAB).Append("}\n");
582 sb.Append(prefix + TAB).Append("}\n");
583 sb.Append("}\n");
584 }
585
EmitKernelStubConstruct(StringBuilder & sb) const586 void CServiceStubCodeEmitter::EmitKernelStubConstruct(StringBuilder &sb) const
587 {
588 std::string stubTypeName = StringHelper::Format("%sStub", baseName_.c_str());
589 std::string objName = "stub";
590 std::string funcName = StringHelper::Format("%sOnRemoteRequest", baseName_.c_str());
591
592 sb.AppendFormat(
593 "bool %sConstruct(struct %s *%s)\n", stubTypeName.c_str(), stubTypeName.c_str(), objName.c_str());
594 sb.Append("{\n");
595 sb.Append(TAB).AppendFormat("if (%s == NULL) {\n", objName.c_str());
596 sb.Append(TAB).Append(TAB).Append("HDF_LOGE(\"%{public}s: stub is null!\", __func__);\n");
597 sb.Append(TAB).Append(TAB).Append("return false;\n");
598 sb.Append(TAB).Append("}\n\n");
599 sb.Append(TAB).AppendFormat("%s->OnRemoteRequest = %s;\n", objName.c_str(), funcName.c_str());
600 sb.Append(TAB).Append("return true;\n");
601 sb.Append("}\n");
602 }
603
EmitStubOnRequestMethodImpl(StringBuilder & sb,const std::string & prefix)604 void CServiceStubCodeEmitter::EmitStubOnRequestMethodImpl(StringBuilder &sb, const std::string &prefix)
605 {
606 std::string remoteName = "remote";
607 std::string codeName = "code";
608 std::string funcName = StringHelper::Format("%sOnRemoteRequest", baseName_.c_str());
609 sb.Append(prefix).AppendFormat("static int32_t %s(struct HdfRemoteService *%s, ", funcName.c_str(),
610 remoteName.c_str());
611 sb.AppendFormat("int %s, struct HdfSBuf *data, struct HdfSBuf *reply)\n", codeName.c_str());
612 sb.Append(prefix).Append("{\n");
613
614 sb.Append(prefix + TAB).AppendFormat("struct %s *stub = (struct %s*)%s;\n", stubName_.c_str(),
615 stubName_.c_str(), remoteName.c_str());
616 sb.Append(prefix + TAB).Append("if (stub == NULL || stub->remote == NULL || stub->interface == NULL) {\n");
617 sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"%{public}s: invalid stub object\", __func__);\n");
618 sb.Append(prefix + TAB + TAB).Append("return HDF_ERR_INVALID_OBJECT;\n");
619 sb.Append(prefix + TAB).Append("}\n");
620
621 sb.Append(prefix + TAB).AppendFormat("if (!HdfRemoteServiceCheckInterfaceToken(stub->%s, data)) {\n",
622 remoteName.c_str());
623 sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"%{public}s: interface token check failed\", __func__);\n");
624 sb.Append(prefix + TAB + TAB).Append("return HDF_ERR_INVALID_PARAM;\n");
625 sb.Append(prefix + TAB).Append("}\n\n");
626
627 sb.Append(prefix + TAB).AppendFormat("switch (%s) {\n", codeName.c_str());
628 for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
629 sb.Append(prefix + TAB + TAB).AppendFormat("case %s:\n", EmitMethodCmdID(method).c_str());
630 sb.Append(prefix + TAB + TAB + TAB)
631 .AppendFormat("return SerStub%s(stub->interface, data, reply);\n", method->GetName().c_str());
632 }
633
634 AutoPtr<ASTMethod> getVerMethod = interface_->GetVersionMethod();
635 sb.Append(prefix + TAB + TAB).AppendFormat("case %s:\n", EmitMethodCmdID(getVerMethod).c_str());
636 sb.Append(prefix + TAB + TAB + TAB)
637 .AppendFormat("return SerStub%s(stub->interface, data, reply);\n", getVerMethod->GetName().c_str());
638
639 sb.Append(prefix + TAB + TAB).Append("default: {\n");
640 sb.Append(prefix + TAB + TAB + TAB)
641 .AppendFormat("HDF_LOGE(\"%%{public}s: not support cmd %%{public}d\", __func__, %s);\n", codeName.c_str());
642 sb.Append(prefix + TAB + TAB + TAB).Append("return HDF_ERR_INVALID_PARAM;\n");
643 sb.Append(prefix + TAB + TAB).Append("}\n");
644 sb.Append(prefix + TAB).Append("}\n");
645 sb.Append("}\n");
646 }
647
EmitStubRemoteDispatcher(StringBuilder & sb) const648 void CServiceStubCodeEmitter::EmitStubRemoteDispatcher(StringBuilder &sb) const
649 {
650 std::string dispatcherName = StringHelper::Format("g_%sDispatcher", StringHelper::StrToLower(baseName_).c_str());
651 sb.AppendFormat("static struct HdfRemoteDispatcher %s = {\n", dispatcherName.c_str());
652 sb.Append(TAB).AppendFormat(".Dispatch = %sOnRemoteRequest,\n", baseName_.c_str());
653 sb.Append(TAB).Append(".DispatchAsync = NULL,\n");
654 sb.Append("};\n");
655 }
656
EmitStubNewInstance(StringBuilder & sb) const657 void CServiceStubCodeEmitter::EmitStubNewInstance(StringBuilder &sb) const
658 {
659 std::string dispatcherName = StringHelper::Format("g_%sDispatcher", StringHelper::StrToLower(baseName_).c_str());
660 sb.AppendFormat("static struct HdfRemoteService **%sNewInstance(void *impl)\n", stubName_.c_str());
661 sb.Append("{\n");
662 sb.Append(TAB).Append("if (impl == NULL) {\n");
663 sb.Append(TAB).Append(TAB).Append("HDF_LOGE(\"%{public}s: impl is null\", __func__);\n");
664 sb.Append(TAB).Append(TAB).Append("return NULL;\n");
665 sb.Append(TAB).Append("}\n\n");
666
667 sb.Append(TAB).AppendFormat("struct %s *serviceImpl = (struct %s *)impl;\n", interfaceName_.c_str(),
668 interfaceName_.c_str());
669 sb.Append(TAB).AppendFormat("struct %s *stub = OsalMemCalloc(sizeof(struct %s));\n", stubName_.c_str(),
670 stubName_.c_str());
671 sb.Append(TAB).Append("if (stub == NULL) {\n");
672 sb.Append(TAB).Append(TAB).Append("HDF_LOGE(\"%{public}s: failed to malloc stub object\", __func__);\n");
673 sb.Append(TAB).Append(TAB).Append("return NULL;\n");
674 sb.Append(TAB).Append("}\n");
675
676 if (interface_->IsSerializable()) {
677 sb.Append(TAB).Append("stub->remote = HdfRemoteServiceObtain((struct HdfObject *)stub, &stub->dispatcher);\n");
678 } else {
679 sb.Append(TAB).AppendFormat("stub->remote = HdfRemoteServiceObtain((struct HdfObject *)stub, &%s);\n",
680 dispatcherName.c_str());
681 }
682
683 sb.Append(TAB).Append("if (stub->remote == NULL) {\n");
684 sb.Append(TAB).Append(TAB).Append("OsalMemFree(stub);\n");
685 sb.Append(TAB).Append(TAB).Append("return NULL;\n");
686 sb.Append(TAB).Append("}\n");
687 sb.Append(TAB).AppendFormat("(void)HdfRemoteServiceSetInterfaceDesc(stub->remote, %s);\n",
688 interface_->EmitDescMacroName().c_str());
689 sb.Append(TAB).AppendFormat("stub->dispatcher.Dispatch = %sOnRemoteRequest;\n", baseName_.c_str());
690 sb.Append(TAB).Append("stub->interface = serviceImpl;\n");
691 sb.Append(TAB).AppendFormat("stub->interface->AsObject = %sStubAsObject;\n", baseName_.c_str());
692 sb.Append(TAB).Append("return &stub->remote;\n");
693 sb.Append("}\n");
694 }
695
EmitStubReleaseMethod(StringBuilder & sb) const696 void CServiceStubCodeEmitter::EmitStubReleaseMethod(StringBuilder &sb) const
697 {
698 sb.AppendFormat("static void %sRelease(struct HdfRemoteService **remote)\n", stubName_.c_str());
699 sb.Append("{\n");
700 sb.Append(TAB).Append("if (remote == NULL) {\n");
701 sb.Append(TAB).Append(TAB).Append("return;\n");
702 sb.Append(TAB).Append("}\n");
703 sb.Append(TAB).AppendFormat("struct %s *stub = CONTAINER_OF(remote, struct %s, remote);\n",
704 stubName_.c_str(), stubName_.c_str());
705 sb.Append(TAB).Append("HdfRemoteServiceRecycle(stub->remote);\n");
706 sb.Append(TAB).Append("OsalMemFree(stub);\n");
707 sb.Append("}\n");
708 }
709
EmitStubConstructor(StringBuilder & sb) const710 void CServiceStubCodeEmitter::EmitStubConstructor(StringBuilder &sb) const
711 {
712 std::string constructorName = StringHelper::Format("g_%sConstructor", StringHelper::StrToLower(baseName_).c_str());
713 sb.AppendFormat("__attribute__((unused)) static struct StubConstructor %s = {\n", constructorName.c_str());
714 sb.Append(TAB).AppendFormat(".constructor = %sNewInstance,\n", stubName_.c_str());
715 sb.Append(TAB).AppendFormat(".destructor = %sRelease,\n", stubName_.c_str());
716 sb.Append("};\n");
717 }
718
EmitStubRegAndUnreg(StringBuilder & sb) const719 void CServiceStubCodeEmitter::EmitStubRegAndUnreg(StringBuilder &sb) const
720 {
721 std::string constructorName = StringHelper::Format("g_%sConstructor", StringHelper::StrToLower(baseName_).c_str());
722 sb.AppendFormat("__attribute__((constructor)) static void %sRegister(void)\n", stubName_.c_str());
723 sb.Append("{\n");
724 sb.Append(TAB).AppendFormat(
725 "HDF_LOGI(\"%%{public}s: register stub constructor of '%%{public}s'\", __func__, %s);\n",
726 interface_->EmitDescMacroName().c_str());
727 sb.Append(TAB).AppendFormat("StubConstructorRegister(%s, &%s);\n", interface_->EmitDescMacroName().c_str(),
728 constructorName.c_str());
729 sb.Append("}\n");
730 }
731
GetUtilMethods(UtilMethodMap & methods)732 void CServiceStubCodeEmitter::GetUtilMethods(UtilMethodMap &methods)
733 {
734 for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
735 for (size_t paramIndex = 0; paramIndex < method->GetParameterNumber(); paramIndex++) {
736 AutoPtr<ASTParameter> param = method->GetParameter(paramIndex);
737 AutoPtr<ASTType> paramType = param->GetType();
738 if (param->GetAttribute() == ParamAttr::PARAM_IN) {
739 paramType->RegisterReadMethod(Options::GetInstance().GetLanguage(), SerMode::STUB_SER, methods);
740 } else {
741 paramType->RegisterWriteMethod(Options::GetInstance().GetLanguage(), SerMode::STUB_SER, methods);
742 }
743 }
744 }
745 }
746 } // namespace HDI
747 } // namespace OHOS
748