• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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> &param, 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> &param,
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> &param,
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> &param, 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