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