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